From f4e9827013ab84e1ca88109889a1a08a9c37ecec Mon Sep 17 00:00:00 2001 From: Samuel Susla Date: Fri, 17 Nov 2023 03:27:51 -0800 Subject: [PATCH 001/162] delete ComponentDescriptor::createEventEmitter (#41514) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41514 changelog: [internal] `ComponentDescriptor::createEventEmitter` can be deleted. Reviewed By: christophpurrer Differential Revision: D51394153 fbshipit-source-id: 7541c3cb018a009e8c9555f9a9b0d41215dca1bc --- .../react/renderer/core/ComponentDescriptor.h | 7 -- .../core/ConcreteComponentDescriptor.h | 11 +- .../react/renderer/core/ShadowNodeFamily.cpp | 4 +- .../react/renderer/core/ShadowNodeFamily.h | 1 + .../renderer/core/tests/ShadowNodeTest.cpp | 104 +++++++----------- 5 files changed, 47 insertions(+), 80 deletions(-) diff --git a/packages/react-native/ReactCommon/react/renderer/core/ComponentDescriptor.h b/packages/react-native/ReactCommon/react/renderer/core/ComponentDescriptor.h index aa9c40fc8dd5e7..7839906e5fc153 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/ComponentDescriptor.h +++ b/packages/react-native/ReactCommon/react/renderer/core/ComponentDescriptor.h @@ -8,7 +8,6 @@ #pragma once #include -#include #include #include #include @@ -130,12 +129,6 @@ class ComponentDescriptor { virtual ShadowNodeFamily::Shared createFamily( const ShadowNodeFamilyFragment& fragment) const = 0; - /* - * Creates an event emitter for particular node. - */ - virtual SharedEventEmitter createEventEmitter( - const InstanceHandle::Shared& instanceHandle) const = 0; - protected: friend ShadowNode; diff --git a/packages/react-native/ReactCommon/react/renderer/core/ConcreteComponentDescriptor.h b/packages/react-native/ReactCommon/react/renderer/core/ConcreteComponentDescriptor.h index 4fc25fe73c7776..f161e9b12c1346 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/ConcreteComponentDescriptor.h +++ b/packages/react-native/ReactCommon/react/renderer/core/ConcreteComponentDescriptor.h @@ -155,14 +155,11 @@ class ConcreteComponentDescriptor : public ComponentDescriptor { ShadowNodeFamily::Shared createFamily( const ShadowNodeFamilyFragment& fragment) const override { + auto eventEmitter = std::make_shared( + std::make_shared(fragment.instanceHandle), + eventDispatcher_); return std::make_shared( - fragment, eventDispatcher_, *this); - } - - SharedEventEmitter createEventEmitter( - const InstanceHandle::Shared& instanceHandle) const override { - return std::make_shared( - std::make_shared(instanceHandle), eventDispatcher_); + fragment, std::move(eventEmitter), eventDispatcher_, *this); } protected: diff --git a/packages/react-native/ReactCommon/react/renderer/core/ShadowNodeFamily.cpp b/packages/react-native/ReactCommon/react/renderer/core/ShadowNodeFamily.cpp index cf2bd385b95c5f..0e73b0a5cf3687 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/ShadowNodeFamily.cpp +++ b/packages/react-native/ReactCommon/react/renderer/core/ShadowNodeFamily.cpp @@ -20,14 +20,14 @@ using AncestorList = ShadowNode::AncestorList; ShadowNodeFamily::ShadowNodeFamily( const ShadowNodeFamilyFragment& fragment, + SharedEventEmitter eventEmitter, EventDispatcher::Weak eventDispatcher, const ComponentDescriptor& componentDescriptor) : eventDispatcher_(std::move(eventDispatcher)), tag_(fragment.tag), surfaceId_(fragment.surfaceId), instanceHandle_(fragment.instanceHandle), - eventEmitter_( - componentDescriptor.createEventEmitter(fragment.instanceHandle)), + eventEmitter_(std::move(eventEmitter)), componentDescriptor_(componentDescriptor), componentHandle_(componentDescriptor.getComponentHandle()), componentName_(componentDescriptor.getComponentName()) {} diff --git a/packages/react-native/ReactCommon/react/renderer/core/ShadowNodeFamily.h b/packages/react-native/ReactCommon/react/renderer/core/ShadowNodeFamily.h index 1fefb9532eae45..dc5dbc815317f0 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/ShadowNodeFamily.h +++ b/packages/react-native/ReactCommon/react/renderer/core/ShadowNodeFamily.h @@ -50,6 +50,7 @@ class ShadowNodeFamily final { ShadowNodeFamily( const ShadowNodeFamilyFragment& fragment, + SharedEventEmitter eventEmitter, EventDispatcher::Weak eventDispatcher, const ComponentDescriptor& componentDescriptor); diff --git a/packages/react-native/ReactCommon/react/renderer/core/tests/ShadowNodeTest.cpp b/packages/react-native/ReactCommon/react/renderer/core/tests/ShadowNodeTest.cpp index 8a1f19bdd8a894..ac00541f1030f4 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/tests/ShadowNodeTest.cpp +++ b/packages/react-native/ReactCommon/react/renderer/core/tests/ShadowNodeTest.cpp @@ -37,14 +37,11 @@ class ShadowNodeTest : public ::testing::Test { auto traits = TestShadowNode::BaseTraits(); - auto familyAA = std::make_shared( - ShadowNodeFamilyFragment{ - /* .tag = */ 11, - /* .surfaceId = */ surfaceId_, - /* .instanceHandle = */ nullptr, - }, - eventDispatcher_, - componentDescriptor_); + auto familyAA = componentDescriptor_.createFamily(ShadowNodeFamilyFragment{ + /* .tag = */ 11, + /* .surfaceId = */ surfaceId_, + /* .instanceHandle = */ nullptr, + }); nodeAA_ = std::make_shared( ShadowNodeFragment{ /* .props = */ props, @@ -53,14 +50,11 @@ class ShadowNodeTest : public ::testing::Test { familyAA, traits); - auto familyABA = std::make_shared( - ShadowNodeFamilyFragment{ - /* .tag = */ 12, - /* .surfaceId = */ surfaceId_, - /* .instanceHandle = */ nullptr, - }, - eventDispatcher_, - componentDescriptor_); + auto familyABA = componentDescriptor_.createFamily(ShadowNodeFamilyFragment{ + /* .tag = */ 12, + /* .surfaceId = */ surfaceId_, + /* .instanceHandle = */ nullptr, + }); nodeABA_ = std::make_shared( ShadowNodeFragment{ /* .props = */ props, @@ -69,14 +63,11 @@ class ShadowNodeTest : public ::testing::Test { familyABA, traits); - auto familyABB = std::make_shared( - ShadowNodeFamilyFragment{ - /* .tag = */ 13, - /* .surfaceId = */ surfaceId_, - /* .instanceHandle = */ nullptr, - }, - eventDispatcher_, - componentDescriptor_); + auto familyABB = componentDescriptor_.createFamily(ShadowNodeFamilyFragment{ + /* .tag = */ 13, + /* .surfaceId = */ surfaceId_, + /* .instanceHandle = */ nullptr, + }); nodeABB_ = std::make_shared( ShadowNodeFragment{ /* .props = */ props, @@ -88,14 +79,11 @@ class ShadowNodeTest : public ::testing::Test { auto nodeABChildren = std::make_shared( ShadowNode::ListOfShared{nodeABA_, nodeABB_}); - auto familyAB = std::make_shared( - ShadowNodeFamilyFragment{ - /* .tag = */ 15, - /* .surfaceId = */ surfaceId_, - /* .instanceHandle = */ nullptr, - }, - eventDispatcher_, - componentDescriptor_); + auto familyAB = componentDescriptor_.createFamily(ShadowNodeFamilyFragment{ + /* .tag = */ 15, + /* .surfaceId = */ surfaceId_, + /* .instanceHandle = */ nullptr, + }); nodeAB_ = std::make_shared( ShadowNodeFragment{ /* .props = */ props, @@ -104,14 +92,11 @@ class ShadowNodeTest : public ::testing::Test { familyAB, traits); - auto familyAC = std::make_shared( - ShadowNodeFamilyFragment{ - /* .tag = */ 16, - /* .surfaceId = */ surfaceId_, - /* .instanceHandle = */ nullptr, - }, - eventDispatcher_, - componentDescriptor_); + auto familyAC = componentDescriptor_.createFamily(ShadowNodeFamilyFragment{ + /* .tag = */ 16, + /* .surfaceId = */ surfaceId_, + /* .instanceHandle = */ nullptr, + }); nodeAC_ = std::make_shared( ShadowNodeFragment{ /* .props = */ props, @@ -123,14 +108,11 @@ class ShadowNodeTest : public ::testing::Test { auto nodeAChildren = std::make_shared( ShadowNode::ListOfShared{nodeAA_, nodeAB_, nodeAC_}); - auto familyA = std::make_shared( - ShadowNodeFamilyFragment{ - /* .tag = */ 17, - /* .surfaceId = */ surfaceId_, - /* .instanceHandle = */ nullptr, - }, - eventDispatcher_, - componentDescriptor_); + auto familyA = componentDescriptor_.createFamily(ShadowNodeFamilyFragment{ + /* .tag = */ 17, + /* .surfaceId = */ surfaceId_, + /* .instanceHandle = */ nullptr, + }); nodeA_ = std::make_shared( ShadowNodeFragment{ /* .props = */ props, @@ -139,14 +121,11 @@ class ShadowNodeTest : public ::testing::Test { familyA, traits); - auto familyZ = std::make_shared( - ShadowNodeFamilyFragment{ - /* .tag = */ 18, - /* .surfaceId = */ surfaceId_, - /* .instanceHandle = */ nullptr, - }, - eventDispatcher_, - componentDescriptor_); + auto familyZ = componentDescriptor_.createFamily(ShadowNodeFamilyFragment{ + /* .tag = */ 18, + /* .surfaceId = */ surfaceId_, + /* .instanceHandle = */ nullptr, + }); nodeZ_ = std::make_shared( ShadowNodeFragment{ /* .props = */ props, @@ -234,14 +213,11 @@ TEST_F(ShadowNodeTest, handleCloneFunction) { } TEST_F(ShadowNodeTest, handleState) { - auto family = std::make_shared( - ShadowNodeFamilyFragment{ - /* .tag = */ 9, - /* .surfaceId = */ surfaceId_, - /* .instanceHandle = */ nullptr, - }, - eventDispatcher_, - componentDescriptor_); + auto family = componentDescriptor_.createFamily(ShadowNodeFamilyFragment{ + /* .tag = */ 9, + /* .surfaceId = */ surfaceId_, + /* .instanceHandle = */ nullptr, + }); auto traits = TestShadowNode::BaseTraits(); From a5d8ea4579c630af1e4e0fe1d99ad9dc0915df86 Mon Sep 17 00:00:00 2001 From: Samuel Susla Date: Fri, 17 Nov 2023 03:27:51 -0800 Subject: [PATCH 002/162] delete ShadowNodeFamily::instanceHandle_ (#41513) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41513 changelog: [internal] Reviewed By: christophpurrer Differential Revision: D51394187 fbshipit-source-id: 3add711a3954ba16bf4524d47c3ed67473e2c0eb --- .../ReactCommon/react/renderer/core/ShadowNode.cpp | 7 +------ .../ReactCommon/react/renderer/core/ShadowNodeFamily.cpp | 1 - .../ReactCommon/react/renderer/core/ShadowNodeFamily.h | 5 ----- 3 files changed, 1 insertion(+), 12 deletions(-) diff --git a/packages/react-native/ReactCommon/react/renderer/core/ShadowNode.cpp b/packages/react-native/ReactCommon/react/renderer/core/ShadowNode.cpp index d51cb8ff2311a1..5d8da6fe6b6ca5 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/ShadowNode.cpp +++ b/packages/react-native/ReactCommon/react/renderer/core/ShadowNode.cpp @@ -173,12 +173,7 @@ const SharedEventEmitter& ShadowNode::getEventEmitter() const { } jsi::Value ShadowNode::getInstanceHandle(jsi::Runtime& runtime) const { - auto instanceHandle = family_->instanceHandle_; - if (instanceHandle == nullptr) { - return jsi::Value::null(); - } - - return instanceHandle->getInstanceHandle(runtime); + return family_->eventEmitter_->getEventTarget()->getInstanceHandle(runtime); } Tag ShadowNode::getTag() const { diff --git a/packages/react-native/ReactCommon/react/renderer/core/ShadowNodeFamily.cpp b/packages/react-native/ReactCommon/react/renderer/core/ShadowNodeFamily.cpp index 0e73b0a5cf3687..88143a9d0c0e47 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/ShadowNodeFamily.cpp +++ b/packages/react-native/ReactCommon/react/renderer/core/ShadowNodeFamily.cpp @@ -26,7 +26,6 @@ ShadowNodeFamily::ShadowNodeFamily( : eventDispatcher_(std::move(eventDispatcher)), tag_(fragment.tag), surfaceId_(fragment.surfaceId), - instanceHandle_(fragment.instanceHandle), eventEmitter_(std::move(eventEmitter)), componentDescriptor_(componentDescriptor), componentHandle_(componentDescriptor.getComponentHandle()), diff --git a/packages/react-native/ReactCommon/react/renderer/core/ShadowNodeFamily.h b/packages/react-native/ReactCommon/react/renderer/core/ShadowNodeFamily.h index dc5dbc815317f0..c4a0b4face1b12 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/ShadowNodeFamily.h +++ b/packages/react-native/ReactCommon/react/renderer/core/ShadowNodeFamily.h @@ -132,11 +132,6 @@ class ShadowNodeFamily final { */ const SurfaceId surfaceId_; - /* - * Weak reference to the React instance handle - */ - InstanceHandle::Shared const instanceHandle_; - /* * `EventEmitter` associated with all nodes of the family. */ From 1204696f08c91e17154d5b9c946d7fe8532510de Mon Sep 17 00:00:00 2001 From: Riccardo Cipolleschi Date: Fri, 17 Nov 2023 04:17:58 -0800 Subject: [PATCH 003/162] Defragment Codegen in OSS between Old and New Architecture (#41500) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41500 Right now, the old architecture uses Codegen in a slightly different way w.r.t. the New Architecture. In the Old Architecture, codegen is used to generate some basic TM and components that are part of Core. Both architectures use the same scripts that actually generates the code, but they are invoked differently. This is causing some maintenance costs that we would like to reduce. ## Changelog: [Internal] - Defragment how Codegen is run between old and new architecture Reviewed By: dmytrorykun Differential Revision: D51349874 fbshipit-source-id: 188d3ed436a30a77bd42a26306d4a08666d3a00b --- .../FBReactNativeSpec.podspec | 58 ----- .../ReactCommon/React-rncore.podspec | 9 - .../cocoapods/__tests__/codegen-test.rb | 217 ------------------ .../cocoapods/__tests__/codegen_utils-test.rb | 3 - .../__tests__/new_architecture-test.rb | 17 +- .../react-native/scripts/cocoapods/codegen.rb | 75 +----- .../scripts/cocoapods/codegen_utils.rb | 7 - .../scripts/cocoapods/new_architecture.rb | 54 ++--- .../react-native/scripts/cocoapods/utils.rb | 16 ++ .../codegen/generate-artifacts-executor.js | 82 +++---- .../react-native/scripts/react_native_pods.rb | 104 +-------- .../MyNativeView.podspec | 8 - .../ScreenshotManager.podspec | 9 - packages/rn-tester/Podfile | 7 +- packages/rn-tester/Podfile.lock | 82 +++++-- 15 files changed, 165 insertions(+), 583 deletions(-) delete mode 100644 packages/react-native/React/FBReactNativeSpec/FBReactNativeSpec.podspec diff --git a/packages/react-native/React/FBReactNativeSpec/FBReactNativeSpec.podspec b/packages/react-native/React/FBReactNativeSpec/FBReactNativeSpec.podspec deleted file mode 100644 index 4480a83562a479..00000000000000 --- a/packages/react-native/React/FBReactNativeSpec/FBReactNativeSpec.podspec +++ /dev/null @@ -1,58 +0,0 @@ -# Copyright (c) Meta Platforms, Inc. and affiliates. -# -# This source code is licensed under the MIT license found in the -# LICENSE file in the root directory of this source tree. - -require "json" - -react_native_path = "../.." -require_relative "#{react_native_path}/scripts/react_native_pods.rb" - -package = JSON.parse(File.read(File.join(__dir__, "..", "..", "package.json"))) -version = package['version'] - -source = { :git => 'https://github.com/facebook/react-native.git' } -if version == '1000.0.0' - # This is an unpublished version, use the latest commit hash of the react-native repo, which we’re presumably in. - source[:commit] = `git rev-parse HEAD`.strip if system("git rev-parse --git-dir > /dev/null 2>&1") -else - source[:tag] = "v#{version}" -end - -folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -DFOLLY_CFG_NO_COROUTINES=1 -DFOLLY_HAVE_CLOCK_GETTIME=1 -Wno-comma -Wno-shorten-64-to-32' -folly_version = '2023.08.07.00' - -Pod::Spec.new do |s| - s.name = "FBReactNativeSpec" - s.version = version - s.summary = "-" # TODO - s.homepage = "https://reactnative.dev/" - s.license = package["license"] - s.author = "Meta Platforms, Inc. and its affiliates" - s.platforms = min_supported_versions - s.compiler_flags = folly_compiler_flags + ' -Wno-nullability-completeness' - s.source = source - # This podspec is used to trigger the codegen, and built files are generated in a different location. - # We don't want this pod to actually include any files. - s.header_dir = "FBReactNativeSpec" - - s.pod_target_xcconfig = { - "USE_HEADERMAP" => "YES", - "CLANG_CXX_LANGUAGE_STANDARD" => "c++20", - "HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/RCT-Folly\"" - } - - s.dependency "RCT-Folly", folly_version - s.dependency "RCTRequired", version - s.dependency "RCTTypeSafety", version - s.dependency "React-Core", version - s.dependency "React-jsi", version - s.dependency "ReactCommon/turbomodule/core", version - - use_react_native_codegen!(s, { - :react_native_path => react_native_path, - :js_srcs_dir => "#{react_native_path}/Libraries", - :library_name => "FBReactNativeSpec", - :library_type => "modules", - }) -end diff --git a/packages/react-native/ReactCommon/React-rncore.podspec b/packages/react-native/ReactCommon/React-rncore.podspec index a4532697403bcb..06b8bc7feff1b7 100644 --- a/packages/react-native/ReactCommon/React-rncore.podspec +++ b/packages/react-native/ReactCommon/React-rncore.podspec @@ -49,13 +49,4 @@ Pod::Spec.new do |s| s.pod_target_xcconfig = { "USE_HEADERMAP" => "YES", "HEADER_SEARCH_PATHS" => header_search_paths.join(' '), "CLANG_CXX_LANGUAGE_STANDARD" => "c++20" } - - - use_react_native_codegen!(s, { - :react_native_path => react_native_sources_path, - :js_srcs_dir => "#{react_native_sources_path}/Libraries", - :library_name => "rncore", - :library_type => "components", - :output_dir => "#{react_native_dependency_path}/ReactCommon" - }) end diff --git a/packages/react-native/scripts/cocoapods/__tests__/codegen-test.rb b/packages/react-native/scripts/cocoapods/__tests__/codegen-test.rb index 6987399ad87f6d..3fcce19e09d728 100644 --- a/packages/react-native/scripts/cocoapods/__tests__/codegen-test.rb +++ b/packages/react-native/scripts/cocoapods/__tests__/codegen-test.rb @@ -40,191 +40,6 @@ def teardown DirMock.reset() end - # ============================================== # - # Test - setup_fabric # - # ============================================== # - def testCheckAndGenerateEmptyThirdPartyProvider_whenFileAlreadyExists_doNothing() - - # Arrange - FileMock.mocked_existing_files([ - @base_path + "/" + @prefix + "/React/Fabric/" + @third_party_provider_header, - @base_path + "/" + @prefix + "/React/Fabric/" + @third_party_provider_implementation, - ]) - - # Act - checkAndGenerateEmptyThirdPartyProvider!(@prefix, false, dir_manager: DirMock, file_manager: FileMock) - - # Assert - assert_equal(Pathname.pwd_invocation_count, 1) - assert_equal(Pod::Config.instance.installation_root.relative_path_from_invocation_count, 1) - assert_equal(FileMock.exist_invocation_params, [ - @base_path + "/" + @prefix + "/React/Fabric/" + @third_party_provider_header, - @base_path + "/" + @prefix + "/React/Fabric/" + @third_party_provider_implementation, - ]) - assert_equal(DirMock.exist_invocation_params, []) - assert_equal(Pod::UI.collected_messages, []) - assert_equal($collected_commands, []) - assert_equal(FileMock.open_files.length, 0) - assert_equal(Pod::Executable.executed_commands.length, 0) - end - - def testCheckAndGenerateEmptyThirdPartyProvider_whenHeaderMissingAndCodegenMissing_dontBuildCodegen() - - # Arrange - FileMock.mocked_existing_files([ - @base_path + "/build/" + @third_party_provider_implementation, - ]) - - # Act - assert_nothing_raised { - checkAndGenerateEmptyThirdPartyProvider!(@prefix, false, dir_manager: DirMock, file_manager: FileMock) - } - - # Assert - assert_equal(Pathname.pwd_invocation_count, 1) - assert_equal(Pod::Config.instance.installation_root.relative_path_from_invocation_count, 1) - assert_equal(FileMock.exist_invocation_params, [ - @base_path + "/" + @prefix + "/React/Fabric/" + @third_party_provider_header, - @base_path + "/" + @prefix + "/React/Fabric/tmpSchemaList.txt", - ]) - assert_equal(DirMock.exist_invocation_params, [ - @base_path + "/"+ @prefix + "/../react-native-codegen", - ]) - assert_equal(Pod::UI.collected_messages, [ - "[Codegen] generating an empty RCTThirdPartyFabricComponentsProvider", - ]) - assert_equal($collected_commands, []) - assert_equal(FileMock.open_files.length, 1) - assert_equal(Pod::Executable.executed_commands.length, 1) - end - - def testCheckAndGenerateEmptyThirdPartyProvider_whenImplementationMissingAndCodegenrepoExists_dontBuildCodegen() - - # Arrange - FileMock.mocked_existing_files([ - @base_path + "/" + @prefix + "/React/Fabric/" + @third_party_provider_header, - @base_path + "/" + @prefix + "/React/Fabric/tmpSchemaList.txt" - ]) - - DirMock.mocked_existing_dirs([ - @base_path + "/"+ @prefix + "/../react-native-codegen", - @base_path + "/"+ @prefix + "/../react-native-codegen/lib" - ]) - - # Act - checkAndGenerateEmptyThirdPartyProvider!(@prefix, false, dir_manager: DirMock, file_manager: FileMock) - - # Assert - assert_equal(Pathname.pwd_invocation_count, 1) - assert_equal(Pod::Config.instance.installation_root.relative_path_from_invocation_count, 1) - assert_equal(FileMock.exist_invocation_params, [ - @base_path + "/" + @prefix + "/React/Fabric/" + @third_party_provider_header, - @base_path + "/" + @prefix + "/React/Fabric/" + @third_party_provider_implementation, - @base_path + "/" + @prefix + "/React/Fabric/tmpSchemaList.txt", - ]) - assert_equal(DirMock.exist_invocation_params, [ - @base_path + "/"+ @prefix + "/../react-native-codegen", - @base_path + "/"+ @prefix + "/../react-native-codegen/lib", - ]) - assert_equal(Pod::UI.collected_messages, ["[Codegen] generating an empty RCTThirdPartyFabricComponentsProvider"]) - assert_equal($collected_commands, []) - assert_equal(FileMock.open_invocation_count, 1) - assert_equal(FileMock.open_files_with_mode[@prefix + "/React/Fabric/tmpSchemaList.txt"], nil) - assert_equal(FileMock.open_files[0].collected_write, ["[]"]) - assert_equal(FileMock.open_files[0].fsync_invocation_count, 1) - assert_equal(Pod::Executable.executed_commands[0], { - "command" => "node", - "arguments" => [ - @base_path + "/" + @prefix + "/scripts/generate-provider-cli.js", - "--platform", 'ios', - "--schemaListPath", @base_path + "/" + @prefix + "/React/Fabric/tmpSchemaList.txt", - "--outputDir", @base_path + "/" + @prefix + "/React/Fabric" - ] - }) - assert_equal(FileMock.delete_invocation_count, 1) - assert_equal(FileMock.deleted_files, [ @base_path + "/" + @prefix + "/React/Fabric/tmpSchemaList.txt"]) - end - - def testCheckAndGenerateEmptyThirdPartyProvider_whenBothMissing_buildCodegen() - # Arrange - codegen_cli_path = @base_path + "/" + @prefix + "/../react-native-codegen" - DirMock.mocked_existing_dirs([ - codegen_cli_path, - ]) - # Act - checkAndGenerateEmptyThirdPartyProvider!(@prefix, false, dir_manager: DirMock, file_manager: FileMock) - - # Assert - assert_equal(Pathname.pwd_invocation_count, 1) - assert_equal(Pod::Config.instance.installation_root.relative_path_from_invocation_count, 1) - assert_equal(FileMock.exist_invocation_params, [ - @base_path + "/" + @prefix + "/React/Fabric/" + @third_party_provider_header, - @base_path + "/" + @prefix + "/React/Fabric/" + @tmp_schema_list_file - ]) - assert_equal(DirMock.exist_invocation_params, [ - codegen_cli_path, - codegen_cli_path + "/lib", - ]) - assert_equal(Pod::UI.collected_messages, [ - "[Codegen] building #{codegen_cli_path}", - "[Codegen] generating an empty RCTThirdPartyFabricComponentsProvider" - ]) - assert_equal($collected_commands, ["~/app/ios/../../../react-native-codegen/scripts/oss/build.sh"]) - assert_equal(FileMock.open_files[0].collected_write, ["[]"]) - assert_equal(FileMock.open_files[0].fsync_invocation_count, 1) - assert_equal(Pod::Executable.executed_commands[0], { - "command" => "node", - "arguments" => [ - @base_path + "/" + @prefix + "/scripts/generate-provider-cli.js", - "--platform", 'ios', - "--schemaListPath", @base_path + "/" + @prefix + "/React/Fabric/" + @tmp_schema_list_file, - "--outputDir", @base_path + "/" + @prefix + "/React/Fabric" - ] - }) - end - - def testCheckAndGenerateEmptyThirdPartyProvider_withAbsoluteReactNativePath_buildCodegen() - # Arrange - rn_path = 'packages/react-native' - codegen_cli_path = rn_path + "/../react-native-codegen" - DirMock.mocked_existing_dirs([ - @base_path + "/" + codegen_cli_path, - ]) - - # Act - checkAndGenerateEmptyThirdPartyProvider!(rn_path, false, dir_manager: DirMock, file_manager: FileMock) - - # Assert - assert_equal(Pathname.pwd_invocation_count, 1) - assert_equal(Pod::Config.instance.installation_root.relative_path_from_invocation_count, 1) - assert_equal(FileMock.exist_invocation_params, [ - @base_path + "/" + rn_path + "/React/Fabric/" + @third_party_provider_header, - @base_path + "/" + rn_path + "/React/Fabric/" + @tmp_schema_list_file - ]) - assert_equal(DirMock.exist_invocation_params, [ - @base_path + "/" + codegen_cli_path, - @base_path + "/" + codegen_cli_path + "/lib", - ]) - assert_equal(Pod::UI.collected_messages, [ - "[Codegen] building #{@base_path + "/" + codegen_cli_path}", - "[Codegen] generating an empty RCTThirdPartyFabricComponentsProvider" - ]) - assert_equal($collected_commands, [ - @base_path + "/" + rn_path + "/../react-native-codegen/scripts/oss/build.sh", - ]) - assert_equal(FileMock.open_files[0].collected_write, ["[]"]) - assert_equal(FileMock.open_files[0].fsync_invocation_count, 1) - assert_equal(Pod::Executable.executed_commands[0], { - "command" => "node", - "arguments" => [ - @base_path + "/" + rn_path + "/scripts/generate-provider-cli.js", - "--platform", 'ios', - "--schemaListPath", @base_path + "/" + rn_path + "/React/Fabric/" + @tmp_schema_list_file, - "--outputDir", @base_path + "/" + rn_path + "/React/Fabric" - ] - }) - end - # ================= # # Test - RunCodegen # # ================= # @@ -250,36 +65,4 @@ def testRunCodegen_whenNewArchEnabled_runsCodegen assert_equal(codegen_utils_mock.get_react_codegen_spec_params, []) assert_equal(codegen_utils_mock.generate_react_codegen_spec_params, []) end - - def testRunCodegen_whenNewArchDisabled_runsCodegen - # Arrange - app_path = "~/app" - config_file = "" - package_json_file = "~/app/package.json" - codegen_specs = { "name" => "React-Codegen" } - codegen_utils_mock = CodegenUtilsMock.new(:react_codegen_spec => codegen_specs) - - # Act - run_codegen!( - app_path, - config_file, - :new_arch_enabled => false, - :fabric_enabled => true, - :package_json_file => package_json_file, - :codegen_utils => codegen_utils_mock) - - # Assert - assert_equal(codegen_utils_mock.use_react_native_codegen_discovery_params, []) - assert_equal(codegen_utils_mock.get_react_codegen_spec_params, [{ - :fabric_enabled => true, - :folly_version=>"2023.08.07.00", - :package_json_file => "~/app/package.json", - :script_phases => nil - }]) - assert_equal(codegen_utils_mock.generate_react_codegen_spec_params, [{ - :codegen_output_dir=>"build/generated/ios", - :react_codegen_spec=>{"name"=>"React-Codegen"} - }]) - - end end diff --git a/packages/react-native/scripts/cocoapods/__tests__/codegen_utils-test.rb b/packages/react-native/scripts/cocoapods/__tests__/codegen_utils-test.rb index 6dd22eb30142b7..1891202664c4cc 100644 --- a/packages/react-native/scripts/cocoapods/__tests__/codegen_utils-test.rb +++ b/packages/react-native/scripts/cocoapods/__tests__/codegen_utils-test.rb @@ -561,14 +561,12 @@ def get_podspec_no_fabric_no_script }, 'dependencies': { "DoubleConversion": [], - "FBReactNativeSpec": [], "RCT-Folly": [], "RCTRequired": [], "RCTTypeSafety": [], "React-Core": [], "React-jsi": [], "React-jsiexecutor": [], - "React-rncore": [], "ReactCommon/turbomodule/bridging": [], "ReactCommon/turbomodule/core": [], "hermes-engine": [], @@ -583,7 +581,6 @@ def get_podspec_fabric_and_script_phases(script_phases) specs[:dependencies].merge!({ 'React-graphics': [], - 'React-rncore': [], 'React-Fabric': [], 'React-utils': [], 'React-debug': [], diff --git a/packages/react-native/scripts/cocoapods/__tests__/new_architecture-test.rb b/packages/react-native/scripts/cocoapods/__tests__/new_architecture-test.rb index 9dcd4a3f15b0d2..fc698ae2166940 100644 --- a/packages/react-native/scripts/cocoapods/__tests__/new_architecture-test.rb +++ b/packages/react-native/scripts/cocoapods/__tests__/new_architecture-test.rb @@ -188,7 +188,22 @@ def test_installModulesDependencies_whenNewArchDisabledAndSearchPathsAndCompiler [ { :dependency_name => "React-Core" }, { :dependency_name => "RCT-Folly", "version"=>"2023.08.07.00" }, - { :dependency_name => "glog" } + { :dependency_name => "glog" }, + { :dependency_name => "React-RCTFabric" }, + { :dependency_name => "React-Codegen" }, + { :dependency_name => "RCTRequired" }, + { :dependency_name => "RCTTypeSafety" }, + { :dependency_name => "ReactCommon/turbomodule/bridging" }, + { :dependency_name => "ReactCommon/turbomodule/core" }, + { :dependency_name => "React-NativeModulesApple" }, + { :dependency_name => "Yoga" }, + { :dependency_name => "React-Fabric" }, + { :dependency_name => "React-graphics" }, + { :dependency_name => "React-utils" }, + { :dependency_name => "React-debug" }, + { :dependency_name => "React-ImageManager" }, + { :dependency_name => "React-rendererdebug" }, + { :dependency_name => "hermes-engine" } ] ) end diff --git a/packages/react-native/scripts/cocoapods/codegen.rb b/packages/react-native/scripts/cocoapods/codegen.rb index 7842f39f4226c5..4c1ac3dc6b59e5 100644 --- a/packages/react-native/scripts/cocoapods/codegen.rb +++ b/packages/react-native/scripts/cocoapods/codegen.rb @@ -18,47 +18,7 @@ def build_codegen!(react_native_path, relative_installation_root, dir_manager: D system("#{codegen_repo_path}/scripts/oss/build.sh") end -# It generates an empty `ThirdPartyProvider`, required by Fabric to load the components -# -# Parameters: -# - react_native_path: path to the react native framework -# - new_arch_enabled: whether the New Architecture is enabled or not -# - dir_manager: a class that implements the `Dir` interface. Defaults to `Dir`, the Dependency can be injected for testing purposes. -# - file_manager: a class that implements the `File` interface. Defaults to `File`, the Dependency can be injected for testing purposes. -def checkAndGenerateEmptyThirdPartyProvider!(react_native_path, new_arch_enabled, dir_manager: Dir, file_manager: File) - return if new_arch_enabled - - relative_installation_root = Pod::Config.instance.installation_root.relative_path_from(Pathname.pwd) - - output_dir = "#{relative_installation_root}/#{react_native_path}/React/Fabric" - - provider_h_path = "#{output_dir}/RCTThirdPartyFabricComponentsProvider.h" - provider_cpp_path ="#{output_dir}/RCTThirdPartyFabricComponentsProvider.mm" - - if(!file_manager.exist?(provider_h_path) || !file_manager.exist?(provider_cpp_path)) - # build codegen - build_codegen!(react_native_path, relative_installation_root, dir_manager: dir_manager) - - # Just use a temp empty schema list. - temp_schema_list_path = "#{output_dir}/tmpSchemaList.txt" - file_manager.open(temp_schema_list_path, 'w') do |f| - f.write('[]') - f.fsync - end - - Pod::UI.puts '[Codegen] generating an empty RCTThirdPartyFabricComponentsProvider' - Pod::Executable.execute_command( - 'node', - [ - "#{basePath(react_native_path, relative_installation_root)}/scripts/generate-provider-cli.js", - "--platform", 'ios', - "--schemaListPath", temp_schema_list_path, - "--outputDir", "#{output_dir}" - ]) - file_manager.delete(temp_schema_list_path) if file_manager.exist?(temp_schema_list_path) - end -end - +# keeping the run_codegen! method for testing purposes def run_codegen!( app_path, config_file_dir, @@ -74,28 +34,17 @@ def run_codegen!( codegen_utils: CodegenUtils.new() ) - if new_arch_enabled - codegen_utils.use_react_native_codegen_discovery!( - disable_codegen, - app_path, - :react_native_path => react_native_path, - :fabric_enabled => fabric_enabled, - :hermes_enabled => hermes_enabled, - :config_file_dir => config_file_dir, - :codegen_output_dir => codegen_output_dir, - :config_key => config_key, - :folly_version => folly_version - ) - else - # Generate a podspec file for generated files. - # This gets generated in use_react_native_codegen_discovery when codegen discovery is enabled. - react_codegen_spec = codegen_utils.get_react_codegen_spec( - package_json_file, - :fabric_enabled => fabric_enabled, - :hermes_enabled => hermes_enabled - ) - codegen_utils.generate_react_codegen_podspec!(react_codegen_spec, codegen_output_dir) - end + codegen_utils.use_react_native_codegen_discovery!( + disable_codegen, + app_path, + :react_native_path => react_native_path, + :fabric_enabled => fabric_enabled, + :hermes_enabled => hermes_enabled, + :config_file_dir => config_file_dir, + :codegen_output_dir => codegen_output_dir, + :config_key => config_key, + :folly_version => folly_version + ) end def basePath(react_native_path, relative_installation_root) diff --git a/packages/react-native/scripts/cocoapods/codegen_utils.rb b/packages/react-native/scripts/cocoapods/codegen_utils.rb index a39c77ed9a9611..9f98a9dfa0984f 100644 --- a/packages/react-native/scripts/cocoapods/codegen_utils.rb +++ b/packages/react-native/scripts/cocoapods/codegen_utils.rb @@ -159,13 +159,6 @@ def get_react_codegen_spec(package_json_file, folly_version: '2023.08.07.00', fa }); end - if new_arch_disabled - spec[:dependencies].merge!({ - 'React-rncore': [], - 'FBReactNativeSpec': [], - }) - end - if script_phases Pod::UI.puts "[Codegen] Adding script_phases to React-Codegen." spec[:'script_phases'] = script_phases diff --git a/packages/react-native/scripts/cocoapods/new_architecture.rb b/packages/react-native/scripts/cocoapods/new_architecture.rb index 20ae33fbe87b57..7bf30e43f604e1 100644 --- a/packages/react-native/scripts/cocoapods/new_architecture.rb +++ b/packages/react-native/scripts/cocoapods/new_architecture.rb @@ -75,17 +75,6 @@ def self.modify_flags_for_new_architecture(installer, is_new_arch_enabled) end end - # Set "RCT_DYNAMIC_FRAMEWORKS=1" if pod are installed with USE_FRAMEWORKS=dynamic - # This helps with backward compatibility. - if pod_name == 'React-RCTFabric' && ENV['USE_FRAMEWORKS'] == 'dynamic' - Pod::UI.puts "Setting -DRCT_DYNAMIC_FRAMEWORKS=1 to React-RCTFabric".green - rct_dynamic_framework_flag = " -DRCT_DYNAMIC_FRAMEWORKS=1" - target_installation_result.native_target.build_configurations.each do |config| - prev_build_settings = config.build_settings['OTHER_CPLUSPLUSFLAGS'] != nil ? config.build_settings['OTHER_CPLUSPLUSFLAGS'] : "$(inherithed)" - config.build_settings['OTHER_CPLUSPLUSFLAGS'] = prev_build_settings + rct_dynamic_framework_flag - end - end - target_installation_result.native_target.build_configurations.each do |config| if config.name == "Release" current_flags = config.build_settings['OTHER_CPLUSPLUSFLAGS'] != nil ? config.build_settings['OTHER_CPLUSPLUSFLAGS'] : "$(inherited)" @@ -138,27 +127,28 @@ def self.install_modules_dependencies(spec, new_arch_enabled, folly_version) if new_arch_enabled current_config["OTHER_CPLUSPLUSFLAGS"] = @@new_arch_cpp_flags - spec.dependency "React-RCTFabric" # This is for Fabric Component - spec.dependency "React-Codegen" - - spec.dependency "RCTRequired" - spec.dependency "RCTTypeSafety" - spec.dependency "ReactCommon/turbomodule/bridging" - spec.dependency "ReactCommon/turbomodule/core" - spec.dependency "React-NativeModulesApple" - spec.dependency "Yoga" - spec.dependency "React-Fabric" - spec.dependency "React-graphics" - spec.dependency "React-utils" - spec.dependency "React-debug" - spec.dependency "React-ImageManager" - spec.dependency "React-rendererdebug" - - if ENV["USE_HERMES"] == nil || ENV["USE_HERMES"] == "1" - spec.dependency "hermes-engine" - else - spec.dependency "React-jsi" - end + end + + spec.dependency "React-RCTFabric" # This is for Fabric Component + spec.dependency "React-Codegen" + + spec.dependency "RCTRequired" + spec.dependency "RCTTypeSafety" + spec.dependency "ReactCommon/turbomodule/bridging" + spec.dependency "ReactCommon/turbomodule/core" + spec.dependency "React-NativeModulesApple" + spec.dependency "Yoga" + spec.dependency "React-Fabric" + spec.dependency "React-graphics" + spec.dependency "React-utils" + spec.dependency "React-debug" + spec.dependency "React-ImageManager" + spec.dependency "React-rendererdebug" + + if ENV["USE_HERMES"] == nil || ENV["USE_HERMES"] == "1" + spec.dependency "hermes-engine" + else + spec.dependency "React-jsi" end spec.pod_target_xcconfig = current_config diff --git a/packages/react-native/scripts/cocoapods/utils.rb b/packages/react-native/scripts/cocoapods/utils.rb index 4a8bd34d71e039..eb89a3de20045d 100644 --- a/packages/react-native/scripts/cocoapods/utils.rb +++ b/packages/react-native/scripts/cocoapods/utils.rb @@ -318,6 +318,22 @@ def self.updateOSDeploymentTarget(installer) end end + def self.set_dynamic_frameworks_flags(installer) + installer.target_installation_results.pod_target_installation_results.each do |pod_name, target_installation_result| + + # Set "RCT_DYNAMIC_FRAMEWORKS=1" if pod are installed with USE_FRAMEWORKS=dynamic + # This helps with backward compatibility. + if pod_name == 'React-RCTFabric' && ENV['USE_FRAMEWORKS'] == 'dynamic' + Pod::UI.puts "Setting -DRCT_DYNAMIC_FRAMEWORKS=1 to React-RCTFabric".green + rct_dynamic_framework_flag = " -DRCT_DYNAMIC_FRAMEWORKS=1" + target_installation_result.native_target.build_configurations.each do |config| + prev_build_settings = config.build_settings['OTHER_CPLUSPLUSFLAGS'] != nil ? config.build_settings['OTHER_CPLUSPLUSFLAGS'] : "$(inherithed)" + config.build_settings['OTHER_CPLUSPLUSFLAGS'] = prev_build_settings + rct_dynamic_framework_flag + end + end + end + end + # ========= # # Utilities # # ========= # diff --git a/packages/react-native/scripts/codegen/generate-artifacts-executor.js b/packages/react-native/scripts/codegen/generate-artifacts-executor.js index dc8a5bab381212..7dc8b92366ed83 100644 --- a/packages/react-native/scripts/codegen/generate-artifacts-executor.js +++ b/packages/react-native/scripts/codegen/generate-artifacts-executor.js @@ -378,23 +378,12 @@ function generateCode(iosOutputDir, library, tmpDir, node, pathToSchema) { function generateNativeCodegenFiles( libraries, - fabricEnabled, iosOutputDir, node, codegenCliPath, schemaPaths, ) { - let fabricEnabledTypes = ['components', 'all']; libraries.forEach(library => { - if ( - !fabricEnabled && - fabricEnabledTypes.indexOf(library.config.type) >= 0 - ) { - console.log( - `[Codegen] ${library.config.name} skipped because fabric is not enabled.`, - ); - return; - } const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), library.config.name)); const pathToSchema = generateSchema(tmpDir, library, node, codegenCliPath); generateCode(iosOutputDir, library, tmpDir, node, pathToSchema); @@ -408,44 +397,37 @@ function generateNativeCodegenFiles( }); } -function createComponentProvider( - fabricEnabled, - schemaPaths, - node, - iosOutputDir, -) { - if (fabricEnabled) { - console.log('\n\n>>>>> Creating component provider'); - // Save the list of spec paths to a temp file. - const schemaListTmpPath = `${os.tmpdir()}/rn-tmp-schema-list.json`; - const fd = fs.openSync(schemaListTmpPath, 'w'); - fs.writeSync(fd, JSON.stringify(schemaPaths)); - fs.closeSync(fd); - console.log(`Generated schema list: ${schemaListTmpPath}`); - - const outputDir = path.join( - REACT_NATIVE_PACKAGE_ROOT_FOLDER, - 'React', - 'Fabric', - ); +function createComponentProvider(schemaPaths, node, iosOutputDir) { + console.log('\n\n>>>>> Creating component provider'); + // Save the list of spec paths to a temp file. + const schemaListTmpPath = `${os.tmpdir()}/rn-tmp-schema-list.json`; + const fd = fs.openSync(schemaListTmpPath, 'w'); + fs.writeSync(fd, JSON.stringify(schemaPaths)); + fs.closeSync(fd); + console.log(`Generated schema list: ${schemaListTmpPath}`); - // Generate FabricComponentProvider. - // Only for iOS at this moment. - executeNodeScript(node, [ - `${path.join( - REACT_NATIVE_PACKAGE_ROOT_FOLDER, - 'scripts', - 'generate-provider-cli.js', - )}`, - '--platform', - 'ios', - '--schemaListPath', - schemaListTmpPath, - '--outputDir', - outputDir, - ]); - console.log(`Generated provider in: ${outputDir}`); - } + const outputDir = path.join( + REACT_NATIVE_PACKAGE_ROOT_FOLDER, + 'React', + 'Fabric', + ); + + // Generate FabricComponentProvider. + // Only for iOS at this moment. + executeNodeScript(node, [ + `${path.join( + REACT_NATIVE_PACKAGE_ROOT_FOLDER, + 'scripts', + 'generate-provider-cli.js', + )}`, + '--platform', + 'ios', + '--schemaListPath', + schemaListTmpPath, + '--outputDir', + outputDir, + ]); + console.log(`Generated provider in: ${outputDir}`); } function findCodegenEnabledLibraries( @@ -541,7 +523,6 @@ function execute( codegenConfigFilename, codegenConfigKey, baseCodegenConfigFileDir, - fabricEnabled, ) { if (!isAppRootValid(appRootDir)) { return; @@ -568,14 +549,13 @@ function execute( generateNativeCodegenFiles( libraries, - fabricEnabled, iosOutputDir, node, codegenCliPath, schemaPaths, ); - createComponentProvider(fabricEnabled, schemaPaths, node, iosOutputDir); + createComponentProvider(schemaPaths, node, iosOutputDir); cleanupEmptyFilesAndFolders(iosOutputDir); } catch (err) { console.error(err); diff --git a/packages/react-native/scripts/react_native_pods.rb b/packages/react-native/scripts/react_native_pods.rb index ed040142261bfd..0bb0bd50cd542b 100644 --- a/packages/react-native/scripts/react_native_pods.rb +++ b/packages/react-native/scripts/react_native_pods.rb @@ -105,7 +105,6 @@ def use_react_native! ( # The Pods which should be included in all projects pod 'FBLazyVector', :path => "#{prefix}/Libraries/FBLazyVector" - pod 'FBReactNativeSpec', :path => "#{prefix}/React/FBReactNativeSpec" if !NewArchitectureHelper.new_arch_enabled pod 'RCTRequired', :path => "#{prefix}/Libraries/Required" pod 'RCTTypeSafety', :path => "#{prefix}/Libraries/TypeSafety", :modular_headers => true pod 'React', :path => "#{prefix}/" @@ -174,7 +173,6 @@ def use_react_native! ( # If the New Arch is turned off, we will use the Old Renderer, though. # RNTester always installed Fabric, this change is required to make the template work. setup_fabric!(:react_native_path => prefix) - checkAndGenerateEmptyThirdPartyProvider!(prefix, NewArchitectureHelper.new_arch_enabled) if !fabric_enabled relative_installation_root = Pod::Config.instance.installation_root.relative_path_from(Pathname.pwd) @@ -286,6 +284,7 @@ def react_native_post_install( ReactNativePodsUtils.apply_xcode_15_patch(installer) ReactNativePodsUtils.apply_ats_config(installer) ReactNativePodsUtils.updateOSDeploymentTarget(installer) + ReactNativePodsUtils.set_dynamic_frameworks_flags(installer) NewArchitectureHelper.set_clang_cxx_language_standard_if_needed(installer) NewArchitectureHelper.modify_flags_for_new_architecture(installer, NewArchitectureHelper.new_arch_enabled) @@ -293,104 +292,3 @@ def react_native_post_install( Pod::UI.puts "Pod install took #{Time.now.to_i - $START_TIME} [s] to run".green end - -# === LEGACY METHOD === -# We need to keep this while we continue to support the old architecture. -# ===================== -def use_react_native_codegen!(spec, options={}) - return if NewArchitectureHelper.new_arch_enabled - # TODO: Once the new codegen approach is ready for use, we should output a warning here to let folks know to migrate. - - # The prefix to react-native - react_native_path = options[:react_native_path] ||= ".." - - # Library name (e.g. FBReactNativeSpec) - library_name = options[:library_name] ||= "#{spec.name.gsub('_','-').split('-').collect(&:capitalize).join}Spec" - Pod::UI.puts "[Codegen] Found #{library_name}" - - relative_installation_root = Pod::Config.instance.installation_root.relative_path_from(Pathname.pwd) - output_dir = options[:output_dir] ||= $CODEGEN_OUTPUT_DIR - output_dir_module = "#{output_dir}/#{$CODEGEN_MODULE_DIR}" - output_dir_component = "#{output_dir}/#{$CODEGEN_COMPONENT_DIR}" - - codegen_config = { - "modules" => { - :js_srcs_pattern => "Native*.js", - :generated_dir => "#{relative_installation_root}/#{output_dir_module}/#{library_name}", - :generated_files => [ - "#{library_name}.h", - "#{library_name}-generated.mm" - ] - }, - "components" => { - :js_srcs_pattern => "*NativeComponent.js", - :generated_dir => "#{relative_installation_root}/#{output_dir_component}/#{library_name}", - :generated_files => [ - "ComponentDescriptors.h", - "EventEmitters.cpp", - "EventEmitters.h", - "Props.cpp", - "Props.h", - "States.cpp", - "States.h", - "RCTComponentViewHelpers.h", - "ShadowNodes.cpp", - "ShadowNodes.h" - ] - } - } - - # The path to JavaScript files - js_srcs_dir = options[:js_srcs_dir] ||= "./" - library_type = options[:library_type] - - if library_type - if !codegen_config[library_type] - raise "[Codegen] invalid library_type: #{library_type}. Check your podspec to make sure it's set to 'modules' or 'components'. Removing the option will generate files for both" - end - js_srcs_pattern = codegen_config[library_type][:js_srcs_pattern] - end - - if library_type - generated_dirs = [ codegen_config[library_type][:generated_dir] ] - generated_files = codegen_config[library_type][:generated_files].map { |filename| "#{codegen_config[library_type][:generated_dir]}/#{filename}" } - else - generated_dirs = [ codegen_config["modules"][:generated_dir], codegen_config["components"][:generated_dir] ] - generated_files = codegen_config["modules"][:generated_files].map { |filename| "#{codegen_config["modules"][:generated_dir]}/#{filename}" } - generated_files = generated_files.concat(codegen_config["components"][:generated_files].map { |filename| "#{codegen_config["components"][:generated_dir]}/#{filename}" }) - end - - if js_srcs_pattern - file_list = `find #{js_srcs_dir} -type f -name #{js_srcs_pattern}`.split("\n").sort - input_files = file_list.map { |filename| "${PODS_TARGET_SRCROOT}/#{filename}" } - else - input_files = [ js_srcs_dir ] - end - - # Prepare filesystem by creating empty files that will be picked up as references by CocoaPods. - prepare_command = "mkdir -p #{generated_dirs.join(" ")} && touch -a #{generated_files.join(" ")}" - system(prepare_command) # Always run prepare_command when a podspec uses the codegen, as CocoaPods may skip invoking this command in certain scenarios. Replace with pre_integrate_hook after updating to CocoaPods 1.11 - spec.prepare_command = prepare_command - - env_files = ["$PODS_ROOT/../.xcode.env.local", "$PODS_ROOT/../.xcode.env"] - - spec.script_phase = { - :name => 'Generate Specs', - :input_files => input_files + env_files, # This also needs to be relative to Xcode - :output_files => ["${DERIVED_FILE_DIR}/codegen-#{library_name}.log"].concat(generated_files.map { |filename| "${PODS_TARGET_SRCROOT}/#{filename}"} ), - # The final generated files will be created when this script is invoked at Xcode build time. - :script => get_script_phases_no_codegen_discovery( - react_native_path: react_native_path, - codegen_output_dir: output_dir, - codegen_module_dir: output_dir_module, - codegen_component_dir: output_dir_component, - library_name: library_name, - library_type: library_type, - js_srcs_pattern: js_srcs_pattern, - js_srcs_dir: js_srcs_dir, - file_list: file_list - ), - :execution_position => :before_compile, - :show_env_vars_in_log => true - } -end diff --git a/packages/rn-tester/NativeComponentExample/MyNativeView.podspec b/packages/rn-tester/NativeComponentExample/MyNativeView.podspec index 23f1db01e1cc11..2e4eb0613d9f41 100644 --- a/packages/rn-tester/NativeComponentExample/MyNativeView.podspec +++ b/packages/rn-tester/NativeComponentExample/MyNativeView.podspec @@ -30,12 +30,4 @@ Pod::Spec.new do |s| s.requires_arc = true install_modules_dependencies(s) - - # Enable codegen for this library - use_react_native_codegen!(s, { - :library_name => "MyNativeViewSpec", - :react_native_path => "../../react-native", - :js_srcs_dir => "./js", - :library_type => "components" - }) end diff --git a/packages/rn-tester/NativeModuleExample/ScreenshotManager.podspec b/packages/rn-tester/NativeModuleExample/ScreenshotManager.podspec index 2082df5691ed09..17daaf5934d9fd 100644 --- a/packages/rn-tester/NativeModuleExample/ScreenshotManager.podspec +++ b/packages/rn-tester/NativeModuleExample/ScreenshotManager.podspec @@ -23,13 +23,4 @@ Pod::Spec.new do |s| s.requires_arc = true install_modules_dependencies(s) - - # s.dependency "..." - - # Enable codegen for this library - use_react_native_codegen!(s, { - :react_native_path => "../../react-native", - :js_srcs_dir => "./", - :library_type => "modules", - }) end diff --git a/packages/rn-tester/Podfile b/packages/rn-tester/Podfile index 8991d28a670e07..1aff97a42fc655 100644 --- a/packages/rn-tester/Podfile +++ b/packages/rn-tester/Podfile @@ -60,11 +60,8 @@ def pods(target_name, options = {}) # RNTester native modules and components pod 'ScreenshotManager', :path => "NativeModuleExample" - - if ENV['RCT_NEW_ARCH_ENABLED'] == '1' - pod 'MyNativeView', :path => "NativeComponentExample" - pod 'NativeCxxModuleExample', :path => "NativeCxxModuleExample" - end + pod 'MyNativeView', :path => "NativeComponentExample" + pod 'NativeCxxModuleExample', :path => "NativeCxxModuleExample" end target 'RNTester' do diff --git a/packages/rn-tester/Podfile.lock b/packages/rn-tester/Podfile.lock index 2d38f0181b3f63..b4e0b2c0f58db8 100644 --- a/packages/rn-tester/Podfile.lock +++ b/packages/rn-tester/Podfile.lock @@ -2,13 +2,6 @@ PODS: - boost (1.83.0) - DoubleConversion (1.1.6) - FBLazyVector (1000.0.0) - - FBReactNativeSpec (1000.0.0): - - RCT-Folly (= 2023.08.07.00) - - RCTRequired (= 1000.0.0) - - RCTTypeSafety (= 1000.0.0) - - React-Core (= 1000.0.0) - - React-jsi (= 1000.0.0) - - ReactCommon/turbomodule/core (= 1000.0.0) - fmt (9.1.0) - glog (0.3.5) - hermes-engine (1000.0.0): @@ -20,6 +13,44 @@ PODS: - hermes-engine/inspector (1000.0.0) - hermes-engine/inspector_chrome (1000.0.0) - hermes-engine/Public (1000.0.0) + - MyNativeView (0.0.1): + - glog + - hermes-engine + - RCT-Folly (= 2023.08.07.00) + - RCTRequired + - RCTTypeSafety + - React-Codegen + - React-Core + - React-debug + - React-Fabric + - React-graphics + - React-ImageManager + - React-NativeModulesApple + - React-RCTFabric + - React-rendererdebug + - React-utils + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - Yoga + - NativeCxxModuleExample (0.0.1): + - glog + - hermes-engine + - RCT-Folly (= 2023.08.07.00) + - RCTRequired + - RCTTypeSafety + - React-Codegen + - React-Core + - React-debug + - React-Fabric + - React-graphics + - React-ImageManager + - React-NativeModulesApple + - React-RCTFabric + - React-rendererdebug + - React-utils + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - Yoga - OCMock (3.9.1) - RCT-Folly (2023.08.07.00): - boost @@ -58,7 +89,6 @@ PODS: - React-callinvoker (1000.0.0) - React-Codegen (1000.0.0): - DoubleConversion - - FBReactNativeSpec - glog - hermes-engine - RCT-Folly @@ -72,7 +102,6 @@ PODS: - React-jsiexecutor - React-NativeModulesApple - React-rendererdebug - - React-rncore - React-utils - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core @@ -1097,8 +1126,23 @@ PODS: - React-perflogger (= 1000.0.0) - ScreenshotManager (0.0.1): - glog + - hermes-engine - RCT-Folly (= 2023.08.07.00) + - RCTRequired + - RCTTypeSafety + - React-Codegen - React-Core + - React-debug + - React-Fabric + - React-graphics + - React-ImageManager + - React-NativeModulesApple + - React-RCTFabric + - React-rendererdebug + - React-utils + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - Yoga - SocketRocket (0.7.0) - Yoga (0.0.0) @@ -1106,10 +1150,11 @@ DEPENDENCIES: - boost (from `../react-native/third-party-podspecs/boost.podspec`) - DoubleConversion (from `../react-native/third-party-podspecs/DoubleConversion.podspec`) - FBLazyVector (from `../react-native/Libraries/FBLazyVector`) - - FBReactNativeSpec (from `../react-native/React/FBReactNativeSpec`) - fmt (from `../react-native/third-party-podspecs/fmt.podspec`) - glog (from `../react-native/third-party-podspecs/glog.podspec`) - hermes-engine (from `../react-native/sdks/hermes-engine/hermes-engine.podspec`) + - MyNativeView (from `NativeComponentExample`) + - NativeCxxModuleExample (from `NativeCxxModuleExample`) - OCMock (~> 3.9.1) - RCT-Folly (from `../react-native/third-party-podspecs/RCT-Folly.podspec`) - RCT-Folly/Fabric (from `../react-native/third-party-podspecs/RCT-Folly.podspec`) @@ -1172,8 +1217,6 @@ EXTERNAL SOURCES: :podspec: "../react-native/third-party-podspecs/DoubleConversion.podspec" FBLazyVector: :path: "../react-native/Libraries/FBLazyVector" - FBReactNativeSpec: - :path: "../react-native/React/FBReactNativeSpec" fmt: :podspec: "../react-native/third-party-podspecs/fmt.podspec" glog: @@ -1181,6 +1224,10 @@ EXTERNAL SOURCES: hermes-engine: :podspec: "../react-native/sdks/hermes-engine/hermes-engine.podspec" :tag: '' + MyNativeView: + :path: NativeComponentExample + NativeCxxModuleExample: + :path: NativeCxxModuleExample RCT-Folly: :podspec: "../react-native/third-party-podspecs/RCT-Folly.podspec" RCTRequired: @@ -1278,17 +1325,18 @@ SPEC CHECKSUMS: boost: 26fad476bfa736552bbfa698a06cc530475c1505 DoubleConversion: fea03f2699887d960129cc54bba7e52542b6f953 FBLazyVector: f4492a543c5a8fa1502d3a5867e3f7252497cfe8 - FBReactNativeSpec: 03da6018f583d64c5944bc4afffb12368e3642a8 fmt: 4c2741a687cc09f0634a2e2c72a838b99f1ff120 glog: c5d68082e772fa1c511173d6b30a9de2c05a69a2 hermes-engine: 2788dfc2ed3699d11b14e815f0c608fc8d770d6b + MyNativeView: 1fb0d21fda6ef12fd5f425f9888c81345a86a3e7 + NativeCxxModuleExample: 19d10636011c914264a5922c6f0f22a2e8fd0910 OCMock: 9491e4bec59e0b267d52a9184ff5605995e74be8 RCT-Folly: 823c6f6ec910a75d4ad28898b4a11cdee140b92a RCTRequired: 82c56a03b3efd524bfdb581a906add903f78f978 RCTTypeSafety: 5f57d4ae5dfafc85a0f575d756c909b584722c52 React: cb6dc75e09f32aeddb4d8fb58a394a67219a92fe React-callinvoker: bae59cbd6affd712bbfc703839dad868ff35069d - React-Codegen: 20baee7c8f2303bc5f34d9e72f93ca55de6cbde3 + React-Codegen: c1e6ea0005a6ecf187d2772f14e5386f1c1f4853 React-Core: f09ea29184cc7f33015a0748588fcfe1d43b3dd1 React-CoreModules: ad1b7cb8efe5f3c7e88548b6ea6aad8507774471 React-cxxreact: 04bf6a12caa850f5d2c7bd6d66dfecd4741989b5 @@ -1321,16 +1369,16 @@ SPEC CHECKSUMS: React-RCTText: d9925903524a7b179cf7803162a98038e0bfb4fd React-RCTVibration: 14322c13fb0c5cc2884b714b11d277dc7fc326c4 React-rendererdebug: 2e58409db231638bc3e78143d8844066a3302939 - React-rncore: 63aced0ca8aff46f8e762663ca4afebb5eedb627 + React-rncore: e903b3d2819a25674403c548ec103f34bf02ba2b React-runtimeexecutor: e1c32bc249dd3cf3919cb4664fd8dc84ef70cff7 React-runtimescheduler: 6529d155a98010b6e8f0a3a86d4184b89a886633 React-utils: 87ed8c079c9991831112fe716f2686c430699fc3 ReactCommon: 4511ea0e8f349de031de7cad88c2ecf871ab69f9 ReactCommon-Samples: cfc3383af93a741319e038977c2ae1082e4ff49e - ScreenshotManager: 2b23b74d25f5e307f7b4d21173a61a3934e69475 + ScreenshotManager: 753da20873c2ada484bdee4143a7248084d3fd35 SocketRocket: abac6f5de4d4d62d24e11868d7a2f427e0ef940d Yoga: 455fa6867657b570a05655dd515c8c6588618fa8 -PODFILE CHECKSUM: c0120ff99aea9c7141bc22179e0f6be99c81a601 +PODFILE CHECKSUM: 426f495a1ad44f3cabea3b7dd2b66a0b71083e26 COCOAPODS: 1.13.0 From 02bb50d9ced2c7ae7b426403e1c4cf5d12728a93 Mon Sep 17 00:00:00 2001 From: zhongwuzw Date: Fri, 17 Nov 2023 06:10:00 -0800 Subject: [PATCH 004/162] Fix assert cxx example crash the app when tap `Run all tests` (#41521) Summary: When I tap the `Run all tests` button in CxxModuleExample, App crashed because our `assert` examples directoly. ![image](https://github.com/facebook/react-native/assets/5061845/6d3fbbc1-9d41-419a-9074-898e839ee51a) I moved the error report examples to individual section so `Run all tests` not crash. ![image](https://github.com/facebook/react-native/assets/5061845/4b781b40-0606-4d40-a752-1cd716073e33) ## Changelog: [INTERNAL] [FIXED] - [RN-Tester] Fix assert cxx example crash the app when tap `Run all tests` Pull Request resolved: https://github.com/facebook/react-native/pull/41521 Test Plan: None. Reviewed By: christophpurrer Differential Revision: D51423538 Pulled By: rshest fbshipit-source-id: 1e2844aa9011de4476ec4b134d43daa3260a73d5 --- .../NativeCxxModuleExampleExample.js | 30 +++++++++++++++++-- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/packages/rn-tester/js/examples/TurboModule/NativeCxxModuleExampleExample.js b/packages/rn-tester/js/examples/TurboModule/NativeCxxModuleExampleExample.js index f4135cc5b5ffc3..189c3a5fd21475 100644 --- a/packages/rn-tester/js/examples/TurboModule/NativeCxxModuleExampleExample.js +++ b/packages/rn-tester/js/examples/TurboModule/NativeCxxModuleExampleExample.js @@ -55,7 +55,9 @@ type Examples = | 'rejectPromise' | 'voidFunc' | 'optionalArgs' - | 'emitDeviceEvent' + | 'emitDeviceEvent'; + +type ErrorExamples = | 'voidFuncThrows' | 'getObjectThrows' | 'promiseThrows' @@ -131,6 +133,10 @@ class NativeCxxModuleExampleExample extends React.Component<{||}, State> { }); NativeCxxModuleExample?.emitCustomDeviceEvent(CUSTOM_EVENT_TYPE); }, + }; + + // $FlowFixMe[missing-local-annot] + _errorTests = { voidFuncThrows: () => { try { NativeCxxModuleExample?.voidFuncThrows(); @@ -202,7 +208,7 @@ class NativeCxxModuleExampleExample extends React.Component<{||}, State> { })); } - _renderResult(name: Examples): React.Node { + _renderResult(name: Examples | ErrorExamples): React.Node { const result = this.state.testResults[name] || {}; return ( @@ -231,7 +237,7 @@ class NativeCxxModuleExampleExample extends React.Component<{||}, State> { this._setResult(item, this._tests[item]()), ) }> - Run all tests + Run function call tests this.setState({testResults: {}})} @@ -254,6 +260,24 @@ class NativeCxxModuleExampleExample extends React.Component<{||}, State> { )} /> + + Report errors tests + + item} + renderItem={({item}: {item: ErrorExamples, ...}) => ( + + this._setResult(item, this._errorTests[item]())}> + {item} + + {this._renderResult(item)} + + )} + /> ); } From 5e7be7e3ab90b6c14bee1ad0fbad9960cd009524 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Norte?= Date: Fri, 17 Nov 2023 08:23:11 -0800 Subject: [PATCH 005/162] Add experimental global callback for attached images (#41525) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41525 This creates an experimental mechanism to get notifications when image instances are created anywhere in the app. This can be useful to set up things like image performance tracking automatically without having to use a custom component and manually access refs from image components. Changelog: [internal] Reviewed By: oprisnik Differential Revision: D49962063 fbshipit-source-id: b991a808aaa723bea98c27812892cfa468f025a6 --- .../Libraries/Image/Image.android.js | 11 +- .../react-native/Libraries/Image/Image.ios.js | 9 +- .../Libraries/Image/ImageInjection.js | 60 +++++- .../Libraries/Image/__tests__/Image-test.js | 191 ++++++++++++++++++ 4 files changed, 265 insertions(+), 6 deletions(-) diff --git a/packages/react-native/Libraries/Image/Image.android.js b/packages/react-native/Libraries/Image/Image.android.js index 3e63b61e717465..e5c5d9f223b616 100644 --- a/packages/react-native/Libraries/Image/Image.android.js +++ b/packages/react-native/Libraries/Image/Image.android.js @@ -16,7 +16,10 @@ import flattenStyle from '../StyleSheet/flattenStyle'; import StyleSheet from '../StyleSheet/StyleSheet'; import TextAncestor from '../Text/TextAncestor'; import ImageAnalyticsTagContext from './ImageAnalyticsTagContext'; -import {unstable_getImageComponentDecorator} from './ImageInjection'; +import { + unstable_getImageComponentDecorator, + useWrapRefWithImageAttachedCallbacks, +} from './ImageInjection'; import {getImageSourcesFromImageProps} from './ImageSourceUtils'; import {convertObjectFitToResizeMode} from './ImageUtils'; import ImageViewNativeComponent from './ImageViewNativeComponent'; @@ -176,7 +179,6 @@ let BaseImage: AbstractImageAndroid = React.forwardRef( loadingIndicatorSrc: loadingIndicatorSource ? loadingIndicatorSource.uri : null, - ref: forwardedRef, accessibilityLabel: props['aria-label'] ?? props.accessibilityLabel ?? props.alt, accessibilityLabelledBy: @@ -197,6 +199,8 @@ let BaseImage: AbstractImageAndroid = React.forwardRef( const resizeMode = objectFit || props.resizeMode || style?.resizeMode || 'cover'; + const actualRef = useWrapRefWithImageAttachedCallbacks(forwardedRef); + return ( {analyticTag => { @@ -218,7 +222,7 @@ let BaseImage: AbstractImageAndroid = React.forwardRef( resizeMode={resizeMode} headers={nativeProps.headers} src={sources} - ref={forwardedRef} + ref={actualRef} /> ); } @@ -227,6 +231,7 @@ let BaseImage: AbstractImageAndroid = React.forwardRef( ); }} diff --git a/packages/react-native/Libraries/Image/Image.ios.js b/packages/react-native/Libraries/Image/Image.ios.js index ea3dcb972aa81d..ce21b5b4edf049 100644 --- a/packages/react-native/Libraries/Image/Image.ios.js +++ b/packages/react-native/Libraries/Image/Image.ios.js @@ -16,7 +16,10 @@ import {createRootTag} from '../ReactNative/RootTag'; import flattenStyle from '../StyleSheet/flattenStyle'; import StyleSheet from '../StyleSheet/StyleSheet'; import ImageAnalyticsTagContext from './ImageAnalyticsTagContext'; -import {unstable_getImageComponentDecorator} from './ImageInjection'; +import { + unstable_getImageComponentDecorator, + useWrapRefWithImageAttachedCallbacks, +} from './ImageInjection'; import {getImageSourcesFromImageProps} from './ImageSourceUtils'; import {convertObjectFitToResizeMode} from './ImageUtils'; import ImageViewNativeComponent from './ImageViewNativeComponent'; @@ -158,6 +161,8 @@ let BaseImage: AbstractImageIOS = React.forwardRef((props, forwardedRef) => { }; const accessibilityLabel = props['aria-label'] ?? props.accessibilityLabel; + const actualRef = useWrapRefWithImageAttachedCallbacks(forwardedRef); + return ( {analyticTag => { @@ -167,7 +172,7 @@ let BaseImage: AbstractImageIOS = React.forwardRef((props, forwardedRef) => { {...restProps} accessible={props.alt !== undefined ? true : props.accessible} accessibilityLabel={accessibilityLabel ?? props.alt} - ref={forwardedRef} + ref={actualRef} style={style} resizeMode={resizeMode} tintColor={tintColor} diff --git a/packages/react-native/Libraries/Image/ImageInjection.js b/packages/react-native/Libraries/Image/ImageInjection.js index 9f4c4b7198349b..38515d46e32799 100644 --- a/packages/react-native/Libraries/Image/ImageInjection.js +++ b/packages/react-native/Libraries/Image/ImageInjection.js @@ -8,7 +8,14 @@ * @flow strict-local */ -import type {AbstractImageAndroid, AbstractImageIOS} from './ImageTypes.flow'; +import type { + AbstractImageAndroid, + AbstractImageIOS, + Image as ImageComponent, +} from './ImageTypes.flow'; + +import * as React from 'react'; +import {useRef} from 'react'; type ImageComponentDecorator = (AbstractImageAndroid => AbstractImageAndroid) & (AbstractImageIOS => AbstractImageIOS); @@ -24,3 +31,54 @@ export function unstable_setImageComponentDecorator( export function unstable_getImageComponentDecorator(): ?ImageComponentDecorator { return injectedImageComponentDecorator; } + +type ImageInstance = React.ElementRef; + +type ImageAttachedCallback = ( + imageInstance: ImageInstance, +) => void | (() => void); + +const imageAttachedCallbacks = new Set(); + +export function unstable_registerImageAttachedCallback( + callback: ImageAttachedCallback, +): void { + imageAttachedCallbacks.add(callback); +} + +export function unstable_unregisterImageAttachedCallback( + callback: ImageAttachedCallback, +): void { + imageAttachedCallbacks.delete(callback); +} + +type ProxyRef = (ImageInstance | null) => void; + +export function useWrapRefWithImageAttachedCallbacks( + forwardedRef?: React.Ref, +): ProxyRef { + const pendingCleanupCallbacks = useRef void>>([]); + const proxyRef = useRef(node => { + if (typeof forwardedRef === 'function') { + forwardedRef(node); + } else if (typeof forwardedRef === 'object' && forwardedRef != null) { + forwardedRef.current = node; + } + + if (node == null) { + if (pendingCleanupCallbacks.current.length > 0) { + pendingCleanupCallbacks.current.forEach(cb => cb()); + pendingCleanupCallbacks.current = []; + } + } else { + imageAttachedCallbacks.forEach(imageAttachedCallback => { + const maybeCleanupCallback = imageAttachedCallback(node); + if (maybeCleanupCallback != null) { + pendingCleanupCallbacks.current.push(maybeCleanupCallback); + } + }); + } + }); + + return proxyRef.current; +} diff --git a/packages/react-native/Libraries/Image/__tests__/Image-test.js b/packages/react-native/Libraries/Image/__tests__/Image-test.js index 6eb4600f191c3c..4cc8d11176d090 100644 --- a/packages/react-native/Libraries/Image/__tests__/Image-test.js +++ b/packages/react-native/Libraries/Image/__tests__/Image-test.js @@ -11,8 +11,13 @@ 'use strict'; +import type {ElementRef} from 'react'; + +import {act, create} from 'react-test-renderer'; + const render = require('../../../jest/renderer'); const Image = require('../Image'); +const ImageInjection = require('../ImageInjection'); const React = require('react'); describe('', () => { @@ -39,4 +44,190 @@ describe('', () => { const instance = render.create(); expect(instance).toMatchSnapshot(); }); + + it('should call image attached callbacks (basic)', () => { + jest.dontMock('../Image'); + + let imageInstanceFromCallback = null; + let imageInstanceFromRef = null; + + const callback = (instance: ElementRef) => { + imageInstanceFromCallback = instance; + + return () => { + imageInstanceFromCallback = null; + }; + }; + + ImageInjection.unstable_registerImageAttachedCallback(callback); + + expect(imageInstanceFromCallback).toBe(null); + + let testRenderer; + + act(() => { + testRenderer = create( + { + imageInstanceFromRef = instance; + }} + />, + ); + }); + + expect(imageInstanceFromCallback).not.toBe(null); + expect(imageInstanceFromRef).not.toBe(null); + expect(imageInstanceFromCallback).toBe(imageInstanceFromRef); + + act(() => { + testRenderer.update(<>); + }); + + expect(imageInstanceFromCallback).toBe(null); + expect(imageInstanceFromRef).toBe(null); + + ImageInjection.unstable_unregisterImageAttachedCallback(callback); + + act(() => { + testRenderer.update( + { + imageInstanceFromRef = instance; + }} + />, + ); + }); + + expect(imageInstanceFromRef).not.toBe(null); + expect(imageInstanceFromCallback).toBe(null); + }); + + it('should call image attached callbacks (multiple callbacks)', () => { + jest.dontMock('../Image'); + + let imageInstanceFromCallback1 = null; + let imageInstanceFromCallback2 = null; + let imageInstanceFromRef = null; + + ImageInjection.unstable_registerImageAttachedCallback(instance => { + imageInstanceFromCallback1 = instance; + + return () => { + imageInstanceFromCallback1 = null; + }; + }); + + ImageInjection.unstable_registerImageAttachedCallback(instance => { + imageInstanceFromCallback2 = instance; + + return () => { + imageInstanceFromCallback2 = null; + }; + }); + + expect(imageInstanceFromCallback1).toBe(null); + expect(imageInstanceFromCallback2).toBe(null); + + let testRenderer; + + act(() => { + testRenderer = create( + { + imageInstanceFromRef = instance; + }} + />, + ); + }); + + expect(imageInstanceFromRef).not.toBe(null); + expect(imageInstanceFromCallback1).not.toBe(null); + expect(imageInstanceFromCallback2).not.toBe(null); + expect(imageInstanceFromCallback1).toBe(imageInstanceFromRef); + expect(imageInstanceFromCallback2).toBe(imageInstanceFromRef); + + act(() => { + testRenderer.update(<>); + }); + + expect(imageInstanceFromRef).toBe(null); + expect(imageInstanceFromCallback1).toBe(null); + expect(imageInstanceFromCallback2).toBe(null); + }); + + it('should call image attached callbacks (multiple images)', () => { + jest.dontMock('../Image'); + + let imageInstancesFromCallback = new Set>(); + + ImageInjection.unstable_registerImageAttachedCallback(instance => { + imageInstancesFromCallback.add(instance); + + return () => { + imageInstancesFromCallback.delete(instance); + }; + }); + + expect(imageInstancesFromCallback.size).toBe(0); + + let testRenderer; + + let firstInstance; + let secondInstance; + + const firstImageElement = ( + { + firstInstance = instance; + }} + /> + ); + + const secondImageElement = ( + { + secondInstance = instance; + }} + /> + ); + + act(() => { + testRenderer = create( + <> + {firstImageElement} + {secondImageElement} + , + ); + }); + + expect(firstInstance).not.toBe(null); + expect(secondInstance).not.toBe(null); + expect(imageInstancesFromCallback.size).toBe(2); + expect([...imageInstancesFromCallback][0]).toBe(firstInstance); + expect([...imageInstancesFromCallback][1]).toBe(secondInstance); + + act(() => { + testRenderer.update(<>{secondImageElement}); + }); + + expect(firstInstance).toBe(null); + expect(secondInstance).not.toBe(null); + expect(imageInstancesFromCallback.size).toBe(1); + expect([...imageInstancesFromCallback][0]).toBe(secondInstance); + + act(() => { + testRenderer.update(<>); + }); + + expect(firstInstance).toBe(null); + expect(secondInstance).toBe(null); + expect(imageInstancesFromCallback.size).toBe(0); + }); }); From 59a2282b29f2f0333f0febf8377e9ad07f0e2a62 Mon Sep 17 00:00:00 2001 From: Rob Hogan Date: Fri, 17 Nov 2023 08:53:14 -0800 Subject: [PATCH 006/162] Restore InspectorProxy tests - fix Windows by Babel-ignoring `node_modules` consistently (#41526) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41526 CI failures in Windows JS tests recently (https://github.com/facebook/react-native/pull/41463) were caused by the triggering of Babel registration during tests, due to an import of `packages/dev-middleware` (index), breaking subsequent transformation of other tests. ## Root cause Example of a problematic import: https://github.com/facebook/react-native/blob/a5d8ea4579c630af1e4e0fe1d99ad9dc0915df86/packages/dev-middleware/src/__tests__/ServerUtils.js#L15 ..which triggers a Babel registration: https://github.com/facebook/react-native/blob/a5d8ea4579c630af1e4e0fe1d99ad9dc0915df86/packages/dev-middleware/src/index.js#L16-L18 That registration behaves differently on Windows due to the `ignore: [/\/node_modules\/\]`, which doesn't match against Windows path separators - Babel matches against system separators. In particular, this changed whether `node_modules/flow-parser` was transformed when loading the RN Babel transformer. Transforming this file causes a `console.warn` from Babel due to its size: > [BABEL] Note: The code generator has deoptimised the styling of /Users/robhogan/workspace/react-native/node_modules/flow-parser/flow_parser.js as it exceeds the max of 500KB. This throws due to our setup: https://github.com/facebook/react-native/blob/a5d8ea4579c630af1e4e0fe1d99ad9dc0915df86/packages/react-native/jest/local-setup.js#L27 This all manifests as the first test following a Babel registration (within the same Jest worker) that requires the RN Babel transformer throwing during script transformation. ## This change This is the minimally disruptive change that makes Babel registration behaviour consistent between Windows and other platforms. The more durable solution here would be *not* to rely on any Babel registration for Jest, which has its own `ScriptTransformer` mechanism for running code from source. Given the fragile way our internal+OSS Babel set up hangs together that's a higher-risk change, so I'll follow up separately. Changelog: [Internal] Reviewed By: huntie Differential Revision: D51424802 fbshipit-source-id: 8b733c0c159ee84690aef04abced682d126c6d27 --- .../src/__tests__/InspectorProxyCdpRewritingHacks-test.js | 3 +-- .../src/__tests__/InspectorProxyCdpTransport-test.js | 3 +-- .../dev-middleware/src/__tests__/InspectorProxyHttpApi-test.js | 3 +-- .../src/__tests__/InspectorProxyReactNativeReloads-test.js | 3 +-- scripts/build/babel-register.js | 2 +- 5 files changed, 5 insertions(+), 9 deletions(-) diff --git a/packages/dev-middleware/src/__tests__/InspectorProxyCdpRewritingHacks-test.js b/packages/dev-middleware/src/__tests__/InspectorProxyCdpRewritingHacks-test.js index d3f57555f25e31..240046a53eb5d1 100644 --- a/packages/dev-middleware/src/__tests__/InspectorProxyCdpRewritingHacks-test.js +++ b/packages/dev-middleware/src/__tests__/InspectorProxyCdpRewritingHacks-test.js @@ -40,8 +40,7 @@ beforeAll(() => { jest.resetModules(); }); -// TODO T169943794 -xdescribe.each(['HTTP', 'HTTPS'])( +describe.each(['HTTP', 'HTTPS'])( 'inspector proxy CDP rewriting hacks over %s', protocol => { const serverRef = withServerForEachTest({ diff --git a/packages/dev-middleware/src/__tests__/InspectorProxyCdpTransport-test.js b/packages/dev-middleware/src/__tests__/InspectorProxyCdpTransport-test.js index 02298adbc1d1c9..6d76d304e84677 100644 --- a/packages/dev-middleware/src/__tests__/InspectorProxyCdpTransport-test.js +++ b/packages/dev-middleware/src/__tests__/InspectorProxyCdpTransport-test.js @@ -23,8 +23,7 @@ jest.useRealTimers(); jest.setTimeout(10000); -// TODO T169943794 -xdescribe.each(['HTTP', 'HTTPS'])( +describe.each(['HTTP', 'HTTPS'])( 'inspector proxy CDP transport over %s', protocol => { const serverRef = withServerForEachTest({ diff --git a/packages/dev-middleware/src/__tests__/InspectorProxyHttpApi-test.js b/packages/dev-middleware/src/__tests__/InspectorProxyHttpApi-test.js index 55128934464a2b..125433757edad1 100644 --- a/packages/dev-middleware/src/__tests__/InspectorProxyHttpApi-test.js +++ b/packages/dev-middleware/src/__tests__/InspectorProxyHttpApi-test.js @@ -24,8 +24,7 @@ const PAGES_POLLING_DELAY = 1000; jest.useFakeTimers(); -// TODO T169943794 -xdescribe('inspector proxy HTTP API', () => { +describe('inspector proxy HTTP API', () => { const serverRef = withServerForEachTest({ logger: undefined, projectRoot: '', diff --git a/packages/dev-middleware/src/__tests__/InspectorProxyReactNativeReloads-test.js b/packages/dev-middleware/src/__tests__/InspectorProxyReactNativeReloads-test.js index e8ca5607e91621..8576c98dbbce1d 100644 --- a/packages/dev-middleware/src/__tests__/InspectorProxyReactNativeReloads-test.js +++ b/packages/dev-middleware/src/__tests__/InspectorProxyReactNativeReloads-test.js @@ -23,8 +23,7 @@ jest.useRealTimers(); jest.setTimeout(10000); -// TODO T169943794 -xdescribe('inspector proxy React Native reloads', () => { +describe('inspector proxy React Native reloads', () => { const serverRef = withServerForEachTest({ logger: undefined, projectRoot: '', diff --git a/scripts/build/babel-register.js b/scripts/build/babel-register.js index a9f99c4fdb429d..f2f1c4eeebb7a4 100644 --- a/scripts/build/babel-register.js +++ b/scripts/build/babel-register.js @@ -50,7 +50,7 @@ function registerPackage(packageName /*: string */) { const registerConfig = { ...getBabelConfig(packageName), root: packageDir, - ignore: [/\/node_modules\//], + ignore: [/[/\\]node_modules[/\\]/], }; require('@babel/register')(registerConfig); From d9fa64ee3e405b25d80534a0015f85f042b2618f Mon Sep 17 00:00:00 2001 From: Ruslan Shestopalyuk Date: Fri, 17 Nov 2023 08:55:17 -0800 Subject: [PATCH 007/162] Extract return types in NativeImageLoader specs (#41529) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41529 # Changelog: [Internal]- The change is equivalent in terms of API, however this makes it work nicer with C++ codegen and easier to use with a pure C++ implementation of the native module. Reviewed By: christophpurrer Differential Revision: D51426015 fbshipit-source-id: aae4d91bb93834e1a9c14a21417724a348de0bd7 --- .../Image/NativeImageLoaderAndroid.js | 22 ++++++------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/packages/react-native/Libraries/Image/NativeImageLoaderAndroid.js b/packages/react-native/Libraries/Image/NativeImageLoaderAndroid.js index 121de3bc99e3de..af55bbe2a44299 100644 --- a/packages/react-native/Libraries/Image/NativeImageLoaderAndroid.js +++ b/packages/react-native/Libraries/Image/NativeImageLoaderAndroid.js @@ -12,24 +12,16 @@ import type {TurboModule} from '../TurboModule/RCTExport'; import * as TurboModuleRegistry from '../TurboModule/TurboModuleRegistry'; +export type ImageSize = {| + width: number, + height: number, +|}; + export interface Spec extends TurboModule { +abortRequest: (requestId: number) => void; +getConstants: () => {||}; - +getSize: (uri: string) => Promise< - $ReadOnly<{ - width: number, - height: number, - ... - }>, - >; - +getSizeWithHeaders: ( - uri: string, - headers: Object, - ) => Promise<{ - width: number, - height: number, - ... - }>; + +getSize: (uri: string) => Promise; + +getSizeWithHeaders: (uri: string, headers: Object) => Promise; +prefetchImage: (uri: string, requestId: number) => Promise; +queryCache: (uris: Array) => Promise; } From ba43dd25135b7cb8306fe693f037187d8e5ab15b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Norte?= Date: Fri, 17 Nov 2023 10:12:42 -0800 Subject: [PATCH 008/162] Revert D51394187: delete ShadowNodeFamily::instanceHandle_ Differential Revision: D51394187 Original commit changeset: 3add711a3954 Original Phabricator Diff: D51394187 fbshipit-source-id: 881fb82c949fef05f001fec57f62911a3a5dc482 --- .../ReactCommon/react/renderer/core/ShadowNode.cpp | 7 ++++++- .../ReactCommon/react/renderer/core/ShadowNodeFamily.cpp | 1 + .../ReactCommon/react/renderer/core/ShadowNodeFamily.h | 5 +++++ 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/packages/react-native/ReactCommon/react/renderer/core/ShadowNode.cpp b/packages/react-native/ReactCommon/react/renderer/core/ShadowNode.cpp index 5d8da6fe6b6ca5..d51cb8ff2311a1 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/ShadowNode.cpp +++ b/packages/react-native/ReactCommon/react/renderer/core/ShadowNode.cpp @@ -173,7 +173,12 @@ const SharedEventEmitter& ShadowNode::getEventEmitter() const { } jsi::Value ShadowNode::getInstanceHandle(jsi::Runtime& runtime) const { - return family_->eventEmitter_->getEventTarget()->getInstanceHandle(runtime); + auto instanceHandle = family_->instanceHandle_; + if (instanceHandle == nullptr) { + return jsi::Value::null(); + } + + return instanceHandle->getInstanceHandle(runtime); } Tag ShadowNode::getTag() const { diff --git a/packages/react-native/ReactCommon/react/renderer/core/ShadowNodeFamily.cpp b/packages/react-native/ReactCommon/react/renderer/core/ShadowNodeFamily.cpp index 88143a9d0c0e47..0e73b0a5cf3687 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/ShadowNodeFamily.cpp +++ b/packages/react-native/ReactCommon/react/renderer/core/ShadowNodeFamily.cpp @@ -26,6 +26,7 @@ ShadowNodeFamily::ShadowNodeFamily( : eventDispatcher_(std::move(eventDispatcher)), tag_(fragment.tag), surfaceId_(fragment.surfaceId), + instanceHandle_(fragment.instanceHandle), eventEmitter_(std::move(eventEmitter)), componentDescriptor_(componentDescriptor), componentHandle_(componentDescriptor.getComponentHandle()), diff --git a/packages/react-native/ReactCommon/react/renderer/core/ShadowNodeFamily.h b/packages/react-native/ReactCommon/react/renderer/core/ShadowNodeFamily.h index c4a0b4face1b12..dc5dbc815317f0 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/ShadowNodeFamily.h +++ b/packages/react-native/ReactCommon/react/renderer/core/ShadowNodeFamily.h @@ -132,6 +132,11 @@ class ShadowNodeFamily final { */ const SurfaceId surfaceId_; + /* + * Weak reference to the React instance handle + */ + InstanceHandle::Shared const instanceHandle_; + /* * `EventEmitter` associated with all nodes of the family. */ From f4d006a785c6bbb753857c3f11118afdf338d1af Mon Sep 17 00:00:00 2001 From: Ruslan Shestopalyuk Date: Fri, 17 Nov 2023 13:10:39 -0800 Subject: [PATCH 009/162] Optional prop for RNTesterApp to provide custom test lists (#41537) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41537 # Changelog: [Internal] - This allows to optionally provide a custom list of component/api test clauses into `RNTesterApp`. Reviewed By: christophpurrer Differential Revision: D51429407 fbshipit-source-id: 3ee35f13f6156fd055f6e0cbc788b7cf01c22b36 --- packages/rn-tester/js/RNTesterAppShared.js | 15 ++++++++++++--- packages/rn-tester/js/utils/testerStateUtils.js | 11 +++++++++-- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/packages/rn-tester/js/RNTesterAppShared.js b/packages/rn-tester/js/RNTesterAppShared.js index 04c17f58f32596..3f93d9aa4801f3 100644 --- a/packages/rn-tester/js/RNTesterAppShared.js +++ b/packages/rn-tester/js/RNTesterAppShared.js @@ -8,6 +8,8 @@ * @flow */ +import type {RNTesterModuleInfo} from './types/RNTesterTypes'; + import RNTesterModuleContainer from './components/RNTesterModuleContainer'; import RNTesterModuleList from './components/RNTesterModuleList'; import RNTesterNavBar, {navBarHeight} from './components/RNTesterNavbar'; @@ -28,7 +30,14 @@ import {BackHandler, StyleSheet, View, useColorScheme} from 'react-native'; // RNTester App currently uses in memory storage for storing navigation state -const RNTesterApp = (): React.Node => { +const RNTesterApp = ({ + testList, +}: { + testList?: { + components?: Array, + apis?: Array, + }, +}): React.Node => { const [state, dispatch] = React.useReducer( RNTesterNavigationReducer, initialNavigationState, @@ -44,8 +53,8 @@ const RNTesterApp = (): React.Node => { } = state; const examplesList = React.useMemo( - () => getExamplesListWithRecentlyUsed({recentlyUsed}), - [recentlyUsed], + () => getExamplesListWithRecentlyUsed({recentlyUsed, testList}), + [recentlyUsed, testList], ); const handleBackPress = React.useCallback(() => { diff --git a/packages/rn-tester/js/utils/testerStateUtils.js b/packages/rn-tester/js/utils/testerStateUtils.js index c3239adeab9737..805cfe83349e8c 100644 --- a/packages/rn-tester/js/utils/testerStateUtils.js +++ b/packages/rn-tester/js/utils/testerStateUtils.js @@ -48,15 +48,21 @@ const filterEmptySections = (examplesList: ExamplesList): any => { export const getExamplesListWithRecentlyUsed = ({ recentlyUsed, + testList, }: { recentlyUsed: ComponentList, + testList?: { + components?: Array, + apis?: Array, + }, }): ExamplesList | null => { // Return early if state has not been initialized from storage if (!recentlyUsed) { return null; } - const components = RNTesterList.Components.map( + const componentList = testList?.components ?? RNTesterList.Components; + const components = componentList.map( (componentExample): RNTesterModuleInfo => ({ ...componentExample, exampleType: Screens.COMPONENTS, @@ -69,7 +75,8 @@ export const getExamplesListWithRecentlyUsed = ({ ) .filter(Boolean); - const apis = RNTesterList.APIs.map((apiExample): RNTesterModuleInfo => ({ + const apisList = testList?.apis ?? RNTesterList.APIs; + const apis = apisList.map((apiExample): RNTesterModuleInfo => ({ ...apiExample, exampleType: Screens.APIS, })); From 361a944348e4da5d17f910965d0b89c9e65b18c7 Mon Sep 17 00:00:00 2001 From: Alex Hunt Date: Fri, 17 Nov 2023 15:42:59 -0800 Subject: [PATCH 010/162] Remove "Open Debugger" action under JSC (#41535) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41535 ## Context **Remote JS Debugging removal** In React Native 0.73, we have deprecated Remote JS Debugging (execution of JavaScript in a separate V8 process) and also removed the Dev Menu launcher (https://github.com/facebook/react-native/pull/36754). ## This diff Follows D46187942 — this option wasn't correctly removed for Android when running JSC. This is now consistent with iOS. Changelog: [Android][Changed] "Open Debugger" is no longer available for remote JS debugging from the Dev Menu (non-Hermes). Please use `NativeDevSettings.setIsDebuggingRemotely()`. Reviewed By: blakef Differential Revision: D50555095 fbshipit-source-id: 1aeb48ab1390dc12ce300d6f321c30de5343cf0a --- .../react/devsupport/DevSupportManagerBase.java | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevSupportManagerBase.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevSupportManagerBase.java index 2b4e4eabb64a98..e242858a71b2fc 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevSupportManagerBase.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevSupportManagerBase.java @@ -363,15 +363,16 @@ public void onOptionSelected() { } }); - if (mDevSettings.isDeviceDebugEnabled()) { - // On-device JS debugging (CDP). Render action to open debugger frontend. + if (mDevSettings.isRemoteJSDebugEnabled()) { + // [Deprecated in React Native 0.73] Remote JS debugging. Handle reload + // via external JS executor. This capability will be removed in a future + // release. + mDevSettings.setRemoteJSDebugEnabled(false); + handleReloadJS(); + } - // Reset the old debugger setting so no one gets stuck. - // TODO: Remove in a few weeks. - if (mDevSettings.isRemoteJSDebugEnabled()) { - mDevSettings.setRemoteJSDebugEnabled(false); - handleReloadJS(); - } + if (mDevSettings.isDeviceDebugEnabled() && !mDevSettings.isRemoteJSDebugEnabled()) { + // On-device JS debugging (CDP). Render action to open debugger frontend. options.put( mApplicationContext.getString(R.string.catalyst_debug_open), () -> From 3bee205c624716b222529514dee50711bacf6ab3 Mon Sep 17 00:00:00 2001 From: Alexander Oprisnik Date: Fri, 17 Nov 2023 18:16:48 -0800 Subject: [PATCH 011/162] Use visibility events for React image component (#41538) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41538 Changelog: [internal] Reviewed By: rubennorte Differential Revision: D51368688 fbshipit-source-id: 8de0d8f81c7454444c484311a37e56d9a4c35c01 --- .../Libraries/Image/ImageViewNativeComponent.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/packages/react-native/Libraries/Image/ImageViewNativeComponent.js b/packages/react-native/Libraries/Image/ImageViewNativeComponent.js index bd9ae7df499b25..c93c6d079eb4cf 100644 --- a/packages/react-native/Libraries/Image/ImageViewNativeComponent.js +++ b/packages/react-native/Libraries/Image/ImageViewNativeComponent.js @@ -20,9 +20,11 @@ import type { } from '../StyleSheet/StyleSheet'; import type {ResolvedAssetSource} from './AssetSourceResolver'; import type {ImageProps} from './ImageProps'; +import type {ElementRef} from 'react'; import * as NativeComponentRegistry from '../NativeComponent/NativeComponentRegistry'; import {ConditionallyIgnoredEventHandlers} from '../NativeComponent/ViewConfigIgnore'; +import codegenNativeCommands from '../Utilities/codegenNativeCommands'; import Platform from '../Utilities/Platform'; type Props = $ReadOnly<{ @@ -44,6 +46,17 @@ type Props = $ReadOnly<{ loadingIndicatorSrc?: ?string, }>; +interface NativeCommands { + +setIsVisible_EXPERIMENTAL: ( + viewRef: ElementRef>, + isVisible: boolean, + ) => void; +} + +export const Commands: NativeCommands = codegenNativeCommands({ + supportedCommands: ['setIsVisible_EXPERIMENTAL'], +}); + export const __INTERNAL_VIEW_CONFIG: PartialViewConfig = Platform.OS === 'android' ? { From 73411f4e0887ddbff4d02126165148504d773915 Mon Sep 17 00:00:00 2001 From: Gijs Weterings Date: Sat, 18 Nov 2023 02:04:44 -0800 Subject: [PATCH 012/162] Back out "Restore InspectorProxy tests - fix Windows by Babel-ignoring `node_modules` consistently" Summary: Changelog: Internal Reviewed By: gsathya Differential Revision: D51447333 fbshipit-source-id: 56eb839671ca62269d59d48fd3c83df4f42a5111 --- .../src/__tests__/InspectorProxyCdpRewritingHacks-test.js | 3 ++- .../src/__tests__/InspectorProxyCdpTransport-test.js | 3 ++- .../dev-middleware/src/__tests__/InspectorProxyHttpApi-test.js | 3 ++- .../src/__tests__/InspectorProxyReactNativeReloads-test.js | 3 ++- scripts/build/babel-register.js | 2 +- 5 files changed, 9 insertions(+), 5 deletions(-) diff --git a/packages/dev-middleware/src/__tests__/InspectorProxyCdpRewritingHacks-test.js b/packages/dev-middleware/src/__tests__/InspectorProxyCdpRewritingHacks-test.js index 240046a53eb5d1..d3f57555f25e31 100644 --- a/packages/dev-middleware/src/__tests__/InspectorProxyCdpRewritingHacks-test.js +++ b/packages/dev-middleware/src/__tests__/InspectorProxyCdpRewritingHacks-test.js @@ -40,7 +40,8 @@ beforeAll(() => { jest.resetModules(); }); -describe.each(['HTTP', 'HTTPS'])( +// TODO T169943794 +xdescribe.each(['HTTP', 'HTTPS'])( 'inspector proxy CDP rewriting hacks over %s', protocol => { const serverRef = withServerForEachTest({ diff --git a/packages/dev-middleware/src/__tests__/InspectorProxyCdpTransport-test.js b/packages/dev-middleware/src/__tests__/InspectorProxyCdpTransport-test.js index 6d76d304e84677..02298adbc1d1c9 100644 --- a/packages/dev-middleware/src/__tests__/InspectorProxyCdpTransport-test.js +++ b/packages/dev-middleware/src/__tests__/InspectorProxyCdpTransport-test.js @@ -23,7 +23,8 @@ jest.useRealTimers(); jest.setTimeout(10000); -describe.each(['HTTP', 'HTTPS'])( +// TODO T169943794 +xdescribe.each(['HTTP', 'HTTPS'])( 'inspector proxy CDP transport over %s', protocol => { const serverRef = withServerForEachTest({ diff --git a/packages/dev-middleware/src/__tests__/InspectorProxyHttpApi-test.js b/packages/dev-middleware/src/__tests__/InspectorProxyHttpApi-test.js index 125433757edad1..55128934464a2b 100644 --- a/packages/dev-middleware/src/__tests__/InspectorProxyHttpApi-test.js +++ b/packages/dev-middleware/src/__tests__/InspectorProxyHttpApi-test.js @@ -24,7 +24,8 @@ const PAGES_POLLING_DELAY = 1000; jest.useFakeTimers(); -describe('inspector proxy HTTP API', () => { +// TODO T169943794 +xdescribe('inspector proxy HTTP API', () => { const serverRef = withServerForEachTest({ logger: undefined, projectRoot: '', diff --git a/packages/dev-middleware/src/__tests__/InspectorProxyReactNativeReloads-test.js b/packages/dev-middleware/src/__tests__/InspectorProxyReactNativeReloads-test.js index 8576c98dbbce1d..e8ca5607e91621 100644 --- a/packages/dev-middleware/src/__tests__/InspectorProxyReactNativeReloads-test.js +++ b/packages/dev-middleware/src/__tests__/InspectorProxyReactNativeReloads-test.js @@ -23,7 +23,8 @@ jest.useRealTimers(); jest.setTimeout(10000); -describe('inspector proxy React Native reloads', () => { +// TODO T169943794 +xdescribe('inspector proxy React Native reloads', () => { const serverRef = withServerForEachTest({ logger: undefined, projectRoot: '', diff --git a/scripts/build/babel-register.js b/scripts/build/babel-register.js index f2f1c4eeebb7a4..a9f99c4fdb429d 100644 --- a/scripts/build/babel-register.js +++ b/scripts/build/babel-register.js @@ -50,7 +50,7 @@ function registerPackage(packageName /*: string */) { const registerConfig = { ...getBabelConfig(packageName), root: packageDir, - ignore: [/[/\\]node_modules[/\\]/], + ignore: [/\/node_modules\//], }; require('@babel/register')(registerConfig); From 917fd25cbb70e3924a59b07b557feca44f424b04 Mon Sep 17 00:00:00 2001 From: Ruslan Shestopalyuk Date: Sat, 18 Nov 2023 04:51:25 -0800 Subject: [PATCH 013/162] Temporarily back out ImageLoaderModule type extraction (#41547) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41547 # Changelog: [Internal]- Pending figuring out why it might break backwards compatibility (which it shouldn't, in practice). Reviewed By: GijsWeterings Differential Revision: D51447646 fbshipit-source-id: c3a4511badc6c1346655f3a1a20050ad719b095b --- .../Image/NativeImageLoaderAndroid.js | 22 +++++++++++++------ 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/packages/react-native/Libraries/Image/NativeImageLoaderAndroid.js b/packages/react-native/Libraries/Image/NativeImageLoaderAndroid.js index af55bbe2a44299..121de3bc99e3de 100644 --- a/packages/react-native/Libraries/Image/NativeImageLoaderAndroid.js +++ b/packages/react-native/Libraries/Image/NativeImageLoaderAndroid.js @@ -12,16 +12,24 @@ import type {TurboModule} from '../TurboModule/RCTExport'; import * as TurboModuleRegistry from '../TurboModule/TurboModuleRegistry'; -export type ImageSize = {| - width: number, - height: number, -|}; - export interface Spec extends TurboModule { +abortRequest: (requestId: number) => void; +getConstants: () => {||}; - +getSize: (uri: string) => Promise; - +getSizeWithHeaders: (uri: string, headers: Object) => Promise; + +getSize: (uri: string) => Promise< + $ReadOnly<{ + width: number, + height: number, + ... + }>, + >; + +getSizeWithHeaders: ( + uri: string, + headers: Object, + ) => Promise<{ + width: number, + height: number, + ... + }>; +prefetchImage: (uri: string, requestId: number) => Promise; +queryCache: (uris: Array) => Promise; } From 9af8f78d3b6c5bb39ea8deeba9481ca1e8e6545c Mon Sep 17 00:00:00 2001 From: Phillip Pan Date: Sat, 18 Nov 2023 22:13:40 -0800 Subject: [PATCH 014/162] introduce ReactApple (#41419) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41419 Changelog: [iOS][something] Creating a new top level directory for Apple platform specific code. Reviewed By: christophpurrer Differential Revision: D51170984 fbshipit-source-id: 1a453c9ae9142167afef5ac4a348c644fa6f1ab3 --- packages/react-native/ReactApple/README.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 packages/react-native/ReactApple/README.md diff --git a/packages/react-native/ReactApple/README.md b/packages/react-native/ReactApple/README.md new file mode 100644 index 00000000000000..faafcb1dabb8de --- /dev/null +++ b/packages/react-native/ReactApple/README.md @@ -0,0 +1,5 @@ +# ReactApple + +ReactApple contains code to ship React Native apps to Apple devices. The dominant language is Objective-C. + +New libraries built with Apple frameworks or intended to ship to Apple devices should live in this directory. From e9ecc656528ec54e93a9bcd43e39e0b6888a6ed5 Mon Sep 17 00:00:00 2001 From: Phillip Pan Date: Sat, 18 Nov 2023 22:13:40 -0800 Subject: [PATCH 015/162] introduce RCTFoundation (#41418) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41418 Changelog: [iOS][Added] creating a top level directory for shared lightweight utility functions open to suggs on naming and rules we want to enforce Reviewed By: shwanton, christophpurrer Differential Revision: D51170983 fbshipit-source-id: 8bc0a193b486f5a0653ad58d92a034cacede2d61 --- .../ReactApple/Libraries/RCTFoundation/README.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 packages/react-native/ReactApple/Libraries/RCTFoundation/README.md diff --git a/packages/react-native/ReactApple/Libraries/RCTFoundation/README.md b/packages/react-native/ReactApple/Libraries/RCTFoundation/README.md new file mode 100644 index 00000000000000..b5bdb2bf6f040d --- /dev/null +++ b/packages/react-native/ReactApple/Libraries/RCTFoundation/README.md @@ -0,0 +1,12 @@ +# RCTFoundation + +RCTFoundation is a collection of lightweight utility libraries. + +Rules for RCTFoundation libraries: +- They must only depend on other RCTFoundation libraries. +- Headers cannot contain C++. +- They have modular set to true in BUCK. +- They have complete_nullability set to true. +- They have enabled Clang compiler warnings. +- They have documentation. +- They have unit tests. From c06beaeed1c5319c59a3e7d3a8a7974f8357e4c8 Mon Sep 17 00:00:00 2001 From: Phillip Pan Date: Sat, 18 Nov 2023 22:13:40 -0800 Subject: [PATCH 016/162] RCTDeprecation BUCK integration (#41417) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41417 Changelog: [Internal] BUCK boilerplate to integrate the first RCTFoundation library. decided to split this up so we can reference it easily in the future when adding new libs Reviewed By: cipolleschi Differential Revision: D51101009 fbshipit-source-id: fe828b64c7fd939f8576a496478b6a401bfae69c --- .../RCTDeprecation/Exported/RCTDeprecation.h | 16 ++++++++++++++++ .../RCTFoundation/RCTDeprecation/README.md | 1 + 2 files changed, 17 insertions(+) create mode 100644 packages/react-native/ReactApple/Libraries/RCTFoundation/RCTDeprecation/Exported/RCTDeprecation.h create mode 100644 packages/react-native/ReactApple/Libraries/RCTFoundation/RCTDeprecation/README.md diff --git a/packages/react-native/ReactApple/Libraries/RCTFoundation/RCTDeprecation/Exported/RCTDeprecation.h b/packages/react-native/ReactApple/Libraries/RCTFoundation/RCTDeprecation/Exported/RCTDeprecation.h new file mode 100644 index 00000000000000..dc7b92b3d88036 --- /dev/null +++ b/packages/react-native/ReactApple/Libraries/RCTFoundation/RCTDeprecation/Exported/RCTDeprecation.h @@ -0,0 +1,16 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#ifndef RCT_DEPRECATED_DECLARATIONS +#define RCT_DEPRECATED_DECLARATIONS 0 +#endif + +#if RCT_DEPRECATED_DECLARATIONS +#define RCT_DEPRECATED __attribute__((deprecated)) +#else +#define RCT_DEPRECATED +#endif diff --git a/packages/react-native/ReactApple/Libraries/RCTFoundation/RCTDeprecation/README.md b/packages/react-native/ReactApple/Libraries/RCTFoundation/RCTDeprecation/README.md new file mode 100644 index 00000000000000..9f0d87aaa6d759 --- /dev/null +++ b/packages/react-native/ReactApple/Libraries/RCTFoundation/RCTDeprecation/README.md @@ -0,0 +1 @@ +RCTDeprecation contains C macros to identify deprecated APIs at build-time. From e7500df57ab44faea91f82faceecf13881f10477 Mon Sep 17 00:00:00 2001 From: Phillip Pan Date: Sat, 18 Nov 2023 22:13:40 -0800 Subject: [PATCH 017/162] RCTDeprecation cocoapods integration (#41416) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41416 Changelog: [Internal] cocoapods boilerplate to integrate the first RCTFoundation library. decided to split this up so we can reference it easily in the future when adding new libs Reviewed By: cipolleschi Differential Revision: D51184321 fbshipit-source-id: 28696f0a8e43e0bcd24a37956823fb544ecd84be --- packages/react-native/React-Core.podspec | 2 ++ .../RCTDeprecation/RCTDeprecation.m | 8 +++++ .../RCTDeprecation/RCTDeprecation.podspec | 25 ++++++++++++++++ packages/react-native/package.json | 1 + .../react-native/scripts/react_native_pods.rb | 3 +- packages/rn-tester/Podfile.lock | 29 ++++++++++++++++--- 6 files changed, 63 insertions(+), 5 deletions(-) create mode 100644 packages/react-native/ReactApple/Libraries/RCTFoundation/RCTDeprecation/RCTDeprecation.m create mode 100644 packages/react-native/ReactApple/Libraries/RCTFoundation/RCTDeprecation/RCTDeprecation.podspec diff --git a/packages/react-native/React-Core.podspec b/packages/react-native/React-Core.podspec index da75b42c0ac996..101b5e9cc10056 100644 --- a/packages/react-native/React-Core.podspec +++ b/packages/react-native/React-Core.podspec @@ -129,6 +129,8 @@ Pod::Spec.new do |s| s.dependency "Yoga" s.dependency "glog" + add_dependency(s, "RCTDeprecation") + if use_hermes s.dependency 'React-hermes' s.dependency 'hermes-engine' diff --git a/packages/react-native/ReactApple/Libraries/RCTFoundation/RCTDeprecation/RCTDeprecation.m b/packages/react-native/ReactApple/Libraries/RCTFoundation/RCTDeprecation/RCTDeprecation.m new file mode 100644 index 00000000000000..cc1cbc7cf3730a --- /dev/null +++ b/packages/react-native/ReactApple/Libraries/RCTFoundation/RCTDeprecation/RCTDeprecation.m @@ -0,0 +1,8 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +// Dummy file to make RCTDeprecation a valid framework. diff --git a/packages/react-native/ReactApple/Libraries/RCTFoundation/RCTDeprecation/RCTDeprecation.podspec b/packages/react-native/ReactApple/Libraries/RCTFoundation/RCTDeprecation/RCTDeprecation.podspec new file mode 100644 index 00000000000000..afd7d4eeb1c97f --- /dev/null +++ b/packages/react-native/ReactApple/Libraries/RCTFoundation/RCTDeprecation/RCTDeprecation.podspec @@ -0,0 +1,25 @@ +# Copyright (c) Meta Platforms, Inc. and affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +require "json" + +package = JSON.parse(File.read(File.join(__dir__, "..", "..", "..", "..", "package.json"))) +version = package['version'] + +Pod::Spec.new do |s| + s.name = "RCTDeprecation" + s.version = version + s.author = "Meta Platforms, Inc. and its affiliates" + s.license = package["license"] + s.homepage = "https://reactnative.dev/" + s.source = { :git => 'https://github.com/facebook/react-native.git', :tag => 'v#{version}' } + s.summary = "Macros for marking APIs as deprecated" + s.source_files = ["Exported/*.h", "RCTDeprecation.m"] + s.pod_target_xcconfig = { + "DEFINES_MODULE" => "YES", + "CLANG_CXX_LANGUAGE_STANDARD" => "c++20" + } + s.compiler_flags = "-Wnullable-to-nonnull-conversion -Wnullability-completeness" + end diff --git a/packages/react-native/package.json b/packages/react-native/package.json index 37f839703342b1..f80ea276738e13 100644 --- a/packages/react-native/package.json +++ b/packages/react-native/package.json @@ -48,6 +48,7 @@ "React.podspec", "React", "ReactAndroid", + "ReactApple", "ReactCommon", "README.md", "rn-get-polyfills.js", diff --git a/packages/react-native/scripts/react_native_pods.rb b/packages/react-native/scripts/react_native_pods.rb index 0bb0bd50cd542b..93d9b6536e3efd 100644 --- a/packages/react-native/scripts/react_native_pods.rb +++ b/packages/react-native/scripts/react_native_pods.rb @@ -127,7 +127,8 @@ def use_react_native! ( pod 'React-utils', :path => "#{prefix}/ReactCommon/react/utils" pod 'React-Mapbuffer', :path => "#{prefix}/ReactCommon" pod 'React-jserrorhandler', :path => "#{prefix}/ReactCommon/jserrorhandler" - pod "React-nativeconfig", :path => "#{prefix}/ReactCommon" + pod 'React-nativeconfig', :path => "#{prefix}/ReactCommon" + pod 'RCTDeprecation', :path => "#{prefix}/ReactApple/Libraries/RCTFoundation/RCTDeprecation" if hermes_enabled setup_hermes!(:react_native_path => prefix) diff --git a/packages/rn-tester/Podfile.lock b/packages/rn-tester/Podfile.lock index b4e0b2c0f58db8..c3ac6564e8ec77 100644 --- a/packages/rn-tester/Podfile.lock +++ b/packages/rn-tester/Podfile.lock @@ -68,6 +68,7 @@ PODS: - DoubleConversion - fmt (= 9.1.0) - glog + - RCTDeprecation (1000.0.0) - RCTRequired (1000.0.0) - RCTTypeSafety (1000.0.0): - FBLazyVector (= 1000.0.0) @@ -109,6 +110,7 @@ PODS: - glog - hermes-engine - RCT-Folly (= 2023.08.07.00) + - RCTDeprecation - React-Core/Default (= 1000.0.0) - React-cxxreact - React-hermes @@ -123,6 +125,7 @@ PODS: - glog - hermes-engine - RCT-Folly (= 2023.08.07.00) + - RCTDeprecation - React-Core/Default - React-cxxreact - React-hermes @@ -137,6 +140,7 @@ PODS: - glog - hermes-engine - RCT-Folly (= 2023.08.07.00) + - RCTDeprecation - React-cxxreact - React-hermes - React-jsi @@ -150,6 +154,7 @@ PODS: - glog - hermes-engine - RCT-Folly (= 2023.08.07.00) + - RCTDeprecation - React-Core/Default (= 1000.0.0) - React-Core/RCTWebSocket (= 1000.0.0) - React-cxxreact @@ -166,6 +171,7 @@ PODS: - glog - hermes-engine - RCT-Folly (= 2023.08.07.00) + - RCTDeprecation - React-Core/Default - React-cxxreact - React-hermes @@ -180,6 +186,7 @@ PODS: - glog - hermes-engine - RCT-Folly (= 2023.08.07.00) + - RCTDeprecation - React-Core/Default - React-cxxreact - React-hermes @@ -194,6 +201,7 @@ PODS: - glog - hermes-engine - RCT-Folly (= 2023.08.07.00) + - RCTDeprecation - React-Core/Default - React-cxxreact - React-hermes @@ -208,6 +216,7 @@ PODS: - glog - hermes-engine - RCT-Folly (= 2023.08.07.00) + - RCTDeprecation - React-Core/Default - React-cxxreact - React-hermes @@ -222,6 +231,7 @@ PODS: - glog - hermes-engine - RCT-Folly (= 2023.08.07.00) + - RCTDeprecation - React-Core/Default - React-cxxreact - React-hermes @@ -236,6 +246,7 @@ PODS: - glog - hermes-engine - RCT-Folly (= 2023.08.07.00) + - RCTDeprecation - React-Core/Default - React-cxxreact - React-hermes @@ -250,6 +261,7 @@ PODS: - glog - hermes-engine - RCT-Folly (= 2023.08.07.00) + - RCTDeprecation - React-Core/Default - React-cxxreact - React-hermes @@ -264,6 +276,7 @@ PODS: - glog - hermes-engine - RCT-Folly (= 2023.08.07.00) + - RCTDeprecation - React-Core/Default - React-cxxreact - React-hermes @@ -278,6 +291,7 @@ PODS: - glog - hermes-engine - RCT-Folly (= 2023.08.07.00) + - RCTDeprecation - React-Core/Default - React-cxxreact - React-hermes @@ -292,6 +306,7 @@ PODS: - glog - hermes-engine - RCT-Folly (= 2023.08.07.00) + - RCTDeprecation - React-Core/Default - React-cxxreact - React-hermes @@ -306,6 +321,7 @@ PODS: - glog - hermes-engine - RCT-Folly (= 2023.08.07.00) + - RCTDeprecation - React-Core/Default (= 1000.0.0) - React-cxxreact - React-hermes @@ -917,6 +933,7 @@ PODS: - DoubleConversion - fmt (= 9.1.0) - glog + - hermes-engine - RCT-Folly (= 2023.08.07.00) - React-jsiexecutor (1000.0.0): - DoubleConversion @@ -1158,6 +1175,7 @@ DEPENDENCIES: - OCMock (~> 3.9.1) - RCT-Folly (from `../react-native/third-party-podspecs/RCT-Folly.podspec`) - RCT-Folly/Fabric (from `../react-native/third-party-podspecs/RCT-Folly.podspec`) + - RCTDeprecation (from `../react-native/ReactApple/Libraries/RCTFoundation/RCTDeprecation`) - RCTRequired (from `../react-native/Libraries/Required`) - RCTTypeSafety (from `../react-native/Libraries/TypeSafety`) - React (from `../react-native/`) @@ -1230,6 +1248,8 @@ EXTERNAL SOURCES: :path: NativeCxxModuleExample RCT-Folly: :podspec: "../react-native/third-party-podspecs/RCT-Folly.podspec" + RCTDeprecation: + :path: "../react-native/ReactApple/Libraries/RCTFoundation/RCTDeprecation" RCTRequired: :path: "../react-native/Libraries/Required" RCTTypeSafety: @@ -1327,17 +1347,18 @@ SPEC CHECKSUMS: FBLazyVector: f4492a543c5a8fa1502d3a5867e3f7252497cfe8 fmt: 4c2741a687cc09f0634a2e2c72a838b99f1ff120 glog: c5d68082e772fa1c511173d6b30a9de2c05a69a2 - hermes-engine: 2788dfc2ed3699d11b14e815f0c608fc8d770d6b + hermes-engine: 3cf266f7eba66a16bcc83d939def2899e6d1a717 MyNativeView: 1fb0d21fda6ef12fd5f425f9888c81345a86a3e7 NativeCxxModuleExample: 19d10636011c914264a5922c6f0f22a2e8fd0910 OCMock: 9491e4bec59e0b267d52a9184ff5605995e74be8 RCT-Folly: 823c6f6ec910a75d4ad28898b4a11cdee140b92a + RCTDeprecation: 3808e36294137f9ee5668f4df2e73dc079cd1dcf RCTRequired: 82c56a03b3efd524bfdb581a906add903f78f978 RCTTypeSafety: 5f57d4ae5dfafc85a0f575d756c909b584722c52 React: cb6dc75e09f32aeddb4d8fb58a394a67219a92fe React-callinvoker: bae59cbd6affd712bbfc703839dad868ff35069d React-Codegen: c1e6ea0005a6ecf187d2772f14e5386f1c1f4853 - React-Core: f09ea29184cc7f33015a0748588fcfe1d43b3dd1 + React-Core: aaf2be188dfb2c342bc504042a92bfff31e2048f React-CoreModules: ad1b7cb8efe5f3c7e88548b6ea6aad8507774471 React-cxxreact: 04bf6a12caa850f5d2c7bd6d66dfecd4741989b5 React-debug: 296b501a90c41f83961f58c6d96a01330d499da5 @@ -1347,7 +1368,7 @@ SPEC CHECKSUMS: React-hermes: f192759ffeb9714917e9c39850ac349d8ea982d8 React-ImageManager: 691c4a56320ab9ab10482cd6306b3a4da004b79c React-jserrorhandler: 79fb3a8860fb1ea22dc77765aac15775593d4f8f - React-jsi: 3c1d8048abf3eaca913944bd9835333bb7b415d4 + React-jsi: 81f4e5b414c992c16c02e22e975a45aeb2b166e4 React-jsiexecutor: 1212e26a01ce4de7443123f0ce090ec1affb3220 React-jsinspector: c867db3338992200616103b2f0ca6882c0c0482d React-logger: 8486d7a1d32b972414b1d34a93470ee2562c6ee2 @@ -1377,7 +1398,7 @@ SPEC CHECKSUMS: ReactCommon-Samples: cfc3383af93a741319e038977c2ae1082e4ff49e ScreenshotManager: 753da20873c2ada484bdee4143a7248084d3fd35 SocketRocket: abac6f5de4d4d62d24e11868d7a2f427e0ef940d - Yoga: 455fa6867657b570a05655dd515c8c6588618fa8 + Yoga: dcc90b6f6863e467adabdd4f4bd963da1faddf1d PODFILE CHECKSUM: 426f495a1ad44f3cabea3b7dd2b66a0b71083e26 From 9b1f8a81e9af971af6ddc1dc4ef96302bf4a08d7 Mon Sep 17 00:00:00 2001 From: Phillip Pan Date: Sat, 18 Nov 2023 22:13:40 -0800 Subject: [PATCH 018/162] hook up RCTDeprecation to [RCTBridgeModule bridge] (#41415) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41415 Changelog: [iOS][Deprecated] an example of RCT_DEPRECATION in action. you will get a build time warning if `RCT_DEPRECATED_DECLARATIONS` is enabled. Reviewed By: cipolleschi Differential Revision: D51184572 fbshipit-source-id: a0bcb4c69e63620bbdf2e2a7afb25c649fcaa100 --- packages/react-native/React/Base/RCTBridgeModule.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/react-native/React/Base/RCTBridgeModule.h b/packages/react-native/React/Base/RCTBridgeModule.h index 15d871fa76a7cd..a43b0b4fccfe93 100644 --- a/packages/react-native/React/Base/RCTBridgeModule.h +++ b/packages/react-native/React/Base/RCTBridgeModule.h @@ -11,6 +11,8 @@ #import #import +#import + #import "RCTBundleManager.h" @class RCTBridge; @@ -146,7 +148,7 @@ RCT_EXTERN_C_END * To implement this in your module, just add `@synthesize bridge = _bridge;` * If using Swift, add `@objc var bridge: RCTBridge!` to your module. */ -@property (nonatomic, weak, readonly) RCTBridge *bridge; +@property (nonatomic, weak, readonly) RCTBridge *bridge RCT_DEPRECATED; /** * The queue that will be used to call all exported methods. If omitted, this From 90b2c3fe43672aeb7d6e28647b5a25ccea7f045a Mon Sep 17 00:00:00 2001 From: Ramanpreet Nara Date: Sun, 19 Nov 2023 18:46:12 -0800 Subject: [PATCH 019/162] Merge ReactModuleInfo removal logic into core (#41468) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41468 Currently ReactPackageTurboModuleManagerDelegate uses ReactModuleInfos to create turbo modules. We want to see if it's possible to remove ReactModuleInfo from React Native's public API. Therefore, we are forking the implementation of each each method inside ReactPackageTurboModuleManagerDelegate: - **lazy mode:** doesn't use ReactModuleInfo - **control:** uses ReactModuleInfo This optimization was previosuly implemented outside of ReactPackageTurboModuleManagerDelegate. But, to simplify things, we are just pulling it inside the ReactPackageTurboModuleManagerDelegate. Changelog: [Internal] Reviewed By: philIip, mdvacca Differential Revision: D51093697 fbshipit-source-id: 6eb11020e0bf87eb704b35b990a0f14f157eea66 --- .../react/LazyTurboModuleManagerDelegate.java | 101 ------------------ ...eactPackageTurboModuleManagerDelegate.java | 75 ++++++++++++- 2 files changed, 74 insertions(+), 102 deletions(-) delete mode 100644 packages/react-native/ReactAndroid/src/main/java/com/facebook/react/LazyTurboModuleManagerDelegate.java diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/LazyTurboModuleManagerDelegate.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/LazyTurboModuleManagerDelegate.java deleted file mode 100644 index be7c47f1611330..00000000000000 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/LazyTurboModuleManagerDelegate.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and 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; - -import androidx.annotation.Nullable; -import com.facebook.react.bridge.NativeModule; -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.common.annotations.UnstableReactNativeAPI; -import com.facebook.react.internal.turbomodule.core.interfaces.TurboModule; -import java.util.List; - -/** - * This abstract class provides a simple Lazy implementation of TurboModuleManagerDelegate. Main - * difference between this class and ReactPackageTurboModuleManagerDelegate is that - * LazyTurboModuleManagerDelegate does not require NativeModules to be annotated using a - * ReactModule, also this class does not use the {@link - * TurboReactPackage#getReactModuleInfoProvider} method. This class is for experimentation purposes - * only, not to meant to be used in production. - */ -@UnstableReactNativeAPI -public abstract class LazyTurboModuleManagerDelegate - extends ReactPackageTurboModuleManagerDelegate { - - private final List mPackages; - private final ReactApplicationContext mReactContext; - - public LazyTurboModuleManagerDelegate( - ReactApplicationContext reactApplicationContext, List packages) { - super(); - mPackages = packages; - mReactContext = reactApplicationContext; - } - - @Override - @Nullable - public TurboModule getModule(String moduleName) { - /* - * Returns first TurboModule found with the name received as a parameter. There's no - * warning or error if there are more than one TurboModule registered with the same name in - * different packages. This method relies on the order of insertion of ReactPackage into - * mPackages. Usually the size of mPackages is very small (2 or 3 packages in the majority of - * the cases) - */ - for (ReactPackage reactPackage : mPackages) { - if (reactPackage instanceof BaseReactPackage) { - BaseReactPackage baseReactPackage = (BaseReactPackage) reactPackage; - try { - TurboModule nativeModule = - (TurboModule) baseReactPackage.getModule(moduleName, mReactContext); - if (nativeModule != null) { - return nativeModule; - } - } catch (IllegalArgumentException ex) { - /* - TurboReactPackages can throw an IllegalArgumentException when a module isn't found. If - this happens, it's safe to ignore the exception because a later TurboReactPackage could - provide the module. - */ - } - } else { - throw new IllegalArgumentException("ReactPackage must be an instance of TurboReactPackage"); - } - } - return null; - } - - @Override - public boolean unstable_isModuleRegistered(String moduleName) { - throw new UnsupportedOperationException("unstable_isModuleRegistered is not supported"); - } - - @Override - public boolean unstable_isLazyTurboModuleDelegate() { - return true; - } - - @Override - public boolean unstable_shouldEnableLegacyModuleInterop() { - return false; - } - - @Override - public boolean unstable_shouldRouteTurboModulesThroughLegacyModuleInterop() { - return false; - } - - @Override - public NativeModule getLegacyModule(String moduleName) { - throw new UnsupportedOperationException("Legacy Modules are not supported"); - } - - @Override - public boolean unstable_isLegacyModuleRegistered(String moduleName) { - return false; - }; -} diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactPackageTurboModuleManagerDelegate.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactPackageTurboModuleManagerDelegate.java index 50b1c6fd32043a..c05f893d1c10f1 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactPackageTurboModuleManagerDelegate.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactPackageTurboModuleManagerDelegate.java @@ -45,6 +45,12 @@ interface ModuleProvider { private final boolean mEnableTurboModuleSyncVoidMethods = ReactFeatureFlags.unstable_enableTurboModuleSyncVoidMethods; + private final boolean mIsLazy = ReactFeatureFlags.enableTurboModuleStableAPI; + + // Lazy Props + private List mPackages; + private ReactApplicationContext mReactContext; + protected ReactPackageTurboModuleManagerDelegate() { super(); } @@ -52,6 +58,12 @@ protected ReactPackageTurboModuleManagerDelegate() { protected ReactPackageTurboModuleManagerDelegate( ReactApplicationContext reactApplicationContext, List packages) { super(); + if (mIsLazy) { + mPackages = packages; + mReactContext = reactApplicationContext; + return; + } + final ReactApplicationContext applicationContext = reactApplicationContext; for (ReactPackage reactPackage : packages) { if (reactPackage instanceof BaseReactPackage) { @@ -130,21 +142,65 @@ protected ReactPackageTurboModuleManagerDelegate( @Override public boolean unstable_shouldEnableLegacyModuleInterop() { + if (mIsLazy) { + return false; + } + return mShouldEnableLegacyModuleInterop; } @Override public boolean unstable_shouldRouteTurboModulesThroughLegacyModuleInterop() { + if (mIsLazy) { + return false; + } + return mShouldRouteTurboModulesThroughLegacyModuleInterop; } public boolean unstable_enableSyncVoidMethods() { + if (mIsLazy) { + return false; + } + return mEnableTurboModuleSyncVoidMethods; } @Nullable @Override public TurboModule getModule(String moduleName) { + if (mIsLazy) { + /* + * Returns first TurboModule found with the name received as a parameter. There's no + * warning or error if there are more than one TurboModule registered with the same name in + * different packages. This method relies on the order of insertion of ReactPackage into + * mPackages. Usually the size of mPackages is very small (2 or 3 packages in the majority of + * the cases) + */ + for (ReactPackage reactPackage : mPackages) { + if (reactPackage instanceof BaseReactPackage) { + BaseReactPackage baseReactPackage = (BaseReactPackage) reactPackage; + try { + TurboModule nativeModule = + (TurboModule) baseReactPackage.getModule(moduleName, mReactContext); + if (nativeModule != null) { + return nativeModule; + } + } catch (IllegalArgumentException ex) { + /* + TurboReactPackages can throw an IllegalArgumentException when a module isn't found. If + this happens, it's safe to ignore the exception because a later TurboReactPackage could + provide the module. + */ + } + } else { + throw new IllegalArgumentException( + "ReactPackage must be an instance of TurboReactPackage"); + } + } + return null; + } + NativeModule resolvedModule = null; for (final ModuleProvider moduleProvider : mModuleProviders) { @@ -180,11 +236,15 @@ public TurboModule getModule(String moduleName) { @Override public boolean unstable_isLazyTurboModuleDelegate() { - return false; + return mIsLazy; } @Override public boolean unstable_isModuleRegistered(String moduleName) { + if (mIsLazy) { + throw new UnsupportedOperationException("unstable_isModuleRegistered is not supported"); + } + for (final ModuleProvider moduleProvider : mModuleProviders) { final ReactModuleInfo moduleInfo = mPackageModuleInfos.get(moduleProvider).get(moduleName); if (moduleInfo != null && moduleInfo.isTurboModule()) { @@ -196,6 +256,10 @@ public boolean unstable_isModuleRegistered(String moduleName) { @Override public boolean unstable_isLegacyModuleRegistered(String moduleName) { + if (mIsLazy) { + return false; + } + for (final ModuleProvider moduleProvider : mModuleProviders) { final ReactModuleInfo moduleInfo = mPackageModuleInfos.get(moduleProvider).get(moduleName); if (moduleInfo != null && !moduleInfo.isTurboModule()) { @@ -208,6 +272,10 @@ public boolean unstable_isLegacyModuleRegistered(String moduleName) { @Nullable @Override public NativeModule getLegacyModule(String moduleName) { + if (mIsLazy) { + throw new UnsupportedOperationException("Legacy Modules are not supported"); + } + if (!unstable_shouldEnableLegacyModuleInterop()) { return null; } @@ -247,6 +315,11 @@ public NativeModule getLegacyModule(String moduleName) { @Override public List getEagerInitModuleNames() { + if (mIsLazy) { + throw new UnsupportedOperationException( + "Running delegate in lazy mode. Please override getEagerInitModuleNames() and return a list of module names that need to be initialized eagerly."); + } + List moduleNames = new ArrayList<>(); for (final ModuleProvider moduleProvider : mModuleProviders) { for (final ReactModuleInfo moduleInfo : mPackageModuleInfos.get(moduleProvider).values()) { From 66051047e03e31fc6f2ec5661391fff96d639bb3 Mon Sep 17 00:00:00 2001 From: Ramanpreet Nara Date: Sun, 19 Nov 2023 18:46:12 -0800 Subject: [PATCH 020/162] Make default tmm delegate provide eager initialized module names (#41544) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41544 ## Change Extend DefaultTurboModuleManagerDelegate's API so that it specify which modules should be eagerly initialized. ## Rationale This information was originally stored on the module's ReactModuleInfo object. But, we're running an experiment (i.e: lazy mode) that gets rid of the ReactModuleInfo object. See D51093697 for more details. Changelog: [Internal] Reviewed By: mdvacca Differential Revision: D51307434 fbshipit-source-id: 6d867436588de2f9b8dd084327e74bd51ed61a2d --- .../DefaultTurboModuleManagerDelegate.kt | 25 ++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultTurboModuleManagerDelegate.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultTurboModuleManagerDelegate.kt index ac1fd1a4c7d90c..67df2f1e0eb8ba 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultTurboModuleManagerDelegate.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultTurboModuleManagerDelegate.kt @@ -21,13 +21,32 @@ import com.facebook.react.bridge.ReactApplicationContext * is hosted inside the React Native framework */ class DefaultTurboModuleManagerDelegate -private constructor(context: ReactApplicationContext, packages: List) : - ReactPackageTurboModuleManagerDelegate(context, packages) { +private constructor( + context: ReactApplicationContext, + packages: List, + private val eagerlyInitializedModules: List, +) : ReactPackageTurboModuleManagerDelegate(context, packages) { @DoNotStrip external override fun initHybrid(): HybridData? + override fun getEagerInitModuleNames(): List { + if (unstable_isLazyTurboModuleDelegate()) { + return eagerlyInitializedModules + } + + // Use ReactModuleInfo to get the eager init module names + return super.getEagerInitModuleNames() + } + class Builder : ReactPackageTurboModuleManagerDelegate.Builder() { + private var eagerInitModuleNames: List = emptyList() + + fun setEagerInitModuleNames(eagerInitModuleNames: List): Builder { + this.eagerInitModuleNames = eagerInitModuleNames + return this + } + override fun build(context: ReactApplicationContext, packages: List) = - DefaultTurboModuleManagerDelegate(context, packages) + DefaultTurboModuleManagerDelegate(context, packages, eagerInitModuleNames) } } From 1394cf7da70cd4831169d0031595101adc3b107e Mon Sep 17 00:00:00 2001 From: Ramanpreet Nara Date: Sun, 19 Nov 2023 18:46:12 -0800 Subject: [PATCH 021/162] Make default classes load their own so's (#41467) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41467 Make the DefaultTurboModuleManagerDelegate and the DefaultComponentRegistry load their own so's when they're created. **Motivation:** We are going to use these two classes in Meta apps. And Meta apps will not invoke DefaultNewArchitectureEntryPoint.load. Changelog: [Internal] Reviewed By: mdvacca Differential Revision: D51036133 fbshipit-source-id: 5ebd4d3b85f435229c9b5950493310aa7fa36ba0 --- .../defaults/DefaultComponentsRegistry.kt | 4 +++ .../DefaultNewArchitectureEntryPoint.kt | 12 +++------ .../react/defaults/DefaultSoLoader.kt | 26 +++++++++++++++++++ .../DefaultTurboModuleManagerDelegate.kt | 5 ++++ 4 files changed, 39 insertions(+), 8 deletions(-) create mode 100644 packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultSoLoader.kt diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultComponentsRegistry.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultComponentsRegistry.kt index 131804140ee901..2cf0b6908e4936 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultComponentsRegistry.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultComponentsRegistry.kt @@ -27,6 +27,10 @@ private constructor(componentFactory: ComponentFactory) { @DoNotStrip private external fun initHybrid(componentFactory: ComponentFactory): HybridData + init { + DefaultSoLoader.maybeLoadSoLibrary() + } + companion object { @JvmStatic @DoNotStrip diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultNewArchitectureEntryPoint.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultNewArchitectureEntryPoint.kt index fa6ff875dda211..a17f1279deece8 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultNewArchitectureEntryPoint.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultNewArchitectureEntryPoint.kt @@ -8,7 +8,6 @@ package com.facebook.react.defaults import com.facebook.react.config.ReactFeatureFlags -import com.facebook.soloader.SoLoader /** * A utility class that serves as an entry point for users setup the New Architecture. @@ -27,8 +26,7 @@ object DefaultNewArchitectureEntryPoint { fun load( turboModulesEnabled: Boolean = true, fabricEnabled: Boolean = true, - bridgelessEnabled: Boolean = false, - dynamicLibraryName: String = "appmodules", + bridgelessEnabled: Boolean = false ) { ReactFeatureFlags.useTurboModules = turboModulesEnabled ReactFeatureFlags.enableFabricRenderer = fabricEnabled @@ -42,23 +40,21 @@ object DefaultNewArchitectureEntryPoint { this.privateConcurrentReactEnabled = fabricEnabled this.privateBridgelessEnabled = bridgelessEnabled - SoLoader.loadLibrary("react_newarchdefaults") - SoLoader.loadLibrary(dynamicLibraryName) + DefaultSoLoader.maybeLoadSoLibrary() } @Deprecated( message = "Calling DefaultNewArchitectureEntryPoint.load() with different fabricEnabled and concurrentReactEnabled is deprecated. Please use a single flag for both Fabric and Concurrent React", - replaceWith = ReplaceWith("load(turboModulesEnabled, fabricEnabled, dynamicLibraryName)"), + replaceWith = ReplaceWith("load(turboModulesEnabled, fabricEnabled, bridgelessEnabled)"), level = DeprecationLevel.WARNING) fun load( turboModulesEnabled: Boolean = true, fabricEnabled: Boolean = true, bridgelessEnabled: Boolean = false, @Suppress("UNUSED_PARAMETER") concurrentReactEnabled: Boolean = true, - dynamicLibraryName: String = "appmodules", ) { - load(turboModulesEnabled, fabricEnabled, bridgelessEnabled, dynamicLibraryName) + load(turboModulesEnabled, fabricEnabled, bridgelessEnabled) } private var privateFabricEnabled: Boolean = false diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultSoLoader.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultSoLoader.kt new file mode 100644 index 00000000000000..cebdc7c93234fa --- /dev/null +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultSoLoader.kt @@ -0,0 +1,26 @@ +/* + * Copyright (c) Meta Platforms, Inc. and 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.defaults + +import com.facebook.soloader.SoLoader + +internal class DefaultSoLoader { + companion object { + @Synchronized + @JvmStatic + fun maybeLoadSoLibrary() { + SoLoader.loadLibrary("react_newarchdefaults") + try { + SoLoader.loadLibrary("appmodules") + } catch (e: UnsatisfiedLinkError) { + // ignore: DefaultTurboModuleManagerDelegate is still used in apps that don't have + // appmodules.so + } + } + } +} diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultTurboModuleManagerDelegate.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultTurboModuleManagerDelegate.kt index 67df2f1e0eb8ba..444cbe7240a0f9 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultTurboModuleManagerDelegate.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultTurboModuleManagerDelegate.kt @@ -49,4 +49,9 @@ private constructor( override fun build(context: ReactApplicationContext, packages: List) = DefaultTurboModuleManagerDelegate(context, packages, eagerInitModuleNames) } + + @Synchronized + override fun maybeLoadOtherSoLibraries() { + DefaultSoLoader.maybeLoadSoLibrary() + } } From a2558d15abe7331aa1dfba56c4e9b8f79d80faca Mon Sep 17 00:00:00 2001 From: Ramanpreet Nara Date: Sun, 19 Nov 2023 18:46:12 -0800 Subject: [PATCH 022/162] Introduce CxxReactPackage Summary: CxxReactPackage is supposed to be the way apps register C++-only turbo modules with React Native. Applications are meant to subclass this jni::HybridObject. Since this is a jni::HybridObject, applications are meant to create this CxxReactPackage in java, and initialize it with java dependencies. React Native will reach into its c++ part, and use it create C++-only turbo modules. NOTE: This is a **temporary** abstraction meant to unblock the stable API effort of removing the turbomodulemanagerdelegate builder from ReactHostDelegate: https://www.internalfb.com/code/fbsource/[e7efced3018f6178b7187a2358f3b76d40e2b43c]/xplat/js/react-native-github/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostDelegate.kt?lines=50-51 Changelog: [Internal] Reviewed By: mdvacca Differential Revision: D51166523 fbshipit-source-id: 51a22411239fbba32f3a70cc363e59947c2782dc --- .../react/utils/NdkConfiguratorUtils.kt | 1 + .../react-native/ReactAndroid/build.gradle | 8 +++++ .../cmake-utils/ReactNative-application.cmake | 2 ++ .../cxxreactpackage/CxxReactPackage.kt | 36 +++++++++++++++++++ .../ReactAndroid/src/main/jni/CMakeLists.txt | 1 + .../runtime/cxxreactpackage/CMakeList.txt | 29 +++++++++++++++ .../ReactCommon/CxxReactPackage.h | 31 ++++++++++++++++ .../cxxreactpackage/ReactCommon/OnLoad.cpp | 14 ++++++++ 8 files changed, 122 insertions(+) create mode 100644 packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/cxxreactpackage/CxxReactPackage.kt create mode 100644 packages/react-native/ReactAndroid/src/main/jni/react/runtime/cxxreactpackage/CMakeList.txt create mode 100644 packages/react-native/ReactAndroid/src/main/jni/react/runtime/cxxreactpackage/ReactCommon/CxxReactPackage.h create mode 100644 packages/react-native/ReactAndroid/src/main/jni/react/runtime/cxxreactpackage/ReactCommon/OnLoad.cpp diff --git a/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/NdkConfiguratorUtils.kt b/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/NdkConfiguratorUtils.kt index 9434b5a3c52f84..d24a9ee99021eb 100644 --- a/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/NdkConfiguratorUtils.kt +++ b/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/NdkConfiguratorUtils.kt @@ -102,6 +102,7 @@ internal object NdkConfiguratorUtils { "**/libreact_debug.so", "**/libreact_nativemodule_core.so", "**/libreact_newarchdefaults.so", + "**/libreact_cxxreactpackage.so", "**/libreact_render_componentregistry.so", "**/libreact_render_core.so", "**/libreact_render_debug.so", diff --git a/packages/react-native/ReactAndroid/build.gradle b/packages/react-native/ReactAndroid/build.gradle index ebf4cf3c26dc67..3dbd23de72c928 100644 --- a/packages/react-native/ReactAndroid/build.gradle +++ b/packages/react-native/ReactAndroid/build.gradle @@ -105,6 +105,10 @@ final def preparePrefab = tasks.register("preparePrefab", PreparePrefabHeadersTa "react_newarchdefaults", new Pair("src/main/jni/react/newarchdefaults", "") ), + new PrefabPreprocessingEntry( + "react_cxxreactpackage", + new Pair("src/main/jni/react/runtime/cxxreactpackage", "") + ), new PrefabPreprocessingEntry( "react_render_animations", new Pair("../ReactCommon/react/renderer/animations/", "react/renderer/animations/") @@ -530,6 +534,7 @@ android { "react_utils", "react_render_componentregistry", "react_newarchdefaults", + "react_cxxreactpackage", "react_render_animations", "react_render_core", "react_render_graphics", @@ -650,6 +655,9 @@ android { react_newarchdefaults { headers(new File(prefabHeadersDir, "react_newarchdefaults").absolutePath) } + react_cxxreactpackage { + headers(new File(prefabHeadersDir, "react_cxxreactpackage").absolutePath) + } react_render_animations { headers(new File(prefabHeadersDir, "react_render_animations").absolutePath) } diff --git a/packages/react-native/ReactAndroid/cmake-utils/ReactNative-application.cmake b/packages/react-native/ReactAndroid/cmake-utils/ReactNative-application.cmake index d49fa9ed80d80b..964e76f3753cf0 100644 --- a/packages/react-native/ReactAndroid/cmake-utils/ReactNative-application.cmake +++ b/packages/react-native/ReactAndroid/cmake-utils/ReactNative-application.cmake @@ -71,6 +71,7 @@ add_library(react_debug ALIAS ReactAndroid::react_debug) add_library(react_utils ALIAS ReactAndroid::react_utils) add_library(react_render_componentregistry ALIAS ReactAndroid::react_render_componentregistry) add_library(react_newarchdefaults ALIAS ReactAndroid::react_newarchdefaults) +add_library(react_cxxreactpackage ALIAS ReactAndroid::react_cxxreactpackage) add_library(react_render_core ALIAS ReactAndroid::react_render_core) add_library(react_render_graphics ALIAS ReactAndroid::react_render_graphics) add_library(rrc_view ALIAS ReactAndroid::rrc_view) @@ -99,6 +100,7 @@ target_link_libraries(${CMAKE_PROJECT_NAME} react_utils # prefab ready react_nativemodule_core # prefab ready react_newarchdefaults # prefab ready + react_cxxreactpackage # prefab ready react_render_componentregistry # prefab ready react_render_core # prefab ready react_render_debug # prefab ready diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/cxxreactpackage/CxxReactPackage.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/cxxreactpackage/CxxReactPackage.kt new file mode 100644 index 00000000000000..278d3d723c3ec7 --- /dev/null +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/cxxreactpackage/CxxReactPackage.kt @@ -0,0 +1,36 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +// TODO(170197717): Consider moving this to runtime.cxx, or just runtime +package com.facebook.react.runtime.cxxreactpackage + +import com.facebook.jni.HybridData +import com.facebook.proguard.annotations.DoNotStrip +import com.facebook.react.common.annotations.UnstableReactNativeAPI +import com.facebook.soloader.SoLoader + +/** CxxReactPackage is used to register C++ Turbo Modules with React Native. */ +@UnstableReactNativeAPI() +abstract class CxxReactPackage { + + @DoNotStrip @SuppressWarnings("unused") private val hybridData: HybridData + + protected abstract fun initHybrid(): HybridData + + protected constructor() { + maybeLoadOtherSoLibraries() + hybridData = initHybrid() + } + + @Synchronized protected open fun maybeLoadOtherSoLibraries(): Unit {} + + companion object { + init { + SoLoader.loadLibrary("react_cxxreactpackage") + } + } +} diff --git a/packages/react-native/ReactAndroid/src/main/jni/CMakeLists.txt b/packages/react-native/ReactAndroid/src/main/jni/CMakeLists.txt index e765f9b67f3708..feb7a3b33cafdd 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/CMakeLists.txt +++ b/packages/react-native/ReactAndroid/src/main/jni/CMakeLists.txt @@ -121,6 +121,7 @@ add_react_android_subdir(src/main/jni/react/fabric) add_react_android_subdir(src/main/jni/react/newarchdefaults) add_react_android_subdir(src/main/jni/react/hermes/reactexecutor) add_react_android_subdir(src/main/jni/react/hermes/instrumentation/) +add_react_android_subdir(src/main/jni/react/runtime/cxxreactpackage) add_react_android_subdir(src/main/jni/react/runtime/jni) add_react_android_subdir(src/main/jni/react/runtime/hermes/jni) add_react_android_subdir(src/main/jni/react/runtime/jsc/jni) diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/runtime/cxxreactpackage/CMakeList.txt b/packages/react-native/ReactAndroid/src/main/jni/react/runtime/cxxreactpackage/CMakeList.txt new file mode 100644 index 00000000000000..3cea95847728f8 --- /dev/null +++ b/packages/react-native/ReactAndroid/src/main/jni/react/runtime/cxxreactpackage/CMakeList.txt @@ -0,0 +1,29 @@ +# Copyright (c) Meta Platforms, Inc. and affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +cmake_minimum_required(VERSION 3.13) +set(CMAKE_VERBOSE_MAKEFILE on) + +add_compile_options( + -fexceptions + -frtti + -Wno-unused-lambda-capture + -std=c++20) + + +######################### +### cxxreactpackage ### +######################### + +add_library(react_cxxreactpackage SHARED ReactCommon/OnLoad.cpp) + +target_include_directories(react_cxxreactpackage + PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR} +) + +target_link_libraries(react_cxxreactpackage + fb + fbjni) diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/runtime/cxxreactpackage/ReactCommon/CxxReactPackage.h b/packages/react-native/ReactAndroid/src/main/jni/react/runtime/cxxreactpackage/ReactCommon/CxxReactPackage.h new file mode 100644 index 00000000000000..cdf1a86a7f4252 --- /dev/null +++ b/packages/react-native/ReactAndroid/src/main/jni/react/runtime/cxxreactpackage/ReactCommon/CxxReactPackage.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#pragma once + +#include +#include + +namespace facebook::react { + +class TurboModule; +class CallInvoker; + +class CxxReactPackage : public jni::HybridClass { + public: + static auto constexpr kJavaDescriptor = + "Lcom/facebook/react/runtime/cxxreactpackage/CxxReactPackage;"; + + virtual std::shared_ptr getModule( + const std::string& name, + const std::shared_ptr& jsInvoker) = 0; + + private: + friend HybridBase; +}; + +} // namespace facebook::react diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/runtime/cxxreactpackage/ReactCommon/OnLoad.cpp b/packages/react-native/ReactAndroid/src/main/jni/react/runtime/cxxreactpackage/ReactCommon/OnLoad.cpp new file mode 100644 index 00000000000000..e7f1f355b50be0 --- /dev/null +++ b/packages/react-native/ReactAndroid/src/main/jni/react/runtime/cxxreactpackage/ReactCommon/OnLoad.cpp @@ -0,0 +1,14 @@ +/* + * Copyright (c) Meta Platforms, Inc. and 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 "CxxReactPackage.h" + +JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void*) { + return facebook::jni::initialize(vm, [] {}); +} From 9fd1c6872fad571c5059fa7cacf45b43d17a38eb Mon Sep 17 00:00:00 2001 From: Ramanpreet Nara Date: Sun, 19 Nov 2023 18:46:12 -0800 Subject: [PATCH 023/162] Integrate default tmm delegate with CxxReactPackage (#41464) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41464 Now, DefaultTurboModuleManagerDelegate can be created with a CxxReactPackage. If it exists, DefaultTurobModuleManager will use the CxxReactPackage to create C++-only turbo modules. Changelog: [Internal] Reviewed By: mdvacca Differential Revision: D51166524 fbshipit-source-id: 2fdc404e79213d685c4f41b2a152b68226bb71b2 --- .../DefaultTurboModuleManagerDelegate.kt | 16 ++++++++++++++-- .../jni/react/newarchdefaults/CMakeLists.txt | 1 + .../DefaultTurboModuleManagerDelegate.cpp | 17 +++++++++++++++-- .../DefaultTurboModuleManagerDelegate.h | 10 +++++++++- 4 files changed, 39 insertions(+), 5 deletions(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultTurboModuleManagerDelegate.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultTurboModuleManagerDelegate.kt index 444cbe7240a0f9..10a7dc7c5d2f75 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultTurboModuleManagerDelegate.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultTurboModuleManagerDelegate.kt @@ -12,6 +12,8 @@ import com.facebook.proguard.annotations.DoNotStrip import com.facebook.react.ReactPackage import com.facebook.react.ReactPackageTurboModuleManagerDelegate import com.facebook.react.bridge.ReactApplicationContext +import com.facebook.react.common.annotations.UnstableReactNativeAPI +import com.facebook.react.runtime.cxxreactpackage.CxxReactPackage /** * A utility class that allows you to simplify the setup of a @@ -20,14 +22,18 @@ import com.facebook.react.bridge.ReactApplicationContext * This class works together with the [DefaultNewArchitectureEntryPoint] and it's C++ implementation * is hosted inside the React Native framework */ +@OptIn(UnstableReactNativeAPI::class) class DefaultTurboModuleManagerDelegate private constructor( context: ReactApplicationContext, packages: List, private val eagerlyInitializedModules: List, + private val cxxReactPackage: CxxReactPackage?, ) : ReactPackageTurboModuleManagerDelegate(context, packages) { - @DoNotStrip external override fun initHybrid(): HybridData? + @DoNotStrip override fun initHybrid() = initHybrid(cxxReactPackage) + + external fun initHybrid(cxxReactPackage: CxxReactPackage?): HybridData? override fun getEagerInitModuleNames(): List { if (unstable_isLazyTurboModuleDelegate()) { @@ -40,14 +46,20 @@ private constructor( class Builder : ReactPackageTurboModuleManagerDelegate.Builder() { private var eagerInitModuleNames: List = emptyList() + private var cxxReactPackage: CxxReactPackage? = null fun setEagerInitModuleNames(eagerInitModuleNames: List): Builder { this.eagerInitModuleNames = eagerInitModuleNames return this } + fun setCxxReactPackage(cxxReactPackage: CxxReactPackage): Builder { + this.cxxReactPackage = cxxReactPackage + return this + } + override fun build(context: ReactApplicationContext, packages: List) = - DefaultTurboModuleManagerDelegate(context, packages, eagerInitModuleNames) + DefaultTurboModuleManagerDelegate(context, packages, eagerInitModuleNames, cxxReactPackage) } @Synchronized diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/newarchdefaults/CMakeLists.txt b/packages/react-native/ReactAndroid/src/main/jni/react/newarchdefaults/CMakeLists.txt index 166c5ed45344ec..b928ca15839865 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/newarchdefaults/CMakeLists.txt +++ b/packages/react-native/ReactAndroid/src/main/jni/react/newarchdefaults/CMakeLists.txt @@ -19,4 +19,5 @@ target_link_libraries(react_newarchdefaults fabricjni react_nativemodule_core react_codegen_rncore + react_cxxreactpackage jsi) diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/newarchdefaults/DefaultTurboModuleManagerDelegate.cpp b/packages/react-native/ReactAndroid/src/main/jni/react/newarchdefaults/DefaultTurboModuleManagerDelegate.cpp index c4a14f39c5349c..86944f2e6c4a20 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/newarchdefaults/DefaultTurboModuleManagerDelegate.cpp +++ b/packages/react-native/ReactAndroid/src/main/jni/react/newarchdefaults/DefaultTurboModuleManagerDelegate.cpp @@ -11,6 +11,10 @@ namespace facebook::react { +DefaultTurboModuleManagerDelegate::DefaultTurboModuleManagerDelegate( + jni::alias_ref cxxReactPackage) + : cxxReactPackage_(jni::make_global(cxxReactPackage)){}; + std::function( const std::string&, const std::shared_ptr&)> @@ -22,8 +26,10 @@ std::function( DefaultTurboModuleManagerDelegate::javaModuleProvider{nullptr}; jni::local_ref -DefaultTurboModuleManagerDelegate::initHybrid(jni::alias_ref) { - return makeCxxInstance(); +DefaultTurboModuleManagerDelegate::initHybrid( + jni::alias_ref, + jni::alias_ref cxxReactPackage) { + return makeCxxInstance(cxxReactPackage); } void DefaultTurboModuleManagerDelegate::registerNatives() { @@ -36,6 +42,13 @@ void DefaultTurboModuleManagerDelegate::registerNatives() { std::shared_ptr DefaultTurboModuleManagerDelegate::getTurboModule( const std::string& name, const std::shared_ptr& jsInvoker) { + if (cxxReactPackage_) { + auto module = cxxReactPackage_->cthis()->getModule(name, jsInvoker); + if (module) { + return module; + } + } + auto moduleProvider = DefaultTurboModuleManagerDelegate::cxxModuleProvider; if (moduleProvider) { return moduleProvider(name, jsInvoker); diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/newarchdefaults/DefaultTurboModuleManagerDelegate.h b/packages/react-native/ReactAndroid/src/main/jni/react/newarchdefaults/DefaultTurboModuleManagerDelegate.h index fdcf8d00ae9b22..e175a574bc394b 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/newarchdefaults/DefaultTurboModuleManagerDelegate.h +++ b/packages/react-native/ReactAndroid/src/main/jni/react/newarchdefaults/DefaultTurboModuleManagerDelegate.h @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -22,7 +23,9 @@ class DefaultTurboModuleManagerDelegate : public jni::HybridClass< static constexpr auto kJavaDescriptor = "Lcom/facebook/react/defaults/DefaultTurboModuleManagerDelegate;"; - static jni::local_ref initHybrid(jni::alias_ref); + static jni::local_ref initHybrid( + jni::alias_ref, + jni::alias_ref); static void registerNatives(); @@ -46,6 +49,11 @@ class DefaultTurboModuleManagerDelegate : public jni::HybridClass< private: friend HybridBase; using HybridBase::HybridBase; + + jni::global_ref cxxReactPackage_; + + DefaultTurboModuleManagerDelegate( + jni::alias_ref); }; } // namespace facebook::react From e2d708875c91cd094fe3f509f664dd38e2da639a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oskar=20Kwa=C5=9Bniewski?= Date: Sun, 19 Nov 2023 22:46:36 -0800 Subject: [PATCH 024/162] fix: typo in cli.js (#41523) Summary: This PR fixes a typo in `cli.js`. ## Changelog: [INTERNAL] [FIXED] - typo in react-native/cli.js Pull Request resolved: https://github.com/facebook/react-native/pull/41523 Test Plan: Not needed Reviewed By: christophpurrer Differential Revision: D51452866 Pulled By: arushikesarwani94 fbshipit-source-id: 61f1da70621bfe1a159ec63da0014141b182c5ac --- packages/react-native/cli.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react-native/cli.js b/packages/react-native/cli.js index 4d84dd6b470d5a..4547d287ec955e 100755 --- a/packages/react-native/cli.js +++ b/packages/react-native/cli.js @@ -40,7 +40,7 @@ async function getLatestVersion(registryHost = DEFAULT_REGISTRY_HOST) { } /** - * npx react-native -> @react-native-comminity/cli + * npx react-native -> @react-native-community/cli * * Will perform a version check and warning if you're not running the latest community cli when executed using npx. If * you know what you're doing, you can skip this check: From 0056fc89ffbbb53e482ccecfd8425c7c81c7d360 Mon Sep 17 00:00:00 2001 From: Riccardo Cipolleschi Date: Mon, 20 Nov 2023 06:41:25 -0800 Subject: [PATCH 025/162] Cleanup fabricEnabled callsites (#41556) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41556 Followup after [#41500](https://github.com/facebook/react-native/pull/41500) to cleanup some callsites that does not need the flag anymore. ## Changelog [Internal] - Callsite cleanup Reviewed By: dmytrorykun Differential Revision: D51465124 fbshipit-source-id: 61c0ac047f6eeb528f9a8aafd6d3f339c0399be9 --- .../scripts/cocoapods/__tests__/codegen_utils-test.rb | 1 - packages/react-native/scripts/cocoapods/codegen_utils.rb | 1 - .../scripts/codegen/generate-artifacts-executor.js | 1 - .../react-native/scripts/generate-codegen-artifacts.js | 8 -------- .../scripts/react_native_pods_utils/script_phases.sh | 2 +- 5 files changed, 1 insertion(+), 12 deletions(-) diff --git a/packages/react-native/scripts/cocoapods/__tests__/codegen_utils-test.rb b/packages/react-native/scripts/cocoapods/__tests__/codegen_utils-test.rb index 1891202664c4cc..e485b89c21d1b8 100644 --- a/packages/react-native/scripts/cocoapods/__tests__/codegen_utils-test.rb +++ b/packages/react-native/scripts/cocoapods/__tests__/codegen_utils-test.rb @@ -399,7 +399,6 @@ def testUseReactCodegenDiscovery_whenParametersAreGood_executeCodegen "arguments"=> ["~/app/ios/../node_modules/react-native/scripts/generate-codegen-artifacts.js", "-p", "~/app", "-o", Pod::Config.instance.installation_root, - "-e", "false", "-c", ""] } ]) diff --git a/packages/react-native/scripts/cocoapods/codegen_utils.rb b/packages/react-native/scripts/cocoapods/codegen_utils.rb index 9f98a9dfa0984f..71018f2b7ee754 100644 --- a/packages/react-native/scripts/cocoapods/codegen_utils.rb +++ b/packages/react-native/scripts/cocoapods/codegen_utils.rb @@ -325,7 +325,6 @@ def use_react_native_codegen_discovery!( "#{relative_installation_root}/#{react_native_path}/scripts/generate-codegen-artifacts.js", "-p", "#{app_path}", "-o", Pod::Config.instance.installation_root, - "-e", "#{fabric_enabled}", "-c", "#{config_file_dir}", ]) Pod::UI.puts out; diff --git a/packages/react-native/scripts/codegen/generate-artifacts-executor.js b/packages/react-native/scripts/codegen/generate-artifacts-executor.js index 7dc8b92366ed83..bc89ed07aa2cfa 100644 --- a/packages/react-native/scripts/codegen/generate-artifacts-executor.js +++ b/packages/react-native/scripts/codegen/generate-artifacts-executor.js @@ -511,7 +511,6 @@ function cleanupEmptyFilesAndFolders(filepath) { * @parameter codegenConfigFilename: the file that contains the codeGen configuration. The default is `package.json`. * @parameter codegenConfigKey: the key in the codegenConfigFile that controls the codegen. * @parameter baseCodegenConfigFileDir: the directory of the codeGenConfigFile. - * @parameter fabricEnabled: whether fabric is enabled or not. * @throws If it can't find a config file for react-native. * @throws If it can't find a CodeGen configuration in the file. * @throws If it can't find a cli for the CodeGen. diff --git a/packages/react-native/scripts/generate-codegen-artifacts.js b/packages/react-native/scripts/generate-codegen-artifacts.js index bde850b940de2c..a73538a788b9d3 100644 --- a/packages/react-native/scripts/generate-codegen-artifacts.js +++ b/packages/react-native/scripts/generate-codegen-artifacts.js @@ -32,12 +32,6 @@ const argv = yargs description: 'The key that contains the codegen configuration in the config file.', }) - .option('e', { - alias: 'fabricEnabled', - default: true, - description: 'A flag to control whether to generate fabric components.', - boolean: 'e', - }) .option('c', { alias: 'configFileDir', default: '', @@ -55,7 +49,6 @@ const argv = yargs const CODEGEN_CONFIG_FILENAME = argv.f; const CODEGEN_CONFIG_FILE_DIR = argv.c; const CODEGEN_CONFIG_KEY = argv.k; -const CODEGEN_FABRIC_ENABLED = argv.e; const NODE = argv.n; const appRoot = argv.path; @@ -68,5 +61,4 @@ executor.execute( CODEGEN_CONFIG_FILENAME, CODEGEN_CONFIG_KEY, CODEGEN_CONFIG_FILE_DIR, - CODEGEN_FABRIC_ENABLED, ); diff --git a/packages/react-native/scripts/react_native_pods_utils/script_phases.sh b/packages/react-native/scripts/react_native_pods_utils/script_phases.sh index 4da11277929abc..d72626232fe549 100755 --- a/packages/react-native/scripts/react_native_pods_utils/script_phases.sh +++ b/packages/react-native/scripts/react_native_pods_utils/script_phases.sh @@ -96,7 +96,7 @@ generateCodegenArtifactsFromSchema () { generateArtifacts () { describe "Generating codegen artifacts" pushd "$RCT_SCRIPT_RN_DIR" >/dev/null || exit 1 - "$NODE_BINARY" "scripts/generate-codegen-artifacts.js" --path "$RCT_SCRIPT_APP_PATH" --outputPath "$TEMP_OUTPUT_DIR" --fabricEnabled "$RCT_SCRIPT_FABRIC_ENABLED" --configFileDir "$RCT_SCRIPT_CONFIG_FILE_DIR" --nodeBinary "$NODE_BINARY" + "$NODE_BINARY" "scripts/generate-codegen-artifacts.js" --path "$RCT_SCRIPT_APP_PATH" --outputPath "$TEMP_OUTPUT_DIR" --configFileDir "$RCT_SCRIPT_CONFIG_FILE_DIR" --nodeBinary "$NODE_BINARY" popd >/dev/null || exit 1 } From 63213712125795ac082597dad2716258b90cdcd5 Mon Sep 17 00:00:00 2001 From: Dmitry Rykun Date: Mon, 20 Nov 2023 07:30:55 -0800 Subject: [PATCH 026/162] Refactor generate-artifacts-executor.js: various cleanups (#41528) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41528 This diff makes some minor cleanups in `generate-artifacts-executor.js`. Specifically: 1. remove unused argument `iosOutputDir` 2. remove unused `libraryConfig.library` property 3. Fix typo in `handleReactNativeCo`**r**`eLibraries` function name Changelog: [Internal] Reviewed By: cipolleschi Differential Revision: D51115394 fbshipit-source-id: 8ee9b5f35cf254510714a023dab32077c700e061 --- .../__tests__/generate-artifacts-executor-test.js | 7 ------- .../codegen/generate-artifacts-executor.js | 15 +++++---------- 2 files changed, 5 insertions(+), 17 deletions(-) diff --git a/packages/react-native/scripts/codegen/__tests__/generate-artifacts-executor-test.js b/packages/react-native/scripts/codegen/__tests__/generate-artifacts-executor-test.js index 703a210f99a6b2..6e49f106225100 100644 --- a/packages/react-native/scripts/codegen/__tests__/generate-artifacts-executor-test.js +++ b/packages/react-native/scripts/codegen/__tests__/generate-artifacts-executor-test.js @@ -120,7 +120,6 @@ describe('extractLibrariesFromJSON', () => { ); expect(libraries.length).toBe(1); expect(libraries[0]).toEqual({ - library: 'my-app', config: { name: 'AppModules', type: 'all', @@ -155,7 +154,6 @@ describe('extractLibrariesFromJSON', () => { ); expect(libraries.length).toBe(1); expect(libraries[0]).toEqual({ - library: reactNativeDependencyName, config: { name: 'react-native', type: 'all', @@ -179,7 +177,6 @@ describe('extractLibrariesFromJSON', () => { ); expect(libraries.length).toBe(3); expect(libraries[0]).toEqual({ - library: myDependency, config: { name: 'react-native', type: 'all', @@ -188,7 +185,6 @@ describe('extractLibrariesFromJSON', () => { libraryPath: myDependencyPath, }); expect(libraries[1]).toEqual({ - library: myDependency, config: { name: 'my-component', type: 'components', @@ -197,7 +193,6 @@ describe('extractLibrariesFromJSON', () => { libraryPath: myDependencyPath, }); expect(libraries[2]).toEqual({ - library: myDependency, config: { name: 'my-module', type: 'module', @@ -272,12 +267,10 @@ describe('findCodegenEnabledLibraries', () => { expect(libraries).toEqual([ { - library: 'react-native', config: {}, libraryPath: baseCodegenConfigFileDir, }, { - library: 'react-native-foo', config: {name: 'RNFooSpec', type: 'modules', jsSrcsDir: 'src'}, libraryPath: path.join(projectDir, 'library-foo'), }, diff --git a/packages/react-native/scripts/codegen/generate-artifacts-executor.js b/packages/react-native/scripts/codegen/generate-artifacts-executor.js index bc89ed07aa2cfa..9cce4ffab73a0b 100644 --- a/packages/react-native/scripts/codegen/generate-artifacts-executor.js +++ b/packages/react-native/scripts/codegen/generate-artifacts-executor.js @@ -105,13 +105,10 @@ function extractLibrariesFromConfigurationArray( configFile, codegenConfigKey, libraries, - dependency, dependencyPath, ) { - console.log(`[Codegen] Found ${dependency}`); configFile[codegenConfigKey].libraries.forEach(config => { const libraryConfig = { - library: dependency, config, libraryPath: dependencyPath, }; @@ -142,11 +139,10 @@ function extractLibrariesFromJSON( return; } + console.log(`[Codegen] Found ${dependency}`); if (configFile[codegenConfigKey].libraries == null) { - console.log(`[Codegen] Found ${dependency}`); var config = configFile[codegenConfigKey]; libraries.push({ - library: dependency, config, libraryPath: dependencyPath, }); @@ -156,13 +152,12 @@ function extractLibrariesFromJSON( configFile, codegenConfigKey, libraries, - dependency, dependencyPath, ); } } -function handleReactNativeCodeLibraries( +function handleReactNativeCoreLibraries( libraries, codegenConfigFilename, codegenConfigKey, @@ -397,7 +392,7 @@ function generateNativeCodegenFiles( }); } -function createComponentProvider(schemaPaths, node, iosOutputDir) { +function createComponentProvider(schemaPaths, node) { console.log('\n\n>>>>> Creating component provider'); // Save the list of spec paths to a temp file. const schemaListTmpPath = `${os.tmpdir()}/rn-tmp-schema-list.json`; @@ -440,7 +435,7 @@ function findCodegenEnabledLibraries( const dependencies = {...pkgJson.dependencies, ...pkgJson.devDependencies}; const libraries = []; - handleReactNativeCodeLibraries( + handleReactNativeCoreLibraries( libraries, codegenConfigFilename, codegenConfigKey, @@ -554,7 +549,7 @@ function execute( schemaPaths, ); - createComponentProvider(schemaPaths, node, iosOutputDir); + createComponentProvider(schemaPaths, node); cleanupEmptyFilesAndFolders(iosOutputDir); } catch (err) { console.error(err); From e8323781fac8b19bb8a4faa53461c33ff201817b Mon Sep 17 00:00:00 2001 From: Arushi Kesarwani Date: Mon, 20 Nov 2023 10:26:27 -0800 Subject: [PATCH 027/162] Fix ReactInstanceManager to add getJSIModule() as an alternate path (#41495) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41495 Fix ReactInstanceManager for adding the callsite of `getJSIModule()` as an alternate path to new way of Fabric initialization in order to make Catalyst and RN-Tester work with the changes for Fabric initialization Reviewed By: javache Differential Revision: D51338036 fbshipit-source-id: 49badac52f1032f1032a989b76dd422e3cf7582f --- .../src/main/java/com/facebook/react/ReactInstanceManager.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java index 2ae69e229714bb..6a4c0df440d9a1 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java @@ -1407,9 +1407,10 @@ private ReactApplicationContext createReactContext( reactContext, catalystInstance.getJavaScriptContextHolder())); } if (ReactFeatureFlags.enableFabricRenderer) { - catalystInstance.getJSIModule(JSIModuleType.UIManager); if (mUIManagerProvider != null) { catalystInstance.setFabricUIManager(mUIManagerProvider.createUIManager(reactContext)); + } else { + catalystInstance.getJSIModule(JSIModuleType.UIManager); } } if (mBridgeIdleDebugListener != null) { From 228193dad5369cdb5e13ba8a926e0ab9d12429e7 Mon Sep 17 00:00:00 2001 From: Pieter De Baets Date: Mon, 20 Nov 2023 13:01:04 -0800 Subject: [PATCH 028/162] Do not suppress IllegalArgumentExceptions during TurboModule creation (#41509) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41509 We currently ignore `IllegalArgumentException` being thrown from TurboModule getters, as it was deemed acceptable to use that to signal a Package didn't have that module. This however can mask legitimate errors thrown during a TurboModule constructor. TurboReactPackage#getModule is already marked as allowing nullable returns, so let's leave the use of exceptions for exceptional scenarios. Changelog: [Android][Changed] Use null to signal a missing TurboModule instead of IllegalArgumentException. Reviewed By: RSNara Differential Revision: D51395165 fbshipit-source-id: 1eea1db6c7e3313a36d24e7837b36a3d0fccc718 --- .../com/facebook/react/DebugCorePackage.java | 5 ++- ...eactPackageTurboModuleManagerDelegate.java | 36 ++++++++++--------- .../facebook/react/bridge/ModuleHolder.java | 3 +- .../react/runtime/CoreReactPackage.java | 6 ++-- 4 files changed, 27 insertions(+), 23 deletions(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/DebugCorePackage.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/DebugCorePackage.java index 0168fce4f5ba7f..398b69ac1a5684 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/DebugCorePackage.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/DebugCorePackage.java @@ -43,13 +43,12 @@ class DebugCorePackage extends TurboReactPackage implements ViewManagerOnDemandR public DebugCorePackage() {} @Override - public NativeModule getModule(String name, ReactApplicationContext reactContext) { + public @Nullable NativeModule getModule(String name, ReactApplicationContext reactContext) { switch (name) { case JSCHeapCapture.NAME: return new JSCHeapCapture(reactContext); default: - throw new IllegalArgumentException( - "In DebugCorePackage, could not find Native module for " + name); + return null; } } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactPackageTurboModuleManagerDelegate.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactPackageTurboModuleManagerDelegate.java index c05f893d1c10f1..30ef9e019b3783 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactPackageTurboModuleManagerDelegate.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactPackageTurboModuleManagerDelegate.java @@ -8,11 +8,13 @@ package com.facebook.react; import androidx.annotation.Nullable; +import com.facebook.common.logging.FLog; import com.facebook.infer.annotation.Assertions; import com.facebook.react.bridge.CxxModuleWrapper; import com.facebook.react.bridge.ModuleSpec; import com.facebook.react.bridge.NativeModule; import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.common.ReactConstants; import com.facebook.react.config.ReactFeatureFlags; import com.facebook.react.internal.turbomodule.core.TurboModuleManagerDelegate; import com.facebook.react.internal.turbomodule.core.interfaces.TurboModule; @@ -187,11 +189,12 @@ public TurboModule getModule(String moduleName) { return nativeModule; } } catch (IllegalArgumentException ex) { - /* - TurboReactPackages can throw an IllegalArgumentException when a module isn't found. If - this happens, it's safe to ignore the exception because a later TurboReactPackage could - provide the module. - */ + // TODO T170570617: remove this catch statement and let exception bubble up + FLog.e( + ReactConstants.TAG, + ex, + "Caught exception while constructing module '%s'. This was previously ignored but will not be caught in the future.", + moduleName); } } else { throw new IllegalArgumentException( @@ -217,11 +220,12 @@ public TurboModule getModule(String moduleName) { } } catch (IllegalArgumentException ex) { - /* - TurboReactPackages can throw an IllegalArgumentException when a module isn't found. If - this happens, it's safe to ignore the exception because a later TurboReactPackage could - provide the module. - */ + // TODO T170570617: remove this catch statement and let exception bubble up + FLog.e( + ReactConstants.TAG, + ex, + "Caught exception while constructing module '%s'. This was previously ignored but will not be caught in the future.", + moduleName); } } @@ -294,13 +298,13 @@ public NativeModule getLegacyModule(String moduleName) { resolvedModule = module; } } - } catch (IllegalArgumentException ex) { - /* - * TurboReactPackages can throw an IllegalArgumentException when a module isn't found. If - * this happens, it's safe to ignore the exception because a later TurboReactPackage could - * provide the module. - */ + // TODO T170570617: remove this catch statement and let exception bubble up + FLog.e( + ReactConstants.TAG, + ex, + "Caught exception while constructing module '%s'. This was previously ignored but will not be caught in the future.", + moduleName); } } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/ModuleHolder.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/ModuleHolder.java index 731aa04fa3cf1b..25f170f1134a92 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/ModuleHolder.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/ModuleHolder.java @@ -19,6 +19,7 @@ import com.facebook.debug.tags.ReactDebugOverlayTags; import com.facebook.infer.annotation.Assertions; import com.facebook.proguard.annotations.DoNotStrip; +import com.facebook.react.common.ReactConstants; import com.facebook.react.internal.turbomodule.core.interfaces.TurboModule; import com.facebook.react.module.model.ReactModuleInfo; import com.facebook.systrace.SystraceMessage; @@ -204,7 +205,7 @@ private NativeModule create() { * * @todo(T53311351) */ - FLog.e("NativeModuleInitError", "Failed to create NativeModule \"" + getName() + "\"", ex); + FLog.e(ReactConstants.TAG, ex, "Failed to create NativeModule '%s'", mName); throw ex; } finally { ReactMarker.logMarker(CREATE_MODULE_END, mName, mInstanceKey); diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/CoreReactPackage.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/CoreReactPackage.java index 2550520a48641e..cb8b9c13af09ae 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/CoreReactPackage.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/CoreReactPackage.java @@ -7,6 +7,7 @@ package com.facebook.react.runtime; +import androidx.annotation.Nullable; import com.facebook.infer.annotation.Nullsafe; import com.facebook.react.TurboReactPackage; import com.facebook.react.bridge.NativeModule; @@ -51,7 +52,7 @@ public CoreReactPackage( } @Override - public NativeModule getModule(String name, ReactApplicationContext reactContext) { + public @Nullable NativeModule getModule(String name, ReactApplicationContext reactContext) { switch (name) { case AndroidInfoModule.NAME: return new AndroidInfoModule(reactContext); @@ -68,8 +69,7 @@ public NativeModule getModule(String name, ReactApplicationContext reactContext) case ExceptionsManagerModule.NAME: return new ExceptionsManagerModule(mDevSupportManager); default: - throw new IllegalArgumentException( - "In BridgelessReactPackage, could not find Native module for " + name); + return null; } } From c7bd397dacc1a809572142bb7f80adf76d6002fe Mon Sep 17 00:00:00 2001 From: Kevin Gozali Date: Mon, 20 Nov 2023 14:02:00 -0800 Subject: [PATCH 029/162] RNTester iOS: require arm64 device capabilities (#41551) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41551 We have since targeted iOS min SDK 13.4, it's time to move to `arm64`. Reference: https://developer.apple.com/documentation/bundleresources/information_property_list/uirequireddevicecapabilities?language=objc Changelog: [iOS][Fixed] Move UIRequiredDeviceCapabilities for RNTester to arm64 Reviewed By: cipolleschi Differential Revision: D51461103 fbshipit-source-id: 726ca1f37d249092e8f10c2043d0b696bf64aa7d --- packages/react-native/template/ios/HelloWorld/Info.plist | 2 +- packages/rn-tester/RNTester/Info.plist | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/react-native/template/ios/HelloWorld/Info.plist b/packages/react-native/template/ios/HelloWorld/Info.plist index c004615da4e278..07b050898d9d30 100644 --- a/packages/react-native/template/ios/HelloWorld/Info.plist +++ b/packages/react-native/template/ios/HelloWorld/Info.plist @@ -38,7 +38,7 @@ LaunchScreen UIRequiredDeviceCapabilities - armv7 + arm64 UISupportedInterfaceOrientations diff --git a/packages/rn-tester/RNTester/Info.plist b/packages/rn-tester/RNTester/Info.plist index 8e05c22beec181..50c8a4c0f3ddb0 100644 --- a/packages/rn-tester/RNTester/Info.plist +++ b/packages/rn-tester/RNTester/Info.plist @@ -50,7 +50,7 @@ LaunchScreen UIRequiredDeviceCapabilities - armv7 + arm64 UISupportedInterfaceOrientations From b4d4aef057ebf90176287f22d72b4b3b8b280c9a Mon Sep 17 00:00:00 2001 From: Nick Gerleman Date: Mon, 20 Nov 2023 14:10:56 -0800 Subject: [PATCH 030/162] Fix modulemap typo (#41564) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41564 X-link: https://github.com/facebook/yoga/pull/1474 Fixes https://github.com/facebook/yoga/issues/1468 We build with Swift, but don't build something consuming Yoga module, and don't use modulemap and CocoaPods. This is a gap in validation we should figure out, but in the meantime, we should fix the typo. Reviewed By: christophpurrer Differential Revision: D51472493 fbshipit-source-id: 60e05cc49969f51d5fc4856cf25ce2afede72f36 --- packages/react-native/ReactCommon/yoga/yoga/module.modulemap | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react-native/ReactCommon/yoga/yoga/module.modulemap b/packages/react-native/ReactCommon/yoga/yoga/module.modulemap index 5a8aad8ff27dce..6a0f46030e8c56 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/module.modulemap +++ b/packages/react-native/ReactCommon/yoga/yoga/module.modulemap @@ -12,7 +12,7 @@ module yoga [system] { header "YGMacros.h" header "YGNode.h" header "YGNodeLayout.h" - header "YGNodeStye.h" + header "YGNodeStyle.h" header "YGPixelGrid.h" header "YGValue.h" header "Yoga.h" From e3645534920e509f1344e6f83916fcd61723403b Mon Sep 17 00:00:00 2001 From: Christoph Purrer Date: Mon, 20 Nov 2023 16:25:46 -0800 Subject: [PATCH 031/162] RNTester-ios / RCTAppDelegate > correctly check for USE_HERMES Flag (#41573) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41573 Changelog: [iOS][Fixed] RNTester-ios / RCTAppDelegate > correctly check for USE_HERMES Flag On iOS we check for ENV flags if Hermes should be used: - https://github.com/facebook/react-native/blob/b4d4aef057ebf90176287f22d72b4b3b8b280c9a/packages/react-native/React-Core.podspec#L24 - https://github.com/facebook/react-native/blob/b4d4aef057ebf90176287f22d72b4b3b8b280c9a/packages/react-native/React/React-RCTFabric.podspec#L90 and add necessary C++ packages based on that flag. In code we do check for those imports https://github.com/facebook/react-native/blob/b4d4aef057ebf90176287f22d72b4b3b8b280c9a/packages/react-native/Libraries/AppDelegate/RCTAppSetupUtils.h#L16-L27 and decided if we should use Hermes or not. However the .mm check is faulty and does not check for the `RCT_USE_HERMES` flag set in code. Reviewed By: fkgozali Differential Revision: D51483740 fbshipit-source-id: 428c27aae80fe6f9799cf6ae21a5d3801fe6ca11 --- packages/react-native/Libraries/AppDelegate/RCTAppDelegate.mm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/react-native/Libraries/AppDelegate/RCTAppDelegate.mm b/packages/react-native/Libraries/AppDelegate/RCTAppDelegate.mm index 82e1911fe12246..b2982786800026 100644 --- a/packages/react-native/Libraries/AppDelegate/RCTAppDelegate.mm +++ b/packages/react-native/Libraries/AppDelegate/RCTAppDelegate.mm @@ -27,7 +27,7 @@ #import #import #import -#if USE_HERMES +#if RCT_USE_HERMES #import #else #import @@ -305,7 +305,7 @@ - (void)createReactHost - (std::shared_ptr)createJSEngineInstance { -#if USE_HERMES +#if RCT_USE_HERMES return std::make_shared(_reactNativeConfig, nullptr); #else return std::make_shared(); From 3f12c45f65d0620bbd84cc973d18e24aff97eae2 Mon Sep 17 00:00:00 2001 From: Ramanpreet Nara Date: Mon, 20 Nov 2023 17:33:28 -0800 Subject: [PATCH 032/162] Fix CircleCI failure with cxxreactpackage (#41571) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41571 The original diff: D51166523 ## The Failure https://app.circleci.com/pipelines/github/facebook/react-native/36821/workflows/7e360d9d-0a8e-4bf9-87d8-91c4cf3db3ca/jobs/1221118 ``` CMake Error at CMakeLists.txt:28 (add_subdirectory): The source directory /root/react-native/packages/react-native/ReactAndroid/src/main/jni/react/runtime/cxxreactpackage does not contain a CMakeLists.txt file. ``` ## The Fix Rename CMakeList.txt to CMakeList*s*.txt Changelog: [Internal] Reviewed By: christophpurrer Differential Revision: D51481098 fbshipit-source-id: 32d71f3fdfe0c473f9b30a278603cf1153cd1df8 --- .../runtime/cxxreactpackage/{CMakeList.txt => CMakeLists.txt} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename packages/react-native/ReactAndroid/src/main/jni/react/runtime/cxxreactpackage/{CMakeList.txt => CMakeLists.txt} (100%) diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/runtime/cxxreactpackage/CMakeList.txt b/packages/react-native/ReactAndroid/src/main/jni/react/runtime/cxxreactpackage/CMakeLists.txt similarity index 100% rename from packages/react-native/ReactAndroid/src/main/jni/react/runtime/cxxreactpackage/CMakeList.txt rename to packages/react-native/ReactAndroid/src/main/jni/react/runtime/cxxreactpackage/CMakeLists.txt From 781b637db4268ad7f5f3910d99ebb5203467840b Mon Sep 17 00:00:00 2001 From: Ruslan Shestopalyuk Date: Mon, 20 Nov 2023 18:10:55 -0800 Subject: [PATCH 033/162] Do not filter out Image.source prop when sending it C++ on New Architecture on Android (#41570) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41570 ## Changelog: [Internal] - This fixes a subtle problem whereas an update to `Image.source` (or `Image.src`) prop on JS side may not end up getting propagated to the C++ side, with New Architecture. As the result, this can lead to some weird corner cases, whereas e.g. layout doesn't update after the image's size changes. Differential Revision: D51479305 fbshipit-source-id: 72afb7dfd0ba32f96af4f9a6564b3b8121a597c7 --- .../react-native/Libraries/Image/ImageViewNativeComponent.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/react-native/Libraries/Image/ImageViewNativeComponent.js b/packages/react-native/Libraries/Image/ImageViewNativeComponent.js index c93c6d079eb4cf..01459dddc053d1 100644 --- a/packages/react-native/Libraries/Image/ImageViewNativeComponent.js +++ b/packages/react-native/Libraries/Image/ImageViewNativeComponent.js @@ -90,6 +90,11 @@ export const __INTERNAL_VIEW_CONFIG: PartialViewConfig = borderTopLeftRadius: true, resizeMethod: true, src: true, + // NOTE: New Architecture expects this to be called `source`, + // regardless of the platform, therefore propagate it as well. + // For the backwards compatibility reasons, we keep both `src` + // and `source`, which will be identical at this stage. + source: true, borderRadius: true, headers: true, shouldNotifyLoadEvents: true, From a1b67f955e24071826da6c1f4633c57cdc7df3b2 Mon Sep 17 00:00:00 2001 From: Moti Zilberman Date: Mon, 20 Nov 2023 21:56:41 -0800 Subject: [PATCH 034/162] Handle all incoming Inspector messages on main thread (#41503) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41503 Changelog: [Internal] Updates RCTInspectorPackagerConnection to dispatch all messages on the main thread (which is SocketRocket's default behaviour). This is in support of a new CDP implementation in React Native that will strictly assume it's called on the main thread (thus avoiding the need for explicit locking in many places). Reviewed By: javache Differential Revision: D51346659 fbshipit-source-id: c529b0aea97f7732cea58a4dc66993c5c8259958 --- .../React/Inspector/RCTInspectorPackagerConnection.m | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/packages/react-native/React/Inspector/RCTInspectorPackagerConnection.m b/packages/react-native/React/Inspector/RCTInspectorPackagerConnection.m index ae28f4c7fa5476..07b1b404b5b1bb 100644 --- a/packages/react-native/React/Inspector/RCTInspectorPackagerConnection.m +++ b/packages/react-native/React/Inspector/RCTInspectorPackagerConnection.m @@ -28,7 +28,6 @@ @interface RCTInspectorPackagerConnection () { NSURL *_url; NSMutableDictionary *_inspectorConnections; SRWebSocket *_webSocket; - dispatch_queue_t _jsQueue; BOOL _closed; BOOL _suppressConnectionErrors; RCTBundleStatusProvider _bundleStatusProvider; @@ -57,7 +56,6 @@ - (instancetype)initWithURL:(NSURL *)url if (self = [super init]) { _url = url; _inspectorConnections = [NSMutableDictionary new]; - _jsQueue = dispatch_queue_create("com.facebook.react.WebSocketExecutor", DISPATCH_QUEUE_SERIAL); } return self; } @@ -247,7 +245,6 @@ - (void)connect // timeouts, but our previous class, RCTSRWebSocket didn't have the same // implemented options. Might be worth reinvestigating for SRWebSocket? _webSocket = [[SRWebSocket alloc] initWithURL:_url]; - [_webSocket setDelegateDispatchQueue:_jsQueue]; _webSocket.delegate = self; [_webSocket open]; } @@ -282,7 +279,7 @@ - (void)closeQuietly - (void)sendToPackager:(NSDictionary *)messageObject { __weak RCTInspectorPackagerConnection *weakSelf = self; - dispatch_async(_jsQueue, ^{ + dispatch_async(dispatch_get_main_queue(), ^{ RCTInspectorPackagerConnection *strongSelf = weakSelf; if (strongSelf && !strongSelf->_closed) { NSError *error; From d1e03f56069d43177bb032a6da39080b2bc59bb9 Mon Sep 17 00:00:00 2001 From: Dmitry Rykun Date: Tue, 21 Nov 2023 03:12:08 -0800 Subject: [PATCH 035/162] Refactor generate-artifacts-executor.js: return libraries array instead of using an inout argument (#41531) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41531 This diff converts in-out `libraries` argument of codegen library lookup functions to a normal return value. This makes these functions simpler to reason about, and simplifies subsequent refactors. Changelog: [Internal] Reviewed By: cipolleschi Differential Revision: D51111416 fbshipit-source-id: 12b5dda4d326e3f1c866c16f7bcd17080be54b58 --- .../generate-artifacts-executor-test.js | 28 +-- .../codegen/generate-artifacts-executor.js | 164 ++++++++---------- 2 files changed, 80 insertions(+), 112 deletions(-) diff --git a/packages/react-native/scripts/codegen/__tests__/generate-artifacts-executor-test.js b/packages/react-native/scripts/codegen/__tests__/generate-artifacts-executor-test.js index 6e49f106225100..7a16802296a92d 100644 --- a/packages/react-native/scripts/codegen/__tests__/generate-artifacts-executor-test.js +++ b/packages/react-native/scripts/codegen/__tests__/generate-artifacts-executor-test.js @@ -83,24 +83,16 @@ describe('generateCode', () => { describe('extractLibrariesFromJSON', () => { it('throws if in react-native and no dependencies found', () => { - let libraries = []; let configFile = {}; expect(() => { - underTest._extractLibrariesFromJSON( - configFile, - libraries, - codegenConfigKey, - ); + underTest._extractLibrariesFromJSON(configFile, codegenConfigKey); }).toThrow(); }); it('it skips if not into react-native and no dependencies found', () => { - let libraries = []; let configFile = {}; - - underTest._extractLibrariesFromJSON( + let libraries = underTest._extractLibrariesFromJSON( configFile, - libraries, codegenConfigKey, 'some-node-module', 'node_modules/some', @@ -109,11 +101,9 @@ describe('extractLibrariesFromJSON', () => { }); it('extracts a single dependency when config has no libraries', () => { - let libraries = []; let configFile = fixtures.noLibrariesConfigFile; - underTest._extractLibrariesFromJSON( + let libraries = underTest._extractLibrariesFromJSON( configFile, - libraries, codegenConfigKey, 'my-app', '.', @@ -131,11 +121,9 @@ describe('extractLibrariesFromJSON', () => { it("extract codegenConfig when it's empty", () => { const configFile = {codegenConfig: {libraries: []}}; - let libraries = []; - underTest._extractLibrariesFromJSON( + let libraries = underTest._extractLibrariesFromJSON( configFile, codegenConfigKey, - libraries, reactNativeDependencyName, rootPath, ); @@ -144,10 +132,8 @@ describe('extractLibrariesFromJSON', () => { it('extract codegenConfig when dependency is one', () => { const configFile = fixtures.singleLibraryCodegenConfig; - let libraries = []; - underTest._extractLibrariesFromJSON( + let libraries = underTest._extractLibrariesFromJSON( configFile, - libraries, codegenConfigKey, reactNativeDependencyName, rootPath, @@ -167,10 +153,8 @@ describe('extractLibrariesFromJSON', () => { const configFile = fixtures.multipleLibrariesCodegenConfig; const myDependency = 'my-dependency'; const myDependencyPath = path.join(__dirname, myDependency); - let libraries = []; - underTest._extractLibrariesFromJSON( + let libraries = underTest._extractLibrariesFromJSON( configFile, - libraries, codegenConfigKey, myDependency, myDependencyPath, diff --git a/packages/react-native/scripts/codegen/generate-artifacts-executor.js b/packages/react-native/scripts/codegen/generate-artifacts-executor.js index 9cce4ffab73a0b..9f925f1e29e9d8 100644 --- a/packages/react-native/scripts/codegen/generate-artifacts-executor.js +++ b/packages/react-native/scripts/codegen/generate-artifacts-executor.js @@ -104,21 +104,18 @@ function printDeprecationWarningIfNeeded(dependency) { function extractLibrariesFromConfigurationArray( configFile, codegenConfigKey, - libraries, dependencyPath, ) { - configFile[codegenConfigKey].libraries.forEach(config => { - const libraryConfig = { + return configFile[codegenConfigKey].libraries.map(config => { + return { config, libraryPath: dependencyPath, }; - libraries.push(libraryConfig); }); } function extractLibrariesFromJSON( configFile, - libraries, codegenConfigKey, dependency, dependencyPath, @@ -136,29 +133,29 @@ function extractLibrariesFromJSON( if (isBlocking) { throw `[Codegen] Error: Could not find codegen config for ${dependency} .`; } - return; + return []; } console.log(`[Codegen] Found ${dependency}`); if (configFile[codegenConfigKey].libraries == null) { var config = configFile[codegenConfigKey]; - libraries.push({ - config, - libraryPath: dependencyPath, - }); + return [ + { + config, + libraryPath: dependencyPath, + }, + ]; } else { printDeprecationWarningIfNeeded(dependency); - extractLibrariesFromConfigurationArray( + return extractLibrariesFromConfigurationArray( configFile, codegenConfigKey, - libraries, dependencyPath, ); } } function handleReactNativeCoreLibraries( - libraries, codegenConfigFilename, codegenConfigKey, ) { @@ -173,11 +170,10 @@ function handleReactNativeCoreLibraries( throw '[Codegen] Error: Could not find config file for react-native.'; } const reactNativeConfigFile = JSON.parse(fs.readFileSync(reactNativePkgJson)); - extractLibrariesFromJSON(reactNativeConfigFile, libraries, codegenConfigKey); + return extractLibrariesFromJSON(reactNativeConfigFile, codegenConfigKey); } function handleThirdPartyLibraries( - libraries, baseCodegenConfigFileDir, dependencies, codegenConfigFilename, @@ -192,31 +188,30 @@ function handleThirdPartyLibraries( ); // Handle third-party libraries - Object.keys(dependencies).forEach(dependency => { + return Object.keys(dependencies).flatMap(dependency => { if (dependency === REACT_NATIVE_DEPENDENCY_NAME) { // react-native should already be added. - return; + return []; } const codegenConfigFileDir = path.join(configDir, dependency); const configFilePath = path.join( codegenConfigFileDir, codegenConfigFilename, ); - if (fs.existsSync(configFilePath)) { - const configFile = JSON.parse(fs.readFileSync(configFilePath)); - extractLibrariesFromJSON( - configFile, - libraries, - codegenConfigKey, - dependency, - codegenConfigFileDir, - ); + if (!fs.existsSync(configFilePath)) { + return []; } + const configFile = JSON.parse(fs.readFileSync(configFilePath)); + return extractLibrariesFromJSON( + configFile, + codegenConfigKey, + dependency, + codegenConfigFileDir, + ); }); } function handleLibrariesFromReactNativeConfig( - libraries, codegenConfigKey, codegenConfigFilename, appRootDir, @@ -229,54 +224,51 @@ function handleLibrariesFromReactNativeConfig( const rnConfigFilePath = path.resolve(appRootDir, rnConfigFileName); - if (fs.existsSync(rnConfigFilePath)) { - const rnConfig = require(rnConfigFilePath); - - if (rnConfig.dependencies != null) { - Object.keys(rnConfig.dependencies).forEach(name => { - const dependencyConfig = rnConfig.dependencies[name]; - - if (dependencyConfig.root) { - const codegenConfigFileDir = path.resolve( - appRootDir, - dependencyConfig.root, - ); - const configFilePath = path.join( - codegenConfigFileDir, - codegenConfigFilename, - ); - const pkgJsonPath = path.join(codegenConfigFileDir, 'package.json'); - - if (fs.existsSync(configFilePath)) { - const pkgJson = JSON.parse(fs.readFileSync(pkgJsonPath)); - const configFile = JSON.parse(fs.readFileSync(configFilePath)); - extractLibrariesFromJSON( - configFile, - libraries, - codegenConfigKey, - pkgJson.name, - codegenConfigFileDir, - ); - } - } - }); - } + if (!fs.existsSync(rnConfigFilePath)) { + return []; } + const rnConfig = require(rnConfigFilePath); + + if (rnConfig.dependencies == null) { + return []; + } + return Object.keys(rnConfig.dependencies).flatMap(name => { + const dependencyConfig = rnConfig.dependencies[name]; + + if (!dependencyConfig.root) { + return []; + } + const codegenConfigFileDir = path.resolve( + appRootDir, + dependencyConfig.root, + ); + const configFilePath = path.join( + codegenConfigFileDir, + codegenConfigFilename, + ); + if (!fs.existsSync(configFilePath)) { + return []; + } + const pkgJsonPath = path.join(codegenConfigFileDir, 'package.json'); + const pkgJson = JSON.parse(fs.readFileSync(pkgJsonPath)); + const configFile = JSON.parse(fs.readFileSync(configFilePath)); + + return extractLibrariesFromJSON( + configFile, + codegenConfigKey, + pkgJson.name, + codegenConfigFileDir, + ); + }); } -function handleInAppLibraries( - libraries, - pkgJson, - codegenConfigKey, - appRootDir, -) { +function handleInAppLibraries(pkgJson, codegenConfigKey, appRootDir) { console.log( '\n\n[Codegen] >>>>> Searching for codegen-enabled libraries in the app', ); - extractLibrariesFromJSON( + return extractLibrariesFromJSON( pkgJson, - libraries, codegenConfigKey, pkgJson.name, appRootDir, @@ -433,29 +425,21 @@ function findCodegenEnabledLibraries( ) { const pkgJson = readPackageJSON(appRootDir); const dependencies = {...pkgJson.dependencies, ...pkgJson.devDependencies}; - const libraries = []; - - handleReactNativeCoreLibraries( - libraries, - codegenConfigFilename, - codegenConfigKey, - ); - handleThirdPartyLibraries( - libraries, - baseCodegenConfigFileDir, - dependencies, - codegenConfigFilename, - codegenConfigKey, - ); - handleLibrariesFromReactNativeConfig( - libraries, - codegenConfigKey, - codegenConfigFilename, - appRootDir, - ); - handleInAppLibraries(libraries, pkgJson, codegenConfigKey, appRootDir); - - return libraries; + return [ + ...handleReactNativeCoreLibraries(codegenConfigFilename, codegenConfigKey), + ...handleThirdPartyLibraries( + baseCodegenConfigFileDir, + dependencies, + codegenConfigFilename, + codegenConfigKey, + ), + ...handleLibrariesFromReactNativeConfig( + codegenConfigKey, + codegenConfigFilename, + appRootDir, + ), + ...handleInAppLibraries(pkgJson, codegenConfigKey, appRootDir), + ]; } // It removes all the empty files and empty folders From 33a44e68fc4c53d48a4cf6c62337ffd13a0197ab Mon Sep 17 00:00:00 2001 From: Dmitry Rykun Date: Tue, 21 Nov 2023 03:53:33 -0800 Subject: [PATCH 036/162] Refactor generate-artifacts-executor.js: delete configFilename and configKey arguments (#41533) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41533 This diff removes `configFilename` and `configKey` arguments from iOS codegen CLI. Now we always expect them to be `package.json` and `codegenConfig` respectively. ## Motivation The existing implementation expects every library to have its codegen config in a file with `configFilename` name. `configFilename` is passed as a single CLI argument and applied to every app dependency. I.e. if `configFilename = codegen.config.json` then we expect to find this file in *every* third-party library. That is weird expectation. This customisation option is unsound. Same with `configKey`. It is much simpler to just stick with convention that `configFilename = "package.json"` and `configKey = "codegenConfig"`. Changelog: [General][Breaking] - Delete `configFilename` and `configKey` arguments from iOS codegen CLI. Now we always expect them to be `package.json` and `codegenConfig` respectively. Reviewed By: cipolleschi Differential Revision: D51256486 fbshipit-source-id: fe190b514be7c4e489c7be01294958cf3254602a --- .../generate-artifacts-executor-test.js | 8 +- .../codegen/generate-artifacts-executor.js | 152 +++++------------- .../scripts/generate-codegen-artifacts.js | 29 +--- 3 files changed, 48 insertions(+), 141 deletions(-) diff --git a/packages/react-native/scripts/codegen/__tests__/generate-artifacts-executor-test.js b/packages/react-native/scripts/codegen/__tests__/generate-artifacts-executor-test.js index 7a16802296a92d..fbff6c7ba9c534 100644 --- a/packages/react-native/scripts/codegen/__tests__/generate-artifacts-executor-test.js +++ b/packages/react-native/scripts/codegen/__tests__/generate-artifacts-executor-test.js @@ -16,7 +16,6 @@ const child_process = require('child_process'); const fs = require('fs'); const path = require('path'); -const codegenConfigKey = 'codegenConfig'; const reactNativeDependencyName = 'react-native'; const rootPath = path.join(__dirname, '../../..'); @@ -85,7 +84,7 @@ describe('extractLibrariesFromJSON', () => { it('throws if in react-native and no dependencies found', () => { let configFile = {}; expect(() => { - underTest._extractLibrariesFromJSON(configFile, codegenConfigKey); + underTest._extractLibrariesFromJSON(configFile); }).toThrow(); }); @@ -93,7 +92,6 @@ describe('extractLibrariesFromJSON', () => { let configFile = {}; let libraries = underTest._extractLibrariesFromJSON( configFile, - codegenConfigKey, 'some-node-module', 'node_modules/some', ); @@ -104,7 +102,6 @@ describe('extractLibrariesFromJSON', () => { let configFile = fixtures.noLibrariesConfigFile; let libraries = underTest._extractLibrariesFromJSON( configFile, - codegenConfigKey, 'my-app', '.', ); @@ -123,7 +120,6 @@ describe('extractLibrariesFromJSON', () => { const configFile = {codegenConfig: {libraries: []}}; let libraries = underTest._extractLibrariesFromJSON( configFile, - codegenConfigKey, reactNativeDependencyName, rootPath, ); @@ -134,7 +130,6 @@ describe('extractLibrariesFromJSON', () => { const configFile = fixtures.singleLibraryCodegenConfig; let libraries = underTest._extractLibrariesFromJSON( configFile, - codegenConfigKey, reactNativeDependencyName, rootPath, ); @@ -155,7 +150,6 @@ describe('extractLibrariesFromJSON', () => { const myDependencyPath = path.join(__dirname, myDependency); let libraries = underTest._extractLibrariesFromJSON( configFile, - codegenConfigKey, myDependency, myDependencyPath, ); diff --git a/packages/react-native/scripts/codegen/generate-artifacts-executor.js b/packages/react-native/scripts/codegen/generate-artifacts-executor.js index 9f925f1e29e9d8..bdfbec6c756fb7 100644 --- a/packages/react-native/scripts/codegen/generate-artifacts-executor.js +++ b/packages/react-native/scripts/codegen/generate-artifacts-executor.js @@ -12,8 +12,8 @@ /** * This script crawls through a React Native application's dependencies and invokes the codegen * for any libraries that require it. - * To enable codegen support, the library should include a config in the codegenConfigKey key - * in a codegenConfigFilename file. + * To enable codegen support, the library should include a config in the codegenConfig key + * in a package.json file. */ const {execFileSync, execSync} = require('child_process'); @@ -37,7 +37,7 @@ const CORE_LIBRARIES_WITH_OUTPUT_FOLDER = { rncore: path.join(REACT_NATIVE_PACKAGE_ROOT_FOLDER, 'ReactCommon'), FBReactNativeSpec: null, }; -const REACT_NATIVE_DEPENDENCY_NAME = 'react-native'; +const REACT_NATIVE = 'react-native'; // HELPERS @@ -58,12 +58,16 @@ function isAppRootValid(appRootDir) { return true; } -function readPackageJSON(appRootDir) { - return JSON.parse(fs.readFileSync(path.join(appRootDir, 'package.json'))); +function readPkgJsonInDirectory(dir) { + const pkgJsonPath = path.join(dir, 'package.json'); + if (!fs.existsSync(pkgJsonPath)) { + throw `[Codegen] Error: ${pkgJsonPath} does not exist.`; + } + return JSON.parse(fs.readFileSync(pkgJsonPath)); } function printDeprecationWarningIfNeeded(dependency) { - if (dependency === REACT_NATIVE_DEPENDENCY_NAME) { + if (dependency === REACT_NATIVE) { return; } console.log(`[Codegen] CodegenConfig Deprecated Setup for ${dependency}. @@ -101,12 +105,8 @@ function printDeprecationWarningIfNeeded(dependency) { } // Reading Libraries -function extractLibrariesFromConfigurationArray( - configFile, - codegenConfigKey, - dependencyPath, -) { - return configFile[codegenConfigKey].libraries.map(config => { +function extractLibrariesFromConfigurationArray(configFile, dependencyPath) { + return configFile.codegenConfig.libraries.map(config => { return { config, libraryPath: dependencyPath, @@ -114,22 +114,17 @@ function extractLibrariesFromConfigurationArray( }); } -function extractLibrariesFromJSON( - configFile, - codegenConfigKey, - dependency, - dependencyPath, -) { +function extractLibrariesFromJSON(configFile, dependency, dependencyPath) { var isBlocking = false; if (dependency == null) { - dependency = REACT_NATIVE_DEPENDENCY_NAME; + dependency = REACT_NATIVE; dependencyPath = REACT_NATIVE_PACKAGE_ROOT_FOLDER; // If we are exploring the ReactNative libraries, we want to raise an error // if the codegen is not properly configured. isBlocking = true; } - if (configFile[codegenConfigKey] == null) { + if (configFile.codegenConfig == null) { if (isBlocking) { throw `[Codegen] Error: Could not find codegen config for ${dependency} .`; } @@ -137,8 +132,8 @@ function extractLibrariesFromJSON( } console.log(`[Codegen] Found ${dependency}`); - if (configFile[codegenConfigKey].libraries == null) { - var config = configFile[codegenConfigKey]; + if (configFile.codegenConfig.libraries == null) { + const config = configFile.codegenConfig; return [ { config, @@ -147,38 +142,20 @@ function extractLibrariesFromJSON( ]; } else { printDeprecationWarningIfNeeded(dependency); - return extractLibrariesFromConfigurationArray( - configFile, - codegenConfigKey, - dependencyPath, - ); + return extractLibrariesFromConfigurationArray(configFile, dependencyPath); } } -function handleReactNativeCoreLibraries( - codegenConfigFilename, - codegenConfigKey, -) { +function handleReactNativeCoreLibraries() { // Handle react-native core libraries. // This is required when react-native is outside of node_modules. console.log('[Codegen] Processing react-native core libraries'); - const reactNativePkgJson = path.join( - REACT_NATIVE_PACKAGE_ROOT_FOLDER, - codegenConfigFilename, + return extractLibrariesFromJSON( + readPkgJsonInDirectory(REACT_NATIVE_PACKAGE_ROOT_FOLDER), ); - if (!fs.existsSync(reactNativePkgJson)) { - throw '[Codegen] Error: Could not find config file for react-native.'; - } - const reactNativeConfigFile = JSON.parse(fs.readFileSync(reactNativePkgJson)); - return extractLibrariesFromJSON(reactNativeConfigFile, codegenConfigKey); } -function handleThirdPartyLibraries( - baseCodegenConfigFileDir, - dependencies, - codegenConfigFilename, - codegenConfigKey, -) { +function handleThirdPartyLibraries(baseCodegenConfigFileDir, dependencies) { // Determine which of these are codegen-enabled libraries const configDir = baseCodegenConfigFileDir || @@ -189,33 +166,25 @@ function handleThirdPartyLibraries( // Handle third-party libraries return Object.keys(dependencies).flatMap(dependency => { - if (dependency === REACT_NATIVE_DEPENDENCY_NAME) { + if (dependency === REACT_NATIVE) { // react-native should already be added. return []; } - const codegenConfigFileDir = path.join(configDir, dependency); - const configFilePath = path.join( - codegenConfigFileDir, - codegenConfigFilename, - ); - if (!fs.existsSync(configFilePath)) { + let configFile; + try { + configFile = readPkgJsonInDirectory(codegenConfigFileDir); + } catch { return []; } - const configFile = JSON.parse(fs.readFileSync(configFilePath)); return extractLibrariesFromJSON( configFile, - codegenConfigKey, dependency, codegenConfigFileDir, ); }); } -function handleLibrariesFromReactNativeConfig( - codegenConfigKey, - codegenConfigFilename, - appRootDir, -) { +function handleLibrariesFromReactNativeConfig(appRootDir) { const rnConfigFileName = 'react-native.config.js'; console.log( @@ -242,37 +211,27 @@ function handleLibrariesFromReactNativeConfig( appRootDir, dependencyConfig.root, ); - const configFilePath = path.join( - codegenConfigFileDir, - codegenConfigFilename, - ); - if (!fs.existsSync(configFilePath)) { + let configFile; + try { + configFile = readPkgJsonInDirectory(codegenConfigFileDir); + } catch { return []; } - const pkgJsonPath = path.join(codegenConfigFileDir, 'package.json'); - const pkgJson = JSON.parse(fs.readFileSync(pkgJsonPath)); - const configFile = JSON.parse(fs.readFileSync(configFilePath)); return extractLibrariesFromJSON( configFile, - codegenConfigKey, - pkgJson.name, + configFile.name, codegenConfigFileDir, ); }); } -function handleInAppLibraries(pkgJson, codegenConfigKey, appRootDir) { +function handleInAppLibraries(pkgJson, appRootDir) { console.log( '\n\n[Codegen] >>>>> Searching for codegen-enabled libraries in the app', ); - return extractLibrariesFromJSON( - pkgJson, - codegenConfigKey, - pkgJson.name, - appRootDir, - ); + return extractLibrariesFromJSON(pkgJson, pkgJson.name, appRootDir); } // CodeGen @@ -417,28 +376,14 @@ function createComponentProvider(schemaPaths, node) { console.log(`Generated provider in: ${outputDir}`); } -function findCodegenEnabledLibraries( - appRootDir, - baseCodegenConfigFileDir, - codegenConfigFilename, - codegenConfigKey, -) { - const pkgJson = readPackageJSON(appRootDir); +function findCodegenEnabledLibraries(appRootDir, baseCodegenConfigFileDir) { + const pkgJson = readPkgJsonInDirectory(appRootDir); const dependencies = {...pkgJson.dependencies, ...pkgJson.devDependencies}; return [ - ...handleReactNativeCoreLibraries(codegenConfigFilename, codegenConfigKey), - ...handleThirdPartyLibraries( - baseCodegenConfigFileDir, - dependencies, - codegenConfigFilename, - codegenConfigKey, - ), - ...handleLibrariesFromReactNativeConfig( - codegenConfigKey, - codegenConfigFilename, - appRootDir, - ), - ...handleInAppLibraries(pkgJson, codegenConfigKey, appRootDir), + ...handleReactNativeCoreLibraries(), + ...handleThirdPartyLibraries(baseCodegenConfigFileDir, dependencies), + ...handleLibrariesFromReactNativeConfig(appRootDir), + ...handleInAppLibraries(pkgJson, appRootDir), ]; } @@ -484,24 +429,15 @@ function cleanupEmptyFilesAndFolders(filepath) { * - setups the CLI to generate the code * - generate the code * - * @parameter appRootDir: the directory with the app source code, where the `codegenConfigFilename` lives. + * @parameter appRootDir: the directory with the app source code, where the package.json lives. * @parameter outputPath: the base output path for the CodeGen. * @parameter node: the path to the node executable, used to run the codegen scripts. - * @parameter codegenConfigFilename: the file that contains the codeGen configuration. The default is `package.json`. - * @parameter codegenConfigKey: the key in the codegenConfigFile that controls the codegen. * @parameter baseCodegenConfigFileDir: the directory of the codeGenConfigFile. * @throws If it can't find a config file for react-native. * @throws If it can't find a CodeGen configuration in the file. * @throws If it can't find a cli for the CodeGen. */ -function execute( - appRootDir, - outputPath, - node, - codegenConfigFilename, - codegenConfigKey, - baseCodegenConfigFileDir, -) { +function execute(appRootDir, outputPath, node, baseCodegenConfigFileDir) { if (!isAppRootValid(appRootDir)) { return; } @@ -510,8 +446,6 @@ function execute( const libraries = findCodegenEnabledLibraries( appRootDir, baseCodegenConfigFileDir, - codegenConfigFilename, - codegenConfigKey, ); if (libraries.length === 0) { diff --git a/packages/react-native/scripts/generate-codegen-artifacts.js b/packages/react-native/scripts/generate-codegen-artifacts.js index a73538a788b9d3..91994044a17abf 100644 --- a/packages/react-native/scripts/generate-codegen-artifacts.js +++ b/packages/react-native/scripts/generate-codegen-artifacts.js @@ -21,17 +21,6 @@ const argv = yargs alias: 'outputPath', description: 'Path where generated artifacts will be output to', }) - .option('f', { - alias: 'configFilename', - default: 'package.json', - description: 'The file that contains the codegen configuration.', - }) - .option('k', { - alias: 'configKey', - default: 'codegenConfig', - description: - 'The key that contains the codegen configuration in the config file.', - }) .option('c', { alias: 'configFileDir', default: '', @@ -46,19 +35,9 @@ const argv = yargs .usage('Usage: $0 -p [path to app]') .demandOption(['p']).argv; -const CODEGEN_CONFIG_FILENAME = argv.f; -const CODEGEN_CONFIG_FILE_DIR = argv.c; -const CODEGEN_CONFIG_KEY = argv.k; -const NODE = argv.n; - -const appRoot = argv.path; -const outputPath = argv.outputPath; - executor.execute( - appRoot, - outputPath, - NODE, - CODEGEN_CONFIG_FILENAME, - CODEGEN_CONFIG_KEY, - CODEGEN_CONFIG_FILE_DIR, + argv.path, + argv.outputPath, + argv.nodeBinary, + argv.configFileDir, ); From ce0dabddf369587311198290b5bfc8e058a39a28 Mon Sep 17 00:00:00 2001 From: Ruslan Shestopalyuk Date: Tue, 21 Nov 2023 05:14:14 -0800 Subject: [PATCH 037/162] Extract ImageSize type from NativeImageLoader interface (re-submit) (#41577) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41577 # Changelog: [Internal]- The change is equivalent in terms of API, however this makes it work nicer with C++ codegen and easier to use with a pure C++ implementation of the native module. Reviewed By: GijsWeterings Differential Revision: D51493466 fbshipit-source-id: bf9105670ae56a191ab2e6c8cfb794c2fecd4809 --- .../Image/NativeImageLoaderAndroid.js | 23 +++++++------------ 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/packages/react-native/Libraries/Image/NativeImageLoaderAndroid.js b/packages/react-native/Libraries/Image/NativeImageLoaderAndroid.js index 121de3bc99e3de..8576e47b4e05f6 100644 --- a/packages/react-native/Libraries/Image/NativeImageLoaderAndroid.js +++ b/packages/react-native/Libraries/Image/NativeImageLoaderAndroid.js @@ -12,24 +12,17 @@ import type {TurboModule} from '../TurboModule/RCTExport'; import * as TurboModuleRegistry from '../TurboModule/TurboModuleRegistry'; +export type ImageSize = { + width: number, + height: number, + ... +}; + export interface Spec extends TurboModule { +abortRequest: (requestId: number) => void; +getConstants: () => {||}; - +getSize: (uri: string) => Promise< - $ReadOnly<{ - width: number, - height: number, - ... - }>, - >; - +getSizeWithHeaders: ( - uri: string, - headers: Object, - ) => Promise<{ - width: number, - height: number, - ... - }>; + +getSize: (uri: string) => Promise; + +getSizeWithHeaders: (uri: string, headers: Object) => Promise; +prefetchImage: (uri: string, requestId: number) => Promise; +queryCache: (uris: Array) => Promise; } From b58cba7ef213766dcc14fb5c12de66ec0da0e7ac Mon Sep 17 00:00:00 2001 From: Moti Zilberman Date: Tue, 21 Nov 2023 07:06:22 -0800 Subject: [PATCH 038/162] Rename JSEngineInstance -> JSRuntimeFactory (#41548) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41548 `JSEngineInstance` is a misnomer - this interface actually creates `jsi::Runtime`s and doesn't represent an "instance of a JS engine". This diff renames it to `JSRuntimeFactory`. Changelog: [Internal] Reviewed By: huntie, arushikesarwani94 Differential Revision: D51447882 fbshipit-source-id: e118fe5c202607500a62d8e15afec088c4946969 --- .../Libraries/AppDelegate/RCTAppDelegate.mm | 8 ++++---- .../com/facebook/react/defaults/DefaultReactHost.kt | 4 ++-- .../react/defaults/DefaultReactHostDelegate.kt | 6 +++--- .../java/com/facebook/react/runtime/JSCInstance.java | 2 +- .../{JSEngineInstance.java => JSRuntimeFactory.java} | 4 ++-- .../com/facebook/react/runtime/ReactHostDelegate.kt | 4 ++-- .../java/com/facebook/react/runtime/ReactInstance.java | 6 +++--- .../facebook/react/runtime/hermes/HermesInstance.kt | 4 ++-- .../jni/react/runtime/hermes/jni/JHermesInstance.h | 6 +++--- .../jni/{JJSEngineInstance.h => JJSRuntimeFactory.h} | 8 ++++---- .../src/main/jni/react/runtime/jni/JReactInstance.cpp | 8 ++++---- .../src/main/jni/react/runtime/jni/JReactInstance.h | 8 ++++---- .../src/main/jni/react/runtime/jsc/jni/OnLoad.cpp | 6 +++--- .../facebook/react/runtime/ReactHostDelegateTest.kt | 4 ++-- .../runtime/{JSEngineInstance.h => JSRuntimeFactory.h} | 6 +++--- .../ReactCommon/react/runtime/iostests/RCTHostTests.mm | 2 +- .../platform/ios/ReactCommon/RCTHermesInstance.h | 4 ++-- .../react/runtime/platform/ios/ReactCommon/RCTHost.h | 4 ++-- .../react/runtime/platform/ios/ReactCommon/RCTHost.mm | 8 ++++---- .../runtime/platform/ios/ReactCommon/RCTInstance.h | 4 ++-- .../runtime/platform/ios/ReactCommon/RCTInstance.mm | 10 +++++----- .../runtime/platform/ios/ReactCommon/RCTJscInstance.h | 4 ++-- .../react/test_utils/ios/Shims/ShimRCTInstance.mm | 6 +++--- 23 files changed, 63 insertions(+), 63 deletions(-) rename packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/{JSEngineInstance.java => JSRuntimeFactory.java} (85%) rename packages/react-native/ReactAndroid/src/main/jni/react/runtime/jni/{JJSEngineInstance.h => JJSRuntimeFactory.h} (64%) rename packages/react-native/ReactCommon/react/runtime/{JSEngineInstance.h => JSRuntimeFactory.h} (79%) diff --git a/packages/react-native/Libraries/AppDelegate/RCTAppDelegate.mm b/packages/react-native/Libraries/AppDelegate/RCTAppDelegate.mm index b2982786800026..3f3bb759ba63e8 100644 --- a/packages/react-native/Libraries/AppDelegate/RCTAppDelegate.mm +++ b/packages/react-native/Libraries/AppDelegate/RCTAppDelegate.mm @@ -38,7 +38,7 @@ #import #import #import -#import +#import static NSString *const kRNConcurrentRoot = @"concurrentRoot"; @@ -293,8 +293,8 @@ - (void)createReactHost _reactHost = [[RCTHost alloc] initWithBundleURL:[self bundleURL] hostDelegate:nil turboModuleManagerDelegate:self - jsEngineProvider:^std::shared_ptr() { - return [weakSelf createJSEngineInstance]; + jsEngineProvider:^std::shared_ptr() { + return [weakSelf createJSRuntimeFactory]; }]; [_reactHost setBundleURLProvider:^NSURL *() { return [weakSelf bundleURL]; @@ -303,7 +303,7 @@ - (void)createReactHost [_reactHost start]; } -- (std::shared_ptr)createJSEngineInstance +- (std::shared_ptr)createJSRuntimeFactory { #if RCT_USE_HERMES return std::make_shared(_reactNativeConfig, nullptr); diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultReactHost.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultReactHost.kt index d481e33c0bd1d9..9a102597199dc1 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultReactHost.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultReactHost.kt @@ -54,13 +54,13 @@ object DefaultReactHost { if (reactHost == null) { val jsBundleLoader = JSBundleLoader.createAssetLoader(context, "assets://$jsBundleAssetPath", true) - val jsEngineInstance = if (isHermesEnabled) HermesInstance() else JSCInstance() + val jsRuntimeFactory = if (isHermesEnabled) HermesInstance() else JSCInstance() val defaultReactHostDelegate = DefaultReactHostDelegate( jsMainModulePath = jsMainModulePath, jsBundleLoader = jsBundleLoader, reactPackages = packageList, - jsEngineInstance = jsEngineInstance, + jsRuntimeFactory = jsRuntimeFactory, turboModuleManagerDelegateBuilder = DefaultTurboModuleManagerDelegate.Builder()) val reactJsExceptionHandler = ReactJsExceptionHandler { _ -> } val componentFactory = ComponentFactory() diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultReactHostDelegate.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultReactHostDelegate.kt index 7221334217754f..40529ef869842e 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultReactHostDelegate.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultReactHostDelegate.kt @@ -14,7 +14,7 @@ import com.facebook.react.bridge.JSBundleLoader import com.facebook.react.common.annotations.UnstableReactNativeAPI import com.facebook.react.fabric.ReactNativeConfig import com.facebook.react.runtime.BindingsInstaller -import com.facebook.react.runtime.JSEngineInstance +import com.facebook.react.runtime.JSRuntimeFactory import com.facebook.react.runtime.ReactHostDelegate import com.facebook.react.runtime.hermes.HermesInstance @@ -28,7 +28,7 @@ import com.facebook.react.runtime.hermes.HermesInstance * @param jsBundleLoader Bundle loader to use when setting up JS environment.

Example: * [JSBundleLoader.createFileLoader(application, bundleFile)] * @param reactPackages list of reactPackages to expose Native Modules and View Components to JS - * @param jsEngineInstance Object that holds a native reference to the javascript engine + * @param jsRuntimeFactory Object that holds a native reference to the JS Runtime factory * @param bindingsInstaller Object that holds a native C++ references that allow host applications * to install C++ objects into jsi::Runtime during the initialization of React Native * @param reactNativeConfig ReactNative Configuration that allows to customize the behavior of @@ -42,7 +42,7 @@ class DefaultReactHostDelegate( override val jsMainModulePath: String, override val jsBundleLoader: JSBundleLoader, override val reactPackages: List = emptyList(), - override val jsEngineInstance: JSEngineInstance = HermesInstance(), + override val jsRuntimeFactory: JSRuntimeFactory = HermesInstance(), override val bindingsInstaller: BindingsInstaller = DefaultBindingsInstaller(), private val reactNativeConfig: ReactNativeConfig = ReactNativeConfig.DEFAULT_CONFIG, private val exceptionHandler: (Exception) -> Unit = {}, diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/JSCInstance.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/JSCInstance.java index 8fb32073cfafed..0524c58eac2312 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/JSCInstance.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/JSCInstance.java @@ -13,7 +13,7 @@ import com.facebook.soloader.SoLoader; @Nullsafe(Nullsafe.Mode.LOCAL) -public class JSCInstance extends JSEngineInstance { +public class JSCInstance extends JSRuntimeFactory { static { SoLoader.loadLibrary("jscinstance"); } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/JSEngineInstance.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/JSRuntimeFactory.java similarity index 85% rename from packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/JSEngineInstance.java rename to packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/JSRuntimeFactory.java index 708e71676641d3..83d3e9f841a801 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/JSEngineInstance.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/JSRuntimeFactory.java @@ -13,14 +13,14 @@ import com.facebook.soloader.SoLoader; @Nullsafe(Nullsafe.Mode.LOCAL) -public abstract class JSEngineInstance { +public abstract class JSRuntimeFactory { static { SoLoader.loadLibrary("rninstance"); } @DoNotStrip private final HybridData mHybridData; - protected JSEngineInstance(HybridData hybridData) { + protected JSRuntimeFactory(HybridData hybridData) { mHybridData = hybridData; } } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostDelegate.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostDelegate.kt index a26880fc71df4b..6b9f71d1f6f02f 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostDelegate.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostDelegate.kt @@ -38,7 +38,7 @@ interface ReactHostDelegate { val reactPackages: List /** Object that holds a native reference to the javascript engine */ - val jsEngineInstance: JSEngineInstance + val jsRuntimeFactory: JSRuntimeFactory /** * Bundle loader to use when setting up JS environment.

Example: @@ -68,7 +68,7 @@ interface ReactHostDelegate { class ReactHostDelegateBase( override val jsMainModulePath: String, override val jsBundleLoader: JSBundleLoader, - override val jsEngineInstance: JSEngineInstance, + override val jsRuntimeFactory: JSRuntimeFactory, override val turboModuleManagerDelegateBuilder: ReactPackageTurboModuleManagerDelegate.Builder, override val reactPackages: List = emptyList(), diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactInstance.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactInstance.java index 8d1b0a52137571..e5e36fe7709deb 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactInstance.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactInstance.java @@ -167,7 +167,7 @@ public void onHostDestroy() { } }); - JSEngineInstance jsEngineInstance = mDelegate.getJsEngineInstance(); + JSRuntimeFactory jsRuntimeFactory = mDelegate.getJsRuntimeFactory(); BindingsInstaller bindingsInstaller = mDelegate.getBindingsInstaller(); // Notify JS if profiling is enabled boolean isProfiling = @@ -177,7 +177,7 @@ public void onHostDestroy() { boolean useModernRuntimeScheduler = ReactFeatureFlags.useModernRuntimeScheduler; mHybridData = initHybrid( - jsEngineInstance, + jsRuntimeFactory, jsMessageQueueThread, nativeModulesMessageQueueThread, mJavaTimerManager, @@ -432,7 +432,7 @@ public Collection getNativeModules() { @DoNotStrip private native HybridData initHybrid( - JSEngineInstance jsEngineInstance, + JSRuntimeFactory jsRuntimeFactory, MessageQueueThread jsMessageQueueThread, MessageQueueThread nativeModulesMessageQueueThread, JavaTimerManager timerManager, diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/hermes/HermesInstance.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/hermes/HermesInstance.kt index 7c96e99b6a5c4e..e20bc7ca0b474e 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/hermes/HermesInstance.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/hermes/HermesInstance.kt @@ -10,11 +10,11 @@ package com.facebook.react.runtime.hermes import com.facebook.jni.HybridData import com.facebook.jni.annotations.DoNotStrip import com.facebook.react.fabric.ReactNativeConfig -import com.facebook.react.runtime.JSEngineInstance +import com.facebook.react.runtime.JSRuntimeFactory import com.facebook.soloader.SoLoader class HermesInstance constructor(reactNativeConfig: ReactNativeConfig?) : - JSEngineInstance(initHybrid(reactNativeConfig as Any?)) { + JSRuntimeFactory(initHybrid(reactNativeConfig as Any?)) { constructor() : this(null) diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/runtime/hermes/jni/JHermesInstance.h b/packages/react-native/ReactAndroid/src/main/jni/react/runtime/hermes/jni/JHermesInstance.h index 9d500aaa3c3c30..abc417cc065433 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/runtime/hermes/jni/JHermesInstance.h +++ b/packages/react-native/ReactAndroid/src/main/jni/react/runtime/hermes/jni/JHermesInstance.h @@ -14,14 +14,14 @@ #include #include #include -#include +#include #include -#include "../../jni/JJSEngineInstance.h" +#include "../../jni/JJSRuntimeFactory.h" namespace facebook::react { class JHermesInstance - : public jni::HybridClass { + : public jni::HybridClass { public: static constexpr auto kJavaDescriptor = "Lcom/facebook/react/runtime/hermes/HermesInstance;"; diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/runtime/jni/JJSEngineInstance.h b/packages/react-native/ReactAndroid/src/main/jni/react/runtime/jni/JJSRuntimeFactory.h similarity index 64% rename from packages/react-native/ReactAndroid/src/main/jni/react/runtime/jni/JJSEngineInstance.h rename to packages/react-native/ReactAndroid/src/main/jni/react/runtime/jni/JJSRuntimeFactory.h index 06619c451c6805..03c312cd378dbc 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/runtime/jni/JJSEngineInstance.h +++ b/packages/react-native/ReactAndroid/src/main/jni/react/runtime/jni/JJSRuntimeFactory.h @@ -9,15 +9,15 @@ #include #include -#include +#include namespace facebook::react { -class JJSEngineInstance : public jni::HybridClass, - public JSEngineInstance { +class JJSRuntimeFactory : public jni::HybridClass, + public JSRuntimeFactory { public: static auto constexpr kJavaDescriptor = - "Lcom/facebook/react/runtime/JSEngineInstance;"; + "Lcom/facebook/react/runtime/JSRuntimeFactory;"; private: friend HybridBase; diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/runtime/jni/JReactInstance.cpp b/packages/react-native/ReactAndroid/src/main/jni/react/runtime/jni/JReactInstance.cpp index 325c3c32d0646d..09a46dc4e58c90 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/runtime/jni/JReactInstance.cpp +++ b/packages/react-native/ReactAndroid/src/main/jni/react/runtime/jni/JReactInstance.cpp @@ -29,7 +29,7 @@ namespace facebook::react { JReactInstance::JReactInstance( - jni::alias_ref jsEngineInstance, + jni::alias_ref jsRuntimeFactory, jni::alias_ref jsMessageQueueThread, jni::alias_ref nativeMessageQueueThread, jni::alias_ref javaTimerManager, @@ -62,7 +62,7 @@ JReactInstance::JReactInstance( jBindingsInstaller_ = jni::make_global(jBindingsInstaller); instance_ = std::make_unique( - jsEngineInstance->cthis()->createJSRuntime(sharedJSMessageQueueThread), + jsRuntimeFactory->cthis()->createJSRuntime(sharedJSMessageQueueThread), sharedJSMessageQueueThread, timerManager, std::move(jsErrorHandlingFunc), @@ -110,7 +110,7 @@ JReactInstance::JReactInstance( jni::local_ref JReactInstance::initHybrid( jni::alias_ref /* unused */, - jni::alias_ref jsEngineInstance, + jni::alias_ref jsRuntimeFactory, jni::alias_ref jsMessageQueueThread, jni::alias_ref nativeMessageQueueThread, jni::alias_ref javaTimerManager, @@ -120,7 +120,7 @@ jni::local_ref JReactInstance::initHybrid( bool isProfiling, bool useModernRuntimeScheduler) { return makeCxxInstance( - jsEngineInstance, + jsRuntimeFactory, jsMessageQueueThread, nativeMessageQueueThread, javaTimerManager, diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/runtime/jni/JReactInstance.h b/packages/react-native/ReactAndroid/src/main/jni/react/runtime/jni/JReactInstance.h index 0fd9a28a438a28..41ea4891bd50bf 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/runtime/jni/JReactInstance.h +++ b/packages/react-native/ReactAndroid/src/main/jni/react/runtime/jni/JReactInstance.h @@ -18,12 +18,12 @@ #include #include #include -#include +#include #include #include #include "JBindingsInstaller.h" -#include "JJSEngineInstance.h" +#include "JJSRuntimeFactory.h" #include "JJSTimerExecutor.h" #include "JJavaTimerManager.h" #include "JReactExceptionManager.h" @@ -37,7 +37,7 @@ class JReactInstance : public jni::HybridClass { static jni::local_ref initHybrid( jni::alias_ref, - jni::alias_ref jsEngineInstance, + jni::alias_ref jsRuntimeFactory, jni::alias_ref jsMessageQueueThread, jni::alias_ref nativeMessageQueueThread, @@ -83,7 +83,7 @@ class JReactInstance : public jni::HybridClass { friend HybridBase; explicit JReactInstance( - jni::alias_ref jsEngineInstance, + jni::alias_ref jsRuntimeFactory, jni::alias_ref jsMessageQueueThread, jni::alias_ref nativeMessageQueueThread, diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/runtime/jsc/jni/OnLoad.cpp b/packages/react-native/ReactAndroid/src/main/jni/react/runtime/jsc/jni/OnLoad.cpp index 02e384cac712dd..068e02b41b8767 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/runtime/jsc/jni/OnLoad.cpp +++ b/packages/react-native/ReactAndroid/src/main/jni/react/runtime/jsc/jni/OnLoad.cpp @@ -10,12 +10,12 @@ #include #include #include -#include -#include +#include +#include namespace facebook::react { -class JSCInstance : public jni::HybridClass { +class JSCInstance : public jni::HybridClass { public: static constexpr auto kJavaDescriptor = "Lcom/facebook/react/runtime/JSCInstance;"; diff --git a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/runtime/ReactHostDelegateTest.kt b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/runtime/ReactHostDelegateTest.kt index 33932b8a87bf34..0407c0ae127f25 100644 --- a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/runtime/ReactHostDelegateTest.kt +++ b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/runtime/ReactHostDelegateTest.kt @@ -34,13 +34,13 @@ class ReactHostDelegateTest { val jsBundleLoader: JSBundleLoader = Mockito.mock(JSBundleLoader::class.java) val turboModuleManagerDelegateBuilderMock: ReactPackageTurboModuleManagerDelegate.Builder = Mockito.mock(ReactPackageTurboModuleManagerDelegate.Builder::class.java) - val hermesInstance: JSEngineInstance = Mockito.mock(HermesInstance::class.java) + val hermesInstance: JSRuntimeFactory = Mockito.mock(HermesInstance::class.java) val jsMainModulePathMocked = "mockedJSMainModulePath" val delegate = DefaultReactHostDelegate( jsMainModulePath = jsMainModulePathMocked, jsBundleLoader = jsBundleLoader, - jsEngineInstance = hermesInstance, + jsRuntimeFactory = hermesInstance, turboModuleManagerDelegateBuilder = turboModuleManagerDelegateBuilderMock) assertThat(delegate.jsMainModulePath).isEqualTo(jsMainModulePathMocked) diff --git a/packages/react-native/ReactCommon/react/runtime/JSEngineInstance.h b/packages/react-native/ReactCommon/react/runtime/JSRuntimeFactory.h similarity index 79% rename from packages/react-native/ReactCommon/react/runtime/JSEngineInstance.h rename to packages/react-native/ReactCommon/react/runtime/JSRuntimeFactory.h index 30cf7025c96eaf..431a2930650444 100644 --- a/packages/react-native/ReactCommon/react/runtime/JSEngineInstance.h +++ b/packages/react-native/ReactCommon/react/runtime/JSRuntimeFactory.h @@ -14,14 +14,14 @@ namespace facebook::react { /** - * Interface for a class that creates and owns an instance of a JS VM + * Interface for a class that creates instances of a JS VM */ -class JSEngineInstance { +class JSRuntimeFactory { public: virtual std::unique_ptr createJSRuntime( std::shared_ptr msgQueueThread) noexcept = 0; - virtual ~JSEngineInstance() = default; + virtual ~JSRuntimeFactory() = default; }; } // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/runtime/iostests/RCTHostTests.mm b/packages/react-native/ReactCommon/react/runtime/iostests/RCTHostTests.mm index 606d2d9dabd1f1..de2e016b95afc4 100644 --- a/packages/react-native/ReactCommon/react/runtime/iostests/RCTHostTests.mm +++ b/packages/react-native/ReactCommon/react/runtime/iostests/RCTHostTests.mm @@ -56,7 +56,7 @@ - (void)setUp _subject = [[RCTHost alloc] initWithBundleURL:OCMClassMock([NSURL class]) hostDelegate:_mockHostDelegate turboModuleManagerDelegate:OCMProtocolMock(@protocol(RCTTurboModuleManagerDelegate)) - jsEngineProvider:^std::shared_ptr() { + jsEngineProvider:^std::shared_ptr() { return std::make_shared(); }]; } diff --git a/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTHermesInstance.h b/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTHermesInstance.h index 0f3722443945dc..d811aa6335652d 100644 --- a/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTHermesInstance.h +++ b/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTHermesInstance.h @@ -10,7 +10,7 @@ #import #import #import -#import +#import #import namespace facebook { @@ -19,7 +19,7 @@ using CrashManagerProvider = std::function()>; // ObjC++ wrapper for HermesInstance.cpp -class RCTHermesInstance : public JSEngineInstance { +class RCTHermesInstance : public JSRuntimeFactory { public: RCTHermesInstance(); RCTHermesInstance( diff --git a/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTHost.h b/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTHost.h index 3dc528f8a506ec..124504a638f997 100644 --- a/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTHost.h +++ b/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTHost.h @@ -9,7 +9,7 @@ #import #import -#import +#import #import "RCTInstance.h" @@ -53,7 +53,7 @@ NS_ASSUME_NONNULL_BEGIN @end -typedef std::shared_ptr (^RCTHostJSEngineProvider)(void); +typedef std::shared_ptr (^RCTHostJSEngineProvider)(void); @interface RCTHost : NSObject diff --git a/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTHost.mm b/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTHost.mm index 53ddc5cab4368b..64daf56c38d7be 100644 --- a/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTHost.mm +++ b/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTHost.mm @@ -147,7 +147,7 @@ - (void)start [_instance invalidate]; } _instance = [[RCTInstance alloc] initWithDelegate:self - jsEngineInstance:[self _provideJSEngine] + jsRuntimeFactory:[self _provideJSEngine] bundleManager:_bundleManager turboModuleManagerDelegate:_turboModuleManagerDelegate onInitialBundleLoad:_onInitialBundleLoad @@ -214,7 +214,7 @@ - (void)didReceiveReloadCommand } _instance = [[RCTInstance alloc] initWithDelegate:self - jsEngineInstance:[self _provideJSEngine] + jsRuntimeFactory:[self _provideJSEngine] bundleManager:_bundleManager turboModuleManagerDelegate:_turboModuleManagerDelegate onInitialBundleLoad:_onInitialBundleLoad @@ -301,10 +301,10 @@ - (void)_attachSurface:(RCTFabricSurface *)surface return surfaces; } -- (std::shared_ptr)_provideJSEngine +- (std::shared_ptr)_provideJSEngine { RCTAssert(_jsEngineProvider, @"_jsEngineProvider must be non-nil"); - std::shared_ptr jsEngine = _jsEngineProvider(); + std::shared_ptr jsEngine = _jsEngineProvider(); RCTAssert(jsEngine != nullptr, @"_jsEngineProvider must return a nonnull pointer"); return jsEngine; diff --git a/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTInstance.h b/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTInstance.h index 79e9ff50e2e9ee..047dc38af97774 100644 --- a/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTInstance.h +++ b/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTInstance.h @@ -9,7 +9,7 @@ #import #import -#import +#import #import #import "RCTContextContainerHandling.h" @@ -68,7 +68,7 @@ typedef void (^_Null_unspecified RCTInstanceInitialBundleLoadCompletionBlock)(); @interface RCTInstance : NSObject - (instancetype)initWithDelegate:(id)delegate - jsEngineInstance:(std::shared_ptr)jsEngineInstance + jsRuntimeFactory:(std::shared_ptr)jsRuntimeFactory bundleManager:(RCTBundleManager *)bundleManager turboModuleManagerDelegate:(id)turboModuleManagerDelegate onInitialBundleLoad:(RCTInstanceInitialBundleLoadCompletionBlock)onInitialBundleLoad diff --git a/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTInstance.mm b/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTInstance.mm index bf5bd8fe6ba42d..6ed73ed4d85814 100644 --- a/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTInstance.mm +++ b/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTInstance.mm @@ -67,7 +67,7 @@ @interface RCTInstance () @implementation RCTInstance { std::unique_ptr _reactInstance; - std::shared_ptr _jsEngineInstance; + std::shared_ptr _jsRuntimeFactory; __weak id _appTMMDelegate; __weak id _delegate; RCTSurfacePresenter *_surfacePresenter; @@ -86,7 +86,7 @@ @implementation RCTInstance { #pragma mark - Public - (instancetype)initWithDelegate:(id)delegate - jsEngineInstance:(std::shared_ptr)jsEngineInstance + jsRuntimeFactory:(std::shared_ptr)jsRuntimeFactory bundleManager:(RCTBundleManager *)bundleManager turboModuleManagerDelegate:(id)tmmDelegate onInitialBundleLoad:(RCTInstanceInitialBundleLoadCompletionBlock)onInitialBundleLoad @@ -98,7 +98,7 @@ - (instancetype)initWithDelegate:(id)delegate [_performanceLogger markStartForTag:RCTPLReactInstanceInit]; _delegate = delegate; - _jsEngineInstance = jsEngineInstance; + _jsRuntimeFactory = jsRuntimeFactory; _appTMMDelegate = tmmDelegate; _jsThreadManager = [RCTJSThreadManager new]; _onInitialBundleLoad = onInitialBundleLoad; @@ -149,7 +149,7 @@ - (void)invalidate // Clean up all the Resources self->_reactInstance = nullptr; - self->_jsEngineInstance = nullptr; + self->_jsRuntimeFactory = nullptr; self->_appTMMDelegate = nil; self->_delegate = nil; self->_displayLink = nil; @@ -223,7 +223,7 @@ - (void)_start // Create the React Instance _reactInstance = std::make_unique( - _jsEngineInstance->createJSRuntime(_jsThreadManager.jsMessageThread), + _jsRuntimeFactory->createJSRuntime(_jsThreadManager.jsMessageThread), _jsThreadManager.jsMessageThread, timerManager, jsErrorHandlingFunc, diff --git a/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTJscInstance.h b/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTJscInstance.h index bcb1393519d1b8..8ad3220f45d309 100644 --- a/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTJscInstance.h +++ b/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTJscInstance.h @@ -7,12 +7,12 @@ #import #import -#import +#import namespace facebook { namespace react { -class RCTJscInstance : public JSEngineInstance { +class RCTJscInstance : public JSRuntimeFactory { public: RCTJscInstance(); diff --git a/packages/react-native/ReactCommon/react/test_utils/ios/Shims/ShimRCTInstance.mm b/packages/react-native/ReactCommon/react/test_utils/ios/Shims/ShimRCTInstance.mm index 77476f9dfd3d52..884448d45b2c84 100644 --- a/packages/react-native/ReactCommon/react/test_utils/ios/Shims/ShimRCTInstance.mm +++ b/packages/react-native/ReactCommon/react/test_utils/ios/Shims/ShimRCTInstance.mm @@ -23,7 +23,7 @@ - (instancetype)init [RCTInstance class], [ShimRCTInstance class], @selector(initWithDelegate: - jsEngineInstance:bundleManager:turboModuleManagerDelegate:onInitialBundleLoad:moduleRegistry:)); + jsRuntimeFactory:bundleManager:turboModuleManagerDelegate:onInitialBundleLoad:moduleRegistry:)); RCTSwizzleInstanceSelector([RCTInstance class], [ShimRCTInstance class], @selector(invalidate)); RCTSwizzleInstanceSelector( [RCTInstance class], [ShimRCTInstance class], @selector(callFunctionOnJSModule:method:args:)); @@ -38,7 +38,7 @@ - (void)reset [RCTInstance class], [ShimRCTInstance class], @selector(initWithDelegate: - jsEngineInstance:bundleManager:turboModuleManagerDelegate:onInitialBundleLoad:moduleRegistry:)); + jsRuntimeFactory:bundleManager:turboModuleManagerDelegate:onInitialBundleLoad:moduleRegistry:)); RCTSwizzleInstanceSelector([RCTInstance class], [ShimRCTInstance class], @selector(invalidate)); RCTSwizzleInstanceSelector( [RCTInstance class], [ShimRCTInstance class], @selector(callFunctionOnJSModule:method:args:)); @@ -47,7 +47,7 @@ - (void)reset } - (instancetype)initWithDelegate:(id)delegate - jsEngineInstance:(std::shared_ptr)jsEngineInstance + jsRuntimeFactory:(std::shared_ptr)jsRuntimeFactory bundleManager:(RCTBundleManager *)bundleManager turboModuleManagerDelegate:(id)tmmDelegate onInitialBundleLoad:(RCTInstanceInitialBundleLoadCompletionBlock)onInitialBundleLoad From 99d407da46ae832b105a598209b3f5b4c265c30f Mon Sep 17 00:00:00 2001 From: Christoph Purrer Date: Tue, 21 Nov 2023 08:07:37 -0800 Subject: [PATCH 039/162] ios|android textInput > Remove #ifdef ANDROID when not needed (#41569) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41569 Changelog: [Internal] Reviewed By: rshest Differential Revision: D51479729 fbshipit-source-id: 0dd78e568b98c93446a59e5f1242d26a24d9fff2 --- .../androidtextinput/AndroidTextInputProps.h | 2 -- .../AndroidTextInputState.cpp | 6 ----- .../androidtextinput/AndroidTextInputState.h | 7 ++---- .../iostextinput/TextInputState.cpp | 24 +------------------ .../components/iostextinput/TextInputState.h | 16 ------------- 5 files changed, 3 insertions(+), 52 deletions(-) diff --git a/packages/react-native/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputProps.h b/packages/react-native/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputProps.h index 43cbb6859047f3..a690816906ae2f 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputProps.h +++ b/packages/react-native/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputProps.h @@ -50,7 +50,6 @@ static inline std::string toString( return "[Object AndroidTextInputTextShadowOffsetStruct]"; } -#ifdef ANDROID inline folly::dynamic toDynamic( const AndroidTextInputTextShadowOffsetStruct& value) { folly::dynamic dynamicValue = folly::dynamic::object(); @@ -58,7 +57,6 @@ inline folly::dynamic toDynamic( dynamicValue["height"] = value.height; return dynamicValue; } -#endif class AndroidTextInputProps final : public ViewProps, public BaseTextProps { public: diff --git a/packages/react-native/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputState.cpp b/packages/react-native/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputState.cpp index 83607848e4d342..ab5516d796e87a 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputState.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputState.cpp @@ -9,11 +9,8 @@ #include #include - -#ifdef ANDROID #include #include -#endif #include @@ -68,7 +65,6 @@ AndroidTextInputState::AndroidTextInputState( previousState.defaultThemePaddingBottom) .getDouble()){}; -#ifdef ANDROID folly::dynamic AndroidTextInputState::getDynamic() const { // Java doesn't need all fields, so we don't pass them all along. folly::dynamic newState = folly::dynamic::object(); @@ -104,6 +100,4 @@ MapBuffer AndroidTextInputState::getMapBuffer() const { return builder.build(); } -#endif - } // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputState.h b/packages/react-native/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputState.h index 1cf73cca7c74c8..b7e4532738ee99 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputState.h +++ b/packages/react-native/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputState.h @@ -7,15 +7,12 @@ #pragma once +#include #include #include -#include - -#ifdef ANDROID -#include #include #include -#endif +#include namespace facebook::react { diff --git a/packages/react-native/ReactCommon/react/renderer/components/textinput/iostextinput/react/renderer/components/iostextinput/TextInputState.cpp b/packages/react-native/ReactCommon/react/renderer/components/textinput/iostextinput/react/renderer/components/iostextinput/TextInputState.cpp index a78a839b419db7..abe682f52e19a1 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/textinput/iostextinput/react/renderer/components/iostextinput/TextInputState.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/textinput/iostextinput/react/renderer/components/iostextinput/TextInputState.cpp @@ -7,26 +7,4 @@ #include "TextInputState.h" -namespace facebook::react { - -#ifdef ANDROID -TextInputState::TextInputState( - const TextInputState& /*previousState*/, - const folly::dynamic& /*data*/){}; - -/* - * Empty implementation for Android because it doesn't use this class. - */ -folly::dynamic TextInputState::getDynamic() const { - return {}; -}; - -/* - * Empty implementation for Android because it doesn't use this class. - */ -MapBuffer TextInputState::getMapBuffer() const { - return MapBufferBuilder::EMPTY(); -}; -#endif - -} // namespace facebook::react +namespace facebook::react {} // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/renderer/components/textinput/iostextinput/react/renderer/components/iostextinput/TextInputState.h b/packages/react-native/ReactCommon/react/renderer/components/textinput/iostextinput/react/renderer/components/iostextinput/TextInputState.h index 3a11436d43608d..fe7dab58255258 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/textinput/iostextinput/react/renderer/components/iostextinput/TextInputState.h +++ b/packages/react-native/ReactCommon/react/renderer/components/textinput/iostextinput/react/renderer/components/iostextinput/TextInputState.h @@ -11,12 +11,6 @@ #include #include -#ifdef ANDROID -#include -#include -#include -#endif - namespace facebook::react { /* @@ -54,16 +48,6 @@ class TextInputState final { std::shared_ptr layoutManager; size_t mostRecentEventCount{0}; - -#ifdef ANDROID - TextInputState( - const TextInputState& previousState, - const folly::dynamic& data); - - folly::dynamic getDynamic() const; - - MapBuffer getMapBuffer() const; -#endif }; } // namespace facebook::react From d9d81a755e74378ea45f54b1d8997f1fc8e7a39d Mon Sep 17 00:00:00 2001 From: Nick Gerleman Date: Tue, 21 Nov 2023 09:03:51 -0800 Subject: [PATCH 040/162] Terminate on logic error in createNode HostFunction (#41567) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41567 Sometimes `createNode` calls into is throwing `std::out_of_range_error` or `std::length_error` in response to both vector and string operations. Instead of propagating `std::logic_error`, which indicates a defect in native code, terminate, so we can get an actionable native stack trace. `createNode` and `cloneNode` also both ocasionally see `bad_alloc`, but this is not usually an instance of a defect at the allocation-site, and throwing would be more graceful. Changelog: [Internal] Reviewed By: javache Differential Revision: D51463600 fbshipit-source-id: 870cbf3538d8ccbc01ded2868781a63ba12a941c --- .../renderer/uimanager/UIManagerBinding.cpp | 36 ++++++++++--------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/packages/react-native/ReactCommon/react/renderer/uimanager/UIManagerBinding.cpp b/packages/react-native/ReactCommon/react/renderer/uimanager/UIManagerBinding.cpp index 9813ea84ccc51f..7b4e412ef25031 100644 --- a/packages/react-native/ReactCommon/react/renderer/uimanager/UIManagerBinding.cpp +++ b/packages/react-native/ReactCommon/react/renderer/uimanager/UIManagerBinding.cpp @@ -230,23 +230,27 @@ jsi::Value UIManagerBinding::get( const jsi::Value& /*thisValue*/, const jsi::Value* arguments, size_t count) -> jsi::Value { - validateArgumentCount(runtime, methodName, paramCount, count); - - auto instanceHandle = - instanceHandleFromValue(runtime, arguments[4], arguments[0]); - if (!instanceHandle) { - react_native_assert(false); - return jsi::Value::undefined(); + try { + validateArgumentCount(runtime, methodName, paramCount, count); + + auto instanceHandle = + instanceHandleFromValue(runtime, arguments[4], arguments[0]); + if (!instanceHandle) { + react_native_assert(false); + return jsi::Value::undefined(); + } + + return valueFromShadowNode( + runtime, + uiManager->createNode( + tagFromValue(arguments[0]), + stringFromValue(runtime, arguments[1]), + surfaceIdFromValue(runtime, arguments[2]), + RawProps(runtime, arguments[3]), + std::move(instanceHandle))); + } catch (const std::logic_error& ex) { + LOG(FATAL) << "logic_error in createNode: " << ex.what(); } - - return valueFromShadowNode( - runtime, - uiManager->createNode( - tagFromValue(arguments[0]), - stringFromValue(runtime, arguments[1]), - surfaceIdFromValue(runtime, arguments[2]), - RawProps(runtime, arguments[3]), - std::move(instanceHandle))); }); } From 7625a502960e6b107e77542ff0d6f40fbf957322 Mon Sep 17 00:00:00 2001 From: Ruslan Shestopalyuk Date: Tue, 21 Nov 2023 09:08:10 -0800 Subject: [PATCH 041/162] Share ImageRequest implementation across the platforms (#41581) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41581 # Changelog: There was nothing platform-specific in `ImageRequest` implementation, defined on iOS, so might as well share across platforms. Reviewed By: christophpurrer Differential Revision: D51495144 fbshipit-source-id: ef15c5c8c6b07c1a87ca83eb15b5997ba703fbcc --- .../imagemanager => }/ImageRequest.cpp | 0 .../renderer/imagemanager/ImageRequest.cpp | 36 ------------------- 2 files changed, 36 deletions(-) rename packages/react-native/ReactCommon/react/renderer/imagemanager/{platform/ios/react/renderer/imagemanager => }/ImageRequest.cpp (100%) delete mode 100644 packages/react-native/ReactCommon/react/renderer/imagemanager/platform/cxx/react/renderer/imagemanager/ImageRequest.cpp diff --git a/packages/react-native/ReactCommon/react/renderer/imagemanager/platform/ios/react/renderer/imagemanager/ImageRequest.cpp b/packages/react-native/ReactCommon/react/renderer/imagemanager/ImageRequest.cpp similarity index 100% rename from packages/react-native/ReactCommon/react/renderer/imagemanager/platform/ios/react/renderer/imagemanager/ImageRequest.cpp rename to packages/react-native/ReactCommon/react/renderer/imagemanager/ImageRequest.cpp diff --git a/packages/react-native/ReactCommon/react/renderer/imagemanager/platform/cxx/react/renderer/imagemanager/ImageRequest.cpp b/packages/react-native/ReactCommon/react/renderer/imagemanager/platform/cxx/react/renderer/imagemanager/ImageRequest.cpp deleted file mode 100644 index 7974e06a2c1b9e..00000000000000 --- a/packages/react-native/ReactCommon/react/renderer/imagemanager/platform/cxx/react/renderer/imagemanager/ImageRequest.cpp +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#include "ImageRequest.h" - -#include - -namespace facebook::react { - -ImageRequest::ImageRequest( - ImageSource imageSource, - std::shared_ptr telemetry, - SharedFunction<> cancelationFunction) - : imageSource_(std::move(imageSource)), - telemetry_(std::move(telemetry)), - cancelRequest_(std::move(cancelationFunction)) { - // Not implemented. -} - -const ImageResponseObserverCoordinator& ImageRequest::getObserverCoordinator() - const { - // Not implemented - abort(); -} - -const std::shared_ptr& -ImageRequest::getSharedObserverCoordinator() const { - // Not implemented - abort(); -} - -} // namespace facebook::react From 16ad818d21773cdf25156642fae83592352ae534 Mon Sep 17 00:00:00 2001 From: Moti Zilberman Date: Tue, 21 Nov 2023 09:56:55 -0800 Subject: [PATCH 042/162] Handle all incoming Inspector messages on main thread, downgrade some errors to logs Summary: Changelog: [Internal] * Updates `InspectorPackagerConnection.java`, `DevServerHelper.java` and `DevSupportManagerBase.java` to perform all connection management and message dispatching for the inspector socket on the main thread. This is in support of a new CDP implementation in React Native that will strictly assume it's called on the main thread (thus avoiding the need for explicit locking in many places). * Downgrades JSON parsing errors and duplicate connection errors from exceptions to logs, matching the [iOS implementation](https://github.com/facebook/react-native/blob/main/packages/react-native/React/Inspector/RCTInspectorPackagerConnection.m). Reviewed By: javache Differential Revision: D51346658 fbshipit-source-id: 3d0d5588a824c1b28da5499ef9d040998a941288 --- .../react/devsupport/DevServerHelper.java | 28 ++----- .../devsupport/DevSupportManagerBase.java | 11 ++- .../InspectorPackagerConnection.java | 79 +++++++++++-------- 3 files changed, 64 insertions(+), 54 deletions(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevServerHelper.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevServerHelper.java index 4cef3eed690491..2b8aee80f75ee0 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevServerHelper.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevServerHelper.java @@ -210,16 +210,10 @@ public void openInspectorConnection() { FLog.w(ReactConstants.TAG, "Inspector connection already open, nooping."); return; } - new AsyncTask() { - @Override - protected Void doInBackground(Void... params) { - mInspectorPackagerConnection = - new InspectorPackagerConnection( - getInspectorDeviceUrl(), mPackageName, mBundlerStatusProvider); - mInspectorPackagerConnection.connect(); - return null; - } - }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + mInspectorPackagerConnection = + new InspectorPackagerConnection( + getInspectorDeviceUrl(), mPackageName, mBundlerStatusProvider); + mInspectorPackagerConnection.connect(); } public void disableDebugger() { @@ -229,16 +223,10 @@ public void disableDebugger() { } public void closeInspectorConnection() { - new AsyncTask() { - @Override - protected Void doInBackground(Void... params) { - if (mInspectorPackagerConnection != null) { - mInspectorPackagerConnection.closeQuietly(); - mInspectorPackagerConnection = null; - } - return null; - } - }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + if (mInspectorPackagerConnection != null) { + mInspectorPackagerConnection.closeQuietly(); + mInspectorPackagerConnection = null; + } } public String getWebsocketProxyURL() { diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevSupportManagerBase.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevSupportManagerBase.java index e242858a71b2fc..a72dc10cf85e74 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevSupportManagerBase.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevSupportManagerBase.java @@ -942,6 +942,7 @@ private void reportBundleLoadingFailure(final Exception cause) { @Override public void startInspector() { + UiThreadUtil.assertOnUiThread(); if (mIsDevSupportEnabled) { mDevServerHelper.openInspectorConnection(); } @@ -949,6 +950,7 @@ public void startInspector() { @Override public void stopInspector() { + UiThreadUtil.assertOnUiThread(); mDevServerHelper.closeInspectorConnection(); } @@ -1045,9 +1047,12 @@ public void onPackagerDisconnected() { @Override public void onPackagerReloadCommand() { - // Disable debugger to resume the JsVM & avoid thread locks while reloading - mDevServerHelper.disableDebugger(); - UiThreadUtil.runOnUiThread(() -> handleReloadJS()); + UiThreadUtil.runOnUiThread( + () -> { + // Disable debugger to resume the JsVM & avoid thread locks while reloading + mDevServerHelper.disableDebugger(); + handleReloadJS(); + }); } @Override diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/InspectorPackagerConnection.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/InspectorPackagerConnection.java index 5f535b7044d6fa..ee4b4e591f983c 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/InspectorPackagerConnection.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/InspectorPackagerConnection.java @@ -8,12 +8,10 @@ package com.facebook.react.devsupport; import android.os.AsyncTask; -import android.os.Handler; -import android.os.Looper; import androidx.annotation.Nullable; import com.facebook.common.logging.FLog; import com.facebook.react.bridge.Inspector; -import java.io.IOException; +import com.facebook.react.bridge.UiThreadUtil; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -37,6 +35,7 @@ public class InspectorPackagerConnection { public InspectorPackagerConnection( String url, String packageName, BundleStatusProvider bundleStatusProvider) { + UiThreadUtil.assertOnUiThread(); mConnection = new Connection(url); mInspectorConnections = new HashMap<>(); mPackageName = packageName; @@ -44,10 +43,12 @@ public InspectorPackagerConnection( } public void connect() { + UiThreadUtil.assertOnUiThread(); mConnection.connect(); } public void closeQuietly() { + UiThreadUtil.assertOnUiThread(); mConnection.close(); } @@ -59,7 +60,7 @@ public void sendEventToAllConnections(String event) { } } - void handleProxyMessage(JSONObject message) throws JSONException, IOException { + void handleProxyMessage(JSONObject message) throws JSONException { String event = message.getString("event"); switch (event) { case "getPages": @@ -75,7 +76,8 @@ void handleProxyMessage(JSONObject message) throws JSONException, IOException { handleDisconnect(message.getJSONObject("payload")); break; default: - throw new IllegalArgumentException("Unknown event: " + event); + FLog.e(TAG, "Unknown event: " + event); + break; } } @@ -90,7 +92,8 @@ private void handleConnect(JSONObject payload) throws JSONException { final String pageId = payload.getString("pageId"); Inspector.LocalConnection inspectorConnection = mInspectorConnections.remove(pageId); if (inspectorConnection != null) { - throw new IllegalStateException("Already connected: " + pageId); + FLog.w(TAG, "Already connected: " + pageId); + return; } try { @@ -191,49 +194,65 @@ private class Connection extends WebSocketListener { private OkHttpClient mHttpClient; private @Nullable WebSocket mWebSocket; - private final Handler mHandler; private boolean mClosed; private boolean mSuppressConnectionErrors; public Connection(String url) { mUrl = url; - mHandler = new Handler(Looper.getMainLooper()); } @Override public void onOpen(WebSocket webSocket, Response response) { - mWebSocket = webSocket; + UiThreadUtil.runOnUiThread( + () -> { + mWebSocket = webSocket; + }); } @Override public void onFailure(WebSocket webSocket, Throwable t, Response response) { - if (mWebSocket != null) { - abort("Websocket exception", t); - } - if (!mClosed) { - reconnect(); - } + UiThreadUtil.runOnUiThread( + () -> { + if (mWebSocket != null) { + abort("Websocket exception", t); + } + if (!mClosed) { + reconnect(); + } + }); } @Override public void onMessage(WebSocket webSocket, String text) { try { - handleProxyMessage(new JSONObject(text)); - } catch (Exception e) { - throw new RuntimeException(e); + JSONObject parsed = new JSONObject(text); + UiThreadUtil.runOnUiThread( + () -> { + try { + handleProxyMessage(parsed); + } catch (JSONException e) { + FLog.w(TAG, "Error handling inspector message", e); + } + }); + } catch (JSONException e) { + FLog.w(TAG, "Unrecognized inspector message, string was not valid JSON: " + text, e); } } @Override public void onClosed(WebSocket webSocket, int code, String reason) { - mWebSocket = null; - closeAllConnections(); - if (!mClosed) { - reconnect(); - } + UiThreadUtil.runOnUiThread( + () -> { + mWebSocket = null; + closeAllConnections(); + if (!mClosed) { + reconnect(); + } + }); } public void connect() { + UiThreadUtil.assertOnUiThread(); if (mClosed) { throw new IllegalStateException("Can't connect closed client"); } @@ -258,20 +277,18 @@ private void reconnect() { FLog.w(TAG, "Couldn't connect to packager, will silently retry"); mSuppressConnectionErrors = true; } - mHandler.postDelayed( - new Runnable() { - @Override - public void run() { - // check that we haven't been closed in the meantime - if (!mClosed) { - connect(); - } + UiThreadUtil.runOnUiThread( + () -> { + // check that we haven't been closed in the meantime + if (!mClosed) { + connect(); } }, RECONNECT_DELAY_MS); } public void close() { + UiThreadUtil.assertOnUiThread(); mClosed = true; if (mWebSocket != null) { try { From 1e43d2b9bdb42e41c34cf10db8ea01518648b831 Mon Sep 17 00:00:00 2001 From: Samuel Susla Date: Tue, 21 Nov 2023 10:37:54 -0800 Subject: [PATCH 043/162] remove unused argument from RawProps (#41565) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41565 changelog: [internal] this argument is never used, let's remove it. Reviewed By: christophpurrer Differential Revision: D51468580 fbshipit-source-id: aec029bc78b5490686a36ac8a5f5d0342bd28d50 --- .../UnimplementedViewComponentDescriptor.cpp | 2 +- .../core/ConcreteComponentDescriptor.h | 2 +- .../react/renderer/core/RawProps.cpp | 4 +--- .../react/renderer/core/RawProps.h | 3 +-- .../react/renderer/core/RawPropsParser.h | 2 +- .../renderer/core/tests/RawPropsTest.cpp | 24 +++++++++---------- 6 files changed, 17 insertions(+), 20 deletions(-) diff --git a/packages/react-native/ReactCommon/react/renderer/components/unimplementedview/UnimplementedViewComponentDescriptor.cpp b/packages/react-native/ReactCommon/react/renderer/components/unimplementedview/UnimplementedViewComponentDescriptor.cpp index 1fd2a48271aa89..d8e9ce211cf4f2 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/unimplementedview/UnimplementedViewComponentDescriptor.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/unimplementedview/UnimplementedViewComponentDescriptor.cpp @@ -29,7 +29,7 @@ Props::Shared UnimplementedViewComponentDescriptor::cloneProps( // We have to clone `Props` object one more time to make sure that we have // an unshared (and non-`const`) copy of it which we can mutate. RawProps emptyRawProps{}; - emptyRawProps.parse(rawPropsParser_, context); + emptyRawProps.parse(rawPropsParser_); auto unimplementedViewProps = std::make_shared( context, static_cast(*clonedProps), diff --git a/packages/react-native/ReactCommon/react/renderer/core/ConcreteComponentDescriptor.h b/packages/react-native/ReactCommon/react/renderer/core/ConcreteComponentDescriptor.h index f161e9b12c1346..e56ac9cad92165 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/ConcreteComponentDescriptor.h +++ b/packages/react-native/ReactCommon/react/renderer/core/ConcreteComponentDescriptor.h @@ -105,7 +105,7 @@ class ConcreteComponentDescriptor : public ComponentDescriptor { return ShadowNodeT::defaultSharedProps(); } - rawProps.parse(rawPropsParser_, context); + rawProps.parse(rawPropsParser_); // Call old-style constructor auto shadowNodeProps = ShadowNodeT::Props(context, rawProps, props); diff --git a/packages/react-native/ReactCommon/react/renderer/core/RawProps.cpp b/packages/react-native/ReactCommon/react/renderer/core/RawProps.cpp index 0739b8ec6b12e9..945566c785e1fc 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/RawProps.cpp +++ b/packages/react-native/ReactCommon/react/renderer/core/RawProps.cpp @@ -47,9 +47,7 @@ RawProps::RawProps(folly::dynamic dynamic) noexcept { dynamic_ = std::move(dynamic); } -void RawProps::parse( - const RawPropsParser& parser, - const PropsParserContext& /*unused*/) const noexcept { +void RawProps::parse(const RawPropsParser& parser) const noexcept { react_native_assert(parser_ == nullptr && "A parser was already assigned."); parser_ = &parser; parser.preparse(*this); diff --git a/packages/react-native/ReactCommon/react/renderer/core/RawProps.h b/packages/react-native/ReactCommon/react/renderer/core/RawProps.h index e01af9f84db306..cfb2bd48cec24a 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/RawProps.h +++ b/packages/react-native/ReactCommon/react/renderer/core/RawProps.h @@ -70,8 +70,7 @@ class RawProps final { RawProps(const RawProps& other) noexcept = delete; RawProps& operator=(const RawProps& other) noexcept = delete; - void parse(const RawPropsParser& parser, const PropsParserContext&) - const noexcept; + void parse(const RawPropsParser& parser) const noexcept; /* * Deprecated. Do not use. diff --git a/packages/react-native/ReactCommon/react/renderer/core/RawPropsParser.h b/packages/react-native/ReactCommon/react/renderer/core/RawPropsParser.h index 5150189817134d..de0b1c7fcfabcc 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/RawPropsParser.h +++ b/packages/react-native/ReactCommon/react/renderer/core/RawPropsParser.h @@ -46,7 +46,7 @@ class RawPropsParser final { ContextContainer contextContainer{}; PropsParserContext parserContext{-1, contextContainer}; - emptyRawProps.parse(*this, parserContext); + emptyRawProps.parse(*this); PropsT(parserContext, {}, emptyRawProps); postPrepare(); } diff --git a/packages/react-native/ReactCommon/react/renderer/core/tests/RawPropsTest.cpp b/packages/react-native/ReactCommon/react/renderer/core/tests/RawPropsTest.cpp index bca6d019ffbbd0..7bec6cfcc45309 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/tests/RawPropsTest.cpp +++ b/packages/react-native/ReactCommon/react/renderer/core/tests/RawPropsTest.cpp @@ -154,7 +154,7 @@ TEST(RawPropsTest, handleProps) { const auto& raw = RawProps(folly::dynamic::object("nativeID", "abc")); auto parser = RawPropsParser(); parser.prepare(); - raw.parse(parser, parserContext); + raw.parse(parser); auto props = std::make_shared(parserContext, Props(), raw); @@ -171,7 +171,7 @@ TEST(RawPropsTest, handleRawPropsSingleString) { const auto& raw = RawProps(folly::dynamic::object("nativeID", "abc")); auto parser = RawPropsParser(); parser.prepare(); - raw.parse(parser, parserContext); + raw.parse(parser); std::string value = (std::string)*raw.at("nativeID", nullptr, nullptr); @@ -186,7 +186,7 @@ TEST(RawPropsTest, handleRawPropsSingleFloat) { RawProps(folly::dynamic::object("floatValue", (float)42.42)); auto parser = RawPropsParser(); parser.prepare(); - raw.parse(parser, parserContext); + raw.parse(parser); auto value = (float)*raw.at("floatValue", nullptr, nullptr); @@ -201,7 +201,7 @@ TEST(RawPropsTest, handleRawPropsSingleDouble) { RawProps(folly::dynamic::object("doubleValue", (double)42.42)); auto parser = RawPropsParser(); parser.prepare(); - raw.parse(parser, parserContext); + raw.parse(parser); auto value = (double)*raw.at("doubleValue", nullptr, nullptr); @@ -215,7 +215,7 @@ TEST(RawPropsTest, handleRawPropsSingleInt) { const auto& raw = RawProps(folly::dynamic::object("intValue", (int)42.42)); auto parser = RawPropsParser(); parser.prepare(); - raw.parse(parser, parserContext); + raw.parse(parser); int value = (int)*raw.at("intValue", nullptr, nullptr); @@ -229,7 +229,7 @@ TEST(RawPropsTest, handleRawPropsSingleIntGetManyTimes) { const auto& raw = RawProps(folly::dynamic::object("intValue", (int)42.42)); auto parser = RawPropsParser(); parser.prepare(); - raw.parse(parser, parserContext); + raw.parse(parser); EXPECT_EQ((int)*raw.at("intValue", nullptr, nullptr), 42); EXPECT_EQ((int)*raw.at("intValue", nullptr, nullptr), 42); @@ -247,7 +247,7 @@ TEST(RawPropsTest, handleRawPropsPrimitiveTypes) { auto parser = RawPropsParser(); parser.prepare(); - raw.parse(parser, parserContext); + raw.parse(parser); EXPECT_EQ((int)*raw.at("intValue", nullptr, nullptr), 42); EXPECT_NEAR((double)*raw.at("doubleValue", nullptr, nullptr), 17.42, 0.0001); @@ -269,7 +269,7 @@ TEST(RawPropsTest, handleRawPropsPrimitiveTypesGetTwice) { auto parser = RawPropsParser(); parser.prepare(); - raw.parse(parser, parserContext); + raw.parse(parser); EXPECT_EQ((int)*raw.at("intValue", nullptr, nullptr), 42); EXPECT_NEAR((double)*raw.at("doubleValue", nullptr, nullptr), 17.42, 0.0001); @@ -299,7 +299,7 @@ TEST(RawPropsTest, handleRawPropsPrimitiveTypesGetOutOfOrder) { auto parser = RawPropsParser(); parser.prepare(); - raw.parse(parser, parserContext); + raw.parse(parser); EXPECT_EQ((int)*raw.at("intValue", nullptr, nullptr), 42); EXPECT_NEAR((double)*raw.at("doubleValue", nullptr, nullptr), 17.42, 0.0001); @@ -326,7 +326,7 @@ TEST(RawPropsTest, handleRawPropsPrimitiveTypesIncomplete) { auto parser = RawPropsParser(); parser.prepare(); - raw.parse(parser, parserContext); + raw.parse(parser); EXPECT_EQ((int)*raw.at("intValue", nullptr, nullptr), 42); EXPECT_EQ(raw.at("doubleValue", nullptr, nullptr), nullptr); @@ -346,7 +346,7 @@ TEST(RawPropsTest, handleRawPropsPrimitiveTypesIncorrectLookup) { auto parser = RawPropsParser(); parser.prepare(); - raw.parse(parser, parserContext); + raw.parse(parser); // Before D18662135, looking up an invalid key would trigger // an infinite loop. This is out of contract, so we should only @@ -363,7 +363,7 @@ TEST(RawPropsTest, handlePropsMultiLookup) { const auto& raw = RawProps(folly::dynamic::object("floatValue", (float)10.0)); auto parser = RawPropsParser(); parser.prepare(); - raw.parse(parser, parserContext); + raw.parse(parser); auto props = std::make_shared( parserContext, PropsMultiLookup(), raw); From ac1cdaa71620d5bb4860237cafb108f6aeae9aef Mon Sep 17 00:00:00 2001 From: Ruslan Shestopalyuk Date: Tue, 21 Nov 2023 10:51:40 -0800 Subject: [PATCH 044/162] Make ImageManager implementation overridable (#41582) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41582 # Changelog: This will allow to have custom `ImageManager` implementations on new platforms. Reviewed By: christophpurrer Differential Revision: D51495143 fbshipit-source-id: bbd03bdad1b87fd53e70a886f1fdc74f371987c8 --- .../react/renderer/imagemanager/ImageManager.h | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/packages/react-native/ReactCommon/react/renderer/imagemanager/ImageManager.h b/packages/react-native/ReactCommon/react/renderer/imagemanager/ImageManager.h index 600e4b3d99138b..128be69838884a 100644 --- a/packages/react-native/ReactCommon/react/renderer/imagemanager/ImageManager.h +++ b/packages/react-native/ReactCommon/react/renderer/imagemanager/ImageManager.h @@ -21,15 +21,17 @@ class ImageManager; using SharedImageManager = std::shared_ptr; /* - * Cross platform facade for iOS-specific RCTImageManager. + * Cross platform facade for image management (e.g. iOS-specific + * RCTImageManager) */ class ImageManager { public: ImageManager(const ContextContainer::Shared& contextContainer); - ~ImageManager(); + virtual ~ImageManager(); - ImageRequest requestImage(const ImageSource& imageSource, SurfaceId surfaceId) - const; + virtual ImageRequest requestImage( + const ImageSource& imageSource, + SurfaceId surfaceId) const; private: void* self_{}; From a6964b36294c3bfea09c0cdd65c5d0e3949f2dae Mon Sep 17 00:00:00 2001 From: Arushi Kesarwani Date: Tue, 21 Nov 2023 11:27:26 -0800 Subject: [PATCH 045/162] Fix ReactNativeHost to have default UIManagerProvider as null (#41593) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41593 Fixing fallback to `getJSIModule()` by defaulting `getUIManagerProvider()` correctly to null Reviewed By: christophpurrer Differential Revision: D51500901 fbshipit-source-id: 91b692e6c88d736970b652179e14bc524a411d0e --- .../src/main/java/com/facebook/react/ReactNativeHost.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactNativeHost.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactNativeHost.java index 3f1fb6f9462045..5352d11ea9b14e 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactNativeHost.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactNativeHost.java @@ -132,7 +132,7 @@ protected final Application getApplication() { } protected @Nullable UIManagerProvider getUIManagerProvider() { - return reactApplicationContext -> null; + return null; } /** Returns whether or not to treat it as normal if Activity is null. */ From 0d715cd01657401f2629b854dc052e1f34ebd757 Mon Sep 17 00:00:00 2001 From: Samuel Susla Date: Tue, 21 Nov 2023 13:31:50 -0800 Subject: [PATCH 046/162] add unit tests for EventTarget (#41596) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41596 changelog: [internal] Reviewed By: rshest Differential Revision: D51499449 fbshipit-source-id: 782108edf24af1c91d77c664bc496b466995621e --- .../renderer/core/tests/EventTargetTests.cpp | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 packages/react-native/ReactCommon/react/renderer/core/tests/EventTargetTests.cpp diff --git a/packages/react-native/ReactCommon/react/renderer/core/tests/EventTargetTests.cpp b/packages/react-native/ReactCommon/react/renderer/core/tests/EventTargetTests.cpp new file mode 100644 index 00000000000000..2f919870c795a3 --- /dev/null +++ b/packages/react-native/ReactCommon/react/renderer/core/tests/EventTargetTests.cpp @@ -0,0 +1,43 @@ +/* + * Copyright (c) Meta Platforms, Inc. and 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 + +using namespace facebook; +using namespace facebook::react; + +TEST(EventTargetTests, getInstanceHandle) { + auto runtime = facebook::hermes::makeHermesRuntime(); + auto object = jsi::Object(*runtime); + auto instanceHandle = std::make_shared( + *runtime, jsi::Value(*runtime, object), 1); + + EXPECT_EQ(instanceHandle->getTag(), 1); + + auto eventTarget = EventTarget(std::move(instanceHandle)); + + EXPECT_EQ(eventTarget.getTag(), 1); + + EXPECT_TRUE(eventTarget.getInstanceHandle(*runtime).isNull()); + + eventTarget.retain(*runtime); + + EXPECT_TRUE(eventTarget.getInstanceHandle(*runtime).isNull()); + + eventTarget.setEnabled(true); + + eventTarget.retain(*runtime); + + EXPECT_FALSE(eventTarget.getInstanceHandle(*runtime).isNull()); + + eventTarget.release(*runtime); + + EXPECT_TRUE(eventTarget.getInstanceHandle(*runtime).isNull()); +} From c497fc61b5ce5e30771f39202c522bc7acae2808 Mon Sep 17 00:00:00 2001 From: Kevin Gozali Date: Tue, 21 Nov 2023 13:43:16 -0800 Subject: [PATCH 047/162] RNTester iOS: setup Meta internal app init logic (#41591) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41591 For internal build integration, invoke Meta internal app setup logic. This has no effect in OSS. Changelog: [Internal] Reviewed By: christophpurrer Differential Revision: D51498070 fbshipit-source-id: 48658d2c3136023d80fbd9a2fdc29996616e1eee --- packages/rn-tester/RNTester/AppDelegate.mm | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/packages/rn-tester/RNTester/AppDelegate.mm b/packages/rn-tester/RNTester/AppDelegate.mm index 16a33fa3cab524..a7fa095e5bc2e6 100644 --- a/packages/rn-tester/RNTester/AppDelegate.mm +++ b/packages/rn-tester/RNTester/AppDelegate.mm @@ -23,6 +23,11 @@ #endif #endif +// FB-internal imports +#ifdef RN_DISABLE_OSS_PLUGIN_HEADER +#import +#endif + #if BUNDLE_PATH NSString *kBundlePath = @"xplat/js/RKJSModules/EntryPoints/RNTesterTestBundle.js"; #else @@ -33,6 +38,11 @@ @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { +#ifdef RN_DISABLE_OSS_PLUGIN_HEADER + // FB-internal app init setup. + RCTFBAppInitApplicationDidFinishLaunching(launchOptions); +#endif + self.moduleName = @"RNTesterApp"; // You can add your custom initial props in the dictionary below. // They will be passed down to the ViewController used by React Native. From bf4e229668c9e885736e8ec939961b85cdbb0141 Mon Sep 17 00:00:00 2001 From: Pieter De Baets Date: Tue, 21 Nov 2023 13:44:18 -0800 Subject: [PATCH 048/162] Clear mLastQueriedSurfaceMountingManager on stopSurface (#41590) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41590 Causing a small leak while we wait for the surface to be fully destroyed. Changelog: [Internal] Reviewed By: fabriziocucci Differential Revision: D51499256 fbshipit-source-id: 8f9e65898dcb9e0261502028874378ec9cc0f3fc --- .../com/facebook/react/fabric/mounting/MountingManager.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/MountingManager.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/MountingManager.java index e65a01cd25e158..3aa8c930349271 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/MountingManager.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/MountingManager.java @@ -143,9 +143,12 @@ public void stopSurface(final int surfaceId) { surfaceMountingManager.stopSurface(); - if (surfaceMountingManager == mMostRecentSurfaceMountingManager) { + if (mMostRecentSurfaceMountingManager == surfaceMountingManager) { mMostRecentSurfaceMountingManager = null; } + if (mLastQueriedSurfaceMountingManager == surfaceMountingManager) { + mLastQueriedSurfaceMountingManager = null; + } } else { ReactSoftExceptionLogger.logSoftException( TAG, From c4519a01ace44041029799d49f5b6f9636c843fa Mon Sep 17 00:00:00 2001 From: Nick Gerleman Date: Tue, 21 Nov 2023 23:17:32 -0800 Subject: [PATCH 049/162] Remove composite border comparisons (#41568) Summary: X-link: https://github.com/facebook/yoga/pull/1475 Pull Request resolved: https://github.com/facebook/react-native/pull/41568 Removes cases where we rely on comparing composite of Yoga edges, since we are removing that internal API (public API is already one at a time). Extracted from D50998164, with more sound facility for looping through edges. Changelog: [Internal] Reviewed By: javache Differential Revision: D51478403 fbshipit-source-id: 162170b91345ff86db44a49a04a2345f0fbd0911 --- .../components/view/ViewShadowNode.cpp | 12 ++++- .../view/YogaStylablePropsMapBuffer.cpp | 38 +++++++++++----- .../ReactCommon/yoga/yoga/enums/YogaEnums.h | 44 ++++++++++++++++++- .../ReactCommon/yoga/yoga/style/Style.h | 1 + 4 files changed, 80 insertions(+), 15 deletions(-) diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/ViewShadowNode.cpp b/packages/react-native/ReactCommon/react/renderer/components/view/ViewShadowNode.cpp index 42575ec6085f35..ad22a350daef23 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/ViewShadowNode.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/view/ViewShadowNode.cpp @@ -39,6 +39,15 @@ ViewShadowNode::ViewShadowNode( void ViewShadowNode::initialize() noexcept { auto& viewProps = static_cast(*props_); + auto hasBorder = [&]() { + for (auto edge : yoga::ordinals()) { + if (viewProps.yogaStyle.border()[yoga::unscopedEnum(edge)].isDefined()) { + return true; + } + } + return false; + }; + bool formsStackingContext = !viewProps.collapsable || viewProps.pointerEvents == PointerEventsMode::None || !viewProps.nativeId.empty() || viewProps.accessible || @@ -55,8 +64,7 @@ void ViewShadowNode::initialize() noexcept { HostPlatformViewTraitsInitializer::formsStackingContext(viewProps); bool formsView = formsStackingContext || - isColorMeaningful(viewProps.backgroundColor) || - !(viewProps.yogaStyle.border() == yoga::Style::Edges{}) || + isColorMeaningful(viewProps.backgroundColor) || hasBorder() || !viewProps.testId.empty() || HostPlatformViewTraitsInitializer::formsView(viewProps); diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/platform/android/react/renderer/components/view/YogaStylablePropsMapBuffer.cpp b/packages/react-native/ReactCommon/react/renderer/components/view/platform/android/react/renderer/components/view/YogaStylablePropsMapBuffer.cpp index 640a407caec03b..315f8b99eeda4c 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/platform/android/react/renderer/components/view/YogaStylablePropsMapBuffer.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/view/platform/android/react/renderer/components/view/YogaStylablePropsMapBuffer.cpp @@ -13,22 +13,30 @@ namespace facebook::react { -MapBuffer convertBorderWidths(const yoga::Style::Edges& border) { +MapBuffer convertBorderWidths(const yoga::Style& style) { MapBufferBuilder builder(7); putOptionalFloat( - builder, EDGE_TOP, optionalFloatFromYogaValue(border[YGEdgeTop])); + builder, EDGE_TOP, optionalFloatFromYogaValue(style.border()[YGEdgeTop])); putOptionalFloat( - builder, EDGE_RIGHT, optionalFloatFromYogaValue(border[YGEdgeRight])); + builder, + EDGE_RIGHT, + optionalFloatFromYogaValue(style.border()[YGEdgeRight])); putOptionalFloat( - builder, EDGE_BOTTOM, optionalFloatFromYogaValue(border[YGEdgeBottom])); + builder, + EDGE_BOTTOM, + optionalFloatFromYogaValue(style.border()[YGEdgeBottom])); putOptionalFloat( - builder, EDGE_LEFT, optionalFloatFromYogaValue(border[YGEdgeLeft])); + builder, + EDGE_LEFT, + optionalFloatFromYogaValue(style.border()[YGEdgeLeft])); putOptionalFloat( - builder, EDGE_START, optionalFloatFromYogaValue(border[YGEdgeStart])); + builder, + EDGE_START, + optionalFloatFromYogaValue(style.border()[YGEdgeStart])); putOptionalFloat( - builder, EDGE_END, optionalFloatFromYogaValue(border[YGEdgeEnd])); + builder, EDGE_END, optionalFloatFromYogaValue(style.border()[YGEdgeEnd])); putOptionalFloat( - builder, EDGE_ALL, optionalFloatFromYogaValue(border[YGEdgeAll])); + builder, EDGE_ALL, optionalFloatFromYogaValue(style.border()[YGEdgeAll])); return builder.build(); } @@ -54,9 +62,17 @@ void YogaStylableProps::propsDiffMapBuffer( const auto& oldStyle = oldProps.yogaStyle; const auto& newStyle = newProps.yogaStyle; - if (!(oldStyle.border() == newStyle.border())) { - builder.putMapBuffer( - YG_BORDER_WIDTH, convertBorderWidths(newStyle.border())); + bool areBordersEqual = true; + for (auto edge : yoga::ordinals()) { + if (oldStyle.border()[yoga::unscopedEnum(edge)] != + newStyle.border()[yoga::unscopedEnum(edge)]) { + areBordersEqual = false; + break; + } + } + + if (!areBordersEqual) { + builder.putMapBuffer(YG_BORDER_WIDTH, convertBorderWidths(newStyle)); } if (oldStyle.overflow() != newStyle.overflow()) { diff --git a/packages/react-native/ReactCommon/yoga/yoga/enums/YogaEnums.h b/packages/react-native/ReactCommon/yoga/yoga/enums/YogaEnums.h index 7cbf94b72f8601..a3e1191de11eae 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/enums/YogaEnums.h +++ b/packages/react-native/ReactCommon/yoga/yoga/enums/YogaEnums.h @@ -7,6 +7,7 @@ #pragma once +#include #include namespace facebook::yoga { @@ -14,13 +15,52 @@ namespace facebook::yoga { template constexpr inline int32_t ordinalCount(); +/** + * Count of bits needed to represent every ordinal + */ template constexpr inline int32_t bitCount(); -// Polyfill of C++ 23 to_underlying() -// https://en.cppreference.com/w/cpp/utility/to_underlying +/** + * Polyfill of C++ 23 to_underlying() + * https://en.cppreference.com/w/cpp/utility/to_underlying + */ constexpr auto to_underlying(auto e) noexcept { return static_cast>(e); } +/** + * Convenience function to iterate through every value in a Yoga enum as part of + * a range-based for loop. + */ +template +auto ordinals() { + struct Iterator { + EnumT e{}; + + EnumT operator*() const { + return e; + } + + Iterator& operator++() { + e = static_cast(to_underlying(e) + 1); + return *this; + } + + bool operator==(const Iterator& other) const = default; + bool operator!=(const Iterator& other) const = default; + }; + + struct Range { + Iterator begin() const { + return Iterator{}; + } + Iterator end() const { + return Iterator{static_cast(ordinalCount())}; + } + }; + + return Range{}; +} + } // namespace facebook::yoga diff --git a/packages/react-native/ReactCommon/yoga/yoga/style/Style.h b/packages/react-native/ReactCommon/yoga/yoga/style/Style.h index 3eb5cadd195e16..2df44a75ab7c89 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/style/Style.h +++ b/packages/react-native/ReactCommon/yoga/yoga/style/Style.h @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include From 08f89eb2ae53162e3eaf8453c859531aa00665cf Mon Sep 17 00:00:00 2001 From: Nick Gerleman Date: Tue, 21 Nov 2023 23:17:32 -0800 Subject: [PATCH 050/162] Remove `yoga::Style::Edges` usage in `AndroidTextInputComponentDescriptor` (#41598) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41598 This code merges native, Android provided theme text input padding, with Yoga style. We are removing operations on all edges as aggregate, so this replaces that. This was previously part of D50998164 Changelog: [Internal] Reviewed By: javache Differential Revision: D51503493 fbshipit-source-id: c6e2f3183a05861745fdd8f044d12e3dd8205804 --- .../AndroidTextInputComponentDescriptor.h | 53 +++++++++---------- 1 file changed, 26 insertions(+), 27 deletions(-) diff --git a/packages/react-native/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputComponentDescriptor.h b/packages/react-native/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputComponentDescriptor.h index 04d19a11bfbdb6..5ca2b167f65a94 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputComponentDescriptor.h +++ b/packages/react-native/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputComponentDescriptor.h @@ -40,7 +40,7 @@ class AndroidTextInputComponentDescriptor final const ShadowNodeFamily::Shared& family) const override { int surfaceId = family->getSurfaceId(); - yoga::Style::Edges theme; + ThemePadding theme; // TODO: figure out RTL/start/end/left/right stuff here if (surfaceIdToThemePaddingMap_.find(surfaceId) != surfaceIdToThemePaddingMap_.end()) { @@ -59,11 +59,10 @@ class AndroidTextInputComponentDescriptor final fabricUIManager, surfaceId, defaultTextInputPaddingArray)) { jfloat* defaultTextInputPadding = env->GetFloatArrayElements(defaultTextInputPaddingArray, 0); - theme[YGEdgeStart] = (YGValue){defaultTextInputPadding[0], YGUnitPoint}; - theme[YGEdgeEnd] = (YGValue){defaultTextInputPadding[1], YGUnitPoint}; - theme[YGEdgeTop] = (YGValue){defaultTextInputPadding[2], YGUnitPoint}; - theme[YGEdgeBottom] = - (YGValue){defaultTextInputPadding[3], YGUnitPoint}; + theme.start = defaultTextInputPadding[0]; + theme.end = defaultTextInputPadding[1]; + theme.top = defaultTextInputPadding[2]; + theme.bottom = defaultTextInputPadding[3]; surfaceIdToThemePaddingMap_.emplace(std::make_pair(surfaceId, theme)); env->ReleaseFloatArrayElements( defaultTextInputPaddingArray, defaultTextInputPadding, JNI_ABORT); @@ -73,14 +72,7 @@ class AndroidTextInputComponentDescriptor final return std::make_shared( std::make_shared(AndroidTextInputState( - 0, - {}, - {}, - {}, - ((YGValue)theme[YGEdgeStart]).value, - ((YGValue)theme[YGEdgeEnd]).value, - ((YGValue)theme[YGEdgeTop]).value, - ((YGValue)theme[YGEdgeBottom]).value)), + 0, {}, {}, {}, theme.start, theme.end, theme.top, theme.bottom)), family); } @@ -99,7 +91,7 @@ class AndroidTextInputComponentDescriptor final int surfaceId = textInputShadowNode.getSurfaceId(); if (surfaceIdToThemePaddingMap_.find(surfaceId) != surfaceIdToThemePaddingMap_.end()) { - yoga::Style::Edges theme = surfaceIdToThemePaddingMap_[surfaceId]; + const auto& theme = surfaceIdToThemePaddingMap_[surfaceId]; auto& textInputProps = textInputShadowNode.getConcreteProps(); @@ -108,29 +100,33 @@ class AndroidTextInputComponentDescriptor final // TODO: T62959168 account for RTL and paddingLeft when setting default // paddingStart, and vice-versa with paddingRight/paddingEnd. // For now this assumes no RTL. - yoga::Style::Edges result = textInputProps.yogaStyle.padding(); + auto& style = const_cast(textInputProps.yogaStyle); bool changedPadding = false; if (!textInputProps.hasPadding && !textInputProps.hasPaddingStart && !textInputProps.hasPaddingLeft && !textInputProps.hasPaddingHorizontal) { changedPadding = true; - result[YGEdgeStart] = theme[YGEdgeStart]; + style.padding()[YGEdgeStart] = + yoga::CompactValue::of(theme.start); } if (!textInputProps.hasPadding && !textInputProps.hasPaddingEnd && !textInputProps.hasPaddingRight && !textInputProps.hasPaddingHorizontal) { changedPadding = true; - result[YGEdgeEnd] = theme[YGEdgeEnd]; + style.padding()[YGEdgeEnd] = + yoga::CompactValue::of(theme.end); } if (!textInputProps.hasPadding && !textInputProps.hasPaddingTop && !textInputProps.hasPaddingVertical) { changedPadding = true; - result[YGEdgeTop] = theme[YGEdgeTop]; + style.padding()[YGEdgeTop] = + yoga::CompactValue::of(theme.top); } if (!textInputProps.hasPadding && !textInputProps.hasPaddingBottom && !textInputProps.hasPaddingVertical) { changedPadding = true; - result[YGEdgeBottom] = theme[YGEdgeBottom]; + style.padding()[YGEdgeBottom] = + yoga::CompactValue::of(theme.bottom); } // If the TextInput initially does not have paddingLeft or paddingStart, a @@ -141,21 +137,18 @@ class AndroidTextInputComponentDescriptor final if ((textInputProps.hasPadding || textInputProps.hasPaddingLeft || textInputProps.hasPaddingHorizontal) && !textInputProps.hasPaddingStart) { - result[YGEdgeStart] = YGValueUndefined; + style.padding()[YGEdgeStart] = yoga::CompactValue::ofUndefined(); } if ((textInputProps.hasPadding || textInputProps.hasPaddingRight || textInputProps.hasPaddingHorizontal) && !textInputProps.hasPaddingEnd) { - result[YGEdgeEnd] = YGValueUndefined; + style.padding()[YGEdgeEnd] = yoga::CompactValue::ofUndefined(); } // Note that this is expensive: on every adopt, we need to set the Yoga // props again, which normally only happens during prop parsing. Every // commit, state update, etc, will incur this cost. if (changedPadding) { - // Set new props on node - const_cast(textInputProps).yogaStyle.padding() = - result; // Communicate new props to Yoga part of the node textInputShadowNode.updateYogaProps(); } @@ -168,13 +161,19 @@ class AndroidTextInputComponentDescriptor final } private: + struct ThemePadding { + float start{}; + float end{}; + float top{}; + float bottom{}; + }; + // TODO T68526882: Unify with Binding::UIManagerJavaDescriptor constexpr static auto UIManagerJavaDescriptor = "com/facebook/react/fabric/FabricUIManager"; SharedTextLayoutManager textLayoutManager_; - mutable std::unordered_map - surfaceIdToThemePaddingMap_; + mutable std::unordered_map surfaceIdToThemePaddingMap_; }; } // namespace facebook::react From 2a4338d09118bb57570bd2493f8375f3dff05127 Mon Sep 17 00:00:00 2001 From: Dark Knight <> Date: Tue, 21 Nov 2023 23:48:48 -0800 Subject: [PATCH 051/162] Revert D51346658: Multisect successfully blamed "D51346658: [RN][Android] Handle all incoming Inspector messages on main thread, downgrade some errors to logs" for otest failure Summary: This diff is reverting D51346658 D51346658: [RN][Android] Handle all incoming Inspector messages on main thread, downgrade some errors to logs by motiz88 has been identified to be causing the following test failure: Tests affected: - [xplat/endtoend/jest-e2e/apps/facebook_xplat/ReactNativeTTRCTester/__tests__/ReactNativeTTRCTester-storeOrNetworkWithoutCachedContent-android-e2e.js](https://www.internalfb.com/intern/test/281475019301167/) Here's the Multisect link: https://www.internalfb.com/multisect/3539088 Here are the tasks that are relevant to this breakage: We're generating a revert to back out the changes in this diff, please note the backout may land if someone accepts it. If you believe this diff has been generated in error you may Commandeer and Abandon it. bypass-github-export-checks Changelog: [Internal] Reviewed By: motiz88 Differential Revision: D51512872 fbshipit-source-id: 8bc8e12b651f91a6f74243a0a85fca7fd1953bdb --- .../react/devsupport/DevServerHelper.java | 28 +++++-- .../devsupport/DevSupportManagerBase.java | 11 +-- .../InspectorPackagerConnection.java | 79 ++++++++----------- 3 files changed, 54 insertions(+), 64 deletions(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevServerHelper.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevServerHelper.java index 2b8aee80f75ee0..4cef3eed690491 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevServerHelper.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevServerHelper.java @@ -210,10 +210,16 @@ public void openInspectorConnection() { FLog.w(ReactConstants.TAG, "Inspector connection already open, nooping."); return; } - mInspectorPackagerConnection = - new InspectorPackagerConnection( - getInspectorDeviceUrl(), mPackageName, mBundlerStatusProvider); - mInspectorPackagerConnection.connect(); + new AsyncTask() { + @Override + protected Void doInBackground(Void... params) { + mInspectorPackagerConnection = + new InspectorPackagerConnection( + getInspectorDeviceUrl(), mPackageName, mBundlerStatusProvider); + mInspectorPackagerConnection.connect(); + return null; + } + }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } public void disableDebugger() { @@ -223,10 +229,16 @@ public void disableDebugger() { } public void closeInspectorConnection() { - if (mInspectorPackagerConnection != null) { - mInspectorPackagerConnection.closeQuietly(); - mInspectorPackagerConnection = null; - } + new AsyncTask() { + @Override + protected Void doInBackground(Void... params) { + if (mInspectorPackagerConnection != null) { + mInspectorPackagerConnection.closeQuietly(); + mInspectorPackagerConnection = null; + } + return null; + } + }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } public String getWebsocketProxyURL() { diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevSupportManagerBase.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevSupportManagerBase.java index a72dc10cf85e74..e242858a71b2fc 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevSupportManagerBase.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevSupportManagerBase.java @@ -942,7 +942,6 @@ private void reportBundleLoadingFailure(final Exception cause) { @Override public void startInspector() { - UiThreadUtil.assertOnUiThread(); if (mIsDevSupportEnabled) { mDevServerHelper.openInspectorConnection(); } @@ -950,7 +949,6 @@ public void startInspector() { @Override public void stopInspector() { - UiThreadUtil.assertOnUiThread(); mDevServerHelper.closeInspectorConnection(); } @@ -1047,12 +1045,9 @@ public void onPackagerDisconnected() { @Override public void onPackagerReloadCommand() { - UiThreadUtil.runOnUiThread( - () -> { - // Disable debugger to resume the JsVM & avoid thread locks while reloading - mDevServerHelper.disableDebugger(); - handleReloadJS(); - }); + // Disable debugger to resume the JsVM & avoid thread locks while reloading + mDevServerHelper.disableDebugger(); + UiThreadUtil.runOnUiThread(() -> handleReloadJS()); } @Override diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/InspectorPackagerConnection.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/InspectorPackagerConnection.java index ee4b4e591f983c..5f535b7044d6fa 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/InspectorPackagerConnection.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/InspectorPackagerConnection.java @@ -8,10 +8,12 @@ package com.facebook.react.devsupport; import android.os.AsyncTask; +import android.os.Handler; +import android.os.Looper; import androidx.annotation.Nullable; import com.facebook.common.logging.FLog; import com.facebook.react.bridge.Inspector; -import com.facebook.react.bridge.UiThreadUtil; +import java.io.IOException; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -35,7 +37,6 @@ public class InspectorPackagerConnection { public InspectorPackagerConnection( String url, String packageName, BundleStatusProvider bundleStatusProvider) { - UiThreadUtil.assertOnUiThread(); mConnection = new Connection(url); mInspectorConnections = new HashMap<>(); mPackageName = packageName; @@ -43,12 +44,10 @@ public InspectorPackagerConnection( } public void connect() { - UiThreadUtil.assertOnUiThread(); mConnection.connect(); } public void closeQuietly() { - UiThreadUtil.assertOnUiThread(); mConnection.close(); } @@ -60,7 +59,7 @@ public void sendEventToAllConnections(String event) { } } - void handleProxyMessage(JSONObject message) throws JSONException { + void handleProxyMessage(JSONObject message) throws JSONException, IOException { String event = message.getString("event"); switch (event) { case "getPages": @@ -76,8 +75,7 @@ void handleProxyMessage(JSONObject message) throws JSONException { handleDisconnect(message.getJSONObject("payload")); break; default: - FLog.e(TAG, "Unknown event: " + event); - break; + throw new IllegalArgumentException("Unknown event: " + event); } } @@ -92,8 +90,7 @@ private void handleConnect(JSONObject payload) throws JSONException { final String pageId = payload.getString("pageId"); Inspector.LocalConnection inspectorConnection = mInspectorConnections.remove(pageId); if (inspectorConnection != null) { - FLog.w(TAG, "Already connected: " + pageId); - return; + throw new IllegalStateException("Already connected: " + pageId); } try { @@ -194,65 +191,49 @@ private class Connection extends WebSocketListener { private OkHttpClient mHttpClient; private @Nullable WebSocket mWebSocket; + private final Handler mHandler; private boolean mClosed; private boolean mSuppressConnectionErrors; public Connection(String url) { mUrl = url; + mHandler = new Handler(Looper.getMainLooper()); } @Override public void onOpen(WebSocket webSocket, Response response) { - UiThreadUtil.runOnUiThread( - () -> { - mWebSocket = webSocket; - }); + mWebSocket = webSocket; } @Override public void onFailure(WebSocket webSocket, Throwable t, Response response) { - UiThreadUtil.runOnUiThread( - () -> { - if (mWebSocket != null) { - abort("Websocket exception", t); - } - if (!mClosed) { - reconnect(); - } - }); + if (mWebSocket != null) { + abort("Websocket exception", t); + } + if (!mClosed) { + reconnect(); + } } @Override public void onMessage(WebSocket webSocket, String text) { try { - JSONObject parsed = new JSONObject(text); - UiThreadUtil.runOnUiThread( - () -> { - try { - handleProxyMessage(parsed); - } catch (JSONException e) { - FLog.w(TAG, "Error handling inspector message", e); - } - }); - } catch (JSONException e) { - FLog.w(TAG, "Unrecognized inspector message, string was not valid JSON: " + text, e); + handleProxyMessage(new JSONObject(text)); + } catch (Exception e) { + throw new RuntimeException(e); } } @Override public void onClosed(WebSocket webSocket, int code, String reason) { - UiThreadUtil.runOnUiThread( - () -> { - mWebSocket = null; - closeAllConnections(); - if (!mClosed) { - reconnect(); - } - }); + mWebSocket = null; + closeAllConnections(); + if (!mClosed) { + reconnect(); + } } public void connect() { - UiThreadUtil.assertOnUiThread(); if (mClosed) { throw new IllegalStateException("Can't connect closed client"); } @@ -277,18 +258,20 @@ private void reconnect() { FLog.w(TAG, "Couldn't connect to packager, will silently retry"); mSuppressConnectionErrors = true; } - UiThreadUtil.runOnUiThread( - () -> { - // check that we haven't been closed in the meantime - if (!mClosed) { - connect(); + mHandler.postDelayed( + new Runnable() { + @Override + public void run() { + // check that we haven't been closed in the meantime + if (!mClosed) { + connect(); + } } }, RECONNECT_DELAY_MS); } public void close() { - UiThreadUtil.assertOnUiThread(); mClosed = true; if (mWebSocket != null) { try { From 0cbd2a345d613b1b6e6a5b1c2965018adfb45f6f Mon Sep 17 00:00:00 2001 From: Nicola Corti Date: Wed, 22 Nov 2023 03:37:13 -0800 Subject: [PATCH 052/162] Update Element Inspector string to "Toggle" (#41595) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41595 Instead of having to select between Enable/Hide the Element Inspector String, let's just use "Toggle". Changelog: [Internal] [Changed] - Update Element Inspector string to "Toggle" Reviewed By: cipolleschi Differential Revision: D51503403 fbshipit-source-id: 2ad24df8324eb789b0016fe7ac5d439cba6f5952 --- packages/react-native/React/CoreModules/RCTDevMenu.mm | 3 +-- .../com/facebook/react/devsupport/DevSupportManagerBase.java | 4 +--- .../ReactAndroid/src/main/res/devsupport/values/strings.xml | 3 +-- 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/packages/react-native/React/CoreModules/RCTDevMenu.mm b/packages/react-native/React/CoreModules/RCTDevMenu.mm index 10b218a3f632e7..1a970a7d086952 100644 --- a/packages/react-native/React/CoreModules/RCTDevMenu.mm +++ b/packages/react-native/React/CoreModules/RCTDevMenu.mm @@ -283,8 +283,7 @@ - (void)setDefaultJSBundle [items addObject:[RCTDevMenuItem buttonItemWithTitleBlock:^NSString * { - return devSettings.isElementInspectorShown ? @"Hide Element Inspector" - : @"Show Element Inspector"; + return @"Toggle Element Inspector"; } handler:^{ [devSettings toggleElementInspector]; diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevSupportManagerBase.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevSupportManagerBase.java index e242858a71b2fc..b9ab16eb9f95d1 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevSupportManagerBase.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevSupportManagerBase.java @@ -414,9 +414,7 @@ public void onClick(DialogInterface dialog, int which) { }); options.put( - mDevSettings.isElementInspectorEnabled() - ? mApplicationContext.getString(R.string.catalyst_inspector_stop) - : mApplicationContext.getString(R.string.catalyst_inspector), + mApplicationContext.getString(R.string.catalyst_inspector_toggle), new DevOptionHandler() { @Override public void onOptionSelected() { diff --git a/packages/react-native/ReactAndroid/src/main/res/devsupport/values/strings.xml b/packages/react-native/ReactAndroid/src/main/res/devsupport/values/strings.xml index 171c092546e813..d562be6d686f5f 100644 --- a/packages/react-native/ReactAndroid/src/main/res/devsupport/values/strings.xml +++ b/packages/react-native/ReactAndroid/src/main/res/devsupport/values/strings.xml @@ -11,8 +11,7 @@ Disable Fast Refresh Disabling Fast Refresh because it requires a development bundle. Switching to development bundle in order to enable Fast Refresh. - Show Element Inspector - Hide Element Inspector + Toggle Element Inspector Show Perf Monitor Hide Perf Monitor Settings From 13d08f146b1fd23d4049b30243c22fa66fa945d7 Mon Sep 17 00:00:00 2001 From: Riccardo Cipolleschi Date: Wed, 22 Nov 2023 03:50:29 -0800 Subject: [PATCH 053/162] Remove RN_FABRIC_ENABLED flag (#41561) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41561 The RN_FABRIC_ENABLED has been deprecated and superseded by the RCT_NEW_ARCH_ENABLED for a while now. This change removes it, from the codebase as now we always have the Fabric pod available to the codebase. ## Changelog [Internal] - Remove RN_FABRIC_ENABLED flag Reviewed By: dmytrorykun Differential Revision: D51468332 fbshipit-source-id: 6b2fc554e6bf5ac748b9e45d7c14f9ba9b57820c --- .../AppDelegate/React-RCTAppDelegate.podspec | 3 +- .../React/React-RCTFabric.podspec | 2 +- .../ReactCommon/jsc/CMakeLists.txt | 4 -- .../ReactCommon/jsc/JSCRuntime.cpp | 13 ---- .../ReactCommon/jsc/React-jsc.podspec | 2 +- .../scripts/cocoapods/__tests__/utils-test.rb | 62 ------------------- .../react-native/scripts/cocoapods/utils.rb | 9 --- .../react-native/scripts/react_native_pods.rb | 1 - .../RNTesterPods.xcodeproj/project.pbxproj | 12 +--- 9 files changed, 5 insertions(+), 103 deletions(-) diff --git a/packages/react-native/Libraries/AppDelegate/React-RCTAppDelegate.podspec b/packages/react-native/Libraries/AppDelegate/React-RCTAppDelegate.podspec index 815c03705ed402..d542966ee1ac94 100644 --- a/packages/react-native/Libraries/AppDelegate/React-RCTAppDelegate.podspec +++ b/packages/react-native/Libraries/AppDelegate/React-RCTAppDelegate.podspec @@ -24,9 +24,8 @@ use_hermes = ENV['USE_HERMES'] == nil || ENV['USE_HERMES'] == '1' new_arch_enabled_flag = (is_new_arch_enabled ? " -DRCT_NEW_ARCH_ENABLED" : "") is_fabric_enabled = is_new_arch_enabled || ENV["RCT_FABRIC_ENABLED"] -fabric_flag = (is_fabric_enabled ? " -DRN_FABRIC_ENABLED" : "") hermes_flag = (use_hermes ? " -DUSE_HERMES" : "") -other_cflags = "$(inherited)" + folly_flags + new_arch_enabled_flag + fabric_flag + hermes_flag +other_cflags = "$(inherited)" + folly_flags + new_arch_enabled_flag + hermes_flag header_search_paths = [ "$(PODS_TARGET_SRCROOT)/../../ReactCommon", diff --git a/packages/react-native/React/React-RCTFabric.podspec b/packages/react-native/React/React-RCTFabric.podspec index 5c2f3c62fd80f4..e6dbb8cb3d4db8 100644 --- a/packages/react-native/React/React-RCTFabric.podspec +++ b/packages/react-native/React/React-RCTFabric.podspec @@ -58,7 +58,7 @@ Pod::Spec.new do |s| s.framework = ["JavaScriptCore", "MobileCoreServices"] s.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => header_search_paths, - "OTHER_CFLAGS" => "$(inherited) -DRN_FABRIC_ENABLED" + " " + folly_flags, + "OTHER_CFLAGS" => "$(inherited) " + folly_flags, "CLANG_CXX_LANGUAGE_STANDARD" => "c++20" }.merge!(ENV['USE_FRAMEWORKS'] != nil ? { "PUBLIC_HEADERS_FOLDER_PATH" => "#{module_name}.framework/Headers/#{header_dir}" diff --git a/packages/react-native/ReactCommon/jsc/CMakeLists.txt b/packages/react-native/ReactCommon/jsc/CMakeLists.txt index c5c17fb4048da8..d71b289679bcfa 100644 --- a/packages/react-native/ReactCommon/jsc/CMakeLists.txt +++ b/packages/react-native/ReactCommon/jsc/CMakeLists.txt @@ -30,10 +30,6 @@ target_link_libraries(jscruntime jsi glog) -# TODO: Remove this flag when ready. -# Android has this enabled by default, but the flag is still needed for iOS. -target_compile_options(jscruntime PRIVATE -DRN_FABRIC_ENABLED) - if(NOT ${CMAKE_BUILD_TYPE} MATCHES Debug) target_compile_options(jscruntime PRIVATE -DNDEBUG) endif() diff --git a/packages/react-native/ReactCommon/jsc/JSCRuntime.cpp b/packages/react-native/ReactCommon/jsc/JSCRuntime.cpp index 34f43c0c08e9a0..40633656596873 100644 --- a/packages/react-native/ReactCommon/jsc/JSCRuntime.cpp +++ b/packages/react-native/ReactCommon/jsc/JSCRuntime.cpp @@ -240,10 +240,7 @@ class JSCRuntime : public jsi::Runtime { static JSStringRef stringRef(const jsi::String& str); static JSStringRef stringRef(const jsi::PropNameID& sym); static JSObjectRef objectRef(const jsi::Object& obj); - -#ifdef RN_FABRIC_ENABLED static JSObjectRef objectRef(const jsi::WeakObject& obj); -#endif // Factory methods for creating String/Object jsi::Symbol createSymbol(JSValueRef symbolRef) const; @@ -1065,23 +1062,15 @@ jsi::Array JSCRuntime::getPropertyNames(const jsi::Object& obj) { } jsi::WeakObject JSCRuntime::createWeakObject(const jsi::Object& obj) { -#ifdef RN_FABRIC_ENABLED // TODO: revisit this implementation JSObjectRef objRef = objectRef(obj); return make(makeObjectValue(objRef)); -#else - throw std::logic_error("Not implemented"); -#endif } jsi::Value JSCRuntime::lockWeakObject(const jsi::WeakObject& obj) { -#ifdef RN_FABRIC_ENABLED // TODO: revisit this implementation JSObjectRef objRef = objectRef(obj); return jsi::Value(createObject(objRef)); -#else - throw std::logic_error("Not implemented"); -#endif } jsi::Array JSCRuntime::createArray(size_t length) { @@ -1527,12 +1516,10 @@ JSObjectRef JSCRuntime::objectRef(const jsi::Object& obj) { return static_cast(getPointerValue(obj))->obj_; } -#ifdef RN_FABRIC_ENABLED JSObjectRef JSCRuntime::objectRef(const jsi::WeakObject& obj) { // TODO: revisit this implementation return static_cast(getPointerValue(obj))->obj_; } -#endif void JSCRuntime::checkException(JSValueRef exc) { if (JSC_UNLIKELY(exc)) { diff --git a/packages/react-native/ReactCommon/jsc/React-jsc.podspec b/packages/react-native/ReactCommon/jsc/React-jsc.podspec index ee9cf096e7a961..6239621c6a8c64 100644 --- a/packages/react-native/ReactCommon/jsc/React-jsc.podspec +++ b/packages/react-native/ReactCommon/jsc/React-jsc.podspec @@ -32,6 +32,6 @@ Pod::Spec.new do |s| s.dependency "React-jsi", version s.subspec "Fabric" do |ss| - ss.pod_target_xcconfig = { "OTHER_CFLAGS" => "$(inherited) -DRN_FABRIC_ENABLED" } + ss.pod_target_xcconfig = { "OTHER_CFLAGS" => "$(inherited)" } end end diff --git a/packages/react-native/scripts/cocoapods/__tests__/utils-test.rb b/packages/react-native/scripts/cocoapods/__tests__/utils-test.rb index 2acd46732eac7d..cf9988492dafb7 100644 --- a/packages/react-native/scripts/cocoapods/__tests__/utils-test.rb +++ b/packages/react-native/scripts/cocoapods/__tests__/utils-test.rb @@ -790,68 +790,6 @@ def test_updateSearchPaths_whenNotUseFrameworks_addsSearchPaths end end - # ============================= # - # Test - Apply Flags For Fabric # - # ============================= # - def test_applyFlagsForFabric_whenFabricEnabled_addsTheFlag - # Arrange - first_target = prepare_target("FirstTarget") - second_target = prepare_target("SecondTarget") - third_target = prepare_target("ThirdTarget", "com.apple.product-type.bundle") - user_project_mock = UserProjectMock.new("a/path", [ - prepare_config("Debug"), - prepare_config("Release"), - ], - :native_targets => [ - first_target, - second_target - ] - ) - pods_projects_mock = PodsProjectMock.new([third_target], {"hermes-engine" => {}}) - installer = InstallerMock.new(pods_projects_mock, [ - AggregatedProjectMock.new(user_project_mock) - ]) - - # Act - ReactNativePodsUtils.apply_flags_for_fabric(installer, fabric_enabled: true) - - # Assert - user_project_mock.build_configurations.each do |config| - received_cflags = config.build_settings["OTHER_CFLAGS"] - expected_cflags = "$(inherited) -DRN_FABRIC_ENABLED" - assert_equal(received_cflags, expected_cflags) - end - - end - - def test_applyFlagsForFabric_whenFabricDisabled_doNothing - # Arrange - first_target = prepare_target("FirstTarget") - second_target = prepare_target("SecondTarget") - third_target = prepare_target("ThirdTarget", "com.apple.product-type.bundle") - user_project_mock = UserProjectMock.new("/a/path", [ - prepare_config("Debug"), - prepare_config("Release"), - ], - :native_targets => [ - first_target, - second_target - ] - ) - pods_projects_mock = PodsProjectMock.new([third_target], {"hermes-engine" => {}}) - installer = InstallerMock.new(pods_projects_mock, [ - AggregatedProjectMock.new(user_project_mock) - ]) - - # Act - ReactNativePodsUtils.apply_flags_for_fabric(installer, fabric_enabled: false) - - # Assert - user_project_mock.build_configurations.each do |config| - assert_equal(config.build_settings["OTHER_CFLAGS"], "$(inherited)") - end - end - # ============================== # # Test - Apply ATS configuration # # ============================== # diff --git a/packages/react-native/scripts/cocoapods/utils.rb b/packages/react-native/scripts/cocoapods/utils.rb index eb89a3de20045d..11cb59a62c528f 100644 --- a/packages/react-native/scripts/cocoapods/utils.rb +++ b/packages/react-native/scripts/cocoapods/utils.rb @@ -147,15 +147,6 @@ def self.apply_xcode_15_patch(installer, xcodebuild_manager: Xcodebuild) end - def self.apply_flags_for_fabric(installer, fabric_enabled: false) - fabric_flag = "-DRN_FABRIC_ENABLED" - if fabric_enabled - self.add_compiler_flag_to_project(installer, fabric_flag) - else - self.remove_compiler_flag_from_project(installer, fabric_flag) - end - end - private def self.add_build_settings_to_pod(installer, settings_name, settings_value, target_pod_name, configuration) diff --git a/packages/react-native/scripts/react_native_pods.rb b/packages/react-native/scripts/react_native_pods.rb index 93d9b6536e3efd..472a563baddc05 100644 --- a/packages/react-native/scripts/react_native_pods.rb +++ b/packages/react-native/scripts/react_native_pods.rb @@ -281,7 +281,6 @@ def react_native_post_install( ReactNativePodsUtils.update_search_paths(installer) ReactNativePodsUtils.set_use_hermes_build_setting(installer, hermes_enabled) ReactNativePodsUtils.set_node_modules_user_settings(installer, react_native_path) - ReactNativePodsUtils.apply_flags_for_fabric(installer, fabric_enabled: fabric_enabled) ReactNativePodsUtils.apply_xcode_15_patch(installer) ReactNativePodsUtils.apply_ats_config(installer) ReactNativePodsUtils.updateOSDeploymentTarget(installer) diff --git a/packages/rn-tester/RNTesterPods.xcodeproj/project.pbxproj b/packages/rn-tester/RNTesterPods.xcodeproj/project.pbxproj index ff0cf5e629d1e3..848876452f472a 100644 --- a/packages/rn-tester/RNTesterPods.xcodeproj/project.pbxproj +++ b/packages/rn-tester/RNTesterPods.xcodeproj/project.pbxproj @@ -933,10 +933,7 @@ IPHONEOS_DEPLOYMENT_TARGET = 13.4; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; - OTHER_CFLAGS = ( - "$(inherited)", - "-DRN_FABRIC_ENABLED", - ); + OTHER_CFLAGS = "$(inherited)"; OTHER_CPLUSPLUSFLAGS = ( "$(OTHER_CFLAGS)", "-DFOLLY_NO_CONFIG", @@ -944,7 +941,6 @@ "-DFOLLY_USE_LIBCPP=1", "-DFOLLY_CFG_NO_COROUTINES=1", "-DFOLLY_HAVE_CLOCK_GETTIME=1", - "-DRN_FABRIC_ENABLED", ); OTHER_LDFLAGS = ( "-ObjC", @@ -1029,10 +1025,7 @@ ); IPHONEOS_DEPLOYMENT_TARGET = 13.4; MTL_ENABLE_DEBUG_INFO = NO; - OTHER_CFLAGS = ( - "$(inherited)", - "-DRN_FABRIC_ENABLED", - ); + OTHER_CFLAGS = "$(inherited)"; OTHER_CPLUSPLUSFLAGS = ( "$(OTHER_CFLAGS)", "-DFOLLY_NO_CONFIG", @@ -1040,7 +1033,6 @@ "-DFOLLY_USE_LIBCPP=1", "-DFOLLY_CFG_NO_COROUTINES=1", "-DFOLLY_HAVE_CLOCK_GETTIME=1", - "-DRN_FABRIC_ENABLED", ); OTHER_LDFLAGS = ( "-ObjC", From a6076924bf43dff6cf4d38d51df279edba3882d0 Mon Sep 17 00:00:00 2001 From: Riccardo Cipolleschi Date: Wed, 22 Nov 2023 03:50:29 -0800 Subject: [PATCH 054/162] Remove unused flag in Old Architecture codegen (#41579) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41579 This change remove a flag that is unused. ## Changelog [Internal] - Remove unused Flag Reviewed By: dmytrorykun Differential Revision: D51493765 fbshipit-source-id: f8cbce991d80d4f51363cdd4f379e6b214b2b2df --- .../react_native_pods_utils/__tests__/script_phases.snap.rb | 2 -- .../scripts/react_native_pods_utils/script_phases.rb | 1 - 2 files changed, 3 deletions(-) diff --git a/packages/react-native/scripts/react_native_pods_utils/__tests__/script_phases.snap.rb b/packages/react-native/scripts/react_native_pods_utils/__tests__/script_phases.snap.rb index e0eadb876940e7..ff4604b259bef4 100644 --- a/packages/react-native/scripts/react_native_pods_utils/__tests__/script_phases.snap.rb +++ b/packages/react-native/scripts/react_native_pods_utils/__tests__/script_phases.snap.rb @@ -13,7 +13,6 @@ def snap_get_script_phases_with_codegen_discovery_with_config_file_dir() export RCT_SCRIPT_APP_PATH=$RCT_SCRIPT_POD_INSTALLATION_ROOT/ export RCT_SCRIPT_CONFIG_FILE_DIR=$RCT_SCRIPT_POD_INSTALLATION_ROOT/node_modules export RCT_SCRIPT_OUTPUT_DIR=$RCT_SCRIPT_POD_INSTALLATION_ROOT - export RCT_SCRIPT_FABRIC_ENABLED=true export RCT_SCRIPT_TYPE=withCodegenDiscovery SCRIPT_PHASES_SCRIPT="$RCT_SCRIPT_RN_DIR/scripts/react_native_pods_utils/script_phases.sh" @@ -32,7 +31,6 @@ def snap_get_script_phases_with_codegen_discovery_without_config_file_dir() export RCT_SCRIPT_APP_PATH=$RCT_SCRIPT_POD_INSTALLATION_ROOT/ export RCT_SCRIPT_CONFIG_FILE_DIR= export RCT_SCRIPT_OUTPUT_DIR=$RCT_SCRIPT_POD_INSTALLATION_ROOT - export RCT_SCRIPT_FABRIC_ENABLED=true export RCT_SCRIPT_TYPE=withCodegenDiscovery SCRIPT_PHASES_SCRIPT="$RCT_SCRIPT_RN_DIR/scripts/react_native_pods_utils/script_phases.sh" diff --git a/packages/react-native/scripts/react_native_pods_utils/script_phases.rb b/packages/react-native/scripts/react_native_pods_utils/script_phases.rb index eb1accba25a285..78a381c403a31b 100644 --- a/packages/react-native/scripts/react_native_pods_utils/script_phases.rb +++ b/packages/react-native/scripts/react_native_pods_utils/script_phases.rb @@ -13,7 +13,6 @@ def get_script_phases_with_codegen_discovery(options) 'RCT_SCRIPT_APP_PATH' => "$RCT_SCRIPT_POD_INSTALLATION_ROOT/#{options[:relative_app_root]}", 'RCT_SCRIPT_CONFIG_FILE_DIR' => "#{options[:relative_config_file_dir] != '' ? "$RCT_SCRIPT_POD_INSTALLATION_ROOT/#{options[:relative_config_file_dir]}" : ''}", 'RCT_SCRIPT_OUTPUT_DIR' => "$RCT_SCRIPT_POD_INSTALLATION_ROOT", - 'RCT_SCRIPT_FABRIC_ENABLED' => "#{options[:fabric_enabled]}", 'RCT_SCRIPT_TYPE' => "withCodegenDiscovery", } return get_script_template(options[:react_native_path], export_vars) From 6b5320540adfe16803ef41353f23115d08819309 Mon Sep 17 00:00:00 2001 From: Riccardo Cipolleschi Date: Wed, 22 Nov 2023 03:50:29 -0800 Subject: [PATCH 055/162] Always install all the pods (#41588) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41588 This change always installs all the Pods for both architecture. This unify the behavior between iOS and Android. ## Changelog: [Internal] - Always install all the pods ## Facebook: The inly four pods that are changed when flipping between the new and the old arch with RNTester are: - MyNativeView - NativeCxxModuleExample - React-RCTAppDelegate - ScreenshotManager The only change there is the RCt_NEW_ARCH_ENABLED flag being set or not in those pods Reviewed By: dmytrorykun Differential Revision: D51494498 fbshipit-source-id: 4cafdef4a4c2b86381067373aed27ed18524e4be --- .../AppDelegate/React-RCTAppDelegate.podspec | 45 ++++++++----------- .../cocoapods/__tests__/codegen_utils-test.rb | 24 +--------- .../__tests__/test_utils/CodegenUtilsMock.rb | 4 +- .../scripts/cocoapods/codegen_utils.rb | 13 ++---- .../react-native/scripts/react_native_pods.rb | 12 ++--- 5 files changed, 26 insertions(+), 72 deletions(-) diff --git a/packages/react-native/Libraries/AppDelegate/React-RCTAppDelegate.podspec b/packages/react-native/Libraries/AppDelegate/React-RCTAppDelegate.podspec index d542966ee1ac94..ad7fee87cfe967 100644 --- a/packages/react-native/Libraries/AppDelegate/React-RCTAppDelegate.podspec +++ b/packages/react-native/Libraries/AppDelegate/React-RCTAppDelegate.podspec @@ -80,42 +80,33 @@ Pod::Spec.new do |s| add_dependency(s, "React-NativeModulesApple") add_dependency(s, "React-runtimescheduler") add_dependency(s, "React-RCTFabric", :framework_name => "RCTFabric") - - if is_new_arch_enabled - add_dependency(s, "React-RuntimeCore") - add_dependency(s, "React-RuntimeApple") - if use_hermes - s.dependency "React-RuntimeHermes" - end - end + add_dependency(s, "React-RuntimeCore") + add_dependency(s, "React-RuntimeApple") + add_dependency(s, "React-Fabric", :additional_framework_paths => ["react/renderer/components/view/platform/cxx"]) + add_dependency(s, "React-graphics", :additional_framework_paths => ["react/renderer/graphics/platform/ios"]) + add_dependency(s, "React-utils") + add_dependency(s, "React-debug") + add_dependency(s, "React-rendererdebug") if use_hermes s.dependency "React-hermes" + s.dependency "React-RuntimeHermes" else s.dependency "React-jsc" end - if is_new_arch_enabled - add_dependency(s, "React-Fabric", :additional_framework_paths => ["react/renderer/components/view/platform/cxx"]) - add_dependency(s, "React-graphics", :additional_framework_paths => ["react/renderer/graphics/platform/ios"]) - add_dependency(s, "React-utils") - add_dependency(s, "React-debug") - add_dependency(s, "React-rendererdebug") - - rel_path_from_pods_root_to_app = Pathname.new(ENV['APP_PATH']).relative_path_from(Pod::Config.instance.installation_root) - rel_path_from_pods_to_app = Pathname.new(ENV['APP_PATH']).relative_path_from(File.join(Pod::Config.instance.installation_root, 'Pods')) + rel_path_from_pods_root_to_app = Pathname.new(ENV['APP_PATH']).relative_path_from(Pod::Config.instance.installation_root) + rel_path_from_pods_to_app = Pathname.new(ENV['APP_PATH']).relative_path_from(File.join(Pod::Config.instance.installation_root, 'Pods')) - - s.script_phases = { - :name => "Generate Legacy Components Interop", - :script => " + s.script_phases = { + :name => "Generate Legacy Components Interop", + :script => " WITH_ENVIRONMENT=\"$REACT_NATIVE_PATH/scripts/xcode/with-environment.sh\" source $WITH_ENVIRONMENT ${NODE_BINARY} ${REACT_NATIVE_PATH}/scripts/codegen/generate-legacy-interop-components.js -p #{rel_path_from_pods_to_app} -o ${REACT_NATIVE_PATH}/Libraries/AppDelegate - ", - :execution_position => :before_compile, - :input_files => ["#{rel_path_from_pods_root_to_app}/react-native.config.js"], - :output_files => ["${REACT_NATIVE_PATH}/Libraries/AppDelegate/RCTLegacyInteropComponents.mm"], - } - end + ", + :execution_position => :before_compile, + :input_files => ["#{rel_path_from_pods_root_to_app}/react-native.config.js"], + :output_files => ["${REACT_NATIVE_PATH}/Libraries/AppDelegate/RCTLegacyInteropComponents.mm"], + } end diff --git a/packages/react-native/scripts/cocoapods/__tests__/codegen_utils-test.rb b/packages/react-native/scripts/cocoapods/__tests__/codegen_utils-test.rb index e485b89c21d1b8..e635db3f708efd 100644 --- a/packages/react-native/scripts/cocoapods/__tests__/codegen_utils-test.rb +++ b/packages/react-native/scripts/cocoapods/__tests__/codegen_utils-test.rb @@ -93,25 +93,6 @@ def testGenerateReactCodegenPodspec_whenItHasNotBeenAlreadyGenerated_generatesIt # ========================== # # Test - GetReactCodegenSpec # # ========================== # - - def testGetReactCodegenSpec_whenFabricDisabledAndNoScriptPhases_generatesAPodspec - # Arrange - FileMock.files_to_read('package.json' => '{ "version": "99.98.97"}') - - # Act - podspec = CodegenUtils.new().get_react_codegen_spec( - 'package.json', - :fabric_enabled => false, - :hermes_enabled => true, - :script_phases => nil, - :file_manager => FileMock - ) - - # Assert - assert_equal(podspec, get_podspec_no_fabric_no_script()) - assert_equal(Pod::UI.collected_messages, []) - end - def testGetReactCodegenSpec_whenFabricEnabledAndScriptPhases_generatesAPodspec # Arrange FileMock.files_to_read('package.json' => '{ "version": "99.98.97"}') @@ -119,7 +100,6 @@ def testGetReactCodegenSpec_whenFabricEnabledAndScriptPhases_generatesAPodspec # Act podspec = CodegenUtils.new().get_react_codegen_spec( 'package.json', - :fabric_enabled => true, :hermes_enabled => true, :script_phases => "echo Test Script Phase", :file_manager => FileMock @@ -138,7 +118,7 @@ def testGetReactCodegenSpec_whenUseFrameworksAndNewArch_generatesAPodspec # Act podspec = CodegenUtils.new().get_react_codegen_spec( 'package.json', - :fabric_enabled => true, + :hermes_enabled => true, :script_phases => nil, :file_manager => FileMock @@ -380,11 +360,9 @@ def testUseReactCodegenDiscovery_whenParametersAreGood_executeCodegen :app_path => app_path, :config_file_dir => "", :config_key => "codegenConfig", - :fabric_enabled => false, :react_native_path => "../node_modules/react-native"} ]) assert_equal(codegen_utils_mock.get_react_codegen_spec_params, [{ - :fabric_enabled => false, :folly_version=>"2023.08.07.00", :package_json_file => "#{app_path}/ios/../node_modules/react-native/package.json", :script_phases => "echo TestScript" diff --git a/packages/react-native/scripts/cocoapods/__tests__/test_utils/CodegenUtilsMock.rb b/packages/react-native/scripts/cocoapods/__tests__/test_utils/CodegenUtilsMock.rb index e6b4174a17e043..4c0cc8d6cbeaa3 100644 --- a/packages/react-native/scripts/cocoapods/__tests__/test_utils/CodegenUtilsMock.rb +++ b/packages/react-native/scripts/cocoapods/__tests__/test_utils/CodegenUtilsMock.rb @@ -58,7 +58,6 @@ def get_react_codegen_script_phases( ) @get_react_codegen_script_phases_params.push({ app_path: app_path, - fabric_enabled: fabric_enabled, config_file_dir: config_file_dir, react_native_path: react_native_path, config_key: config_key @@ -66,11 +65,10 @@ def get_react_codegen_script_phases( return @react_codegen_script_phases end - def get_react_codegen_spec(package_json_file, folly_version: '2023.08.07.00', fabric_enabled: false, hermes_enabled: true, script_phases: nil) + def get_react_codegen_spec(package_json_file, folly_version: '2023.08.07.00', hermes_enabled: true, script_phases: nil) @get_react_codegen_spec_params.push({ package_json_file: package_json_file, folly_version: folly_version, - fabric_enabled: fabric_enabled, script_phases: script_phases }) return @react_codegen_spec diff --git a/packages/react-native/scripts/cocoapods/codegen_utils.rb b/packages/react-native/scripts/cocoapods/codegen_utils.rb index 71018f2b7ee754..951adaaa2572cc 100644 --- a/packages/react-native/scripts/cocoapods/codegen_utils.rb +++ b/packages/react-native/scripts/cocoapods/codegen_utils.rb @@ -66,11 +66,10 @@ def generate_react_codegen_podspec!(spec, codegen_output_dir, file_manager: File # # Parameters # - package_json_file: the path to the `package.json`, required to extract the proper React Native version - # - fabric_enabled: whether fabric is enabled or not. # - hermes_enabled: whether hermes is enabled or not. # - script_phases: whether we want to add some build script phases or not. # - file_manager: a class that implements the `File` interface. Defaults to `File`, the Dependency can be injected for testing purposes. - def get_react_codegen_spec(package_json_file, folly_version: '2023.08.07.00', fabric_enabled: false, hermes_enabled: true, script_phases: nil, file_manager: File) + def get_react_codegen_spec(package_json_file, folly_version: '2023.08.07.00', hermes_enabled: true, script_phases: nil, file_manager: File) package = JSON.parse(file_manager.read(package_json_file)) version = package['version'] new_arch_disabled = ENV['RCT_NEW_ARCH_ENABLED'] != "1" @@ -136,18 +135,13 @@ def get_react_codegen_spec(package_json_file, folly_version: '2023.08.07.00', fa "React-NativeModulesApple": [], "glog": [], "DoubleConversion": [], - } - } - - if fabric_enabled - spec[:'dependencies'].merge!({ 'React-graphics': [], 'React-rendererdebug': [], 'React-Fabric': [], 'React-debug': [], 'React-utils': [], - }); - end + } + } if hermes_enabled spec[:'dependencies'].merge!({ @@ -313,7 +307,6 @@ def use_react_native_codegen_discovery!( react_codegen_spec = codegen_utils.get_react_codegen_spec( file_manager.join(relative_installation_root, react_native_path, "package.json"), :folly_version => folly_version, - :fabric_enabled => fabric_enabled, :hermes_enabled => hermes_enabled, :script_phases => script_phases ) diff --git a/packages/react-native/scripts/react_native_pods.rb b/packages/react-native/scripts/react_native_pods.rb index 472a563baddc05..f0a0ba120cfcba 100644 --- a/packages/react-native/scripts/react_native_pods.rb +++ b/packages/react-native/scripts/react_native_pods.rb @@ -103,6 +103,8 @@ def use_react_native! ( ReactNativePodsUtils.warn_if_not_on_arm64() + build_codegen!(prefix, relative_path_from_current) + # The Pods which should be included in all projects pod 'FBLazyVector', :path => "#{prefix}/Libraries/FBLazyVector" pod 'RCTRequired', :path => "#{prefix}/Libraries/Required" @@ -174,15 +176,7 @@ def use_react_native! ( # If the New Arch is turned off, we will use the Old Renderer, though. # RNTester always installed Fabric, this change is required to make the template work. setup_fabric!(:react_native_path => prefix) - - if !fabric_enabled - relative_installation_root = Pod::Config.instance.installation_root.relative_path_from(Pathname.pwd) - build_codegen!(prefix, relative_installation_root) - end - - if NewArchitectureHelper.new_arch_enabled - setup_bridgeless!(:react_native_path => prefix, :use_hermes => hermes_enabled) - end + setup_bridgeless!(:react_native_path => prefix, :use_hermes => hermes_enabled) pods_to_update = LocalPodspecPatch.pods_to_update(:react_native_path => prefix) if !pods_to_update.empty? From 951efc8ce2a6d34aa6df6d1ad205db2661143855 Mon Sep 17 00:00:00 2001 From: Riccardo Cipolleschi Date: Wed, 22 Nov 2023 03:50:29 -0800 Subject: [PATCH 056/162] Remove some usages of RCT_NEW_ARCH_ENABLED (#41589) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41589 This is a cleanup diffs that removes some of the usages of RCT_NEW_ARCH_ENABLED. Now that we are shipping all the pods, there is no need to conditionally compile-out part of the codebase depending on whether the new architecture is running or not. This change will not alter the behavior of the app. ## Changelog: [iOS][Breaking] - Remove some usages of RCT_NEW_ARCH_ENABLED. The change should be transparent BUT some **Swift** libraries might get broken by this change. Reviewed By: dmytrorykun Differential Revision: D51498730 fbshipit-source-id: c83416480eea1f7bbc55f72c31e7b69ad0e9e01a --- .../Libraries/AppDelegate/RCTAppDelegate.h | 3 - .../Libraries/AppDelegate/RCTAppDelegate.mm | 87 ++++++++----------- .../Libraries/AppDelegate/RCTAppSetupUtils.h | 7 +- .../Libraries/AppDelegate/RCTAppSetupUtils.mm | 10 --- packages/rn-tester/RNTester/AppDelegate.mm | 6 -- 5 files changed, 37 insertions(+), 76 deletions(-) diff --git a/packages/react-native/Libraries/AppDelegate/RCTAppDelegate.h b/packages/react-native/Libraries/AppDelegate/RCTAppDelegate.h index 71739d159ff40c..f6a35caf3f0cb3 100644 --- a/packages/react-native/Libraries/AppDelegate/RCTAppDelegate.h +++ b/packages/react-native/Libraries/AppDelegate/RCTAppDelegate.h @@ -109,7 +109,6 @@ /// @return: `YES` to use RuntimeScheduler, `NO` to use JavaScript scheduler. The default value is `YES`. - (BOOL)runtimeSchedulerEnabled; -#if RCT_NEW_ARCH_ENABLED @property (nonatomic, strong) RCTSurfacePresenterBridgeAdapter *bridgeAdapter; /// This method returns a map of Component Descriptors and Components classes that needs to be registered in the @@ -139,6 +138,4 @@ /// Return the bundle URL for the main bundle. - (NSURL *)bundleURL; -#endif - @end diff --git a/packages/react-native/Libraries/AppDelegate/RCTAppDelegate.mm b/packages/react-native/Libraries/AppDelegate/RCTAppDelegate.mm index 3f3bb759ba63e8..414534f9fb4dbe 100644 --- a/packages/react-native/Libraries/AppDelegate/RCTAppDelegate.mm +++ b/packages/react-native/Libraries/AppDelegate/RCTAppDelegate.mm @@ -13,7 +13,6 @@ #import "RCTAppSetupUtils.h" #import "RCTLegacyInteropComponents.h" -#if RCT_NEW_ARCH_ENABLED #if RN_DISABLE_OSS_PLUGIN_HEADER #import #else @@ -51,19 +50,13 @@ @interface RCTAppDelegate () < } @end -#endif - static NSDictionary *updateInitialProps(NSDictionary *initialProps, BOOL isFabricEnabled) { -#ifdef RCT_NEW_ARCH_ENABLED NSMutableDictionary *mutableProps = [initialProps mutableCopy] ?: [NSMutableDictionary new]; // Hardcoding the Concurrent Root as it it not recommended to // have the concurrentRoot turned off when Fabric is enabled. mutableProps[kRNConcurrentRoot] = @(isFabricEnabled); return mutableProps; -#else - return initialProps; -#endif } @interface RCTAppDelegate () { @@ -72,12 +65,9 @@ @interface RCTAppDelegate () { @end @implementation RCTAppDelegate { -#if RCT_NEW_ARCH_ENABLED RCTHost *_reactHost; -#endif } -#if RCT_NEW_ARCH_ENABLED - (instancetype)init { if (self = [super init]) { @@ -87,25 +77,20 @@ - (instancetype)init } return self; } -#endif - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - BOOL enableTM = NO; - BOOL enableBridgeless = NO; - BOOL fabricEnabled = NO; -#if RCT_NEW_ARCH_ENABLED - enableTM = self.turboModuleEnabled; - enableBridgeless = self.bridgelessEnabled; - fabricEnabled = [self fabricEnabled]; -#endif + BOOL enableTM = self.turboModuleEnabled; + ; + BOOL enableBridgeless = self.bridgelessEnabled; + BOOL fabricEnabled = self.fabricEnabled; + NSDictionary *initProps = updateInitialProps([self prepareInitialProps], fabricEnabled); RCTAppSetupPrepareApp(application, enableTM); UIView *rootView; if (enableBridgeless) { -#if RCT_NEW_ARCH_ENABLED // Enable native view config interop only if both bridgeless mode and Fabric is enabled. RCTSetUseNativeViewConfigsInBridgelessMode(fabricEnabled); @@ -123,7 +108,6 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:( sizeMeasureMode:RCTSurfaceSizeMeasureModeWidthExact | RCTSurfaceSizeMeasureModeHeightExact]; rootView = (RCTRootView *)surfaceHostingProxyRootView; -#endif } else { if (!self.bridge) { self.bridge = [self createBridgeWithDelegate:self launchOptions:launchOptions]; @@ -170,10 +154,7 @@ - (UIView *)createRootViewWithBridge:(RCTBridge *)bridge moduleName:(NSString *)moduleName initProps:(NSDictionary *)initProps { - BOOL enableFabric = NO; -#if RCT_NEW_ARCH_ENABLED - enableFabric = self.fabricEnabled; -#endif + BOOL enableFabric = self.fabricEnabled; UIView *rootView = RCTAppSetupDefaultRootView(bridge, moduleName, initProps, enableFabric); rootView.backgroundColor = [UIColor systemBackgroundColor]; @@ -223,7 +204,37 @@ - (void)windowScene:(UIWindowScene *)windowScene #endif } +#pragma mark - New Arch Enabled settings + +- (BOOL)turboModuleEnabled +{ +#if RCT_NEW_ARCH_ENABLED + return YES; +#else + return NO; +#endif +} + +- (BOOL)fabricEnabled +{ #if RCT_NEW_ARCH_ENABLED + return YES; +#else + return NO; +#endif +} + +- (BOOL)bridgelessEnabled +{ + return NO; +} + +#pragma mark - RCTComponentViewFactoryComponentProvider + +- (NSDictionary> *)thirdPartyFabricComponents +{ + return @{}; +} #pragma mark - RCTTurboModuleManagerDelegate @@ -254,30 +265,6 @@ - (Class)getModuleClassFromName:(const char *)name return RCTAppSetupDefaultModuleFromClass(moduleClass); } -#pragma mark - RCTComponentViewFactoryComponentProvider - -- (NSDictionary> *)thirdPartyFabricComponents -{ - return @{}; -} - -#pragma mark - New Arch Enabled settings - -- (BOOL)turboModuleEnabled -{ - return YES; -} - -- (BOOL)fabricEnabled -{ - return YES; -} - -- (BOOL)bridgelessEnabled -{ - return NO; -} - #pragma mark - New Arch Utilities - (void)unstable_registerLegacyComponents @@ -324,6 +311,4 @@ - (NSURL *)bundleURL return nullptr; } -#endif - @end diff --git a/packages/react-native/Libraries/AppDelegate/RCTAppSetupUtils.h b/packages/react-native/Libraries/AppDelegate/RCTAppSetupUtils.h index e1c69078409caf..d661fb4355c1c1 100644 --- a/packages/react-native/Libraries/AppDelegate/RCTAppSetupUtils.h +++ b/packages/react-native/Libraries/AppDelegate/RCTAppSetupUtils.h @@ -26,28 +26,23 @@ #endif #endif -#if RCT_NEW_ARCH_ENABLED #import -#endif // Forward declaration to decrease compilation coupling namespace facebook::react { class RuntimeScheduler; } -#if RCT_NEW_ARCH_ENABLED - RCT_EXTERN id RCTAppSetupDefaultModuleFromClass(Class moduleClass); std::unique_ptr RCTAppSetupDefaultJsExecutorFactory( RCTBridge *bridge, RCTTurboModuleManager *turboModuleManager, const std::shared_ptr &runtimeScheduler); -#else + std::unique_ptr RCTAppSetupJsExecutorFactoryForOldArch( RCTBridge *bridge, const std::shared_ptr &runtimeScheduler); -#endif #endif // __cplusplus diff --git a/packages/react-native/Libraries/AppDelegate/RCTAppSetupUtils.mm b/packages/react-native/Libraries/AppDelegate/RCTAppSetupUtils.mm index 6241f62831cf40..3127588b7de0a1 100644 --- a/packages/react-native/Libraries/AppDelegate/RCTAppSetupUtils.mm +++ b/packages/react-native/Libraries/AppDelegate/RCTAppSetupUtils.mm @@ -11,7 +11,6 @@ #import #import -#if RCT_NEW_ARCH_ENABLED // Turbo Module #import #import @@ -24,13 +23,10 @@ // Fabric #import #import -#endif void RCTAppSetupPrepareApp(UIApplication *application, BOOL turboModuleEnabled) { -#if RCT_NEW_ARCH_ENABLED RCTEnableTurboModule(turboModuleEnabled); -#endif #if DEBUG // Disable idle timer in dev builds to avoid putting application in background and complicating @@ -42,18 +38,15 @@ void RCTAppSetupPrepareApp(UIApplication *application, BOOL turboModuleEnabled) UIView * RCTAppSetupDefaultRootView(RCTBridge *bridge, NSString *moduleName, NSDictionary *initialProperties, BOOL fabricEnabled) { -#if RCT_NEW_ARCH_ENABLED if (fabricEnabled) { id surface = [[RCTFabricSurface alloc] initWithBridge:bridge moduleName:moduleName initialProperties:initialProperties]; return [[RCTSurfaceHostingProxyRootView alloc] initWithSurface:surface]; } -#endif return [[RCTRootView alloc] initWithBridge:bridge moduleName:moduleName initialProperties:initialProperties]; } -#if RCT_NEW_ARCH_ENABLED id RCTAppSetupDefaultModuleFromClass(Class moduleClass) { // Set up the default RCTImageLoader and RCTNetworking modules. @@ -114,8 +107,6 @@ void RCTAppSetupPrepareApp(UIApplication *application, BOOL turboModuleEnabled) })); } -#else // else !RCT_NEW_ARCH_ENABLED - std::unique_ptr RCTAppSetupJsExecutorFactoryForOldArch( RCTBridge *bridge, const std::shared_ptr &runtimeScheduler) @@ -134,4 +125,3 @@ void RCTAppSetupPrepareApp(UIApplication *application, BOOL turboModuleEnabled) } })); } -#endif // end RCT_NEW_ARCH_ENABLED diff --git a/packages/rn-tester/RNTester/AppDelegate.mm b/packages/rn-tester/RNTester/AppDelegate.mm index a7fa095e5bc2e6..0692f5b4cb5eea 100644 --- a/packages/rn-tester/RNTester/AppDelegate.mm +++ b/packages/rn-tester/RNTester/AppDelegate.mm @@ -16,12 +16,10 @@ #import #endif -#if RCT_NEW_ARCH_ENABLED #import #ifndef RN_DISABLE_OSS_PLUGIN_HEADER #import #endif -#endif // FB-internal imports #ifdef RN_DISABLE_OSS_PLUGIN_HEADER @@ -88,11 +86,9 @@ - (void)loadSourceForBridge:(RCTBridge *)bridge if (name == std::string([@"SampleTurboCxxModule" UTF8String])) { return std::make_shared(jsInvoker); } -#ifdef RCT_NEW_ARCH_ENABLED if (name == facebook::react::NativeCxxModuleExample::kModuleName) { return std::make_shared(jsInvoker); } -#endif return nullptr; } @@ -129,7 +125,6 @@ - (void)application:(__unused UIApplication *)application #pragma mark - RCTComponentViewFactoryComponentProvider -#if RCT_NEW_ARCH_ENABLED #ifndef RN_DISABLE_OSS_PLUGIN_HEADER - (nonnull NSDictionary> *)thirdPartyFabricComponents { @@ -141,6 +136,5 @@ - (NSURL *)bundleURL { return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:kBundlePath]; } -#endif @end From 91d4b1bd80a099af1adae1854da64191dad02ce1 Mon Sep 17 00:00:00 2001 From: Samuel Susla Date: Wed, 22 Nov 2023 04:33:02 -0800 Subject: [PATCH 057/162] pass RawProps by rvalue (#41604) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41604 changelog: [internal] Remove const requirement when using RawProps and prefer passing it by rvalue. Reviewed By: javache Differential Revision: D51471667 fbshipit-source-id: 479bcebe642e168ff1f110e7b2bfaf20a3e82821 --- .../UnimplementedViewComponentDescriptor.cpp | 6 +- .../UnimplementedViewComponentDescriptor.h | 2 +- .../react/renderer/core/ComponentDescriptor.h | 2 +- .../core/ConcreteComponentDescriptor.h | 2 +- .../react/renderer/core/RawProps.cpp | 25 +++- .../react/renderer/core/RawProps.h | 20 +-- .../core/tests/ComponentDescriptorTest.cpp | 15 ++- .../renderer/core/tests/RawPropsTest.cpp | 121 ++++++++++++++++-- .../react/renderer/uimanager/UIManager.cpp | 48 +++---- .../react/renderer/uimanager/UIManager.h | 8 +- .../renderer/uimanager/UIManagerBinding.cpp | 13 +- 11 files changed, 187 insertions(+), 75 deletions(-) diff --git a/packages/react-native/ReactCommon/react/renderer/components/unimplementedview/UnimplementedViewComponentDescriptor.cpp b/packages/react-native/ReactCommon/react/renderer/components/unimplementedview/UnimplementedViewComponentDescriptor.cpp index d8e9ce211cf4f2..7b42990f7c414b 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/unimplementedview/UnimplementedViewComponentDescriptor.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/unimplementedview/UnimplementedViewComponentDescriptor.cpp @@ -21,10 +21,10 @@ ComponentName UnimplementedViewComponentDescriptor::getComponentName() const { Props::Shared UnimplementedViewComponentDescriptor::cloneProps( const PropsParserContext& context, const Props::Shared& props, - const RawProps& rawProps) const { + RawProps rawProps) const { auto clonedProps = ConcreteComponentDescriptor::cloneProps( - context, props, rawProps); + context, props, std::move(rawProps)); // We have to clone `Props` object one more time to make sure that we have // an unshared (and non-`const`) copy of it which we can mutate. @@ -33,7 +33,7 @@ Props::Shared UnimplementedViewComponentDescriptor::cloneProps( auto unimplementedViewProps = std::make_shared( context, static_cast(*clonedProps), - emptyRawProps); + std::move(emptyRawProps)); unimplementedViewProps->setComponentName(getComponentName()); return unimplementedViewProps; diff --git a/packages/react-native/ReactCommon/react/renderer/components/unimplementedview/UnimplementedViewComponentDescriptor.h b/packages/react-native/ReactCommon/react/renderer/components/unimplementedview/UnimplementedViewComponentDescriptor.h index 6240fae281d820..e73046568de792 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/unimplementedview/UnimplementedViewComponentDescriptor.h +++ b/packages/react-native/ReactCommon/react/renderer/components/unimplementedview/UnimplementedViewComponentDescriptor.h @@ -35,7 +35,7 @@ class UnimplementedViewComponentDescriptor final Props::Shared cloneProps( const PropsParserContext& context, const Props::Shared& props, - const RawProps& rawProps) const override; + RawProps rawProps) const override; }; } // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/renderer/core/ComponentDescriptor.h b/packages/react-native/ReactCommon/react/renderer/core/ComponentDescriptor.h index 7839906e5fc153..fe4be3a27ba551 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/ComponentDescriptor.h +++ b/packages/react-native/ReactCommon/react/renderer/core/ComponentDescriptor.h @@ -105,7 +105,7 @@ class ComponentDescriptor { virtual Props::Shared cloneProps( const PropsParserContext& context, const Props::Shared& props, - const RawProps& rawProps) const = 0; + RawProps rawProps) const = 0; /* * Create an initial State object that represents (and contains) an initial diff --git a/packages/react-native/ReactCommon/react/renderer/core/ConcreteComponentDescriptor.h b/packages/react-native/ReactCommon/react/renderer/core/ConcreteComponentDescriptor.h index e56ac9cad92165..a527d267eb41dd 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/ConcreteComponentDescriptor.h +++ b/packages/react-native/ReactCommon/react/renderer/core/ConcreteComponentDescriptor.h @@ -95,7 +95,7 @@ class ConcreteComponentDescriptor : public ComponentDescriptor { virtual Props::Shared cloneProps( const PropsParserContext& context, const Props::Shared& props, - const RawProps& rawProps) const override { + RawProps rawProps) const override { // Optimization: // Quite often nodes are constructed with default/empty props: the base // `props` object is `null` (there no base because it's not cloning) and the diff --git a/packages/react-native/ReactCommon/react/renderer/core/RawProps.cpp b/packages/react-native/ReactCommon/react/renderer/core/RawProps.cpp index 945566c785e1fc..046e8c521ae33a 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/RawProps.cpp +++ b/packages/react-native/ReactCommon/react/renderer/core/RawProps.cpp @@ -26,7 +26,7 @@ RawProps::RawProps(jsi::Runtime& runtime, const jsi::Value& value) noexcept { return; } - mode_ = mode_ = Mode::JSI; + mode_ = Mode::JSI; runtime_ = &runtime; value_ = jsi::Value(runtime, value); } @@ -47,7 +47,28 @@ RawProps::RawProps(folly::dynamic dynamic) noexcept { dynamic_ = std::move(dynamic); } -void RawProps::parse(const RawPropsParser& parser) const noexcept { +RawProps::RawProps(const RawProps& other) noexcept { + mode_ = other.mode_; + if (mode_ == Mode::JSI) { + runtime_ = other.runtime_; + value_ = jsi::Value(*runtime_, other.value_); + } else if (mode_ == Mode::Dynamic) { + dynamic_ = other.dynamic_; + } +} + +RawProps& RawProps::operator=(const RawProps& other) noexcept { + mode_ = other.mode_; + if (mode_ == Mode::JSI) { + runtime_ = other.runtime_; + value_ = jsi::Value(*runtime_, other.value_); + } else if (mode_ == Mode::Dynamic) { + dynamic_ = other.dynamic_; + } + return *this; +} + +void RawProps::parse(const RawPropsParser& parser) noexcept { react_native_assert(parser_ == nullptr && "A parser was already assigned."); parser_ = &parser; parser.preparse(*this); diff --git a/packages/react-native/ReactCommon/react/renderer/core/RawProps.h b/packages/react-native/ReactCommon/react/renderer/core/RawProps.h index cfb2bd48cec24a..c08cf928a508bd 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/RawProps.h +++ b/packages/react-native/ReactCommon/react/renderer/core/RawProps.h @@ -50,6 +50,12 @@ class RawProps final { */ RawProps(jsi::Runtime& runtime, const jsi::Value& value) noexcept; + explicit RawProps(const RawProps& rawProps) noexcept; + RawProps& operator=(const RawProps& other) noexcept; + + RawProps(RawProps&& other) noexcept = default; + RawProps& operator=(RawProps&& other) noexcept = default; + /* * Creates an object with given `folly::dynamic` object. * Deprecated. Do not use. @@ -58,19 +64,7 @@ class RawProps final { */ explicit RawProps(folly::dynamic dynamic) noexcept; - /* - * Not moveable. - */ - RawProps(RawProps&& other) noexcept = delete; - RawProps& operator=(RawProps&& other) noexcept = delete; - - /* - * Not copyable. - */ - RawProps(const RawProps& other) noexcept = delete; - RawProps& operator=(const RawProps& other) noexcept = delete; - - void parse(const RawPropsParser& parser) const noexcept; + void parse(const RawPropsParser& parser) noexcept; /* * Deprecated. Do not use. diff --git a/packages/react-native/ReactCommon/react/renderer/core/tests/ComponentDescriptorTest.cpp b/packages/react-native/ReactCommon/react/renderer/core/tests/ComponentDescriptorTest.cpp index d9d623713d4ef6..1b29638cc019ba 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/tests/ComponentDescriptorTest.cpp +++ b/packages/react-native/ReactCommon/react/renderer/core/tests/ComponentDescriptorTest.cpp @@ -26,8 +26,9 @@ TEST(ComponentDescriptorTest, createShadowNode) { ContextContainer contextContainer{}; PropsParserContext parserContext{-1, contextContainer}; - const auto& raw = RawProps(folly::dynamic::object("nativeID", "abc")); - Props::Shared props = descriptor->cloneProps(parserContext, nullptr, raw); + auto rawProps = RawProps(folly::dynamic::object("nativeID", "abc")); + Props::Shared props = + descriptor->cloneProps(parserContext, nullptr, std::move(rawProps)); auto family = descriptor->createFamily(ShadowNodeFamilyFragment{ /* .tag = */ 9, @@ -58,8 +59,9 @@ TEST(ComponentDescriptorTest, cloneShadowNode) { ContextContainer contextContainer{}; PropsParserContext parserContext{-1, contextContainer}; - const auto& raw = RawProps(folly::dynamic::object("nativeID", "abc")); - Props::Shared props = descriptor->cloneProps(parserContext, nullptr, raw); + auto rawProps = RawProps(folly::dynamic::object("nativeID", "abc")); + Props::Shared props = + descriptor->cloneProps(parserContext, nullptr, std::move(rawProps)); auto family = descriptor->createFamily(ShadowNodeFamilyFragment{ /* .tag = */ 9, /* .surfaceId = */ 1, @@ -91,8 +93,9 @@ TEST(ComponentDescriptorTest, appendChild) { ContextContainer contextContainer{}; PropsParserContext parserContext{-1, contextContainer}; - const auto& raw = RawProps(folly::dynamic::object("nativeID", "abc")); - Props::Shared props = descriptor->cloneProps(parserContext, nullptr, raw); + auto rawProps = RawProps(folly::dynamic::object("nativeID", "abc")); + Props::Shared props = + descriptor->cloneProps(parserContext, nullptr, std::move(rawProps)); auto family1 = descriptor->createFamily(ShadowNodeFamilyFragment{ /* .tag = */ 1, /* .surfaceId = */ 1, diff --git a/packages/react-native/ReactCommon/react/renderer/core/tests/RawPropsTest.cpp b/packages/react-native/ReactCommon/react/renderer/core/tests/RawPropsTest.cpp index 7bec6cfcc45309..9b57fe14586d62 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/tests/RawPropsTest.cpp +++ b/packages/react-native/ReactCommon/react/renderer/core/tests/RawPropsTest.cpp @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -16,6 +17,7 @@ #include "TestComponent.h" +using namespace facebook; using namespace facebook::react; class PropsSingleFloat : public Props { @@ -151,7 +153,7 @@ TEST(RawPropsTest, handleProps) { ContextContainer contextContainer{}; PropsParserContext parserContext{-1, contextContainer}; - const auto& raw = RawProps(folly::dynamic::object("nativeID", "abc")); + auto raw = RawProps(folly::dynamic::object("nativeID", "abc")); auto parser = RawPropsParser(); parser.prepare(); raw.parse(parser); @@ -168,7 +170,7 @@ TEST(RawPropsTest, handleRawPropsSingleString) { ContextContainer contextContainer{}; PropsParserContext parserContext{-1, contextContainer}; - const auto& raw = RawProps(folly::dynamic::object("nativeID", "abc")); + auto raw = RawProps(folly::dynamic::object("nativeID", "abc")); auto parser = RawPropsParser(); parser.prepare(); raw.parse(parser); @@ -182,8 +184,7 @@ TEST(RawPropsTest, handleRawPropsSingleFloat) { ContextContainer contextContainer{}; PropsParserContext parserContext{-1, contextContainer}; - const auto& raw = - RawProps(folly::dynamic::object("floatValue", (float)42.42)); + auto raw = RawProps(folly::dynamic::object("floatValue", (float)42.42)); auto parser = RawPropsParser(); parser.prepare(); raw.parse(parser); @@ -197,8 +198,7 @@ TEST(RawPropsTest, handleRawPropsSingleDouble) { ContextContainer contextContainer{}; PropsParserContext parserContext{-1, contextContainer}; - const auto& raw = - RawProps(folly::dynamic::object("doubleValue", (double)42.42)); + auto raw = RawProps(folly::dynamic::object("doubleValue", (double)42.42)); auto parser = RawPropsParser(); parser.prepare(); raw.parse(parser); @@ -212,7 +212,7 @@ TEST(RawPropsTest, handleRawPropsSingleInt) { ContextContainer contextContainer{}; PropsParserContext parserContext{-1, contextContainer}; - const auto& raw = RawProps(folly::dynamic::object("intValue", (int)42.42)); + auto raw = RawProps(folly::dynamic::object("intValue", (int)42.42)); auto parser = RawPropsParser(); parser.prepare(); raw.parse(parser); @@ -226,7 +226,7 @@ TEST(RawPropsTest, handleRawPropsSingleIntGetManyTimes) { ContextContainer contextContainer{}; PropsParserContext parserContext{-1, contextContainer}; - const auto& raw = RawProps(folly::dynamic::object("intValue", (int)42.42)); + auto raw = RawProps(folly::dynamic::object("intValue", (int)42.42)); auto parser = RawPropsParser(); parser.prepare(); raw.parse(parser); @@ -240,7 +240,7 @@ TEST(RawPropsTest, handleRawPropsPrimitiveTypes) { ContextContainer contextContainer{}; PropsParserContext parserContext{-1, contextContainer}; - const auto& raw = RawProps( + auto raw = RawProps( folly::dynamic::object("intValue", (int)42)("doubleValue", (double)17.42)( "floatValue", (float)66.67)("stringValue", "helloworld")("boolValue", true)); @@ -262,7 +262,7 @@ TEST(RawPropsTest, handleRawPropsPrimitiveTypesGetTwice) { ContextContainer contextContainer{}; PropsParserContext parserContext{-1, contextContainer}; - const auto& raw = RawProps( + auto raw = RawProps( folly::dynamic::object("intValue", (int)42)("doubleValue", (double)17.42)( "floatValue", (float)66.67)("stringValue", "helloworld")("boolValue", true)); @@ -292,7 +292,7 @@ TEST(RawPropsTest, handleRawPropsPrimitiveTypesGetOutOfOrder) { ContextContainer contextContainer{}; PropsParserContext parserContext{-1, contextContainer}; - const auto& raw = RawProps( + auto raw = RawProps( folly::dynamic::object("intValue", (int)42)("doubleValue", (double)17.42)( "floatValue", (float)66.67)("stringValue", "helloworld")("boolValue", true)); @@ -322,7 +322,7 @@ TEST(RawPropsTest, handleRawPropsPrimitiveTypesIncomplete) { ContextContainer contextContainer{}; PropsParserContext parserContext{-1, contextContainer}; - const auto& raw = RawProps(folly::dynamic::object("intValue", (int)42)); + auto raw = RawProps(folly::dynamic::object("intValue", (int)42)); auto parser = RawPropsParser(); parser.prepare(); @@ -342,7 +342,7 @@ TEST(RawPropsTest, handleRawPropsPrimitiveTypesIncorrectLookup) { ContextContainer contextContainer{}; PropsParserContext parserContext{-1, contextContainer}; - const auto& raw = RawProps(folly::dynamic::object("intValue", (int)42)); + auto raw = RawProps(folly::dynamic::object("intValue", (int)42)); auto parser = RawPropsParser(); parser.prepare(); @@ -360,7 +360,7 @@ TEST(RawPropsTest, handlePropsMultiLookup) { ContextContainer contextContainer{}; PropsParserContext parserContext{-1, contextContainer}; - const auto& raw = RawProps(folly::dynamic::object("floatValue", (float)10.0)); + auto raw = RawProps(folly::dynamic::object("floatValue", (float)10.0)); auto parser = RawPropsParser(); parser.prepare(); raw.parse(parser); @@ -374,3 +374,96 @@ TEST(RawPropsTest, handlePropsMultiLookup) { EXPECT_NEAR(props->floatValue, 10.0, 0.00001); EXPECT_NEAR(props->derivedFloatValue, 20.0, 0.00001); } + +TEST(RawPropsTest, copyDynamicRawProps) { + ContextContainer contextContainer{}; + PropsParserContext parserContext{-1, contextContainer}; + + auto rawProps = RawProps(folly::dynamic::object("floatValue", (float)10.0)); + + auto copy = RawProps(rawProps); + + EXPECT_FALSE(copy.isEmpty()); + + auto parser = RawPropsParser(); + parser.prepare(); + + rawProps.parse(parser); + copy.parse(parser); + + auto originalProps = std::make_shared( + parserContext, PropsMultiLookup(), rawProps); + auto copyProps = std::make_shared( + parserContext, PropsMultiLookup(), copy); + + // Props are not sealed after applying raw props. + EXPECT_FALSE(copyProps->getSealed()); + + EXPECT_NEAR(copyProps->floatValue, originalProps->floatValue, 0.00001); + EXPECT_NEAR( + copyProps->derivedFloatValue, originalProps->derivedFloatValue, 0.00001); +} + +TEST(RawPropsTest, copyEmptyRawProps) { + ContextContainer contextContainer{}; + PropsParserContext parserContext{-1, contextContainer}; + + auto rawProps = RawProps(); + + auto copy = RawProps(rawProps); + + EXPECT_TRUE(rawProps.isEmpty()); + EXPECT_TRUE(copy.isEmpty()); + + EXPECT_TRUE(((folly::dynamic)copy).empty()); +} + +TEST(RawPropsTest, copyNullJSIRawProps) { + auto runtime = facebook::hermes::makeHermesRuntime(); + + ContextContainer contextContainer{}; + PropsParserContext parserContext{-1, contextContainer}; + + auto rawProps = RawProps(*runtime, jsi::Value::null()); + + auto copy = RawProps(rawProps); + + EXPECT_TRUE(rawProps.isEmpty()); + EXPECT_TRUE(copy.isEmpty()); + + EXPECT_TRUE(((folly::dynamic)copy).empty()); +} + +TEST(RawPropsTest, copyJSIRawProps) { + auto runtime = facebook::hermes::makeHermesRuntime(); + + ContextContainer contextContainer{}; + PropsParserContext parserContext{-1, contextContainer}; + + auto object = jsi::Object(*runtime); + object.setProperty(*runtime, "floatValue", 10.0); + + auto rawProps = RawProps(*runtime, jsi::Value(*runtime, object)); + auto copy = RawProps(rawProps); + + EXPECT_FALSE(rawProps.isEmpty()); + EXPECT_FALSE(copy.isEmpty()); + + auto parser = RawPropsParser(); + parser.prepare(); + + rawProps.parse(parser); + copy.parse(parser); + + auto originalProps = std::make_shared( + parserContext, PropsMultiLookup(), rawProps); + auto copyProps = std::make_shared( + parserContext, PropsMultiLookup(), copy); + + // Props are not sealed after applying raw props. + EXPECT_FALSE(copyProps->getSealed()); + + EXPECT_NEAR(copyProps->floatValue, originalProps->floatValue, 0.00001); + EXPECT_NEAR( + copyProps->derivedFloatValue, originalProps->derivedFloatValue, 0.00001); +} diff --git a/packages/react-native/ReactCommon/react/renderer/uimanager/UIManager.cpp b/packages/react-native/ReactCommon/react/renderer/uimanager/UIManager.cpp index 0dd12526bc730e..b83cc710b69ef0 100644 --- a/packages/react-native/ReactCommon/react/renderer/uimanager/UIManager.cpp +++ b/packages/react-native/ReactCommon/react/renderer/uimanager/UIManager.cpp @@ -66,7 +66,7 @@ std::shared_ptr UIManager::createNode( Tag tag, const std::string& name, SurfaceId surfaceId, - const RawProps& rawProps, + RawProps rawProps, InstanceHandle::Shared instanceHandle) const { SystraceSection s("UIManager::createNode", "componentName", name); @@ -78,8 +78,8 @@ std::shared_ptr UIManager::createNode( auto family = componentDescriptor.createFamily( {tag, surfaceId, std::move(instanceHandle)}); - const auto props = - componentDescriptor.cloneProps(propsParserContext, nullptr, rawProps); + const auto props = componentDescriptor.cloneProps( + propsParserContext, nullptr, std::move(rawProps)); const auto state = componentDescriptor.createInitialState(props, family); auto shadowNode = componentDescriptor.createShadowNode( @@ -111,7 +111,7 @@ std::shared_ptr UIManager::createNode( std::shared_ptr UIManager::cloneNode( const ShadowNode& shadowNode, const ShadowNode::SharedListOfShared& children, - const RawProps* rawProps) const { + RawProps rawProps) const { SystraceSection s( "UIManager::cloneNode", "componentName", shadowNode.getComponentName()); @@ -122,24 +122,22 @@ std::shared_ptr UIManager::cloneNode( auto& family = shadowNode.getFamily(); auto props = ShadowNodeFragment::propsPlaceholder(); - if (rawProps != nullptr) { - if (family.nativeProps_DEPRECATED != nullptr) { - // Values in `rawProps` patch (take precedence over) - // `nativeProps_DEPRECATED`. For example, if both `nativeProps_DEPRECATED` - // and `rawProps` contain key 'A'. Value from `rawProps` overrides what - // was previously in `nativeProps_DEPRECATED`. - family.nativeProps_DEPRECATED = - std::make_unique(mergeDynamicProps( - *family.nativeProps_DEPRECATED, (folly::dynamic)*rawProps)); - - props = componentDescriptor.cloneProps( - propsParserContext, - shadowNode.getProps(), - RawProps(*family.nativeProps_DEPRECATED)); - } else { - props = componentDescriptor.cloneProps( - propsParserContext, shadowNode.getProps(), *rawProps); - } + if (family.nativeProps_DEPRECATED != nullptr) { + // Values in `rawProps` patch (take precedence over) + // `nativeProps_DEPRECATED`. For example, if both `nativeProps_DEPRECATED` + // and `rawProps` contain key 'A'. Value from `rawProps` overrides what + // was previously in `nativeProps_DEPRECATED`. + family.nativeProps_DEPRECATED = + std::make_unique(mergeDynamicProps( + *family.nativeProps_DEPRECATED, (folly::dynamic)rawProps)); + + props = componentDescriptor.cloneProps( + propsParserContext, + shadowNode.getProps(), + RawProps(*family.nativeProps_DEPRECATED)); + } else { + props = componentDescriptor.cloneProps( + propsParserContext, shadowNode.getProps(), std::move(rawProps)); } auto clonedShadowNode = componentDescriptor.cloneShadowNode( @@ -457,7 +455,7 @@ void UIManager::dispatchCommand( void UIManager::setNativeProps_DEPRECATED( const ShadowNode::Shared& shadowNode, - const RawProps& rawProps) const { + RawProps rawProps) const { auto& family = shadowNode->getFamily(); if (family.nativeProps_DEPRECATED) { // Values in `rawProps` patch (take precedence over) @@ -474,6 +472,8 @@ void UIManager::setNativeProps_DEPRECATED( shadowTreeRegistry_.visit( family.getSurfaceId(), [&](const ShadowTree& shadowTree) { + // The lambda passed to `commit` may be executed multiple times. + // We need to create fresh copy of the `RawProps` object each time. shadowTree.commit( [&](RootShadowNode const& oldRootShadowNode) { auto rootNode = oldRootShadowNode.cloneTree( @@ -486,7 +486,7 @@ void UIManager::setNativeProps_DEPRECATED( auto props = componentDescriptor.cloneProps( propsParserContext, getNewestCloneOfShadowNode(*shadowNode)->getProps(), - rawProps); + RawProps(rawProps)); return oldShadowNode.clone({/* .props = */ props}); }); diff --git a/packages/react-native/ReactCommon/react/renderer/uimanager/UIManager.h b/packages/react-native/ReactCommon/react/renderer/uimanager/UIManager.h index 7ea9b28dcdff9b..e63941b24b3205 100644 --- a/packages/react-native/ReactCommon/react/renderer/uimanager/UIManager.h +++ b/packages/react-native/ReactCommon/react/renderer/uimanager/UIManager.h @@ -134,13 +134,13 @@ class UIManager final : public ShadowTreeDelegate { Tag tag, const std::string& componentName, SurfaceId surfaceId, - const RawProps& props, + RawProps props, InstanceHandle::Shared instanceHandle) const; std::shared_ptr cloneNode( const ShadowNode& shadowNode, - const ShadowNode::SharedListOfShared& children = nullptr, - const RawProps* rawProps = nullptr) const; + const ShadowNode::SharedListOfShared& children, + RawProps rawProps) const; void appendChild( const ShadowNode::Shared& parentShadowNode, @@ -183,7 +183,7 @@ class UIManager final : public ShadowTreeDelegate { void setNativeProps_DEPRECATED( const ShadowNode::Shared& shadowNode, - const RawProps& rawProps) const; + RawProps rawProps) const; void sendAccessibilityEvent( const ShadowNode::Shared& shadowNode, diff --git a/packages/react-native/ReactCommon/react/renderer/uimanager/UIManagerBinding.cpp b/packages/react-native/ReactCommon/react/renderer/uimanager/UIManagerBinding.cpp index 7b4e412ef25031..739729f2d8fe6b 100644 --- a/packages/react-native/ReactCommon/react/renderer/uimanager/UIManagerBinding.cpp +++ b/packages/react-native/ReactCommon/react/renderer/uimanager/UIManagerBinding.cpp @@ -271,7 +271,9 @@ jsi::Value UIManagerBinding::get( return valueFromShadowNode( runtime, uiManager->cloneNode( - *shadowNodeFromValue(runtime, arguments[0]))); + *shadowNodeFromValue(runtime, arguments[0]), + nullptr, + RawProps())); }); } @@ -351,7 +353,8 @@ jsi::Value UIManagerBinding::get( uiManager->cloneNode( *shadowNodeFromValue(runtime, arguments[0]), count > 1 ? shadowNodeListFromValue(runtime, arguments[1]) - : ShadowNode::emptySharedShadowNodeSharedList())); + : ShadowNode::emptySharedShadowNodeSharedList(), + RawProps())); }); } @@ -369,13 +372,12 @@ jsi::Value UIManagerBinding::get( size_t count) -> jsi::Value { validateArgumentCount(runtime, methodName, paramCount, count); - RawProps rawProps(runtime, arguments[1]); return valueFromShadowNode( runtime, uiManager->cloneNode( *shadowNodeFromValue(runtime, arguments[0]), nullptr, - &rawProps)); + RawProps(runtime, arguments[1]))); }); } @@ -396,7 +398,6 @@ jsi::Value UIManagerBinding::get( // validateArgumentCount(runtime, methodName, paramCount, count); bool hasChildrenArg = count == 3; - RawProps rawProps(runtime, arguments[hasChildrenArg ? 2 : 1]); return valueFromShadowNode( runtime, uiManager->cloneNode( @@ -404,7 +405,7 @@ jsi::Value UIManagerBinding::get( hasChildrenArg ? shadowNodeListFromValue(runtime, arguments[1]) : ShadowNode::emptySharedShadowNodeSharedList(), - &rawProps)); + RawProps(runtime, arguments[hasChildrenArg ? 2 : 1]))); }); } From 81e368e1d33bbbebe3c46df045536bbd7d1454bc Mon Sep 17 00:00:00 2001 From: Samuel Susla Date: Wed, 22 Nov 2023 04:33:02 -0800 Subject: [PATCH 058/162] introduce ShadowNode::IdentityTrait (#41603) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41603 changelog: [internal] `ShadowNode::IdentityTrait` was already a thing. Let's make it available in ConcreteComponentDescriptor. Reviewed By: rshest Differential Revision: D51471666 fbshipit-source-id: 7919a9b7238d766ee3913a5ab239bf254fab0996 --- .../ReactCommon/react/renderer/core/ConcreteShadowNode.h | 4 ++++ .../react-native/ReactCommon/react/renderer/core/ShadowNode.h | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/packages/react-native/ReactCommon/react/renderer/core/ConcreteShadowNode.h b/packages/react-native/ReactCommon/react/renderer/core/ConcreteShadowNode.h index 14c3e9ac481833..e2a793b507185e 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/ConcreteShadowNode.h +++ b/packages/react-native/ReactCommon/react/renderer/core/ConcreteShadowNode.h @@ -70,6 +70,10 @@ class ConcreteShadowNode : public BaseShadowNodeT { return BaseShadowNodeT::BaseTraits(); } + static ShadowNodeTraits::Trait IdentifierTrait() { + return BaseShadowNodeT::IdentifierTrait(); + } + static UnsharedConcreteProps Props( const PropsParserContext& context, const RawProps& rawProps, diff --git a/packages/react-native/ReactCommon/react/renderer/core/ShadowNode.h b/packages/react-native/ReactCommon/react/renderer/core/ShadowNode.h index 74f08707b12c48..630082ce698692 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/ShadowNode.h +++ b/packages/react-native/ReactCommon/react/renderer/core/ShadowNode.h @@ -59,6 +59,10 @@ class ShadowNode : public Sealable, return ShadowNodeTraits{}; } + static ShadowNodeTraits::Trait IdentifierTrait() { + return ShadowNodeTraits::Trait::None; + } + #pragma mark - Constructors /* From 9071a3a0b0e11ad711927651bcb2412f553b6fe9 Mon Sep 17 00:00:00 2001 From: Dmitry Rykun Date: Wed, 22 Nov 2023 05:18:15 -0800 Subject: [PATCH 059/162] Delete node calls from generate-artifacts-executor.js (#41534) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41534 This diff deletes calls to `node` from `generate-artifacts-executor.js`, and replaces them with normal `requires` of JS sources. This is a squashed version of (D51116291 ... D51158799). The following sequence of changes has been made: 1. Require and directly invoke `generate-specs-cli-executor` instead of using `node`. 2. Use `codegen-util` to get `RNCodegen` in `generate-provider-cli.js`. 3. Use `RNCodegen` directly instead of using `node`. 4. Move all implementation code from `combine-js-to-schema-cli.js` to `combine-js-to-schema.js`. 5. Decouple building the codegen from getting the codegen CLI. 6. Use `combine-js-to-schema` directly instead of using `node`. 7. Delete unit test that was testing node invocation. 8. Delete `nodeBinary` argument form `generate-codegen-artifacts.js` and its callsites. Changelog: [Internal] Reviewed By: cipolleschi Differential Revision: D51158845 fbshipit-source-id: 5e039801c8045a42349f7cb6ca28e2df24634589 --- .../cli/combine/combine-js-to-schema-cli.js | 42 +---- .../src/cli/combine/combine-js-to-schema.js | 44 ++++- .../generate-artifacts-executor-test.js | 63 ------- .../scripts/codegen/codegen-utils.js | 14 ++ .../codegen/generate-artifacts-executor.js | 157 ++++++------------ .../codegen/generate-specs-cli-executor.js | 3 +- .../scripts/generate-codegen-artifacts.js | 12 +- .../scripts/generate-provider-cli.js | 13 +- .../react_native_pods_utils/script_phases.sh | 2 +- 9 files changed, 119 insertions(+), 231 deletions(-) diff --git a/packages/react-native-codegen/src/cli/combine/combine-js-to-schema-cli.js b/packages/react-native-codegen/src/cli/combine/combine-js-to-schema-cli.js index b67a92a1a42261..8db212a1941176 100644 --- a/packages/react-native-codegen/src/cli/combine/combine-js-to-schema-cli.js +++ b/packages/react-native-codegen/src/cli/combine/combine-js-to-schema-cli.js @@ -11,45 +11,9 @@ 'use strict'; -const combine = require('./combine-js-to-schema'); -const {filterJSFile, parseArgs} = require('./combine-utils'); -const fs = require('fs'); -const glob = require('glob'); -const path = require('path'); +const {combineSchemasInFileList} = require('./combine-js-to-schema'); +const {parseArgs} = require('./combine-utils'); const {platform, outfile, fileList} = parseArgs(process.argv); -const allFiles = []; -fileList.forEach(file => { - if (fs.lstatSync(file).isDirectory()) { - const filePattern = path.sep === '\\' ? file.replace(/\\/g, '/') : file; - const dirFiles = glob - .sync(`${filePattern}/**/*.{js,ts,tsx}`, { - nodir: true, - // TODO: This will remove the need of slash substitution above for Windows, - // but it requires glob@v9+; with the package currenlty relying on - // glob@7.1.1; and flow-typed repo not having definitions for glob@9+. - // windowsPathsNoEscape: true, - }) - .filter(element => filterJSFile(element, platform)); - allFiles.push(...dirFiles); - } else if (filterJSFile(file)) { - allFiles.push(file); - } -}); - -const combined = combine(allFiles); - -// Warn users if there is no modules to process -if (Object.keys(combined.modules).length === 0) { - console.error( - 'No modules to process in combine-js-to-schema-cli. If this is unexpected, please check if you set up your NativeComponent correctly. See combine-js-to-schema.js for how codegen finds modules.', - ); -} -const formattedSchema = JSON.stringify(combined, null, 2); - -if (outfile != null) { - fs.writeFileSync(outfile, formattedSchema); -} else { - console.log(formattedSchema); -} +combineSchemasInFileList(fileList, platform, outfile); diff --git a/packages/react-native-codegen/src/cli/combine/combine-js-to-schema.js b/packages/react-native-codegen/src/cli/combine/combine-js-to-schema.js index a2dcef55c43dab..a0c418b64d5e56 100644 --- a/packages/react-native-codegen/src/cli/combine/combine-js-to-schema.js +++ b/packages/react-native-codegen/src/cli/combine/combine-js-to-schema.js @@ -13,7 +13,9 @@ import type {SchemaType} from '../../CodegenSchema.js'; const {FlowParser} = require('../../parsers/flow/parser'); const {TypeScriptParser} = require('../../parsers/typescript/parser'); +const {filterJSFile} = require('./combine-utils'); const fs = require('fs'); +const glob = require('glob'); const path = require('path'); const flowParser = new FlowParser(); @@ -46,4 +48,44 @@ function combineSchemas(files: Array): SchemaType { ); } -module.exports = combineSchemas; +function expandDirectoriesIntoFiles( + fileList: Array, + platform: ?string, +): Array { + return fileList + .flatMap(file => { + if (!fs.lstatSync(file).isDirectory()) { + return [file]; + } + const filePattern = path.sep === '\\' ? file.replace(/\\/g, '/') : file; + return glob.sync(`${filePattern}/**/*.{js,ts,tsx}`, { + nodir: true, + // TODO: This will remove the need of slash substitution above for Windows, + // but it requires glob@v9+; with the package currenlty relying on + // glob@7.1.1; and flow-typed repo not having definitions for glob@9+. + // windowsPathsNoEscape: true, + }); + }) + .filter(element => filterJSFile(element, platform)); +} + +function combineSchemasInFileList( + fileList: Array, + platform: ?string, + outfile: string, +): void { + const expandedFileList = expandDirectoriesIntoFiles(fileList, platform); + const combined = combineSchemas(expandedFileList); + if (Object.keys(combined.modules).length === 0) { + console.error( + 'No modules to process in combine-js-to-schema-cli. If this is unexpected, please check if you set up your NativeComponent correctly. See combine-js-to-schema.js for how codegen finds modules.', + ); + } + const formattedSchema = JSON.stringify(combined, null, 2); + fs.writeFileSync(outfile, formattedSchema); +} + +module.exports = { + combineSchemas, + combineSchemasInFileList, +}; diff --git a/packages/react-native/scripts/codegen/__tests__/generate-artifacts-executor-test.js b/packages/react-native/scripts/codegen/__tests__/generate-artifacts-executor-test.js index fbff6c7ba9c534..d5e45257fc270e 100644 --- a/packages/react-native/scripts/codegen/__tests__/generate-artifacts-executor-test.js +++ b/packages/react-native/scripts/codegen/__tests__/generate-artifacts-executor-test.js @@ -12,74 +12,11 @@ const fixtures = require('../__test_fixtures__/fixtures'); const underTest = require('../generate-artifacts-executor'); -const child_process = require('child_process'); -const fs = require('fs'); const path = require('path'); const reactNativeDependencyName = 'react-native'; const rootPath = path.join(__dirname, '../../..'); -describe('generateCode', () => { - afterEach(() => { - jest.resetModules(); - jest.resetAllMocks(); - }); - - beforeEach(() => { - // Silence logs from printDeprecationWarningIfNeeded. Ideally, we should have test assertions on these warnings. - jest.spyOn(console, 'log').mockImplementation(); - jest.spyOn(console, 'debug').mockImplementation(); - }); - - it('executeNodes with the right arguments', () => { - // Define variables and expected values - const iosOutputDir = 'app/ios/build/generated/ios'; - const library = {config: {name: 'library', type: 'all'}}; - const tmpDir = 'tmp'; - const node = 'usr/bin/node'; - const pathToSchema = 'app/build/schema.json'; - const rnRoot = path.join(__dirname, '../..'); - const libraryTypeArg = 'all'; - - const tmpOutputDir = path.join(tmpDir, 'out'); - - // mock used functions - jest.spyOn(fs, 'mkdirSync').mockImplementation(); - jest.spyOn(child_process, 'execSync').mockImplementation(); - jest.spyOn(child_process, 'execFileSync').mockImplementation(); - - underTest._generateCode(iosOutputDir, library, tmpDir, node, pathToSchema); - - expect(child_process.execFileSync).toHaveBeenCalledTimes(1); - expect(child_process.execFileSync).toHaveBeenNthCalledWith(1, node, [ - `${path.join(rnRoot, 'generate-specs-cli.js')}`, - '--platform', - 'ios', - '--schemaPath', - pathToSchema, - '--outputDir', - tmpOutputDir, - '--libraryName', - library.config.name, - '--libraryType', - libraryTypeArg, - ]); - expect(child_process.execSync).toHaveBeenCalledTimes(1); - expect(child_process.execSync).toHaveBeenNthCalledWith( - 1, - `cp -R ${tmpOutputDir}/* "${iosOutputDir}"`, - ); - - expect(fs.mkdirSync).toHaveBeenCalledTimes(2); - expect(fs.mkdirSync).toHaveBeenNthCalledWith(1, tmpOutputDir, { - recursive: true, - }); - expect(fs.mkdirSync).toHaveBeenNthCalledWith(2, iosOutputDir, { - recursive: true, - }); - }); -}); - describe('extractLibrariesFromJSON', () => { it('throws if in react-native and no dependencies found', () => { let configFile = {}; diff --git a/packages/react-native/scripts/codegen/codegen-utils.js b/packages/react-native/scripts/codegen/codegen-utils.js index b739d81c5a4075..d151bda6eff5c2 100644 --- a/packages/react-native/scripts/codegen/codegen-utils.js +++ b/packages/react-native/scripts/codegen/codegen-utils.js @@ -32,6 +32,20 @@ function getCodegen() { return RNCodegen; } +function getCombineJSToSchema() { + let combineJSToSchema; + try { + combineJSToSchema = require('../../packages/react-native-codegen/lib/cli/combine/combine-js-to-schema.js'); + } catch (e) { + combineJSToSchema = require('@react-native/codegen/lib/cli/combine/combine-js-to-schema.js'); + } + if (!combineJSToSchema) { + throw 'combine-js-to-schema not found.'; + } + return combineJSToSchema; +} + module.exports = { getCodegen: getCodegen, + getCombineJSToSchema: getCombineJSToSchema, }; diff --git a/packages/react-native/scripts/codegen/generate-artifacts-executor.js b/packages/react-native/scripts/codegen/generate-artifacts-executor.js index bdfbec6c756fb7..8ac62e39cd14f2 100644 --- a/packages/react-native/scripts/codegen/generate-artifacts-executor.js +++ b/packages/react-native/scripts/codegen/generate-artifacts-executor.js @@ -16,8 +16,11 @@ * in a package.json file. */ -const {execFileSync, execSync} = require('child_process'); +const utils = require('./codegen-utils'); +const generateSpecsCLIExecutor = require('./generate-specs-cli-executor'); +const {execSync} = require('child_process'); const fs = require('fs'); +const mkdirp = require('mkdirp'); const os = require('os'); const path = require('path'); @@ -29,10 +32,7 @@ const REACT_NATIVE_REPOSITORY_ROOT = path.join( '..', ); const REACT_NATIVE_PACKAGE_ROOT_FOLDER = path.join(__dirname, '..', '..'); - -const CODEGEN_DEPENDENCY_NAME = '@react-native/codegen'; const CODEGEN_REPO_PATH = `${REACT_NATIVE_REPOSITORY_ROOT}/packages/react-native-codegen`; -const CODEGEN_NPM_PATH = `${REACT_NATIVE_PACKAGE_ROOT_FOLDER}/../${CODEGEN_DEPENDENCY_NAME}`; const CORE_LIBRARIES_WITH_OUTPUT_FOLDER = { rncore: path.join(REACT_NATIVE_PACKAGE_ROOT_FOLDER, 'ReactCommon'), FBReactNativeSpec: null, @@ -45,10 +45,6 @@ function isReactNativeCoreLibrary(libraryName) { return libraryName in CORE_LIBRARIES_WITH_OUTPUT_FOLDER; } -function executeNodeScript(node, scriptArgs) { - execFileSync(node, scriptArgs); -} - function isAppRootValid(appRootDir) { if (appRootDir == null) { console.error('Missing path to React Native application'); @@ -235,84 +231,61 @@ function handleInAppLibraries(pkgJson, appRootDir) { } // CodeGen -function getCodeGenCliPath() { - let codegenCliPath; - if (fs.existsSync(CODEGEN_REPO_PATH)) { - codegenCliPath = CODEGEN_REPO_PATH; - - if (!fs.existsSync(path.join(CODEGEN_REPO_PATH, 'lib'))) { - console.log('\n\n[Codegen] >>>>> Building react-native-codegen package'); - execSync('yarn install', { - cwd: codegenCliPath, - stdio: 'inherit', - }); - execSync('yarn build', { - cwd: codegenCliPath, - stdio: 'inherit', - }); - } - } else if (fs.existsSync(CODEGEN_NPM_PATH)) { - codegenCliPath = CODEGEN_NPM_PATH; - } else { - throw `error: Could not determine ${CODEGEN_DEPENDENCY_NAME} location. Try running 'yarn install' or 'npm install' in your project root.`; +function buildCodegenIfNeeded() { + if (!fs.existsSync(CODEGEN_REPO_PATH)) { + return; } - return codegenCliPath; + // Assuming we are working in the react-native repo. We might need to build the codegen. + // This will become unnecessary once we start using Babel Register for the codegen package. + const libPath = path.join(CODEGEN_REPO_PATH, 'lib'); + if (fs.existsSync(libPath) && fs.readdirSync(libPath).length > 0) { + return; + } + console.log('\n\n[Codegen] >>>>> Building react-native-codegen package'); + execSync('yarn install', { + cwd: CODEGEN_REPO_PATH, + stdio: 'inherit', + }); + execSync('yarn build', { + cwd: CODEGEN_REPO_PATH, + stdio: 'inherit', + }); } function computeIOSOutputDir(outputPath, appRootDir) { return path.join(outputPath ? outputPath : appRootDir, 'build/generated/ios'); } -function generateSchema(tmpDir, library, node, codegenCliPath) { +function generateSchema(tmpDir, library) { const pathToSchema = path.join(tmpDir, 'schema.json'); const pathToJavaScriptSources = path.join( library.libraryPath, library.config.jsSrcsDir, ); - console.log(`\n\n[Codegen] >>>>> Processing ${library.config.name}`); // Generate one schema for the entire library... - executeNodeScript(node, [ - `${path.join( - codegenCliPath, - 'lib', - 'cli', - 'combine', - 'combine-js-to-schema-cli.js', - )}`, - '--platform', - 'ios', - pathToSchema, - pathToJavaScriptSources, - ]); + utils + .getCombineJSToSchema() + .combineSchemasInFileList([pathToJavaScriptSources], 'ios', pathToSchema); console.log(`[Codegen] Generated schema: ${pathToSchema}`); return pathToSchema; } -function generateCode(iosOutputDir, library, tmpDir, node, pathToSchema) { +function generateCode(iosOutputDir, library, tmpDir, pathToSchema) { // ...then generate native code artifacts. const libraryTypeArg = library.config.type ? `${library.config.type}` : ''; const tmpOutputDir = path.join(tmpDir, 'out'); fs.mkdirSync(tmpOutputDir, {recursive: true}); - executeNodeScript(node, [ - `${path.join( - REACT_NATIVE_PACKAGE_ROOT_FOLDER, - 'scripts', - 'generate-specs-cli.js', - )}`, - '--platform', + generateSpecsCLIExecutor.execute( 'ios', - '--schemaPath', pathToSchema, - '--outputDir', tmpOutputDir, - '--libraryName', library.config.name, - '--libraryType', + 'com.facebook.fbreact.specs', libraryTypeArg, - ]); + ); // Finally, copy artifacts to the final output directory. const outputDir = @@ -322,17 +295,11 @@ function generateCode(iosOutputDir, library, tmpDir, node, pathToSchema) { console.log(`[Codegen] Generated artifacts: ${iosOutputDir}`); } -function generateNativeCodegenFiles( - libraries, - iosOutputDir, - node, - codegenCliPath, - schemaPaths, -) { +function generateNativeCodegenFiles(libraries, iosOutputDir, schemaPaths) { libraries.forEach(library => { const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), library.config.name)); - const pathToSchema = generateSchema(tmpDir, library, node, codegenCliPath); - generateCode(iosOutputDir, library, tmpDir, node, pathToSchema); + const pathToSchema = generateSchema(tmpDir, library); + generateCode(iosOutputDir, library, tmpDir, pathToSchema); // Filter the react native core library out. // In the future, core library and third party library should @@ -343,36 +310,28 @@ function generateNativeCodegenFiles( }); } -function createComponentProvider(schemaPaths, node) { +function createComponentProvider(schemaPaths) { console.log('\n\n>>>>> Creating component provider'); - // Save the list of spec paths to a temp file. - const schemaListTmpPath = `${os.tmpdir()}/rn-tmp-schema-list.json`; - const fd = fs.openSync(schemaListTmpPath, 'w'); - fs.writeSync(fd, JSON.stringify(schemaPaths)); - fs.closeSync(fd); - console.log(`Generated schema list: ${schemaListTmpPath}`); - const outputDir = path.join( REACT_NATIVE_PACKAGE_ROOT_FOLDER, 'React', 'Fabric', ); - - // Generate FabricComponentProvider. - // Only for iOS at this moment. - executeNodeScript(node, [ - `${path.join( - REACT_NATIVE_PACKAGE_ROOT_FOLDER, - 'scripts', - 'generate-provider-cli.js', - )}`, - '--platform', - 'ios', - '--schemaListPath', - schemaListTmpPath, - '--outputDir', - outputDir, - ]); + mkdirp.sync(outputDir); + const schemas = {}; + for (const libraryName of Object.keys(schemaPaths)) { + const tmpSchemaText = fs.readFileSync(schemaPaths[libraryName], 'utf-8'); + schemas[libraryName] = JSON.parse(tmpSchemaText); + } + utils.getCodegen().generateFromSchemas( + { + schemas: schemas, + outputDirectory: outputDir, + }, + { + generators: ['providerIOS'], + }, + ); console.log(`Generated provider in: ${outputDir}`); } @@ -431,17 +390,18 @@ function cleanupEmptyFilesAndFolders(filepath) { * * @parameter appRootDir: the directory with the app source code, where the package.json lives. * @parameter outputPath: the base output path for the CodeGen. - * @parameter node: the path to the node executable, used to run the codegen scripts. * @parameter baseCodegenConfigFileDir: the directory of the codeGenConfigFile. * @throws If it can't find a config file for react-native. * @throws If it can't find a CodeGen configuration in the file. * @throws If it can't find a cli for the CodeGen. */ -function execute(appRootDir, outputPath, node, baseCodegenConfigFileDir) { +function execute(appRootDir, outputPath, baseCodegenConfigFileDir) { if (!isAppRootValid(appRootDir)) { return; } + buildCodegenIfNeeded(); + try { const libraries = findCodegenEnabledLibraries( appRootDir, @@ -453,21 +413,13 @@ function execute(appRootDir, outputPath, node, baseCodegenConfigFileDir) { return; } - const codegenCliPath = getCodeGenCliPath(); - const schemaPaths = {}; const iosOutputDir = computeIOSOutputDir(outputPath, appRootDir); - generateNativeCodegenFiles( - libraries, - iosOutputDir, - node, - codegenCliPath, - schemaPaths, - ); + generateNativeCodegenFiles(libraries, iosOutputDir, schemaPaths); - createComponentProvider(schemaPaths, node); + createComponentProvider(schemaPaths); cleanupEmptyFilesAndFolders(iosOutputDir); } catch (err) { console.error(err); @@ -483,7 +435,6 @@ module.exports = { // exported for testing purposes only: _extractLibrariesFromJSON: extractLibrariesFromJSON, _findCodegenEnabledLibraries: findCodegenEnabledLibraries, - _executeNodeScript: executeNodeScript, _generateCode: generateCode, _cleanupEmptyFilesAndFolders: cleanupEmptyFilesAndFolders, }; diff --git a/packages/react-native/scripts/codegen/generate-specs-cli-executor.js b/packages/react-native/scripts/codegen/generate-specs-cli-executor.js index 3f4f93cdc1c812..b2f82fd51f5311 100644 --- a/packages/react-native/scripts/codegen/generate-specs-cli-executor.js +++ b/packages/react-native/scripts/codegen/generate-specs-cli-executor.js @@ -13,7 +13,6 @@ const utils = require('./codegen-utils'); const fs = require('fs'); const mkdirp = require('mkdirp'); const path = require('path'); -const RNCodegen = utils.getCodegen(); const GENERATORS = { all: { @@ -94,7 +93,7 @@ function generateSpec( createFolderIfDefined(composePath('react/renderer/components/')); createFolderIfDefined(composePath('./')); - RNCodegen.generate( + utils.getCodegen().generate( { libraryName, schema, diff --git a/packages/react-native/scripts/generate-codegen-artifacts.js b/packages/react-native/scripts/generate-codegen-artifacts.js index 91994044a17abf..bcbc8aaf039f28 100644 --- a/packages/react-native/scripts/generate-codegen-artifacts.js +++ b/packages/react-native/scripts/generate-codegen-artifacts.js @@ -27,17 +27,7 @@ const argv = yargs description: 'Path where codegen config files are located (e.g. node_modules dir).', }) - .option('n', { - alias: 'nodeBinary', - default: 'node', - description: 'Path to the node executable.', - }) .usage('Usage: $0 -p [path to app]') .demandOption(['p']).argv; -executor.execute( - argv.path, - argv.outputPath, - argv.nodeBinary, - argv.configFileDir, -); +executor.execute(argv.path, argv.outputPath, argv.configFileDir); diff --git a/packages/react-native/scripts/generate-provider-cli.js b/packages/react-native/scripts/generate-provider-cli.js index 852a8d300093ac..22afb409405dbd 100644 --- a/packages/react-native/scripts/generate-provider-cli.js +++ b/packages/react-native/scripts/generate-provider-cli.js @@ -9,16 +9,7 @@ 'use strict'; -let RNCodegen; -try { - RNCodegen = require('../packages/react-native-codegen/lib/generators/RNCodegen.js'); -} catch (e) { - RNCodegen = require('@react-native/codegen/lib/generators/RNCodegen.js'); - if (!RNCodegen) { - throw 'RNCodegen not found.'; - } -} - +const utils = require('./codegen/codegen-utils'); const fs = require('fs'); const mkdirp = require('mkdirp'); const yargs = require('yargs'); @@ -81,7 +72,7 @@ function generateProvider(platform, schemaListPath, outputDirectory) { throw new Error(`Invalid platform type. ${platform}`); } - RNCodegen.generateFromSchemas( + utils.getCodegen().generateFromSchemas( { schemas, outputDirectory, diff --git a/packages/react-native/scripts/react_native_pods_utils/script_phases.sh b/packages/react-native/scripts/react_native_pods_utils/script_phases.sh index d72626232fe549..ab1eddfca72188 100755 --- a/packages/react-native/scripts/react_native_pods_utils/script_phases.sh +++ b/packages/react-native/scripts/react_native_pods_utils/script_phases.sh @@ -96,7 +96,7 @@ generateCodegenArtifactsFromSchema () { generateArtifacts () { describe "Generating codegen artifacts" pushd "$RCT_SCRIPT_RN_DIR" >/dev/null || exit 1 - "$NODE_BINARY" "scripts/generate-codegen-artifacts.js" --path "$RCT_SCRIPT_APP_PATH" --outputPath "$TEMP_OUTPUT_DIR" --configFileDir "$RCT_SCRIPT_CONFIG_FILE_DIR" --nodeBinary "$NODE_BINARY" + "$NODE_BINARY" "scripts/generate-codegen-artifacts.js" --path "$RCT_SCRIPT_APP_PATH" --outputPath "$TEMP_OUTPUT_DIR" --configFileDir "$RCT_SCRIPT_CONFIG_FILE_DIR" popd >/dev/null || exit 1 } From e989d0bf77199743785a8e4e96ef7d06222953c4 Mon Sep 17 00:00:00 2001 From: zhongwuzw Date: Wed, 22 Nov 2023 05:18:30 -0800 Subject: [PATCH 060/162] Fix Fabric componentregistrynative spec not work (#41602) Summary: `componentregistry`'s `source_files` of spec contains the `componentregistrynative`'s `source_files`, it caused `componentregistrynative` spec not work. ![image](https://github.com/facebook/react-native/assets/5061845/9d8706d3-d5a4-4637-8cf4-db095264cda5) cc. sammy-SC ## Changelog: [IOS] [FIXED] - Fix Fabric componentregistrynative spec not work Pull Request resolved: https://github.com/facebook/react-native/pull/41602 Test Plan: None. Reviewed By: javache Differential Revision: D51525001 Pulled By: cipolleschi fbshipit-source-id: 63f4ecb640f513170824cee6cbc800e805a81adb --- packages/react-native/ReactCommon/React-Fabric.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react-native/ReactCommon/React-Fabric.podspec b/packages/react-native/ReactCommon/React-Fabric.podspec index d4d6eb87d43164..eb47078b78c891 100644 --- a/packages/react-native/ReactCommon/React-Fabric.podspec +++ b/packages/react-native/ReactCommon/React-Fabric.podspec @@ -115,7 +115,7 @@ Pod::Spec.new do |s| s.subspec "componentregistry" do |ss| ss.dependency folly_dep_name, folly_version ss.compiler_flags = folly_compiler_flags - ss.source_files = "react/renderer/componentregistry/**/*.{m,mm,cpp,h}" + ss.source_files = "react/renderer/componentregistry/*.{m,mm,cpp,h}" ss.header_dir = "react/renderer/componentregistry" end From 3ecf1bce1dc5f12ed8328f30a7c2e3d1631fa616 Mon Sep 17 00:00:00 2001 From: Dmitry Rykun Date: Wed, 22 Nov 2023 06:57:03 -0800 Subject: [PATCH 061/162] Refactor generate-artifacts-executor.js: keep schema in memory instead of writing/reading from disk (#41554) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41554 This diff removes inefficiency where we first write schema to disk in `combine-js-to-schema.js`, and then read it from disk in `generate-specs-cli-executor.js`. With this change we can just pass it as an argument. Changelog: [Internal] Reviewed By: cipolleschi Differential Revision: D51161162 fbshipit-source-id: 35d14ca3e53e4bf999520c635c66909c20081096 --- .../cli/combine/combine-js-to-schema-cli.js | 6 ++- .../src/cli/combine/combine-js-to-schema.js | 13 ++++++- .../codegen/generate-artifacts-executor.js | 38 ++++++++----------- .../codegen/generate-specs-cli-executor.js | 26 ++++++++++--- 4 files changed, 51 insertions(+), 32 deletions(-) diff --git a/packages/react-native-codegen/src/cli/combine/combine-js-to-schema-cli.js b/packages/react-native-codegen/src/cli/combine/combine-js-to-schema-cli.js index 8db212a1941176..fbcc50be7c7da8 100644 --- a/packages/react-native-codegen/src/cli/combine/combine-js-to-schema-cli.js +++ b/packages/react-native-codegen/src/cli/combine/combine-js-to-schema-cli.js @@ -11,9 +11,11 @@ 'use strict'; -const {combineSchemasInFileList} = require('./combine-js-to-schema'); +const { + combineSchemasInFileListAndWriteToFile, +} = require('./combine-js-to-schema'); const {parseArgs} = require('./combine-utils'); const {platform, outfile, fileList} = parseArgs(process.argv); -combineSchemasInFileList(fileList, platform, outfile); +combineSchemasInFileListAndWriteToFile(fileList, platform, outfile); diff --git a/packages/react-native-codegen/src/cli/combine/combine-js-to-schema.js b/packages/react-native-codegen/src/cli/combine/combine-js-to-schema.js index a0c418b64d5e56..01af2f8b29b66d 100644 --- a/packages/react-native-codegen/src/cli/combine/combine-js-to-schema.js +++ b/packages/react-native-codegen/src/cli/combine/combine-js-to-schema.js @@ -72,8 +72,7 @@ function expandDirectoriesIntoFiles( function combineSchemasInFileList( fileList: Array, platform: ?string, - outfile: string, -): void { +): SchemaType { const expandedFileList = expandDirectoriesIntoFiles(fileList, platform); const combined = combineSchemas(expandedFileList); if (Object.keys(combined.modules).length === 0) { @@ -81,6 +80,15 @@ function combineSchemasInFileList( 'No modules to process in combine-js-to-schema-cli. If this is unexpected, please check if you set up your NativeComponent correctly. See combine-js-to-schema.js for how codegen finds modules.', ); } + return combined; +} + +function combineSchemasInFileListAndWriteToFile( + fileList: Array, + platform: ?string, + outfile: string, +): void { + const combined = combineSchemasInFileList(fileList, platform); const formattedSchema = JSON.stringify(combined, null, 2); fs.writeFileSync(outfile, formattedSchema); } @@ -88,4 +96,5 @@ function combineSchemasInFileList( module.exports = { combineSchemas, combineSchemasInFileList, + combineSchemasInFileListAndWriteToFile, }; diff --git a/packages/react-native/scripts/codegen/generate-artifacts-executor.js b/packages/react-native/scripts/codegen/generate-artifacts-executor.js index 8ac62e39cd14f2..6af23b2f664cc5 100644 --- a/packages/react-native/scripts/codegen/generate-artifacts-executor.js +++ b/packages/react-native/scripts/codegen/generate-artifacts-executor.js @@ -256,31 +256,28 @@ function computeIOSOutputDir(outputPath, appRootDir) { return path.join(outputPath ? outputPath : appRootDir, 'build/generated/ios'); } -function generateSchema(tmpDir, library) { - const pathToSchema = path.join(tmpDir, 'schema.json'); +function generateSchema(library) { const pathToJavaScriptSources = path.join( library.libraryPath, library.config.jsSrcsDir, ); console.log(`\n\n[Codegen] >>>>> Processing ${library.config.name}`); // Generate one schema for the entire library... - utils + return utils .getCombineJSToSchema() - .combineSchemasInFileList([pathToJavaScriptSources], 'ios', pathToSchema); - console.log(`[Codegen] Generated schema: ${pathToSchema}`); - return pathToSchema; + .combineSchemasInFileList([pathToJavaScriptSources], 'ios'); } -function generateCode(iosOutputDir, library, tmpDir, pathToSchema) { +function generateCode(iosOutputDir, library, tmpDir, schema) { // ...then generate native code artifacts. const libraryTypeArg = library.config.type ? `${library.config.type}` : ''; const tmpOutputDir = path.join(tmpDir, 'out'); fs.mkdirSync(tmpOutputDir, {recursive: true}); - generateSpecsCLIExecutor.execute( + generateSpecsCLIExecutor.generateSpecFromInMemorySchema( 'ios', - pathToSchema, + schema, tmpOutputDir, library.config.name, 'com.facebook.fbreact.specs', @@ -295,22 +292,24 @@ function generateCode(iosOutputDir, library, tmpDir, pathToSchema) { console.log(`[Codegen] Generated artifacts: ${iosOutputDir}`); } -function generateNativeCodegenFiles(libraries, iosOutputDir, schemaPaths) { +function generateNativeCodegenFiles(libraries, iosOutputDir) { + const schemas = {}; libraries.forEach(library => { const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), library.config.name)); - const pathToSchema = generateSchema(tmpDir, library); - generateCode(iosOutputDir, library, tmpDir, pathToSchema); + const schema = generateSchema(library); + generateCode(iosOutputDir, library, tmpDir, schema); // Filter the react native core library out. // In the future, core library and third party library should // use the same way to generate/register the fabric components. if (!isReactNativeCoreLibrary(library.config.name)) { - schemaPaths[library.config.name] = pathToSchema; + schemas[library.config.name] = schema; } }); + return schemas; } -function createComponentProvider(schemaPaths) { +function createComponentProvider(schemas) { console.log('\n\n>>>>> Creating component provider'); const outputDir = path.join( REACT_NATIVE_PACKAGE_ROOT_FOLDER, @@ -318,11 +317,6 @@ function createComponentProvider(schemaPaths) { 'Fabric', ); mkdirp.sync(outputDir); - const schemas = {}; - for (const libraryName of Object.keys(schemaPaths)) { - const tmpSchemaText = fs.readFileSync(schemaPaths[libraryName], 'utf-8'); - schemas[libraryName] = JSON.parse(tmpSchemaText); - } utils.getCodegen().generateFromSchemas( { schemas: schemas, @@ -413,13 +407,11 @@ function execute(appRootDir, outputPath, baseCodegenConfigFileDir) { return; } - const schemaPaths = {}; - const iosOutputDir = computeIOSOutputDir(outputPath, appRootDir); - generateNativeCodegenFiles(libraries, iosOutputDir, schemaPaths); + const schemas = generateNativeCodegenFiles(libraries, iosOutputDir); - createComponentProvider(schemaPaths); + createComponentProvider(schemas); cleanupEmptyFilesAndFolders(iosOutputDir); } catch (err) { console.error(err); diff --git a/packages/react-native/scripts/codegen/generate-specs-cli-executor.js b/packages/react-native/scripts/codegen/generate-specs-cli-executor.js index b2f82fd51f5311..fb88e4a1dd54d2 100644 --- a/packages/react-native/scripts/codegen/generate-specs-cli-executor.js +++ b/packages/react-native/scripts/codegen/generate-specs-cli-executor.js @@ -70,18 +70,15 @@ function validateLibraryType(libraryType) { } } -function generateSpec( +function generateSpecFromInMemorySchema( platform, - schemaPath, + schema, outputDirectory, libraryName, packageName, libraryType, ) { validateLibraryType(libraryType); - - let schema = readAndParseSchema(schemaPath); - createOutputDirectoryIfNeeded(outputDirectory, libraryName); function composePath(intermediate) { return path.join(outputDirectory, intermediate, libraryName); @@ -121,6 +118,25 @@ function generateSpec( } } +function generateSpec( + platform, + schemaPath, + outputDirectory, + libraryName, + packageName, + libraryType, +) { + generateSpecFromInMemorySchema( + platform, + readAndParseSchema(schemaPath), + outputDirectory, + libraryName, + packageName, + libraryType, + ); +} + module.exports = { execute: generateSpec, + generateSpecFromInMemorySchema: generateSpecFromInMemorySchema, }; From 980fb0cb518072e7ce066a331f8cbbedc035b441 Mon Sep 17 00:00:00 2001 From: Dmitry Rykun Date: Wed, 22 Nov 2023 07:59:54 -0800 Subject: [PATCH 062/162] Refactor generate-artifacts-executor.js: decouple schema and native files generation (#41555) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41555 This diff splits `generateNativeCodegenFiles` into two simpler steps: `generateSchemaInfos` and `generateCode`. `SchemaInfo` is a (library, schema) pair, it is convenient for further transformations. Changelog: [Internal] Reviewed By: cipolleschi Differential Revision: D51204077 fbshipit-source-id: 8a1f585a79a2a0241b544a8a131b59250d803e2e --- .../codegen/generate-artifacts-executor.js | 65 +++++++++++-------- 1 file changed, 37 insertions(+), 28 deletions(-) diff --git a/packages/react-native/scripts/codegen/generate-artifacts-executor.js b/packages/react-native/scripts/codegen/generate-artifacts-executor.js index 6af23b2f664cc5..f2ec937fa1c5ac 100644 --- a/packages/react-native/scripts/codegen/generate-artifacts-executor.js +++ b/packages/react-native/scripts/codegen/generate-artifacts-executor.js @@ -256,57 +256,62 @@ function computeIOSOutputDir(outputPath, appRootDir) { return path.join(outputPath ? outputPath : appRootDir, 'build/generated/ios'); } -function generateSchema(library) { +function generateSchemaInfo(library) { const pathToJavaScriptSources = path.join( library.libraryPath, library.config.jsSrcsDir, ); console.log(`\n\n[Codegen] >>>>> Processing ${library.config.name}`); // Generate one schema for the entire library... - return utils - .getCombineJSToSchema() - .combineSchemasInFileList([pathToJavaScriptSources], 'ios'); + return { + library: library, + schema: utils + .getCombineJSToSchema() + .combineSchemasInFileList([pathToJavaScriptSources], 'ios'), + }; } -function generateCode(iosOutputDir, library, tmpDir, schema) { - // ...then generate native code artifacts. - const libraryTypeArg = library.config.type ? `${library.config.type}` : ''; - +function generateCode(iosOutputDir, schemaInfo) { + const tmpDir = fs.mkdtempSync( + path.join(os.tmpdir(), schemaInfo.library.config.name), + ); const tmpOutputDir = path.join(tmpDir, 'out'); fs.mkdirSync(tmpOutputDir, {recursive: true}); generateSpecsCLIExecutor.generateSpecFromInMemorySchema( 'ios', - schema, + schemaInfo.schema, tmpOutputDir, - library.config.name, + schemaInfo.library.config.name, 'com.facebook.fbreact.specs', - libraryTypeArg, + schemaInfo.library.config.type, ); // Finally, copy artifacts to the final output directory. const outputDir = - CORE_LIBRARIES_WITH_OUTPUT_FOLDER[library.config.name] ?? iosOutputDir; + CORE_LIBRARIES_WITH_OUTPUT_FOLDER[schemaInfo.library.config.name] ?? + iosOutputDir; fs.mkdirSync(outputDir, {recursive: true}); + // TODO: Fix this. This will not work on Windows. execSync(`cp -R ${tmpOutputDir}/* "${outputDir}"`); - console.log(`[Codegen] Generated artifacts: ${iosOutputDir}`); + console.log(`[Codegen] Generated artifacts: ${outputDir}`); } -function generateNativeCodegenFiles(libraries, iosOutputDir) { - const schemas = {}; - libraries.forEach(library => { - const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), library.config.name)); - const schema = generateSchema(library); - generateCode(iosOutputDir, library, tmpDir, schema); - - // Filter the react native core library out. - // In the future, core library and third party library should - // use the same way to generate/register the fabric components. - if (!isReactNativeCoreLibrary(library.config.name)) { - schemas[library.config.name] = schema; - } +function generateSchemaInfos(libraries) { + return libraries.map(generateSchemaInfo); +} + +function generateNativeCode(iosOutputDir, schemaInfos) { + return schemaInfos.map(schemaInfo => { + generateCode(iosOutputDir, schemaInfo); }); - return schemas; +} + +function needsThirdPartyComponentProvider(schemaInfo) { + // Filter the react native core library out. + // In the future, core library and third party library should + // use the same way to generate/register the fabric components. + return !isReactNativeCoreLibrary(schemaInfo.library.config.name); } function createComponentProvider(schemas) { @@ -409,8 +414,12 @@ function execute(appRootDir, outputPath, baseCodegenConfigFileDir) { const iosOutputDir = computeIOSOutputDir(outputPath, appRootDir); - const schemas = generateNativeCodegenFiles(libraries, iosOutputDir); + const schemaInfos = generateSchemaInfos(libraries); + generateNativeCode(iosOutputDir, schemaInfos); + const schemas = schemaInfos + .filter(needsThirdPartyComponentProvider) + .map(schemaInfo => schemaInfo.schema); createComponentProvider(schemas); cleanupEmptyFilesAndFolders(iosOutputDir); } catch (err) { From 4e59a2f791996c0db26908a888587e095198ac03 Mon Sep 17 00:00:00 2001 From: Intl Scheduler <> Date: Wed, 22 Nov 2023 08:08:15 -0800 Subject: [PATCH 063/162] translation auto-update for i18n/fb4a.config.json on master Summary: Chronos Job Instance ID: 1125907943710647 Sandcastle Job Instance ID: 22517999251971187 allow-large-files ignore-conflict-markers opt-out-review Differential Revision: D51528777 fbshipit-source-id: bc9fd635117aac9dd50130f01bb317bb93ff7c36 --- .../src/main/res/views/uimanager/values-kk/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/react-native/ReactAndroid/src/main/res/views/uimanager/values-kk/strings.xml b/packages/react-native/ReactAndroid/src/main/res/views/uimanager/values-kk/strings.xml index b8a8437b146fe5..278368ed76b950 100644 --- a/packages/react-native/ReactAndroid/src/main/res/views/uimanager/values-kk/strings.xml +++ b/packages/react-native/ReactAndroid/src/main/res/views/uimanager/values-kk/strings.xml @@ -7,6 +7,7 @@ Кескін Түйме, кескін Біріктірілген тізім + Мәзір қосулы өшірулі From 414357acdedc1486f0bdb4710eaeb950e5a906ee Mon Sep 17 00:00:00 2001 From: Sam Zhou Date: Wed, 22 Nov 2023 10:41:58 -0800 Subject: [PATCH 064/162] Update babel-types codegen to use type guards instead of `%checks` (#41597) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41597 Changelog: [Internal] Reviewed By: motiz88 Differential Revision: D51508414 fbshipit-source-id: 6572e02a42c30874bc7e2ef48b9c389dcb906914 --- flow-typed/npm/babel-types_v7.x.x.js | 610 +++++++++++++-------------- 1 file changed, 305 insertions(+), 305 deletions(-) diff --git a/flow-typed/npm/babel-types_v7.x.x.js b/flow-typed/npm/babel-types_v7.x.x.js index 74249fe3c2fd76..6f344941bc71fd 100644 --- a/flow-typed/npm/babel-types_v7.x.x.js +++ b/flow-typed/npm/babel-types_v7.x.x.js @@ -3443,308 +3443,308 @@ declare module "@babel/types" { declare export function tsTypeParameterInstantiation(params: Array): BabelNodeTSTypeParameterInstantiation; declare export function tsTypeParameterDeclaration(params: Array): BabelNodeTSTypeParameterDeclaration; declare export function tsTypeParameter(constraint?: BabelNodeTSType, _default?: BabelNodeTSType, name: string): BabelNodeTSTypeParameter; - declare export function isArrayExpression(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'ArrayExpression'); - declare export function isAssignmentExpression(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'AssignmentExpression'); - declare export function isBinaryExpression(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'BinaryExpression'); - declare export function isInterpreterDirective(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'InterpreterDirective'); - declare export function isDirective(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'Directive'); - declare export function isDirectiveLiteral(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'DirectiveLiteral'); - declare export function isBlockStatement(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'BlockStatement'); - declare export function isBreakStatement(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'BreakStatement'); - declare export function isCallExpression(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'CallExpression'); - declare export function isCatchClause(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'CatchClause'); - declare export function isConditionalExpression(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'ConditionalExpression'); - declare export function isContinueStatement(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'ContinueStatement'); - declare export function isDebuggerStatement(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'DebuggerStatement'); - declare export function isDoWhileStatement(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'DoWhileStatement'); - declare export function isEmptyStatement(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'EmptyStatement'); - declare export function isExpressionStatement(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'ExpressionStatement'); - declare export function isFile(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'File'); - declare export function isForInStatement(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'ForInStatement'); - declare export function isForStatement(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'ForStatement'); - declare export function isFunctionDeclaration(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'FunctionDeclaration'); - declare export function isFunctionExpression(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'FunctionExpression'); - declare export function isIdentifier(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'Identifier'); - declare export function isIfStatement(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'IfStatement'); - declare export function isLabeledStatement(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'LabeledStatement'); - declare export function isStringLiteral(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'StringLiteral'); - declare export function isNumericLiteral(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'NumericLiteral'); - declare export function isNullLiteral(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'NullLiteral'); - declare export function isBooleanLiteral(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'BooleanLiteral'); - declare export function isRegExpLiteral(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'RegExpLiteral'); - declare export function isLogicalExpression(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'LogicalExpression'); - declare export function isMemberExpression(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'MemberExpression'); - declare export function isNewExpression(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'NewExpression'); - declare export function isProgram(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'Program'); - declare export function isObjectExpression(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'ObjectExpression'); - declare export function isObjectMethod(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'ObjectMethod'); - declare export function isObjectProperty(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'ObjectProperty'); - declare export function isRestElement(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'RestElement'); - declare export function isReturnStatement(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'ReturnStatement'); - declare export function isSequenceExpression(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'SequenceExpression'); - declare export function isParenthesizedExpression(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'ParenthesizedExpression'); - declare export function isSwitchCase(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'SwitchCase'); - declare export function isSwitchStatement(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'SwitchStatement'); - declare export function isThisExpression(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'ThisExpression'); - declare export function isThrowStatement(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'ThrowStatement'); - declare export function isTryStatement(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'TryStatement'); - declare export function isUnaryExpression(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'UnaryExpression'); - declare export function isUpdateExpression(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'UpdateExpression'); - declare export function isVariableDeclaration(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'VariableDeclaration'); - declare export function isVariableDeclarator(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'VariableDeclarator'); - declare export function isWhileStatement(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'WhileStatement'); - declare export function isWithStatement(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'WithStatement'); - declare export function isAssignmentPattern(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'AssignmentPattern'); - declare export function isArrayPattern(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'ArrayPattern'); - declare export function isArrowFunctionExpression(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'ArrowFunctionExpression'); - declare export function isClassBody(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'ClassBody'); - declare export function isClassExpression(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'ClassExpression'); - declare export function isClassDeclaration(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'ClassDeclaration'); - declare export function isExportAllDeclaration(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'ExportAllDeclaration'); - declare export function isExportDefaultDeclaration(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'ExportDefaultDeclaration'); - declare export function isExportNamedDeclaration(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'ExportNamedDeclaration'); - declare export function isExportSpecifier(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'ExportSpecifier'); - declare export function isForOfStatement(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'ForOfStatement'); - declare export function isImportDeclaration(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'ImportDeclaration'); - declare export function isImportDefaultSpecifier(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'ImportDefaultSpecifier'); - declare export function isImportNamespaceSpecifier(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'ImportNamespaceSpecifier'); - declare export function isImportSpecifier(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'ImportSpecifier'); - declare export function isMetaProperty(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'MetaProperty'); - declare export function isClassMethod(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'ClassMethod'); - declare export function isObjectPattern(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'ObjectPattern'); - declare export function isSpreadElement(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'SpreadElement'); - declare export function isSuper(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'Super'); - declare export function isTaggedTemplateExpression(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'TaggedTemplateExpression'); - declare export function isTemplateElement(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'TemplateElement'); - declare export function isTemplateLiteral(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'TemplateLiteral'); - declare export function isYieldExpression(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'YieldExpression'); - declare export function isAwaitExpression(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'AwaitExpression'); - declare export function isImport(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'Import'); - declare export function isBigIntLiteral(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'BigIntLiteral'); - declare export function isExportNamespaceSpecifier(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'ExportNamespaceSpecifier'); - declare export function isOptionalMemberExpression(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'OptionalMemberExpression'); - declare export function isOptionalCallExpression(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'OptionalCallExpression'); - declare export function isClassProperty(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'ClassProperty'); - declare export function isClassAccessorProperty(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'ClassAccessorProperty'); - declare export function isClassPrivateProperty(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'ClassPrivateProperty'); - declare export function isClassPrivateMethod(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'ClassPrivateMethod'); - declare export function isPrivateName(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'PrivateName'); - declare export function isStaticBlock(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'StaticBlock'); - declare export function isAnyTypeAnnotation(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'AnyTypeAnnotation'); - declare export function isArrayTypeAnnotation(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'ArrayTypeAnnotation'); - declare export function isBooleanTypeAnnotation(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'BooleanTypeAnnotation'); - declare export function isBooleanLiteralTypeAnnotation(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'BooleanLiteralTypeAnnotation'); - declare export function isNullLiteralTypeAnnotation(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'NullLiteralTypeAnnotation'); - declare export function isClassImplements(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'ClassImplements'); - declare export function isDeclareClass(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'DeclareClass'); - declare export function isDeclareFunction(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'DeclareFunction'); - declare export function isDeclareInterface(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'DeclareInterface'); - declare export function isDeclareModule(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'DeclareModule'); - declare export function isDeclareModuleExports(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'DeclareModuleExports'); - declare export function isDeclareTypeAlias(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'DeclareTypeAlias'); - declare export function isDeclareOpaqueType(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'DeclareOpaqueType'); - declare export function isDeclareVariable(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'DeclareVariable'); - declare export function isDeclareExportDeclaration(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'DeclareExportDeclaration'); - declare export function isDeclareExportAllDeclaration(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'DeclareExportAllDeclaration'); - declare export function isDeclaredPredicate(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'DeclaredPredicate'); - declare export function isExistsTypeAnnotation(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'ExistsTypeAnnotation'); - declare export function isFunctionTypeAnnotation(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'FunctionTypeAnnotation'); - declare export function isFunctionTypeParam(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'FunctionTypeParam'); - declare export function isGenericTypeAnnotation(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'GenericTypeAnnotation'); - declare export function isInferredPredicate(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'InferredPredicate'); - declare export function isInterfaceExtends(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'InterfaceExtends'); - declare export function isInterfaceDeclaration(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'InterfaceDeclaration'); - declare export function isInterfaceTypeAnnotation(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'InterfaceTypeAnnotation'); - declare export function isIntersectionTypeAnnotation(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'IntersectionTypeAnnotation'); - declare export function isMixedTypeAnnotation(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'MixedTypeAnnotation'); - declare export function isEmptyTypeAnnotation(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'EmptyTypeAnnotation'); - declare export function isNullableTypeAnnotation(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'NullableTypeAnnotation'); - declare export function isNumberLiteralTypeAnnotation(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'NumberLiteralTypeAnnotation'); - declare export function isNumberTypeAnnotation(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'NumberTypeAnnotation'); - declare export function isObjectTypeAnnotation(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'ObjectTypeAnnotation'); - declare export function isObjectTypeInternalSlot(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'ObjectTypeInternalSlot'); - declare export function isObjectTypeCallProperty(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'ObjectTypeCallProperty'); - declare export function isObjectTypeIndexer(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'ObjectTypeIndexer'); - declare export function isObjectTypeProperty(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'ObjectTypeProperty'); - declare export function isObjectTypeSpreadProperty(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'ObjectTypeSpreadProperty'); - declare export function isOpaqueType(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'OpaqueType'); - declare export function isQualifiedTypeIdentifier(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'QualifiedTypeIdentifier'); - declare export function isStringLiteralTypeAnnotation(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'StringLiteralTypeAnnotation'); - declare export function isStringTypeAnnotation(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'StringTypeAnnotation'); - declare export function isSymbolTypeAnnotation(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'SymbolTypeAnnotation'); - declare export function isThisTypeAnnotation(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'ThisTypeAnnotation'); - declare export function isTupleTypeAnnotation(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'TupleTypeAnnotation'); - declare export function isTypeofTypeAnnotation(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'TypeofTypeAnnotation'); - declare export function isTypeAlias(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'TypeAlias'); - declare export function isTypeAnnotation(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'TypeAnnotation'); - declare export function isTypeCastExpression(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'TypeCastExpression'); - declare export function isTypeParameter(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'TypeParameter'); - declare export function isTypeParameterDeclaration(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'TypeParameterDeclaration'); - declare export function isTypeParameterInstantiation(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'TypeParameterInstantiation'); - declare export function isUnionTypeAnnotation(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'UnionTypeAnnotation'); - declare export function isVariance(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'Variance'); - declare export function isVoidTypeAnnotation(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'VoidTypeAnnotation'); - declare export function isEnumDeclaration(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'EnumDeclaration'); - declare export function isEnumBooleanBody(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'EnumBooleanBody'); - declare export function isEnumNumberBody(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'EnumNumberBody'); - declare export function isEnumStringBody(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'EnumStringBody'); - declare export function isEnumSymbolBody(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'EnumSymbolBody'); - declare export function isEnumBooleanMember(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'EnumBooleanMember'); - declare export function isEnumNumberMember(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'EnumNumberMember'); - declare export function isEnumStringMember(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'EnumStringMember'); - declare export function isEnumDefaultedMember(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'EnumDefaultedMember'); - declare export function isIndexedAccessType(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'IndexedAccessType'); - declare export function isOptionalIndexedAccessType(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'OptionalIndexedAccessType'); - declare export function isJSXAttribute(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'JSXAttribute'); - declare export function isJSXClosingElement(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'JSXClosingElement'); - declare export function isJSXElement(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'JSXElement'); - declare export function isJSXEmptyExpression(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'JSXEmptyExpression'); - declare export function isJSXExpressionContainer(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'JSXExpressionContainer'); - declare export function isJSXSpreadChild(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'JSXSpreadChild'); - declare export function isJSXIdentifier(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'JSXIdentifier'); - declare export function isJSXMemberExpression(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'JSXMemberExpression'); - declare export function isJSXNamespacedName(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'JSXNamespacedName'); - declare export function isJSXOpeningElement(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'JSXOpeningElement'); - declare export function isJSXSpreadAttribute(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'JSXSpreadAttribute'); - declare export function isJSXText(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'JSXText'); - declare export function isJSXFragment(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'JSXFragment'); - declare export function isJSXOpeningFragment(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'JSXOpeningFragment'); - declare export function isJSXClosingFragment(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'JSXClosingFragment'); - declare export function isNoop(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'Noop'); - declare export function isPlaceholder(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'Placeholder'); - declare export function isV8IntrinsicIdentifier(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'V8IntrinsicIdentifier'); - declare export function isArgumentPlaceholder(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'ArgumentPlaceholder'); - declare export function isBindExpression(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'BindExpression'); - declare export function isImportAttribute(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'ImportAttribute'); - declare export function isDecorator(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'Decorator'); - declare export function isDoExpression(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'DoExpression'); - declare export function isExportDefaultSpecifier(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'ExportDefaultSpecifier'); - declare export function isRecordExpression(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'RecordExpression'); - declare export function isTupleExpression(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'TupleExpression'); - declare export function isDecimalLiteral(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'DecimalLiteral'); - declare export function isModuleExpression(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'ModuleExpression'); - declare export function isTopicReference(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'TopicReference'); - declare export function isPipelineTopicExpression(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'PipelineTopicExpression'); - declare export function isPipelineBareFunction(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'PipelineBareFunction'); - declare export function isPipelinePrimaryTopicReference(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'PipelinePrimaryTopicReference'); - declare export function isTSParameterProperty(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'TSParameterProperty'); - declare export function isTSDeclareFunction(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'TSDeclareFunction'); - declare export function isTSDeclareMethod(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'TSDeclareMethod'); - declare export function isTSQualifiedName(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'TSQualifiedName'); - declare export function isTSCallSignatureDeclaration(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'TSCallSignatureDeclaration'); - declare export function isTSConstructSignatureDeclaration(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'TSConstructSignatureDeclaration'); - declare export function isTSPropertySignature(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'TSPropertySignature'); - declare export function isTSMethodSignature(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'TSMethodSignature'); - declare export function isTSIndexSignature(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'TSIndexSignature'); - declare export function isTSAnyKeyword(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'TSAnyKeyword'); - declare export function isTSBooleanKeyword(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'TSBooleanKeyword'); - declare export function isTSBigIntKeyword(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'TSBigIntKeyword'); - declare export function isTSIntrinsicKeyword(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'TSIntrinsicKeyword'); - declare export function isTSNeverKeyword(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'TSNeverKeyword'); - declare export function isTSNullKeyword(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'TSNullKeyword'); - declare export function isTSNumberKeyword(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'TSNumberKeyword'); - declare export function isTSObjectKeyword(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'TSObjectKeyword'); - declare export function isTSStringKeyword(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'TSStringKeyword'); - declare export function isTSSymbolKeyword(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'TSSymbolKeyword'); - declare export function isTSUndefinedKeyword(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'TSUndefinedKeyword'); - declare export function isTSUnknownKeyword(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'TSUnknownKeyword'); - declare export function isTSVoidKeyword(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'TSVoidKeyword'); - declare export function isTSThisType(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'TSThisType'); - declare export function isTSFunctionType(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'TSFunctionType'); - declare export function isTSConstructorType(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'TSConstructorType'); - declare export function isTSTypeReference(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'TSTypeReference'); - declare export function isTSTypePredicate(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'TSTypePredicate'); - declare export function isTSTypeQuery(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'TSTypeQuery'); - declare export function isTSTypeLiteral(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'TSTypeLiteral'); - declare export function isTSArrayType(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'TSArrayType'); - declare export function isTSTupleType(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'TSTupleType'); - declare export function isTSOptionalType(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'TSOptionalType'); - declare export function isTSRestType(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'TSRestType'); - declare export function isTSNamedTupleMember(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'TSNamedTupleMember'); - declare export function isTSUnionType(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'TSUnionType'); - declare export function isTSIntersectionType(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'TSIntersectionType'); - declare export function isTSConditionalType(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'TSConditionalType'); - declare export function isTSInferType(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'TSInferType'); - declare export function isTSParenthesizedType(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'TSParenthesizedType'); - declare export function isTSTypeOperator(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'TSTypeOperator'); - declare export function isTSIndexedAccessType(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'TSIndexedAccessType'); - declare export function isTSMappedType(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'TSMappedType'); - declare export function isTSLiteralType(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'TSLiteralType'); - declare export function isTSExpressionWithTypeArguments(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'TSExpressionWithTypeArguments'); - declare export function isTSInterfaceDeclaration(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'TSInterfaceDeclaration'); - declare export function isTSInterfaceBody(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'TSInterfaceBody'); - declare export function isTSTypeAliasDeclaration(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'TSTypeAliasDeclaration'); - declare export function isTSInstantiationExpression(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'TSInstantiationExpression'); - declare export function isTSAsExpression(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'TSAsExpression'); - declare export function isTSSatisfiesExpression(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'TSSatisfiesExpression'); - declare export function isTSTypeAssertion(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'TSTypeAssertion'); - declare export function isTSEnumDeclaration(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'TSEnumDeclaration'); - declare export function isTSEnumMember(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'TSEnumMember'); - declare export function isTSModuleDeclaration(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'TSModuleDeclaration'); - declare export function isTSModuleBlock(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'TSModuleBlock'); - declare export function isTSImportType(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'TSImportType'); - declare export function isTSImportEqualsDeclaration(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'TSImportEqualsDeclaration'); - declare export function isTSExternalModuleReference(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'TSExternalModuleReference'); - declare export function isTSNonNullExpression(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'TSNonNullExpression'); - declare export function isTSExportAssignment(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'TSExportAssignment'); - declare export function isTSNamespaceExportDeclaration(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'TSNamespaceExportDeclaration'); - declare export function isTSTypeAnnotation(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'TSTypeAnnotation'); - declare export function isTSTypeParameterInstantiation(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'TSTypeParameterInstantiation'); - declare export function isTSTypeParameterDeclaration(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'TSTypeParameterDeclaration'); - declare export function isTSTypeParameter(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'TSTypeParameter'); - declare export function isStandardized(node: ?Object, opts?: ?Object): boolean %checks (node != null && (node.type === 'ArrayExpression' || node.type === 'AssignmentExpression' || node.type === 'BinaryExpression' || node.type === 'InterpreterDirective' || node.type === 'Directive' || node.type === 'DirectiveLiteral' || node.type === 'BlockStatement' || node.type === 'BreakStatement' || node.type === 'CallExpression' || node.type === 'CatchClause' || node.type === 'ConditionalExpression' || node.type === 'ContinueStatement' || node.type === 'DebuggerStatement' || node.type === 'DoWhileStatement' || node.type === 'EmptyStatement' || node.type === 'ExpressionStatement' || node.type === 'File' || node.type === 'ForInStatement' || node.type === 'ForStatement' || node.type === 'FunctionDeclaration' || node.type === 'FunctionExpression' || node.type === 'Identifier' || node.type === 'IfStatement' || node.type === 'LabeledStatement' || node.type === 'StringLiteral' || node.type === 'NumericLiteral' || node.type === 'NullLiteral' || node.type === 'BooleanLiteral' || node.type === 'RegExpLiteral' || node.type === 'LogicalExpression' || node.type === 'MemberExpression' || node.type === 'NewExpression' || node.type === 'Program' || node.type === 'ObjectExpression' || node.type === 'ObjectMethod' || node.type === 'ObjectProperty' || node.type === 'RestElement' || node.type === 'ReturnStatement' || node.type === 'SequenceExpression' || node.type === 'ParenthesizedExpression' || node.type === 'SwitchCase' || node.type === 'SwitchStatement' || node.type === 'ThisExpression' || node.type === 'ThrowStatement' || node.type === 'TryStatement' || node.type === 'UnaryExpression' || node.type === 'UpdateExpression' || node.type === 'VariableDeclaration' || node.type === 'VariableDeclarator' || node.type === 'WhileStatement' || node.type === 'WithStatement' || node.type === 'AssignmentPattern' || node.type === 'ArrayPattern' || node.type === 'ArrowFunctionExpression' || node.type === 'ClassBody' || node.type === 'ClassExpression' || node.type === 'ClassDeclaration' || node.type === 'ExportAllDeclaration' || node.type === 'ExportDefaultDeclaration' || node.type === 'ExportNamedDeclaration' || node.type === 'ExportSpecifier' || node.type === 'ForOfStatement' || node.type === 'ImportDeclaration' || node.type === 'ImportDefaultSpecifier' || node.type === 'ImportNamespaceSpecifier' || node.type === 'ImportSpecifier' || node.type === 'MetaProperty' || node.type === 'ClassMethod' || node.type === 'ObjectPattern' || node.type === 'SpreadElement' || node.type === 'Super' || node.type === 'TaggedTemplateExpression' || node.type === 'TemplateElement' || node.type === 'TemplateLiteral' || node.type === 'YieldExpression' || node.type === 'AwaitExpression' || node.type === 'Import' || node.type === 'BigIntLiteral' || node.type === 'ExportNamespaceSpecifier' || node.type === 'OptionalMemberExpression' || node.type === 'OptionalCallExpression' || node.type === 'ClassProperty' || node.type === 'ClassAccessorProperty' || node.type === 'ClassPrivateProperty' || node.type === 'ClassPrivateMethod' || node.type === 'PrivateName' || node.type === 'StaticBlock')); - declare export function isExpression(node: ?Object, opts?: ?Object): boolean %checks (node != null && (node.type === 'ArrayExpression' || node.type === 'AssignmentExpression' || node.type === 'BinaryExpression' || node.type === 'CallExpression' || node.type === 'ConditionalExpression' || node.type === 'FunctionExpression' || node.type === 'Identifier' || node.type === 'StringLiteral' || node.type === 'NumericLiteral' || node.type === 'NullLiteral' || node.type === 'BooleanLiteral' || node.type === 'RegExpLiteral' || node.type === 'LogicalExpression' || node.type === 'MemberExpression' || node.type === 'NewExpression' || node.type === 'ObjectExpression' || node.type === 'SequenceExpression' || node.type === 'ParenthesizedExpression' || node.type === 'ThisExpression' || node.type === 'UnaryExpression' || node.type === 'UpdateExpression' || node.type === 'ArrowFunctionExpression' || node.type === 'ClassExpression' || node.type === 'MetaProperty' || node.type === 'Super' || node.type === 'TaggedTemplateExpression' || node.type === 'TemplateLiteral' || node.type === 'YieldExpression' || node.type === 'AwaitExpression' || node.type === 'Import' || node.type === 'BigIntLiteral' || node.type === 'OptionalMemberExpression' || node.type === 'OptionalCallExpression' || node.type === 'TypeCastExpression' || node.type === 'JSXElement' || node.type === 'JSXFragment' || node.type === 'BindExpression' || node.type === 'DoExpression' || node.type === 'RecordExpression' || node.type === 'TupleExpression' || node.type === 'DecimalLiteral' || node.type === 'ModuleExpression' || node.type === 'TopicReference' || node.type === 'PipelineTopicExpression' || node.type === 'PipelineBareFunction' || node.type === 'PipelinePrimaryTopicReference' || node.type === 'TSInstantiationExpression' || node.type === 'TSAsExpression' || node.type === 'TSSatisfiesExpression' || node.type === 'TSTypeAssertion' || node.type === 'TSNonNullExpression')); - declare export function isBinary(node: ?Object, opts?: ?Object): boolean %checks (node != null && (node.type === 'BinaryExpression' || node.type === 'LogicalExpression')); - declare export function isScopable(node: ?Object, opts?: ?Object): boolean %checks (node != null && (node.type === 'BlockStatement' || node.type === 'CatchClause' || node.type === 'DoWhileStatement' || node.type === 'ForInStatement' || node.type === 'ForStatement' || node.type === 'FunctionDeclaration' || node.type === 'FunctionExpression' || node.type === 'Program' || node.type === 'ObjectMethod' || node.type === 'SwitchStatement' || node.type === 'WhileStatement' || node.type === 'ArrowFunctionExpression' || node.type === 'ClassExpression' || node.type === 'ClassDeclaration' || node.type === 'ForOfStatement' || node.type === 'ClassMethod' || node.type === 'ClassPrivateMethod' || node.type === 'StaticBlock' || node.type === 'TSModuleBlock')); - declare export function isBlockParent(node: ?Object, opts?: ?Object): boolean %checks (node != null && (node.type === 'BlockStatement' || node.type === 'CatchClause' || node.type === 'DoWhileStatement' || node.type === 'ForInStatement' || node.type === 'ForStatement' || node.type === 'FunctionDeclaration' || node.type === 'FunctionExpression' || node.type === 'Program' || node.type === 'ObjectMethod' || node.type === 'SwitchStatement' || node.type === 'WhileStatement' || node.type === 'ArrowFunctionExpression' || node.type === 'ForOfStatement' || node.type === 'ClassMethod' || node.type === 'ClassPrivateMethod' || node.type === 'StaticBlock' || node.type === 'TSModuleBlock')); - declare export function isBlock(node: ?Object, opts?: ?Object): boolean %checks (node != null && (node.type === 'BlockStatement' || node.type === 'Program' || node.type === 'TSModuleBlock')); - declare export function isStatement(node: ?Object, opts?: ?Object): boolean %checks (node != null && (node.type === 'BlockStatement' || node.type === 'BreakStatement' || node.type === 'ContinueStatement' || node.type === 'DebuggerStatement' || node.type === 'DoWhileStatement' || node.type === 'EmptyStatement' || node.type === 'ExpressionStatement' || node.type === 'ForInStatement' || node.type === 'ForStatement' || node.type === 'FunctionDeclaration' || node.type === 'IfStatement' || node.type === 'LabeledStatement' || node.type === 'ReturnStatement' || node.type === 'SwitchStatement' || node.type === 'ThrowStatement' || node.type === 'TryStatement' || node.type === 'VariableDeclaration' || node.type === 'WhileStatement' || node.type === 'WithStatement' || node.type === 'ClassDeclaration' || node.type === 'ExportAllDeclaration' || node.type === 'ExportDefaultDeclaration' || node.type === 'ExportNamedDeclaration' || node.type === 'ForOfStatement' || node.type === 'ImportDeclaration' || node.type === 'DeclareClass' || node.type === 'DeclareFunction' || node.type === 'DeclareInterface' || node.type === 'DeclareModule' || node.type === 'DeclareModuleExports' || node.type === 'DeclareTypeAlias' || node.type === 'DeclareOpaqueType' || node.type === 'DeclareVariable' || node.type === 'DeclareExportDeclaration' || node.type === 'DeclareExportAllDeclaration' || node.type === 'InterfaceDeclaration' || node.type === 'OpaqueType' || node.type === 'TypeAlias' || node.type === 'EnumDeclaration' || node.type === 'TSDeclareFunction' || node.type === 'TSInterfaceDeclaration' || node.type === 'TSTypeAliasDeclaration' || node.type === 'TSEnumDeclaration' || node.type === 'TSModuleDeclaration' || node.type === 'TSImportEqualsDeclaration' || node.type === 'TSExportAssignment' || node.type === 'TSNamespaceExportDeclaration')); - declare export function isTerminatorless(node: ?Object, opts?: ?Object): boolean %checks (node != null && (node.type === 'BreakStatement' || node.type === 'ContinueStatement' || node.type === 'ReturnStatement' || node.type === 'ThrowStatement' || node.type === 'YieldExpression' || node.type === 'AwaitExpression')); - declare export function isCompletionStatement(node: ?Object, opts?: ?Object): boolean %checks (node != null && (node.type === 'BreakStatement' || node.type === 'ContinueStatement' || node.type === 'ReturnStatement' || node.type === 'ThrowStatement')); - declare export function isConditional(node: ?Object, opts?: ?Object): boolean %checks (node != null && (node.type === 'ConditionalExpression' || node.type === 'IfStatement')); - declare export function isLoop(node: ?Object, opts?: ?Object): boolean %checks (node != null && (node.type === 'DoWhileStatement' || node.type === 'ForInStatement' || node.type === 'ForStatement' || node.type === 'WhileStatement' || node.type === 'ForOfStatement')); - declare export function isWhile(node: ?Object, opts?: ?Object): boolean %checks (node != null && (node.type === 'DoWhileStatement' || node.type === 'WhileStatement')); - declare export function isExpressionWrapper(node: ?Object, opts?: ?Object): boolean %checks (node != null && (node.type === 'ExpressionStatement' || node.type === 'ParenthesizedExpression' || node.type === 'TypeCastExpression')); - declare export function isFor(node: ?Object, opts?: ?Object): boolean %checks (node != null && (node.type === 'ForInStatement' || node.type === 'ForStatement' || node.type === 'ForOfStatement')); - declare export function isForXStatement(node: ?Object, opts?: ?Object): boolean %checks (node != null && (node.type === 'ForInStatement' || node.type === 'ForOfStatement')); - declare export function isFunction(node: ?Object, opts?: ?Object): boolean %checks (node != null && (node.type === 'FunctionDeclaration' || node.type === 'FunctionExpression' || node.type === 'ObjectMethod' || node.type === 'ArrowFunctionExpression' || node.type === 'ClassMethod' || node.type === 'ClassPrivateMethod')); - declare export function isFunctionParent(node: ?Object, opts?: ?Object): boolean %checks (node != null && (node.type === 'FunctionDeclaration' || node.type === 'FunctionExpression' || node.type === 'ObjectMethod' || node.type === 'ArrowFunctionExpression' || node.type === 'ClassMethod' || node.type === 'ClassPrivateMethod' || node.type === 'StaticBlock' || node.type === 'TSModuleBlock')); - declare export function isPureish(node: ?Object, opts?: ?Object): boolean %checks (node != null && (node.type === 'FunctionDeclaration' || node.type === 'FunctionExpression' || node.type === 'StringLiteral' || node.type === 'NumericLiteral' || node.type === 'NullLiteral' || node.type === 'BooleanLiteral' || node.type === 'RegExpLiteral' || node.type === 'ArrowFunctionExpression' || node.type === 'BigIntLiteral' || node.type === 'DecimalLiteral')); - declare export function isDeclaration(node: ?Object, opts?: ?Object): boolean %checks (node != null && (node.type === 'FunctionDeclaration' || node.type === 'VariableDeclaration' || node.type === 'ClassDeclaration' || node.type === 'ExportAllDeclaration' || node.type === 'ExportDefaultDeclaration' || node.type === 'ExportNamedDeclaration' || node.type === 'ImportDeclaration' || node.type === 'DeclareClass' || node.type === 'DeclareFunction' || node.type === 'DeclareInterface' || node.type === 'DeclareModule' || node.type === 'DeclareModuleExports' || node.type === 'DeclareTypeAlias' || node.type === 'DeclareOpaqueType' || node.type === 'DeclareVariable' || node.type === 'DeclareExportDeclaration' || node.type === 'DeclareExportAllDeclaration' || node.type === 'InterfaceDeclaration' || node.type === 'OpaqueType' || node.type === 'TypeAlias' || node.type === 'EnumDeclaration' || node.type === 'TSDeclareFunction' || node.type === 'TSInterfaceDeclaration' || node.type === 'TSTypeAliasDeclaration' || node.type === 'TSEnumDeclaration' || node.type === 'TSModuleDeclaration')); - declare export function isPatternLike(node: ?Object, opts?: ?Object): boolean %checks (node != null && (node.type === 'Identifier' || node.type === 'RestElement' || node.type === 'AssignmentPattern' || node.type === 'ArrayPattern' || node.type === 'ObjectPattern' || node.type === 'TSAsExpression' || node.type === 'TSSatisfiesExpression' || node.type === 'TSTypeAssertion' || node.type === 'TSNonNullExpression')); - declare export function isLVal(node: ?Object, opts?: ?Object): boolean %checks (node != null && (node.type === 'Identifier' || node.type === 'MemberExpression' || node.type === 'RestElement' || node.type === 'AssignmentPattern' || node.type === 'ArrayPattern' || node.type === 'ObjectPattern' || node.type === 'TSParameterProperty' || node.type === 'TSAsExpression' || node.type === 'TSSatisfiesExpression' || node.type === 'TSTypeAssertion' || node.type === 'TSNonNullExpression')); - declare export function isTSEntityName(node: ?Object, opts?: ?Object): boolean %checks (node != null && (node.type === 'Identifier' || node.type === 'TSQualifiedName')); - declare export function isLiteral(node: ?Object, opts?: ?Object): boolean %checks (node != null && (node.type === 'StringLiteral' || node.type === 'NumericLiteral' || node.type === 'NullLiteral' || node.type === 'BooleanLiteral' || node.type === 'RegExpLiteral' || node.type === 'TemplateLiteral' || node.type === 'BigIntLiteral' || node.type === 'DecimalLiteral')); - declare export function isImmutable(node: ?Object, opts?: ?Object): boolean %checks (node != null && (node.type === 'StringLiteral' || node.type === 'NumericLiteral' || node.type === 'NullLiteral' || node.type === 'BooleanLiteral' || node.type === 'BigIntLiteral' || node.type === 'JSXAttribute' || node.type === 'JSXClosingElement' || node.type === 'JSXElement' || node.type === 'JSXExpressionContainer' || node.type === 'JSXSpreadChild' || node.type === 'JSXOpeningElement' || node.type === 'JSXText' || node.type === 'JSXFragment' || node.type === 'JSXOpeningFragment' || node.type === 'JSXClosingFragment' || node.type === 'DecimalLiteral')); - declare export function isUserWhitespacable(node: ?Object, opts?: ?Object): boolean %checks (node != null && (node.type === 'ObjectMethod' || node.type === 'ObjectProperty' || node.type === 'ObjectTypeInternalSlot' || node.type === 'ObjectTypeCallProperty' || node.type === 'ObjectTypeIndexer' || node.type === 'ObjectTypeProperty' || node.type === 'ObjectTypeSpreadProperty')); - declare export function isMethod(node: ?Object, opts?: ?Object): boolean %checks (node != null && (node.type === 'ObjectMethod' || node.type === 'ClassMethod' || node.type === 'ClassPrivateMethod')); - declare export function isObjectMember(node: ?Object, opts?: ?Object): boolean %checks (node != null && (node.type === 'ObjectMethod' || node.type === 'ObjectProperty')); - declare export function isProperty(node: ?Object, opts?: ?Object): boolean %checks (node != null && (node.type === 'ObjectProperty' || node.type === 'ClassProperty' || node.type === 'ClassAccessorProperty' || node.type === 'ClassPrivateProperty')); - declare export function isUnaryLike(node: ?Object, opts?: ?Object): boolean %checks (node != null && (node.type === 'UnaryExpression' || node.type === 'SpreadElement')); - declare export function isPattern(node: ?Object, opts?: ?Object): boolean %checks (node != null && (node.type === 'AssignmentPattern' || node.type === 'ArrayPattern' || node.type === 'ObjectPattern')); - declare export function isClass(node: ?Object, opts?: ?Object): boolean %checks (node != null && (node.type === 'ClassExpression' || node.type === 'ClassDeclaration')); - declare export function isModuleDeclaration(node: ?Object, opts?: ?Object): boolean %checks (node != null && (node.type === 'ExportAllDeclaration' || node.type === 'ExportDefaultDeclaration' || node.type === 'ExportNamedDeclaration' || node.type === 'ImportDeclaration')); - declare export function isExportDeclaration(node: ?Object, opts?: ?Object): boolean %checks (node != null && (node.type === 'ExportAllDeclaration' || node.type === 'ExportDefaultDeclaration' || node.type === 'ExportNamedDeclaration')); - declare export function isModuleSpecifier(node: ?Object, opts?: ?Object): boolean %checks (node != null && (node.type === 'ExportSpecifier' || node.type === 'ImportDefaultSpecifier' || node.type === 'ImportNamespaceSpecifier' || node.type === 'ImportSpecifier' || node.type === 'ExportNamespaceSpecifier' || node.type === 'ExportDefaultSpecifier')); - declare export function isAccessor(node: ?Object, opts?: ?Object): boolean %checks (node != null && (node.type === 'ClassAccessorProperty')); - declare export function isPrivate(node: ?Object, opts?: ?Object): boolean %checks (node != null && (node.type === 'ClassPrivateProperty' || node.type === 'ClassPrivateMethod' || node.type === 'PrivateName')); - declare export function isFlow(node: ?Object, opts?: ?Object): boolean %checks (node != null && (node.type === 'AnyTypeAnnotation' || node.type === 'ArrayTypeAnnotation' || node.type === 'BooleanTypeAnnotation' || node.type === 'BooleanLiteralTypeAnnotation' || node.type === 'NullLiteralTypeAnnotation' || node.type === 'ClassImplements' || node.type === 'DeclareClass' || node.type === 'DeclareFunction' || node.type === 'DeclareInterface' || node.type === 'DeclareModule' || node.type === 'DeclareModuleExports' || node.type === 'DeclareTypeAlias' || node.type === 'DeclareOpaqueType' || node.type === 'DeclareVariable' || node.type === 'DeclareExportDeclaration' || node.type === 'DeclareExportAllDeclaration' || node.type === 'DeclaredPredicate' || node.type === 'ExistsTypeAnnotation' || node.type === 'FunctionTypeAnnotation' || node.type === 'FunctionTypeParam' || node.type === 'GenericTypeAnnotation' || node.type === 'InferredPredicate' || node.type === 'InterfaceExtends' || node.type === 'InterfaceDeclaration' || node.type === 'InterfaceTypeAnnotation' || node.type === 'IntersectionTypeAnnotation' || node.type === 'MixedTypeAnnotation' || node.type === 'EmptyTypeAnnotation' || node.type === 'NullableTypeAnnotation' || node.type === 'NumberLiteralTypeAnnotation' || node.type === 'NumberTypeAnnotation' || node.type === 'ObjectTypeAnnotation' || node.type === 'ObjectTypeInternalSlot' || node.type === 'ObjectTypeCallProperty' || node.type === 'ObjectTypeIndexer' || node.type === 'ObjectTypeProperty' || node.type === 'ObjectTypeSpreadProperty' || node.type === 'OpaqueType' || node.type === 'QualifiedTypeIdentifier' || node.type === 'StringLiteralTypeAnnotation' || node.type === 'StringTypeAnnotation' || node.type === 'SymbolTypeAnnotation' || node.type === 'ThisTypeAnnotation' || node.type === 'TupleTypeAnnotation' || node.type === 'TypeofTypeAnnotation' || node.type === 'TypeAlias' || node.type === 'TypeAnnotation' || node.type === 'TypeCastExpression' || node.type === 'TypeParameter' || node.type === 'TypeParameterDeclaration' || node.type === 'TypeParameterInstantiation' || node.type === 'UnionTypeAnnotation' || node.type === 'Variance' || node.type === 'VoidTypeAnnotation' || node.type === 'EnumDeclaration' || node.type === 'EnumBooleanBody' || node.type === 'EnumNumberBody' || node.type === 'EnumStringBody' || node.type === 'EnumSymbolBody' || node.type === 'EnumBooleanMember' || node.type === 'EnumNumberMember' || node.type === 'EnumStringMember' || node.type === 'EnumDefaultedMember' || node.type === 'IndexedAccessType' || node.type === 'OptionalIndexedAccessType')); - declare export function isFlowType(node: ?Object, opts?: ?Object): boolean %checks (node != null && (node.type === 'AnyTypeAnnotation' || node.type === 'ArrayTypeAnnotation' || node.type === 'BooleanTypeAnnotation' || node.type === 'BooleanLiteralTypeAnnotation' || node.type === 'NullLiteralTypeAnnotation' || node.type === 'ExistsTypeAnnotation' || node.type === 'FunctionTypeAnnotation' || node.type === 'GenericTypeAnnotation' || node.type === 'InterfaceTypeAnnotation' || node.type === 'IntersectionTypeAnnotation' || node.type === 'MixedTypeAnnotation' || node.type === 'EmptyTypeAnnotation' || node.type === 'NullableTypeAnnotation' || node.type === 'NumberLiteralTypeAnnotation' || node.type === 'NumberTypeAnnotation' || node.type === 'ObjectTypeAnnotation' || node.type === 'StringLiteralTypeAnnotation' || node.type === 'StringTypeAnnotation' || node.type === 'SymbolTypeAnnotation' || node.type === 'ThisTypeAnnotation' || node.type === 'TupleTypeAnnotation' || node.type === 'TypeofTypeAnnotation' || node.type === 'UnionTypeAnnotation' || node.type === 'VoidTypeAnnotation' || node.type === 'IndexedAccessType' || node.type === 'OptionalIndexedAccessType')); - declare export function isFlowBaseAnnotation(node: ?Object, opts?: ?Object): boolean %checks (node != null && (node.type === 'AnyTypeAnnotation' || node.type === 'BooleanTypeAnnotation' || node.type === 'NullLiteralTypeAnnotation' || node.type === 'MixedTypeAnnotation' || node.type === 'EmptyTypeAnnotation' || node.type === 'NumberTypeAnnotation' || node.type === 'StringTypeAnnotation' || node.type === 'SymbolTypeAnnotation' || node.type === 'ThisTypeAnnotation' || node.type === 'VoidTypeAnnotation')); - declare export function isFlowDeclaration(node: ?Object, opts?: ?Object): boolean %checks (node != null && (node.type === 'DeclareClass' || node.type === 'DeclareFunction' || node.type === 'DeclareInterface' || node.type === 'DeclareModule' || node.type === 'DeclareModuleExports' || node.type === 'DeclareTypeAlias' || node.type === 'DeclareOpaqueType' || node.type === 'DeclareVariable' || node.type === 'DeclareExportDeclaration' || node.type === 'DeclareExportAllDeclaration' || node.type === 'InterfaceDeclaration' || node.type === 'OpaqueType' || node.type === 'TypeAlias')); - declare export function isFlowPredicate(node: ?Object, opts?: ?Object): boolean %checks (node != null && (node.type === 'DeclaredPredicate' || node.type === 'InferredPredicate')); - declare export function isEnumBody(node: ?Object, opts?: ?Object): boolean %checks (node != null && (node.type === 'EnumBooleanBody' || node.type === 'EnumNumberBody' || node.type === 'EnumStringBody' || node.type === 'EnumSymbolBody')); - declare export function isEnumMember(node: ?Object, opts?: ?Object): boolean %checks (node != null && (node.type === 'EnumBooleanMember' || node.type === 'EnumNumberMember' || node.type === 'EnumStringMember' || node.type === 'EnumDefaultedMember')); - declare export function isJSX(node: ?Object, opts?: ?Object): boolean %checks (node != null && (node.type === 'JSXAttribute' || node.type === 'JSXClosingElement' || node.type === 'JSXElement' || node.type === 'JSXEmptyExpression' || node.type === 'JSXExpressionContainer' || node.type === 'JSXSpreadChild' || node.type === 'JSXIdentifier' || node.type === 'JSXMemberExpression' || node.type === 'JSXNamespacedName' || node.type === 'JSXOpeningElement' || node.type === 'JSXSpreadAttribute' || node.type === 'JSXText' || node.type === 'JSXFragment' || node.type === 'JSXOpeningFragment' || node.type === 'JSXClosingFragment')); - declare export function isMiscellaneous(node: ?Object, opts?: ?Object): boolean %checks (node != null && (node.type === 'Noop' || node.type === 'Placeholder' || node.type === 'V8IntrinsicIdentifier')); - declare export function isTypeScript(node: ?Object, opts?: ?Object): boolean %checks (node != null && (node.type === 'TSParameterProperty' || node.type === 'TSDeclareFunction' || node.type === 'TSDeclareMethod' || node.type === 'TSQualifiedName' || node.type === 'TSCallSignatureDeclaration' || node.type === 'TSConstructSignatureDeclaration' || node.type === 'TSPropertySignature' || node.type === 'TSMethodSignature' || node.type === 'TSIndexSignature' || node.type === 'TSAnyKeyword' || node.type === 'TSBooleanKeyword' || node.type === 'TSBigIntKeyword' || node.type === 'TSIntrinsicKeyword' || node.type === 'TSNeverKeyword' || node.type === 'TSNullKeyword' || node.type === 'TSNumberKeyword' || node.type === 'TSObjectKeyword' || node.type === 'TSStringKeyword' || node.type === 'TSSymbolKeyword' || node.type === 'TSUndefinedKeyword' || node.type === 'TSUnknownKeyword' || node.type === 'TSVoidKeyword' || node.type === 'TSThisType' || node.type === 'TSFunctionType' || node.type === 'TSConstructorType' || node.type === 'TSTypeReference' || node.type === 'TSTypePredicate' || node.type === 'TSTypeQuery' || node.type === 'TSTypeLiteral' || node.type === 'TSArrayType' || node.type === 'TSTupleType' || node.type === 'TSOptionalType' || node.type === 'TSRestType' || node.type === 'TSNamedTupleMember' || node.type === 'TSUnionType' || node.type === 'TSIntersectionType' || node.type === 'TSConditionalType' || node.type === 'TSInferType' || node.type === 'TSParenthesizedType' || node.type === 'TSTypeOperator' || node.type === 'TSIndexedAccessType' || node.type === 'TSMappedType' || node.type === 'TSLiteralType' || node.type === 'TSExpressionWithTypeArguments' || node.type === 'TSInterfaceDeclaration' || node.type === 'TSInterfaceBody' || node.type === 'TSTypeAliasDeclaration' || node.type === 'TSInstantiationExpression' || node.type === 'TSAsExpression' || node.type === 'TSSatisfiesExpression' || node.type === 'TSTypeAssertion' || node.type === 'TSEnumDeclaration' || node.type === 'TSEnumMember' || node.type === 'TSModuleDeclaration' || node.type === 'TSModuleBlock' || node.type === 'TSImportType' || node.type === 'TSImportEqualsDeclaration' || node.type === 'TSExternalModuleReference' || node.type === 'TSNonNullExpression' || node.type === 'TSExportAssignment' || node.type === 'TSNamespaceExportDeclaration' || node.type === 'TSTypeAnnotation' || node.type === 'TSTypeParameterInstantiation' || node.type === 'TSTypeParameterDeclaration' || node.type === 'TSTypeParameter')); - declare export function isTSTypeElement(node: ?Object, opts?: ?Object): boolean %checks (node != null && (node.type === 'TSCallSignatureDeclaration' || node.type === 'TSConstructSignatureDeclaration' || node.type === 'TSPropertySignature' || node.type === 'TSMethodSignature' || node.type === 'TSIndexSignature')); - declare export function isTSType(node: ?Object, opts?: ?Object): boolean %checks (node != null && (node.type === 'TSAnyKeyword' || node.type === 'TSBooleanKeyword' || node.type === 'TSBigIntKeyword' || node.type === 'TSIntrinsicKeyword' || node.type === 'TSNeverKeyword' || node.type === 'TSNullKeyword' || node.type === 'TSNumberKeyword' || node.type === 'TSObjectKeyword' || node.type === 'TSStringKeyword' || node.type === 'TSSymbolKeyword' || node.type === 'TSUndefinedKeyword' || node.type === 'TSUnknownKeyword' || node.type === 'TSVoidKeyword' || node.type === 'TSThisType' || node.type === 'TSFunctionType' || node.type === 'TSConstructorType' || node.type === 'TSTypeReference' || node.type === 'TSTypePredicate' || node.type === 'TSTypeQuery' || node.type === 'TSTypeLiteral' || node.type === 'TSArrayType' || node.type === 'TSTupleType' || node.type === 'TSOptionalType' || node.type === 'TSRestType' || node.type === 'TSUnionType' || node.type === 'TSIntersectionType' || node.type === 'TSConditionalType' || node.type === 'TSInferType' || node.type === 'TSParenthesizedType' || node.type === 'TSTypeOperator' || node.type === 'TSIndexedAccessType' || node.type === 'TSMappedType' || node.type === 'TSLiteralType' || node.type === 'TSExpressionWithTypeArguments' || node.type === 'TSImportType')); - declare export function isTSBaseType(node: ?Object, opts?: ?Object): boolean %checks (node != null && (node.type === 'TSAnyKeyword' || node.type === 'TSBooleanKeyword' || node.type === 'TSBigIntKeyword' || node.type === 'TSIntrinsicKeyword' || node.type === 'TSNeverKeyword' || node.type === 'TSNullKeyword' || node.type === 'TSNumberKeyword' || node.type === 'TSObjectKeyword' || node.type === 'TSStringKeyword' || node.type === 'TSSymbolKeyword' || node.type === 'TSUndefinedKeyword' || node.type === 'TSUnknownKeyword' || node.type === 'TSVoidKeyword' || node.type === 'TSThisType' || node.type === 'TSLiteralType')); - declare export function isNumberLiteral(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'NumericLiteral'); - declare export function isRegexLiteral(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'RegExpLiteral'); - declare export function isRestProperty(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'RestElement'); - declare export function isSpreadProperty(node: ?Object, opts?: ?Object): boolean %checks (node != null && node.type === 'SpreadElement'); + declare export function isArrayExpression(node: ?Object, opts?: ?Object): node is ArrayExpression; + declare export function isAssignmentExpression(node: ?Object, opts?: ?Object): node is AssignmentExpression; + declare export function isBinaryExpression(node: ?Object, opts?: ?Object): node is BinaryExpression; + declare export function isInterpreterDirective(node: ?Object, opts?: ?Object): node is InterpreterDirective; + declare export function isDirective(node: ?Object, opts?: ?Object): node is Directive; + declare export function isDirectiveLiteral(node: ?Object, opts?: ?Object): node is DirectiveLiteral; + declare export function isBlockStatement(node: ?Object, opts?: ?Object): node is BlockStatement; + declare export function isBreakStatement(node: ?Object, opts?: ?Object): node is BreakStatement; + declare export function isCallExpression(node: ?Object, opts?: ?Object): node is CallExpression; + declare export function isCatchClause(node: ?Object, opts?: ?Object): node is CatchClause; + declare export function isConditionalExpression(node: ?Object, opts?: ?Object): node is ConditionalExpression; + declare export function isContinueStatement(node: ?Object, opts?: ?Object): node is ContinueStatement; + declare export function isDebuggerStatement(node: ?Object, opts?: ?Object): node is DebuggerStatement; + declare export function isDoWhileStatement(node: ?Object, opts?: ?Object): node is DoWhileStatement; + declare export function isEmptyStatement(node: ?Object, opts?: ?Object): node is EmptyStatement; + declare export function isExpressionStatement(node: ?Object, opts?: ?Object): node is ExpressionStatement; + declare export function isFile(node: ?Object, opts?: ?Object): node is File; + declare export function isForInStatement(node: ?Object, opts?: ?Object): node is ForInStatement; + declare export function isForStatement(node: ?Object, opts?: ?Object): node is ForStatement; + declare export function isFunctionDeclaration(node: ?Object, opts?: ?Object): node is FunctionDeclaration; + declare export function isFunctionExpression(node: ?Object, opts?: ?Object): node is FunctionExpression; + declare export function isIdentifier(node: ?Object, opts?: ?Object): node is Identifier; + declare export function isIfStatement(node: ?Object, opts?: ?Object): node is IfStatement; + declare export function isLabeledStatement(node: ?Object, opts?: ?Object): node is LabeledStatement; + declare export function isStringLiteral(node: ?Object, opts?: ?Object): node is StringLiteral; + declare export function isNumericLiteral(node: ?Object, opts?: ?Object): node is NumericLiteral; + declare export function isNullLiteral(node: ?Object, opts?: ?Object): node is NullLiteral; + declare export function isBooleanLiteral(node: ?Object, opts?: ?Object): node is BooleanLiteral; + declare export function isRegExpLiteral(node: ?Object, opts?: ?Object): node is RegExpLiteral; + declare export function isLogicalExpression(node: ?Object, opts?: ?Object): node is LogicalExpression; + declare export function isMemberExpression(node: ?Object, opts?: ?Object): node is MemberExpression; + declare export function isNewExpression(node: ?Object, opts?: ?Object): node is NewExpression; + declare export function isProgram(node: ?Object, opts?: ?Object): node is Program; + declare export function isObjectExpression(node: ?Object, opts?: ?Object): node is ObjectExpression; + declare export function isObjectMethod(node: ?Object, opts?: ?Object): node is ObjectMethod; + declare export function isObjectProperty(node: ?Object, opts?: ?Object): node is ObjectProperty; + declare export function isRestElement(node: ?Object, opts?: ?Object): node is RestElement; + declare export function isReturnStatement(node: ?Object, opts?: ?Object): node is ReturnStatement; + declare export function isSequenceExpression(node: ?Object, opts?: ?Object): node is SequenceExpression; + declare export function isParenthesizedExpression(node: ?Object, opts?: ?Object): node is ParenthesizedExpression; + declare export function isSwitchCase(node: ?Object, opts?: ?Object): node is SwitchCase; + declare export function isSwitchStatement(node: ?Object, opts?: ?Object): node is SwitchStatement; + declare export function isThisExpression(node: ?Object, opts?: ?Object): node is ThisExpression; + declare export function isThrowStatement(node: ?Object, opts?: ?Object): node is ThrowStatement; + declare export function isTryStatement(node: ?Object, opts?: ?Object): node is TryStatement; + declare export function isUnaryExpression(node: ?Object, opts?: ?Object): node is UnaryExpression; + declare export function isUpdateExpression(node: ?Object, opts?: ?Object): node is UpdateExpression; + declare export function isVariableDeclaration(node: ?Object, opts?: ?Object): node is VariableDeclaration; + declare export function isVariableDeclarator(node: ?Object, opts?: ?Object): node is VariableDeclarator; + declare export function isWhileStatement(node: ?Object, opts?: ?Object): node is WhileStatement; + declare export function isWithStatement(node: ?Object, opts?: ?Object): node is WithStatement; + declare export function isAssignmentPattern(node: ?Object, opts?: ?Object): node is AssignmentPattern; + declare export function isArrayPattern(node: ?Object, opts?: ?Object): node is ArrayPattern; + declare export function isArrowFunctionExpression(node: ?Object, opts?: ?Object): node is ArrowFunctionExpression; + declare export function isClassBody(node: ?Object, opts?: ?Object): node is ClassBody; + declare export function isClassExpression(node: ?Object, opts?: ?Object): node is ClassExpression; + declare export function isClassDeclaration(node: ?Object, opts?: ?Object): node is ClassDeclaration; + declare export function isExportAllDeclaration(node: ?Object, opts?: ?Object): node is ExportAllDeclaration; + declare export function isExportDefaultDeclaration(node: ?Object, opts?: ?Object): node is ExportDefaultDeclaration; + declare export function isExportNamedDeclaration(node: ?Object, opts?: ?Object): node is ExportNamedDeclaration; + declare export function isExportSpecifier(node: ?Object, opts?: ?Object): node is ExportSpecifier; + declare export function isForOfStatement(node: ?Object, opts?: ?Object): node is ForOfStatement; + declare export function isImportDeclaration(node: ?Object, opts?: ?Object): node is ImportDeclaration; + declare export function isImportDefaultSpecifier(node: ?Object, opts?: ?Object): node is ImportDefaultSpecifier; + declare export function isImportNamespaceSpecifier(node: ?Object, opts?: ?Object): node is ImportNamespaceSpecifier; + declare export function isImportSpecifier(node: ?Object, opts?: ?Object): node is ImportSpecifier; + declare export function isMetaProperty(node: ?Object, opts?: ?Object): node is MetaProperty; + declare export function isClassMethod(node: ?Object, opts?: ?Object): node is ClassMethod; + declare export function isObjectPattern(node: ?Object, opts?: ?Object): node is ObjectPattern; + declare export function isSpreadElement(node: ?Object, opts?: ?Object): node is SpreadElement; + declare export function isSuper(node: ?Object, opts?: ?Object): node is Super; + declare export function isTaggedTemplateExpression(node: ?Object, opts?: ?Object): node is TaggedTemplateExpression; + declare export function isTemplateElement(node: ?Object, opts?: ?Object): node is TemplateElement; + declare export function isTemplateLiteral(node: ?Object, opts?: ?Object): node is TemplateLiteral; + declare export function isYieldExpression(node: ?Object, opts?: ?Object): node is YieldExpression; + declare export function isAwaitExpression(node: ?Object, opts?: ?Object): node is AwaitExpression; + declare export function isImport(node: ?Object, opts?: ?Object): node is Import; + declare export function isBigIntLiteral(node: ?Object, opts?: ?Object): node is BigIntLiteral; + declare export function isExportNamespaceSpecifier(node: ?Object, opts?: ?Object): node is ExportNamespaceSpecifier; + declare export function isOptionalMemberExpression(node: ?Object, opts?: ?Object): node is OptionalMemberExpression; + declare export function isOptionalCallExpression(node: ?Object, opts?: ?Object): node is OptionalCallExpression; + declare export function isClassProperty(node: ?Object, opts?: ?Object): node is ClassProperty; + declare export function isClassAccessorProperty(node: ?Object, opts?: ?Object): node is ClassAccessorProperty; + declare export function isClassPrivateProperty(node: ?Object, opts?: ?Object): node is ClassPrivateProperty; + declare export function isClassPrivateMethod(node: ?Object, opts?: ?Object): node is ClassPrivateMethod; + declare export function isPrivateName(node: ?Object, opts?: ?Object): node is PrivateName; + declare export function isStaticBlock(node: ?Object, opts?: ?Object): node is StaticBlock; + declare export function isAnyTypeAnnotation(node: ?Object, opts?: ?Object): node is AnyTypeAnnotation; + declare export function isArrayTypeAnnotation(node: ?Object, opts?: ?Object): node is ArrayTypeAnnotation; + declare export function isBooleanTypeAnnotation(node: ?Object, opts?: ?Object): node is BooleanTypeAnnotation; + declare export function isBooleanLiteralTypeAnnotation(node: ?Object, opts?: ?Object): node is BooleanLiteralTypeAnnotation; + declare export function isNullLiteralTypeAnnotation(node: ?Object, opts?: ?Object): node is NullLiteralTypeAnnotation; + declare export function isClassImplements(node: ?Object, opts?: ?Object): node is ClassImplements; + declare export function isDeclareClass(node: ?Object, opts?: ?Object): node is DeclareClass; + declare export function isDeclareFunction(node: ?Object, opts?: ?Object): node is DeclareFunction; + declare export function isDeclareInterface(node: ?Object, opts?: ?Object): node is DeclareInterface; + declare export function isDeclareModule(node: ?Object, opts?: ?Object): node is DeclareModule; + declare export function isDeclareModuleExports(node: ?Object, opts?: ?Object): node is DeclareModuleExports; + declare export function isDeclareTypeAlias(node: ?Object, opts?: ?Object): node is DeclareTypeAlias; + declare export function isDeclareOpaqueType(node: ?Object, opts?: ?Object): node is DeclareOpaqueType; + declare export function isDeclareVariable(node: ?Object, opts?: ?Object): node is DeclareVariable; + declare export function isDeclareExportDeclaration(node: ?Object, opts?: ?Object): node is DeclareExportDeclaration; + declare export function isDeclareExportAllDeclaration(node: ?Object, opts?: ?Object): node is DeclareExportAllDeclaration; + declare export function isDeclaredPredicate(node: ?Object, opts?: ?Object): node is DeclaredPredicate; + declare export function isExistsTypeAnnotation(node: ?Object, opts?: ?Object): node is ExistsTypeAnnotation; + declare export function isFunctionTypeAnnotation(node: ?Object, opts?: ?Object): node is FunctionTypeAnnotation; + declare export function isFunctionTypeParam(node: ?Object, opts?: ?Object): node is FunctionTypeParam; + declare export function isGenericTypeAnnotation(node: ?Object, opts?: ?Object): node is GenericTypeAnnotation; + declare export function isInferredPredicate(node: ?Object, opts?: ?Object): node is InferredPredicate; + declare export function isInterfaceExtends(node: ?Object, opts?: ?Object): node is InterfaceExtends; + declare export function isInterfaceDeclaration(node: ?Object, opts?: ?Object): node is InterfaceDeclaration; + declare export function isInterfaceTypeAnnotation(node: ?Object, opts?: ?Object): node is InterfaceTypeAnnotation; + declare export function isIntersectionTypeAnnotation(node: ?Object, opts?: ?Object): node is IntersectionTypeAnnotation; + declare export function isMixedTypeAnnotation(node: ?Object, opts?: ?Object): node is MixedTypeAnnotation; + declare export function isEmptyTypeAnnotation(node: ?Object, opts?: ?Object): node is EmptyTypeAnnotation; + declare export function isNullableTypeAnnotation(node: ?Object, opts?: ?Object): node is NullableTypeAnnotation; + declare export function isNumberLiteralTypeAnnotation(node: ?Object, opts?: ?Object): node is NumberLiteralTypeAnnotation; + declare export function isNumberTypeAnnotation(node: ?Object, opts?: ?Object): node is NumberTypeAnnotation; + declare export function isObjectTypeAnnotation(node: ?Object, opts?: ?Object): node is ObjectTypeAnnotation; + declare export function isObjectTypeInternalSlot(node: ?Object, opts?: ?Object): node is ObjectTypeInternalSlot; + declare export function isObjectTypeCallProperty(node: ?Object, opts?: ?Object): node is ObjectTypeCallProperty; + declare export function isObjectTypeIndexer(node: ?Object, opts?: ?Object): node is ObjectTypeIndexer; + declare export function isObjectTypeProperty(node: ?Object, opts?: ?Object): node is ObjectTypeProperty; + declare export function isObjectTypeSpreadProperty(node: ?Object, opts?: ?Object): node is ObjectTypeSpreadProperty; + declare export function isOpaqueType(node: ?Object, opts?: ?Object): node is OpaqueType; + declare export function isQualifiedTypeIdentifier(node: ?Object, opts?: ?Object): node is QualifiedTypeIdentifier; + declare export function isStringLiteralTypeAnnotation(node: ?Object, opts?: ?Object): node is StringLiteralTypeAnnotation; + declare export function isStringTypeAnnotation(node: ?Object, opts?: ?Object): node is StringTypeAnnotation; + declare export function isSymbolTypeAnnotation(node: ?Object, opts?: ?Object): node is SymbolTypeAnnotation; + declare export function isThisTypeAnnotation(node: ?Object, opts?: ?Object): node is ThisTypeAnnotation; + declare export function isTupleTypeAnnotation(node: ?Object, opts?: ?Object): node is TupleTypeAnnotation; + declare export function isTypeofTypeAnnotation(node: ?Object, opts?: ?Object): node is TypeofTypeAnnotation; + declare export function isTypeAlias(node: ?Object, opts?: ?Object): node is TypeAlias; + declare export function isTypeAnnotation(node: ?Object, opts?: ?Object): node is TypeAnnotation; + declare export function isTypeCastExpression(node: ?Object, opts?: ?Object): node is TypeCastExpression; + declare export function isTypeParameter(node: ?Object, opts?: ?Object): node is TypeParameter; + declare export function isTypeParameterDeclaration(node: ?Object, opts?: ?Object): node is TypeParameterDeclaration; + declare export function isTypeParameterInstantiation(node: ?Object, opts?: ?Object): node is TypeParameterInstantiation; + declare export function isUnionTypeAnnotation(node: ?Object, opts?: ?Object): node is UnionTypeAnnotation; + declare export function isVariance(node: ?Object, opts?: ?Object): node is Variance; + declare export function isVoidTypeAnnotation(node: ?Object, opts?: ?Object): node is VoidTypeAnnotation; + declare export function isEnumDeclaration(node: ?Object, opts?: ?Object): node is EnumDeclaration; + declare export function isEnumBooleanBody(node: ?Object, opts?: ?Object): node is EnumBooleanBody; + declare export function isEnumNumberBody(node: ?Object, opts?: ?Object): node is EnumNumberBody; + declare export function isEnumStringBody(node: ?Object, opts?: ?Object): node is EnumStringBody; + declare export function isEnumSymbolBody(node: ?Object, opts?: ?Object): node is EnumSymbolBody; + declare export function isEnumBooleanMember(node: ?Object, opts?: ?Object): node is EnumBooleanMember; + declare export function isEnumNumberMember(node: ?Object, opts?: ?Object): node is EnumNumberMember; + declare export function isEnumStringMember(node: ?Object, opts?: ?Object): node is EnumStringMember; + declare export function isEnumDefaultedMember(node: ?Object, opts?: ?Object): node is EnumDefaultedMember; + declare export function isIndexedAccessType(node: ?Object, opts?: ?Object): node is IndexedAccessType; + declare export function isOptionalIndexedAccessType(node: ?Object, opts?: ?Object): node is OptionalIndexedAccessType; + declare export function isJSXAttribute(node: ?Object, opts?: ?Object): node is JSXAttribute; + declare export function isJSXClosingElement(node: ?Object, opts?: ?Object): node is JSXClosingElement; + declare export function isJSXElement(node: ?Object, opts?: ?Object): node is JSXElement; + declare export function isJSXEmptyExpression(node: ?Object, opts?: ?Object): node is JSXEmptyExpression; + declare export function isJSXExpressionContainer(node: ?Object, opts?: ?Object): node is JSXExpressionContainer; + declare export function isJSXSpreadChild(node: ?Object, opts?: ?Object): node is JSXSpreadChild; + declare export function isJSXIdentifier(node: ?Object, opts?: ?Object): node is JSXIdentifier; + declare export function isJSXMemberExpression(node: ?Object, opts?: ?Object): node is JSXMemberExpression; + declare export function isJSXNamespacedName(node: ?Object, opts?: ?Object): node is JSXNamespacedName; + declare export function isJSXOpeningElement(node: ?Object, opts?: ?Object): node is JSXOpeningElement; + declare export function isJSXSpreadAttribute(node: ?Object, opts?: ?Object): node is JSXSpreadAttribute; + declare export function isJSXText(node: ?Object, opts?: ?Object): node is JSXText; + declare export function isJSXFragment(node: ?Object, opts?: ?Object): node is JSXFragment; + declare export function isJSXOpeningFragment(node: ?Object, opts?: ?Object): node is JSXOpeningFragment; + declare export function isJSXClosingFragment(node: ?Object, opts?: ?Object): node is JSXClosingFragment; + declare export function isNoop(node: ?Object, opts?: ?Object): node is Noop; + declare export function isPlaceholder(node: ?Object, opts?: ?Object): node is Placeholder; + declare export function isV8IntrinsicIdentifier(node: ?Object, opts?: ?Object): node is V8IntrinsicIdentifier; + declare export function isArgumentPlaceholder(node: ?Object, opts?: ?Object): node is ArgumentPlaceholder; + declare export function isBindExpression(node: ?Object, opts?: ?Object): node is BindExpression; + declare export function isImportAttribute(node: ?Object, opts?: ?Object): node is ImportAttribute; + declare export function isDecorator(node: ?Object, opts?: ?Object): node is Decorator; + declare export function isDoExpression(node: ?Object, opts?: ?Object): node is DoExpression; + declare export function isExportDefaultSpecifier(node: ?Object, opts?: ?Object): node is ExportDefaultSpecifier; + declare export function isRecordExpression(node: ?Object, opts?: ?Object): node is RecordExpression; + declare export function isTupleExpression(node: ?Object, opts?: ?Object): node is TupleExpression; + declare export function isDecimalLiteral(node: ?Object, opts?: ?Object): node is DecimalLiteral; + declare export function isModuleExpression(node: ?Object, opts?: ?Object): node is ModuleExpression; + declare export function isTopicReference(node: ?Object, opts?: ?Object): node is TopicReference; + declare export function isPipelineTopicExpression(node: ?Object, opts?: ?Object): node is PipelineTopicExpression; + declare export function isPipelineBareFunction(node: ?Object, opts?: ?Object): node is PipelineBareFunction; + declare export function isPipelinePrimaryTopicReference(node: ?Object, opts?: ?Object): node is PipelinePrimaryTopicReference; + declare export function isTSParameterProperty(node: ?Object, opts?: ?Object): node is TSParameterProperty; + declare export function isTSDeclareFunction(node: ?Object, opts?: ?Object): node is TSDeclareFunction; + declare export function isTSDeclareMethod(node: ?Object, opts?: ?Object): node is TSDeclareMethod; + declare export function isTSQualifiedName(node: ?Object, opts?: ?Object): node is TSQualifiedName; + declare export function isTSCallSignatureDeclaration(node: ?Object, opts?: ?Object): node is TSCallSignatureDeclaration; + declare export function isTSConstructSignatureDeclaration(node: ?Object, opts?: ?Object): node is TSConstructSignatureDeclaration; + declare export function isTSPropertySignature(node: ?Object, opts?: ?Object): node is TSPropertySignature; + declare export function isTSMethodSignature(node: ?Object, opts?: ?Object): node is TSMethodSignature; + declare export function isTSIndexSignature(node: ?Object, opts?: ?Object): node is TSIndexSignature; + declare export function isTSAnyKeyword(node: ?Object, opts?: ?Object): node is TSAnyKeyword; + declare export function isTSBooleanKeyword(node: ?Object, opts?: ?Object): node is TSBooleanKeyword; + declare export function isTSBigIntKeyword(node: ?Object, opts?: ?Object): node is TSBigIntKeyword; + declare export function isTSIntrinsicKeyword(node: ?Object, opts?: ?Object): node is TSIntrinsicKeyword; + declare export function isTSNeverKeyword(node: ?Object, opts?: ?Object): node is TSNeverKeyword; + declare export function isTSNullKeyword(node: ?Object, opts?: ?Object): node is TSNullKeyword; + declare export function isTSNumberKeyword(node: ?Object, opts?: ?Object): node is TSNumberKeyword; + declare export function isTSObjectKeyword(node: ?Object, opts?: ?Object): node is TSObjectKeyword; + declare export function isTSStringKeyword(node: ?Object, opts?: ?Object): node is TSStringKeyword; + declare export function isTSSymbolKeyword(node: ?Object, opts?: ?Object): node is TSSymbolKeyword; + declare export function isTSUndefinedKeyword(node: ?Object, opts?: ?Object): node is TSUndefinedKeyword; + declare export function isTSUnknownKeyword(node: ?Object, opts?: ?Object): node is TSUnknownKeyword; + declare export function isTSVoidKeyword(node: ?Object, opts?: ?Object): node is TSVoidKeyword; + declare export function isTSThisType(node: ?Object, opts?: ?Object): node is TSThisType; + declare export function isTSFunctionType(node: ?Object, opts?: ?Object): node is TSFunctionType; + declare export function isTSConstructorType(node: ?Object, opts?: ?Object): node is TSConstructorType; + declare export function isTSTypeReference(node: ?Object, opts?: ?Object): node is TSTypeReference; + declare export function isTSTypePredicate(node: ?Object, opts?: ?Object): node is TSTypePredicate; + declare export function isTSTypeQuery(node: ?Object, opts?: ?Object): node is TSTypeQuery; + declare export function isTSTypeLiteral(node: ?Object, opts?: ?Object): node is TSTypeLiteral; + declare export function isTSArrayType(node: ?Object, opts?: ?Object): node is TSArrayType; + declare export function isTSTupleType(node: ?Object, opts?: ?Object): node is TSTupleType; + declare export function isTSOptionalType(node: ?Object, opts?: ?Object): node is TSOptionalType; + declare export function isTSRestType(node: ?Object, opts?: ?Object): node is TSRestType; + declare export function isTSNamedTupleMember(node: ?Object, opts?: ?Object): node is TSNamedTupleMember; + declare export function isTSUnionType(node: ?Object, opts?: ?Object): node is TSUnionType; + declare export function isTSIntersectionType(node: ?Object, opts?: ?Object): node is TSIntersectionType; + declare export function isTSConditionalType(node: ?Object, opts?: ?Object): node is TSConditionalType; + declare export function isTSInferType(node: ?Object, opts?: ?Object): node is TSInferType; + declare export function isTSParenthesizedType(node: ?Object, opts?: ?Object): node is TSParenthesizedType; + declare export function isTSTypeOperator(node: ?Object, opts?: ?Object): node is TSTypeOperator; + declare export function isTSIndexedAccessType(node: ?Object, opts?: ?Object): node is TSIndexedAccessType; + declare export function isTSMappedType(node: ?Object, opts?: ?Object): node is TSMappedType; + declare export function isTSLiteralType(node: ?Object, opts?: ?Object): node is TSLiteralType; + declare export function isTSExpressionWithTypeArguments(node: ?Object, opts?: ?Object): node is TSExpressionWithTypeArguments; + declare export function isTSInterfaceDeclaration(node: ?Object, opts?: ?Object): node is TSInterfaceDeclaration; + declare export function isTSInterfaceBody(node: ?Object, opts?: ?Object): node is TSInterfaceBody; + declare export function isTSTypeAliasDeclaration(node: ?Object, opts?: ?Object): node is TSTypeAliasDeclaration; + declare export function isTSInstantiationExpression(node: ?Object, opts?: ?Object): node is TSInstantiationExpression; + declare export function isTSAsExpression(node: ?Object, opts?: ?Object): node is TSAsExpression; + declare export function isTSSatisfiesExpression(node: ?Object, opts?: ?Object): node is TSSatisfiesExpression; + declare export function isTSTypeAssertion(node: ?Object, opts?: ?Object): node is TSTypeAssertion; + declare export function isTSEnumDeclaration(node: ?Object, opts?: ?Object): node is TSEnumDeclaration; + declare export function isTSEnumMember(node: ?Object, opts?: ?Object): node is TSEnumMember; + declare export function isTSModuleDeclaration(node: ?Object, opts?: ?Object): node is TSModuleDeclaration; + declare export function isTSModuleBlock(node: ?Object, opts?: ?Object): node is TSModuleBlock; + declare export function isTSImportType(node: ?Object, opts?: ?Object): node is TSImportType; + declare export function isTSImportEqualsDeclaration(node: ?Object, opts?: ?Object): node is TSImportEqualsDeclaration; + declare export function isTSExternalModuleReference(node: ?Object, opts?: ?Object): node is TSExternalModuleReference; + declare export function isTSNonNullExpression(node: ?Object, opts?: ?Object): node is TSNonNullExpression; + declare export function isTSExportAssignment(node: ?Object, opts?: ?Object): node is TSExportAssignment; + declare export function isTSNamespaceExportDeclaration(node: ?Object, opts?: ?Object): node is TSNamespaceExportDeclaration; + declare export function isTSTypeAnnotation(node: ?Object, opts?: ?Object): node is TSTypeAnnotation; + declare export function isTSTypeParameterInstantiation(node: ?Object, opts?: ?Object): node is TSTypeParameterInstantiation; + declare export function isTSTypeParameterDeclaration(node: ?Object, opts?: ?Object): node is TSTypeParameterDeclaration; + declare export function isTSTypeParameter(node: ?Object, opts?: ?Object): node is TSTypeParameter; + declare export function isStandardized(node: ?Object, opts?: ?Object): node is (ArrayExpression | AssignmentExpression | BinaryExpression | InterpreterDirective | Directive | DirectiveLiteral | BlockStatement | BreakStatement | CallExpression | CatchClause | ConditionalExpression | ContinueStatement | DebuggerStatement | DoWhileStatement | EmptyStatement | ExpressionStatement | File | ForInStatement | ForStatement | FunctionDeclaration | FunctionExpression | Identifier | IfStatement | LabeledStatement | StringLiteral | NumericLiteral | NullLiteral | BooleanLiteral | RegExpLiteral | LogicalExpression | MemberExpression | NewExpression | Program | ObjectExpression | ObjectMethod | ObjectProperty | RestElement | ReturnStatement | SequenceExpression | ParenthesizedExpression | SwitchCase | SwitchStatement | ThisExpression | ThrowStatement | TryStatement | UnaryExpression | UpdateExpression | VariableDeclaration | VariableDeclarator | WhileStatement | WithStatement | AssignmentPattern | ArrayPattern | ArrowFunctionExpression | ClassBody | ClassExpression | ClassDeclaration | ExportAllDeclaration | ExportDefaultDeclaration | ExportNamedDeclaration | ExportSpecifier | ForOfStatement | ImportDeclaration | ImportDefaultSpecifier | ImportNamespaceSpecifier | ImportSpecifier | MetaProperty | ClassMethod | ObjectPattern | SpreadElement | Super | TaggedTemplateExpression | TemplateElement | TemplateLiteral | YieldExpression | AwaitExpression | Import | BigIntLiteral | ExportNamespaceSpecifier | OptionalMemberExpression | OptionalCallExpression | ClassProperty | ClassAccessorProperty | ClassPrivateProperty | ClassPrivateMethod | PrivateName | StaticBlock); + declare export function isExpression(node: ?Object, opts?: ?Object): node is (ArrayExpression | AssignmentExpression | BinaryExpression | CallExpression | ConditionalExpression | FunctionExpression | Identifier | StringLiteral | NumericLiteral | NullLiteral | BooleanLiteral | RegExpLiteral | LogicalExpression | MemberExpression | NewExpression | ObjectExpression | SequenceExpression | ParenthesizedExpression | ThisExpression | UnaryExpression | UpdateExpression | ArrowFunctionExpression | ClassExpression | MetaProperty | Super | TaggedTemplateExpression | TemplateLiteral | YieldExpression | AwaitExpression | Import | BigIntLiteral | OptionalMemberExpression | OptionalCallExpression | TypeCastExpression | JSXElement | JSXFragment | BindExpression | DoExpression | RecordExpression | TupleExpression | DecimalLiteral | ModuleExpression | TopicReference | PipelineTopicExpression | PipelineBareFunction | PipelinePrimaryTopicReference | TSInstantiationExpression | TSAsExpression | TSSatisfiesExpression | TSTypeAssertion | TSNonNullExpression); + declare export function isBinary(node: ?Object, opts?: ?Object): node is (BinaryExpression | LogicalExpression); + declare export function isScopable(node: ?Object, opts?: ?Object): node is (BlockStatement | CatchClause | DoWhileStatement | ForInStatement | ForStatement | FunctionDeclaration | FunctionExpression | Program | ObjectMethod | SwitchStatement | WhileStatement | ArrowFunctionExpression | ClassExpression | ClassDeclaration | ForOfStatement | ClassMethod | ClassPrivateMethod | StaticBlock | TSModuleBlock); + declare export function isBlockParent(node: ?Object, opts?: ?Object): node is (BlockStatement | CatchClause | DoWhileStatement | ForInStatement | ForStatement | FunctionDeclaration | FunctionExpression | Program | ObjectMethod | SwitchStatement | WhileStatement | ArrowFunctionExpression | ForOfStatement | ClassMethod | ClassPrivateMethod | StaticBlock | TSModuleBlock); + declare export function isBlock(node: ?Object, opts?: ?Object): node is (BlockStatement | Program | TSModuleBlock); + declare export function isStatement(node: ?Object, opts?: ?Object): node is (BlockStatement | BreakStatement | ContinueStatement | DebuggerStatement | DoWhileStatement | EmptyStatement | ExpressionStatement | ForInStatement | ForStatement | FunctionDeclaration | IfStatement | LabeledStatement | ReturnStatement | SwitchStatement | ThrowStatement | TryStatement | VariableDeclaration | WhileStatement | WithStatement | ClassDeclaration | ExportAllDeclaration | ExportDefaultDeclaration | ExportNamedDeclaration | ForOfStatement | ImportDeclaration | DeclareClass | DeclareFunction | DeclareInterface | DeclareModule | DeclareModuleExports | DeclareTypeAlias | DeclareOpaqueType | DeclareVariable | DeclareExportDeclaration | DeclareExportAllDeclaration | InterfaceDeclaration | OpaqueType | TypeAlias | EnumDeclaration | TSDeclareFunction | TSInterfaceDeclaration | TSTypeAliasDeclaration | TSEnumDeclaration | TSModuleDeclaration | TSImportEqualsDeclaration | TSExportAssignment | TSNamespaceExportDeclaration); + declare export function isTerminatorless(node: ?Object, opts?: ?Object): node is (BreakStatement | ContinueStatement | ReturnStatement | ThrowStatement | YieldExpression | AwaitExpression); + declare export function isCompletionStatement(node: ?Object, opts?: ?Object): node is (BreakStatement | ContinueStatement | ReturnStatement | ThrowStatement); + declare export function isConditional(node: ?Object, opts?: ?Object): node is (ConditionalExpression | IfStatement); + declare export function isLoop(node: ?Object, opts?: ?Object): node is (DoWhileStatement | ForInStatement | ForStatement | WhileStatement | ForOfStatement); + declare export function isWhile(node: ?Object, opts?: ?Object): node is (DoWhileStatement | WhileStatement); + declare export function isExpressionWrapper(node: ?Object, opts?: ?Object): node is (ExpressionStatement | ParenthesizedExpression | TypeCastExpression); + declare export function isFor(node: ?Object, opts?: ?Object): node is (ForInStatement | ForStatement | ForOfStatement); + declare export function isForXStatement(node: ?Object, opts?: ?Object): node is (ForInStatement | ForOfStatement); + declare export function isFunction(node: ?Object, opts?: ?Object): node is (FunctionDeclaration | FunctionExpression | ObjectMethod | ArrowFunctionExpression | ClassMethod | ClassPrivateMethod); + declare export function isFunctionParent(node: ?Object, opts?: ?Object): node is (FunctionDeclaration | FunctionExpression | ObjectMethod | ArrowFunctionExpression | ClassMethod | ClassPrivateMethod | StaticBlock | TSModuleBlock); + declare export function isPureish(node: ?Object, opts?: ?Object): node is (FunctionDeclaration | FunctionExpression | StringLiteral | NumericLiteral | NullLiteral | BooleanLiteral | RegExpLiteral | ArrowFunctionExpression | BigIntLiteral | DecimalLiteral); + declare export function isDeclaration(node: ?Object, opts?: ?Object): node is (FunctionDeclaration | VariableDeclaration | ClassDeclaration | ExportAllDeclaration | ExportDefaultDeclaration | ExportNamedDeclaration | ImportDeclaration | DeclareClass | DeclareFunction | DeclareInterface | DeclareModule | DeclareModuleExports | DeclareTypeAlias | DeclareOpaqueType | DeclareVariable | DeclareExportDeclaration | DeclareExportAllDeclaration | InterfaceDeclaration | OpaqueType | TypeAlias | EnumDeclaration | TSDeclareFunction | TSInterfaceDeclaration | TSTypeAliasDeclaration | TSEnumDeclaration | TSModuleDeclaration); + declare export function isPatternLike(node: ?Object, opts?: ?Object): node is (Identifier | RestElement | AssignmentPattern | ArrayPattern | ObjectPattern | TSAsExpression | TSSatisfiesExpression | TSTypeAssertion | TSNonNullExpression); + declare export function isLVal(node: ?Object, opts?: ?Object): node is (Identifier | MemberExpression | RestElement | AssignmentPattern | ArrayPattern | ObjectPattern | TSParameterProperty | TSAsExpression | TSSatisfiesExpression | TSTypeAssertion | TSNonNullExpression); + declare export function isTSEntityName(node: ?Object, opts?: ?Object): node is (Identifier | TSQualifiedName); + declare export function isLiteral(node: ?Object, opts?: ?Object): node is (StringLiteral | NumericLiteral | NullLiteral | BooleanLiteral | RegExpLiteral | TemplateLiteral | BigIntLiteral | DecimalLiteral); + declare export function isImmutable(node: ?Object, opts?: ?Object): node is (StringLiteral | NumericLiteral | NullLiteral | BooleanLiteral | BigIntLiteral | JSXAttribute | JSXClosingElement | JSXElement | JSXExpressionContainer | JSXSpreadChild | JSXOpeningElement | JSXText | JSXFragment | JSXOpeningFragment | JSXClosingFragment | DecimalLiteral); + declare export function isUserWhitespacable(node: ?Object, opts?: ?Object): node is (ObjectMethod | ObjectProperty | ObjectTypeInternalSlot | ObjectTypeCallProperty | ObjectTypeIndexer | ObjectTypeProperty | ObjectTypeSpreadProperty); + declare export function isMethod(node: ?Object, opts?: ?Object): node is (ObjectMethod | ClassMethod | ClassPrivateMethod); + declare export function isObjectMember(node: ?Object, opts?: ?Object): node is (ObjectMethod | ObjectProperty); + declare export function isProperty(node: ?Object, opts?: ?Object): node is (ObjectProperty | ClassProperty | ClassAccessorProperty | ClassPrivateProperty); + declare export function isUnaryLike(node: ?Object, opts?: ?Object): node is (UnaryExpression | SpreadElement); + declare export function isPattern(node: ?Object, opts?: ?Object): node is (AssignmentPattern | ArrayPattern | ObjectPattern); + declare export function isClass(node: ?Object, opts?: ?Object): node is (ClassExpression | ClassDeclaration); + declare export function isModuleDeclaration(node: ?Object, opts?: ?Object): node is (ExportAllDeclaration | ExportDefaultDeclaration | ExportNamedDeclaration | ImportDeclaration); + declare export function isExportDeclaration(node: ?Object, opts?: ?Object): node is (ExportAllDeclaration | ExportDefaultDeclaration | ExportNamedDeclaration); + declare export function isModuleSpecifier(node: ?Object, opts?: ?Object): node is (ExportSpecifier | ImportDefaultSpecifier | ImportNamespaceSpecifier | ImportSpecifier | ExportNamespaceSpecifier | ExportDefaultSpecifier); + declare export function isAccessor(node: ?Object, opts?: ?Object): node is (ClassAccessorProperty); + declare export function isPrivate(node: ?Object, opts?: ?Object): node is (ClassPrivateProperty | ClassPrivateMethod | PrivateName); + declare export function isFlow(node: ?Object, opts?: ?Object): node is (AnyTypeAnnotation | ArrayTypeAnnotation | BooleanTypeAnnotation | BooleanLiteralTypeAnnotation | NullLiteralTypeAnnotation | ClassImplements | DeclareClass | DeclareFunction | DeclareInterface | DeclareModule | DeclareModuleExports | DeclareTypeAlias | DeclareOpaqueType | DeclareVariable | DeclareExportDeclaration | DeclareExportAllDeclaration | DeclaredPredicate | ExistsTypeAnnotation | FunctionTypeAnnotation | FunctionTypeParam | GenericTypeAnnotation | InferredPredicate | InterfaceExtends | InterfaceDeclaration | InterfaceTypeAnnotation | IntersectionTypeAnnotation | MixedTypeAnnotation | EmptyTypeAnnotation | NullableTypeAnnotation | NumberLiteralTypeAnnotation | NumberTypeAnnotation | ObjectTypeAnnotation | ObjectTypeInternalSlot | ObjectTypeCallProperty | ObjectTypeIndexer | ObjectTypeProperty | ObjectTypeSpreadProperty | OpaqueType | QualifiedTypeIdentifier | StringLiteralTypeAnnotation | StringTypeAnnotation | SymbolTypeAnnotation | ThisTypeAnnotation | TupleTypeAnnotation | TypeofTypeAnnotation | TypeAlias | TypeAnnotation | TypeCastExpression | TypeParameter | TypeParameterDeclaration | TypeParameterInstantiation | UnionTypeAnnotation | Variance | VoidTypeAnnotation | EnumDeclaration | EnumBooleanBody | EnumNumberBody | EnumStringBody | EnumSymbolBody | EnumBooleanMember | EnumNumberMember | EnumStringMember | EnumDefaultedMember | IndexedAccessType | OptionalIndexedAccessType); + declare export function isFlowType(node: ?Object, opts?: ?Object): node is (AnyTypeAnnotation | ArrayTypeAnnotation | BooleanTypeAnnotation | BooleanLiteralTypeAnnotation | NullLiteralTypeAnnotation | ExistsTypeAnnotation | FunctionTypeAnnotation | GenericTypeAnnotation | InterfaceTypeAnnotation | IntersectionTypeAnnotation | MixedTypeAnnotation | EmptyTypeAnnotation | NullableTypeAnnotation | NumberLiteralTypeAnnotation | NumberTypeAnnotation | ObjectTypeAnnotation | StringLiteralTypeAnnotation | StringTypeAnnotation | SymbolTypeAnnotation | ThisTypeAnnotation | TupleTypeAnnotation | TypeofTypeAnnotation | UnionTypeAnnotation | VoidTypeAnnotation | IndexedAccessType | OptionalIndexedAccessType); + declare export function isFlowBaseAnnotation(node: ?Object, opts?: ?Object): node is (AnyTypeAnnotation | BooleanTypeAnnotation | NullLiteralTypeAnnotation | MixedTypeAnnotation | EmptyTypeAnnotation | NumberTypeAnnotation | StringTypeAnnotation | SymbolTypeAnnotation | ThisTypeAnnotation | VoidTypeAnnotation); + declare export function isFlowDeclaration(node: ?Object, opts?: ?Object): node is (DeclareClass | DeclareFunction | DeclareInterface | DeclareModule | DeclareModuleExports | DeclareTypeAlias | DeclareOpaqueType | DeclareVariable | DeclareExportDeclaration | DeclareExportAllDeclaration | InterfaceDeclaration | OpaqueType | TypeAlias); + declare export function isFlowPredicate(node: ?Object, opts?: ?Object): node is (DeclaredPredicate | InferredPredicate); + declare export function isEnumBody(node: ?Object, opts?: ?Object): node is (EnumBooleanBody | EnumNumberBody | EnumStringBody | EnumSymbolBody); + declare export function isEnumMember(node: ?Object, opts?: ?Object): node is (EnumBooleanMember | EnumNumberMember | EnumStringMember | EnumDefaultedMember); + declare export function isJSX(node: ?Object, opts?: ?Object): node is (JSXAttribute | JSXClosingElement | JSXElement | JSXEmptyExpression | JSXExpressionContainer | JSXSpreadChild | JSXIdentifier | JSXMemberExpression | JSXNamespacedName | JSXOpeningElement | JSXSpreadAttribute | JSXText | JSXFragment | JSXOpeningFragment | JSXClosingFragment); + declare export function isMiscellaneous(node: ?Object, opts?: ?Object): node is (Noop | Placeholder | V8IntrinsicIdentifier); + declare export function isTypeScript(node: ?Object, opts?: ?Object): node is (TSParameterProperty | TSDeclareFunction | TSDeclareMethod | TSQualifiedName | TSCallSignatureDeclaration | TSConstructSignatureDeclaration | TSPropertySignature | TSMethodSignature | TSIndexSignature | TSAnyKeyword | TSBooleanKeyword | TSBigIntKeyword | TSIntrinsicKeyword | TSNeverKeyword | TSNullKeyword | TSNumberKeyword | TSObjectKeyword | TSStringKeyword | TSSymbolKeyword | TSUndefinedKeyword | TSUnknownKeyword | TSVoidKeyword | TSThisType | TSFunctionType | TSConstructorType | TSTypeReference | TSTypePredicate | TSTypeQuery | TSTypeLiteral | TSArrayType | TSTupleType | TSOptionalType | TSRestType | TSNamedTupleMember | TSUnionType | TSIntersectionType | TSConditionalType | TSInferType | TSParenthesizedType | TSTypeOperator | TSIndexedAccessType | TSMappedType | TSLiteralType | TSExpressionWithTypeArguments | TSInterfaceDeclaration | TSInterfaceBody | TSTypeAliasDeclaration | TSInstantiationExpression | TSAsExpression | TSSatisfiesExpression | TSTypeAssertion | TSEnumDeclaration | TSEnumMember | TSModuleDeclaration | TSModuleBlock | TSImportType | TSImportEqualsDeclaration | TSExternalModuleReference | TSNonNullExpression | TSExportAssignment | TSNamespaceExportDeclaration | TSTypeAnnotation | TSTypeParameterInstantiation | TSTypeParameterDeclaration | TSTypeParameter); + declare export function isTSTypeElement(node: ?Object, opts?: ?Object): node is (TSCallSignatureDeclaration | TSConstructSignatureDeclaration | TSPropertySignature | TSMethodSignature | TSIndexSignature); + declare export function isTSType(node: ?Object, opts?: ?Object): node is (TSAnyKeyword | TSBooleanKeyword | TSBigIntKeyword | TSIntrinsicKeyword | TSNeverKeyword | TSNullKeyword | TSNumberKeyword | TSObjectKeyword | TSStringKeyword | TSSymbolKeyword | TSUndefinedKeyword | TSUnknownKeyword | TSVoidKeyword | TSThisType | TSFunctionType | TSConstructorType | TSTypeReference | TSTypePredicate | TSTypeQuery | TSTypeLiteral | TSArrayType | TSTupleType | TSOptionalType | TSRestType | TSUnionType | TSIntersectionType | TSConditionalType | TSInferType | TSParenthesizedType | TSTypeOperator | TSIndexedAccessType | TSMappedType | TSLiteralType | TSExpressionWithTypeArguments | TSImportType); + declare export function isTSBaseType(node: ?Object, opts?: ?Object): node is (TSAnyKeyword | TSBooleanKeyword | TSBigIntKeyword | TSIntrinsicKeyword | TSNeverKeyword | TSNullKeyword | TSNumberKeyword | TSObjectKeyword | TSStringKeyword | TSSymbolKeyword | TSUndefinedKeyword | TSUnknownKeyword | TSVoidKeyword | TSThisType | TSLiteralType); + declare export function isNumberLiteral(node: ?Object, opts?: ?Object): node is NumericLiteral; + declare export function isRegexLiteral(node: ?Object, opts?: ?Object): node is RegExpLiteral; + declare export function isRestProperty(node: ?Object, opts?: ?Object): node is RestElement; + declare export function isSpreadProperty(node: ?Object, opts?: ?Object): node is SpreadElement; declare export function createTypeAnnotationBasedOnTypeof(type: 'string' | 'number' | 'undefined' | 'boolean' | 'function' | 'object' | 'symbol'): BabelNodeTypeAnnotation declare export function createUnionTypeAnnotation(types: Array): BabelNodeUnionTypeAnnotation declare export function createFlowUnionType(types: Array): BabelNodeUnionTypeAnnotation @@ -3796,18 +3796,18 @@ declare module "@babel/types" { declare export function is(type: string, n: BabelNode, opts: Object): boolean; declare export function isBinding(node: BabelNode, parent: BabelNode, grandparent?: BabelNode): boolean declare export function isBlockScoped(node: BabelNode): boolean - declare export function isLet(node: BabelNode): boolean %checks (node.type === 'VariableDeclaration') + declare export function isLet(node: BabelNode): node is VariableDeclaration declare export function isNode(node: ?Object): boolean declare export function isNodesEquivalent(a: any, b: any): boolean declare export function isPlaceholderType(placeholderType: string, targetType: string): boolean declare export function isReferenced(node: BabelNode, parent: BabelNode, grandparent?: BabelNode): boolean - declare export function isScope(node: BabelNode, parent: BabelNode): boolean %checks (node.type === 'BlockStatement' || node.type === 'CatchClause' || node.type === 'DoWhileStatement' || node.type === 'ForInStatement' || node.type === 'ForStatement' || node.type === 'FunctionDeclaration' || node.type === 'FunctionExpression' || node.type === 'Program' || node.type === 'ObjectMethod' || node.type === 'SwitchStatement' || node.type === 'WhileStatement' || node.type === 'ArrowFunctionExpression' || node.type === 'ClassExpression' || node.type === 'ClassDeclaration' || node.type === 'ForOfStatement' || node.type === 'ClassMethod' || node.type === 'ClassPrivateMethod' || node.type === 'TSModuleBlock') + declare export function isScope(node: BabelNode, parent: BabelNode): node is (BlockStatement | CatchClause | DoWhileStatement | ForInStatement | ForStatement | FunctionDeclaration | FunctionExpression | Program | ObjectMethod | SwitchStatement | WhileStatement | ArrowFunctionExpression | ClassExpression | ClassDeclaration | ForOfStatement | ClassMethod | ClassPrivateMethod | TSModuleBlock) declare export function isSpecifierDefault(specifier: BabelNodeModuleSpecifier): boolean declare export function isType(nodetype: ?string, targetType: string): boolean declare export function isValidES3Identifier(name: string): boolean declare export function isValidES3Identifier(name: string): boolean declare export function isValidIdentifier(name: string): boolean - declare export function isVar(node: BabelNode): boolean %checks (node.type === 'VariableDeclaration') + declare export function isVar(node: BabelNode): node is VariableDeclaration declare export function matchesPattern(node: ?BabelNode, match: string | Array, allowPartial?: boolean): boolean declare export function validate(n: BabelNode, key: string, value: mixed): void; declare export type Node = BabelNode; From d4399c5f15bdf926903043c2448bc7461bb6a3f9 Mon Sep 17 00:00:00 2001 From: Nick Gerleman Date: Wed, 22 Nov 2023 11:06:31 -0800 Subject: [PATCH 065/162] Don't enable `ordinalCount()` or `bitCount()` for bitset enums Summary: Bitfield enums are not sequential, so use of these functions on these enums would be invalid. I looked at whether we could trivially move `bitCount` to template based on `ordinalCount`. `bitCount` must be constexpr, since we use it directly as a bit-field size constant. `log2` and `ceil` to be constexpr, which isn't here until C++ 26. Reviewed By: javache Differential Revision: D51518899 fbshipit-source-id: 256f15bbed517be6f90bf43baa43ce96e9259a71 --- .../react-native/ReactCommon/yoga/yoga/enums/Errata.h | 10 ---------- .../ReactCommon/yoga/yoga/enums/PrintOptions.h | 10 ---------- 2 files changed, 20 deletions(-) diff --git a/packages/react-native/ReactCommon/yoga/yoga/enums/Errata.h b/packages/react-native/ReactCommon/yoga/yoga/enums/Errata.h index 6a085bf58da825..134f5fffc012fe 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/enums/Errata.h +++ b/packages/react-native/ReactCommon/yoga/yoga/enums/Errata.h @@ -26,16 +26,6 @@ enum class Errata : uint32_t { YG_DEFINE_ENUM_FLAG_OPERATORS(Errata) -template <> -constexpr inline int32_t ordinalCount() { - return 6; -} - -template <> -constexpr inline int32_t bitCount() { - return 3; -} - constexpr inline Errata scopedEnum(YGErrata unscoped) { return static_cast(unscoped); } diff --git a/packages/react-native/ReactCommon/yoga/yoga/enums/PrintOptions.h b/packages/react-native/ReactCommon/yoga/yoga/enums/PrintOptions.h index c61fbc6383a279..90d0043c74a4dd 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/enums/PrintOptions.h +++ b/packages/react-native/ReactCommon/yoga/yoga/enums/PrintOptions.h @@ -23,16 +23,6 @@ enum class PrintOptions : uint32_t { YG_DEFINE_ENUM_FLAG_OPERATORS(PrintOptions) -template <> -constexpr inline int32_t ordinalCount() { - return 3; -} - -template <> -constexpr inline int32_t bitCount() { - return 2; -} - constexpr inline PrintOptions scopedEnum(YGPrintOptions unscoped) { return static_cast(unscoped); } From 3ee4b8f5a1107d9c126c31ea21f43f6334232a3e Mon Sep 17 00:00:00 2001 From: Ramanpreet Nara Date: Wed, 22 Nov 2023 13:52:51 -0800 Subject: [PATCH 066/162] Create genrule to generate appmodules.so (#41466) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41466 ## Context In open source, all apps use the same turbomodulemanager delegate (i.e: the default delegate). This diff introduces the buck infra that makes the oss default delegate work for meta apps. Concretely, we are going to make React Native use the same delegate for **all** Meta apps. Each Meta app will: 1. At build time, generate a unique TMProvider map 2. At app init time, initialize the default delegate with the TMProvider map. ## Implementation **Step #1:** At build time, generate a unique TMProvider map **Insight:** Buck genrules can accept, as input, the output of a buck query. So, here's how we get this done: 1. Buck query (i.e: input to Genrule): Given the app's deps, query all the schemas in the app. 2. Genrule: Read the schemas to generate the TMProvider map. The TMProvider map will also contain **all** the app's C++ module codegen. Concretely: 1. This diff introduces a macro: rn_codegen_appmodules(deps). 2. rn_codegen_appmodules(deps) generates appmodules.so, which contains the TMProvider map. **Step #2:** At app init time, initialize the default delegate with the TMProvider map. This is how we'll initialize the DefaultTurboModuleManagerDelegate: 1. DefaultTurboModuleManagerDelegate will load appmodules.so during init. 2. When loaded, appmodules.so will assign the code-generated TMProvider map to DefaultTurboModuleManagerDelegate. ## Impact This should allow us to: 1. Get one step closer to getting rid of the `js1 build turbomodule-manager-delegates --target ` script 3. Remove the TurboModuleManagerDelegate from React Native's public API. (Because we use one delegate for all React Native apps in Meta and OSS) Changelog: [Internal] Reviewed By: mdvacca Differential Revision: D50988397 fbshipit-source-id: 0ca5dec14e2dae89ec97f5d39a182c7937c5c7bf --- .../src/cli/combine/combine-schemas-cli.js | 85 +++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 packages/react-native-codegen/src/cli/combine/combine-schemas-cli.js diff --git a/packages/react-native-codegen/src/cli/combine/combine-schemas-cli.js b/packages/react-native-codegen/src/cli/combine/combine-schemas-cli.js new file mode 100644 index 00000000000000..d8425e10ef018a --- /dev/null +++ b/packages/react-native-codegen/src/cli/combine/combine-schemas-cli.js @@ -0,0 +1,85 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict-local + * @format + */ + +'use strict'; + +import type { + ComponentSchema, + NativeModuleSchema, + SchemaType, +} from '../../CodegenSchema.js'; + +const assert = require('assert'); +const fs = require('fs'); +const util = require('util'); + +const {values: args} = util.parseArgs({ + options: { + platform: { + type: 'string', + }, + output: { + type: 'string', + }, + ['schema-query']: { + type: 'string', + }, + }, +}); +if (!['iOS', 'android'].includes(args.platform)) { + throw new Error(`Invalid platform ${args.platform}`); +} +const platform = args.platform; +const output = args.output; +const schemaQuery: string = args['schema-query']; + +if (!schemaQuery.startsWith('@')) { + throw new Error( + "The argument provided to --schema-query must be a filename that starts with '@'.", + ); +} + +const schemaQueryOutputFile = schemaQuery.replace(/^@/, ''); +const schemaQueryOutput = fs.readFileSync(schemaQueryOutputFile, 'utf8'); + +const schemaFiles = schemaQueryOutput.split(' '); +const modules: { + [hasteModuleName: string]: NativeModuleSchema | ComponentSchema, +} = {}; +const specNameToFile: {[hasteModuleName: string]: string} = {}; + +for (const file of schemaFiles) { + const schema: SchemaType = JSON.parse(fs.readFileSync(file, 'utf8')); + + if (schema.modules) { + for (const specName in schema.modules) { + const module = schema.modules[specName]; + if (modules[specName]) { + assert.deepEqual( + module, + modules[specName], + `App contained two specs with the same file name '${specName}'. Schemas: ${specNameToFile[specName]}, ${file}. Please rename one of the specs.`, + ); + } + + if ( + module.excludedPlatforms && + module.excludedPlatforms.indexOf(platform) >= 0 + ) { + continue; + } + + modules[specName] = module; + specNameToFile[specName] = file; + } + } +} + +fs.writeFileSync(output, JSON.stringify({modules}, null, 2)); From 4e92016a09e00a0fb049340c8176462a34f1db68 Mon Sep 17 00:00:00 2001 From: Ramanpreet Nara Date: Wed, 22 Nov 2023 13:52:51 -0800 Subject: [PATCH 067/162] Remove hard-coded SampleTurboModule exclude (#41574) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41574 The codegen scripts hard-code to exclude NativeSampleTurboModule. This diff modifies the codegen infra (i.e: combine-js-to-schema-cli.js) to accept an argument: --exclude . Auxiliary changes: - Refactor argument parsing to rely on node's util.parseArgs Changelog: [Internal] Reviewed By: javache, dmytrorykun Differential Revision: D51471526 fbshipit-source-id: 98b88058f8c4b6fa4d776d96a1eb0f15144906a8 --- .../combine/__tests__/combine-utils-test.js | 12 ++++- .../cli/combine/combine-js-to-schema-cli.js | 6 ++- .../src/cli/combine/combine-js-to-schema.js | 13 +++-- .../src/cli/combine/combine-utils.js | 47 +++++++++++++------ .../react/tasks/GenerateCodegenSchemaTask.kt | 2 + .../tasks/GenerateCodegenSchemaTaskTest.kt | 4 ++ .../codegen/generate-artifacts-executor.js | 6 ++- .../react_native_pods_utils/script_phases.sh | 2 +- 8 files changed, 69 insertions(+), 23 deletions(-) diff --git a/packages/react-native-codegen/src/cli/combine/__tests__/combine-utils-test.js b/packages/react-native-codegen/src/cli/combine/__tests__/combine-utils-test.js index 08b75933d863b1..117dcb0f596772 100644 --- a/packages/react-native-codegen/src/cli/combine/__tests__/combine-utils-test.js +++ b/packages/react-native-codegen/src/cli/combine/__tests__/combine-utils-test.js @@ -103,9 +103,19 @@ describe('filterJSFile', () => { }); describe('When the file is NativeSampleTurboModule', () => { - it('returns false', () => { + it('returns true', () => { const file = 'NativeSampleTurboModule.js'; const result = filterJSFile(file); + expect(result).toBeTruthy(); + }); + + it('returns false, when excluded', () => { + const file = 'NativeSampleTurboModule.js'; + const result = filterJSFile( + file, + null, + new RegExp('NativeSampleTurboModule'), + ); expect(result).toBeFalsy(); }); }); diff --git a/packages/react-native-codegen/src/cli/combine/combine-js-to-schema-cli.js b/packages/react-native-codegen/src/cli/combine/combine-js-to-schema-cli.js index fbcc50be7c7da8..790b47d4fcf966 100644 --- a/packages/react-native-codegen/src/cli/combine/combine-js-to-schema-cli.js +++ b/packages/react-native-codegen/src/cli/combine/combine-js-to-schema-cli.js @@ -16,6 +16,8 @@ const { } = require('./combine-js-to-schema'); const {parseArgs} = require('./combine-utils'); -const {platform, outfile, fileList} = parseArgs(process.argv); +const parsedArgs = parseArgs(process.argv); -combineSchemasInFileListAndWriteToFile(fileList, platform, outfile); +const {platform, outfile, fileList, exclude} = parsedArgs; + +combineSchemasInFileListAndWriteToFile(fileList, platform, outfile, exclude); diff --git a/packages/react-native-codegen/src/cli/combine/combine-js-to-schema.js b/packages/react-native-codegen/src/cli/combine/combine-js-to-schema.js index 01af2f8b29b66d..108edf99d81319 100644 --- a/packages/react-native-codegen/src/cli/combine/combine-js-to-schema.js +++ b/packages/react-native-codegen/src/cli/combine/combine-js-to-schema.js @@ -51,6 +51,7 @@ function combineSchemas(files: Array): SchemaType { function expandDirectoriesIntoFiles( fileList: Array, platform: ?string, + exclude: ?RegExp, ): Array { return fileList .flatMap(file => { @@ -66,14 +67,19 @@ function expandDirectoriesIntoFiles( // windowsPathsNoEscape: true, }); }) - .filter(element => filterJSFile(element, platform)); + .filter(element => filterJSFile(element, platform, exclude)); } function combineSchemasInFileList( fileList: Array, platform: ?string, + exclude: ?RegExp, ): SchemaType { - const expandedFileList = expandDirectoriesIntoFiles(fileList, platform); + const expandedFileList = expandDirectoriesIntoFiles( + fileList, + platform, + exclude, + ); const combined = combineSchemas(expandedFileList); if (Object.keys(combined.modules).length === 0) { console.error( @@ -87,8 +93,9 @@ function combineSchemasInFileListAndWriteToFile( fileList: Array, platform: ?string, outfile: string, + exclude: ?RegExp, ): void { - const combined = combineSchemasInFileList(fileList, platform); + const combined = combineSchemasInFileList(fileList, platform, exclude); const formattedSchema = JSON.stringify(combined, null, 2); fs.writeFileSync(outfile, formattedSchema); } diff --git a/packages/react-native-codegen/src/cli/combine/combine-utils.js b/packages/react-native-codegen/src/cli/combine/combine-utils.js index 5dad6e041b6b99..a54a17ce26b504 100644 --- a/packages/react-native-codegen/src/cli/combine/combine-utils.js +++ b/packages/react-native-codegen/src/cli/combine/combine-utils.js @@ -12,26 +12,41 @@ 'use strict'; const path = require('path'); +const util = require('util'); function parseArgs(args: string[]): { platform: ?string, outfile: string, fileList: string[], + exclude: ?RegExp, } { - if (args.length > 2 && ['-p', '--platform'].indexOf(args[2]) >= 0) { - const [outfile, ...fileList] = args.slice(4); - return { - platform: args[3], - outfile, - fileList, - }; - } + const parsedArgs = util.parseArgs({ + args: args.slice(2), + options: { + platform: { + short: 'p', + type: 'string', + }, + exclude: { + short: 'e', + type: 'string', + }, + }, + allowPositionals: true, + }); + + const { + values: {platform, exclude}, + positionals: files, + } = parsedArgs; + + const [outfile, ...fileList] = files; - const [outfile, ...fileList] = args.slice(2); return { - platform: null, + platform: platform ?? null, outfile, fileList, + exclude: exclude != null && exclude !== '' ? new RegExp(exclude) : null, }; } @@ -43,19 +58,21 @@ function parseArgs(args: string[]): { * Returns: `true` if the file can be used to generate some code; `false` otherwise * */ -function filterJSFile(file: string, currentPlatform: ?string): boolean { +function filterJSFile( + file: string, + currentPlatform: ?string, + excludeRegExp: ?RegExp, +): boolean { const isSpecFile = /^(Native.+|.+NativeComponent)/.test(path.basename(file)); const isNotNativeUIManager = !file.endsWith('NativeUIManager.js'); - const isNotNativeSampleTurboModule = !file.endsWith( - 'NativeSampleTurboModule.js', - ); const isNotTest = !file.includes('__tests'); + const isNotExcluded = excludeRegExp == null || !excludeRegExp.test(file); const isNotTSTypeDefinition = !file.endsWith('.d.ts'); const isValidCandidate = isSpecFile && isNotNativeUIManager && - isNotNativeSampleTurboModule && + isNotExcluded && isNotTest && isNotTSTypeDefinition; diff --git a/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/GenerateCodegenSchemaTask.kt b/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/GenerateCodegenSchemaTask.kt index 3c65387a4036c9..828a145b0076a0 100644 --- a/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/GenerateCodegenSchemaTask.kt +++ b/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/GenerateCodegenSchemaTask.kt @@ -67,6 +67,8 @@ abstract class GenerateCodegenSchemaTask : Exec() { .cliPath(workingDir), "--platform", "android", + "--exclude", + "NativeSampleTurboModule", generatedSchemaFile.get().asFile.cliPath(workingDir), jsRootDir.asFile.get().cliPath(workingDir), )) diff --git a/packages/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tasks/GenerateCodegenSchemaTaskTest.kt b/packages/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tasks/GenerateCodegenSchemaTaskTest.kt index b97c1b29a204f6..0d0f159923821a 100644 --- a/packages/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tasks/GenerateCodegenSchemaTaskTest.kt +++ b/packages/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tasks/GenerateCodegenSchemaTaskTest.kt @@ -145,6 +145,8 @@ class GenerateCodegenSchemaTaskTest { File(codegenDir, "lib/cli/combine/combine-js-to-schema-cli.js").toString(), "--platform", "android", + "--exclude", + "NativeSampleTurboModule", File(outputDir, "schema.json").toString(), jsRootDir.toString(), ), @@ -180,6 +182,8 @@ class GenerateCodegenSchemaTaskTest { .path, "--platform", "android", + "--exclude", + "NativeSampleTurboModule", File(outputDir, "schema.json").relativeTo(project.projectDir).path, jsRootDir.relativeTo(project.projectDir).path, ), diff --git a/packages/react-native/scripts/codegen/generate-artifacts-executor.js b/packages/react-native/scripts/codegen/generate-artifacts-executor.js index f2ec937fa1c5ac..a4c07c487200f9 100644 --- a/packages/react-native/scripts/codegen/generate-artifacts-executor.js +++ b/packages/react-native/scripts/codegen/generate-artifacts-executor.js @@ -267,7 +267,11 @@ function generateSchemaInfo(library) { library: library, schema: utils .getCombineJSToSchema() - .combineSchemasInFileList([pathToJavaScriptSources], 'ios'), + .combineSchemasInFileList( + [pathToJavaScriptSources], + 'ios', + /NativeSampleTurboModule/, + ), }; } diff --git a/packages/react-native/scripts/react_native_pods_utils/script_phases.sh b/packages/react-native/scripts/react_native_pods_utils/script_phases.sh index ab1eddfca72188..aff355264ff7bc 100755 --- a/packages/react-native/scripts/react_native_pods_utils/script_phases.sh +++ b/packages/react-native/scripts/react_native_pods_utils/script_phases.sh @@ -76,7 +76,7 @@ generateCodegenSchemaFromJavaScript () { # shellcheck disable=SC2086 # $JS_SRCS not having double quotations is intentional - "$NODE_BINARY" "$CODEGEN_CLI_PATH/lib/cli/combine/combine-js-to-schema-cli.js" "$GENERATED_SCHEMA_FILE" $JS_SRCS + "$NODE_BINARY" "$CODEGEN_CLI_PATH/lib/cli/combine/combine-js-to-schema-cli.js" --exclude NativeSampleTurboModule "$GENERATED_SCHEMA_FILE" $JS_SRCS } generateCodegenArtifactsFromSchema () { From 0f239d3301cce409476370294f782e76cc59a1ec Mon Sep 17 00:00:00 2001 From: Arushi Kesarwani Date: Wed, 22 Nov 2023 14:19:21 -0800 Subject: [PATCH 068/162] Fix ReactInstanceManager to initialize the UIManager (#41594) Summary: Adding `initialize()` to FabricUIManager just as was done by JSIModule Without this change switching to UIManagerProvider would cause the UI to be Frozen and the events not correctly registered. Pull Request resolved: https://github.com/facebook/react-native/pull/41594 Reviewed By: javache Differential Revision: D51456979 fbshipit-source-id: 8d97533340a88ec6bb2bf0f257b6acfaa59da471 --- .../main/java/com/facebook/react/ReactInstanceManager.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java index 6a4c0df440d9a1..be0ca24b62f2ad 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java @@ -1408,7 +1408,9 @@ private ReactApplicationContext createReactContext( } if (ReactFeatureFlags.enableFabricRenderer) { if (mUIManagerProvider != null) { - catalystInstance.setFabricUIManager(mUIManagerProvider.createUIManager(reactContext)); + UIManager uiManager = mUIManagerProvider.createUIManager(reactContext); + uiManager.initialize(); + catalystInstance.setFabricUIManager(uiManager); } else { catalystInstance.getJSIModule(JSIModuleType.UIManager); } From 072a2006e0bd8bd8cc9a75385cc03759bcf63c61 Mon Sep 17 00:00:00 2001 From: Phillip Pan Date: Wed, 22 Nov 2023 15:51:20 -0800 Subject: [PATCH 069/162] delete RCTBlockGuard (#41599) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41599 Changelog: [iOS][Breaking] this is not used in our framework, delete. feel free to fork this implementation if you are using it or interested in using it Reviewed By: cipolleschi Differential Revision: D51516680 fbshipit-source-id: 4ca23a5b78bf18a84ea0ab4fe16419db7aea03d9 --- .../platform/ios/ReactCommon/RCTBlockGuard.h | 24 ---------------- .../platform/ios/ReactCommon/RCTBlockGuard.mm | 28 ------------------- 2 files changed, 52 deletions(-) delete mode 100644 packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTBlockGuard.h delete mode 100644 packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTBlockGuard.mm diff --git a/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTBlockGuard.h b/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTBlockGuard.h deleted file mode 100644 index 0e34516bedaa14..00000000000000 --- a/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTBlockGuard.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#import - -NS_ASSUME_NONNULL_BEGIN - -/** - * RCTBlockGuard is designed to be used with obj-c blocks to assist with manual deallocation of C++ resources - * tied to lifetime of a block. If C++ resources needs to be manually released at the end of block or when the block - * is deallocated, place the clean up code inside constructor and make sure the instance of the class is references in - * the block. - */ -@interface RCTBlockGuard : NSObject - -- (instancetype)initWithCleanup:(void (^)(void))cleanup; - -@end - -NS_ASSUME_NONNULL_END diff --git a/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTBlockGuard.mm b/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTBlockGuard.mm deleted file mode 100644 index c88429c67a8c53..00000000000000 --- a/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTBlockGuard.mm +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#import "RCTBlockGuard.h" - -@implementation RCTBlockGuard { - void (^_cleanup)(void); -} - -- (instancetype)initWithCleanup:(void (^)(void))cleanup -{ - if (self = [super init]) { - _cleanup = cleanup; - } - - return self; -} - -- (void)dealloc -{ - _cleanup(); -} - -@end From c9c56511087d6e33bd4d2e86cbc1a76fc99ec8df Mon Sep 17 00:00:00 2001 From: Nick Gerleman Date: Wed, 22 Nov 2023 16:58:31 -0800 Subject: [PATCH 070/162] FP Tolerance in iOS Paper SafeAreaView debouncing (#41614) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41614 Fixes https://github.com/facebook/react-native/issues/41545 SafeAreaView works by adding padding in order to shift content out of the safe area. This may change the layout dimensions of the SafeAreaView, in turn effecting its safe area insets. This can cause layout results to change, which in turn changes the inset value. Because of this, there is a tolerance, where safe area inset changes do not trigger a new update. Yoga is instructed to round layout dimensions to the closest physical pixel, so a very small difference in layout may result being off by about a pixel. Right now the tolerance is exactly one physical pixel, and if there is FP error here, we may not pass the test, and start oscillating with different layout values. After changing affected ShadowNode order to always be root-first, the first call to set the frame of the `SafeAreaView` happens when a non-zero-sized RootView is present, which I think may lead to a safe area inset update communicated that wasn't before? Or other cosmic butterflies. Layout rounds to one physical pixel in difference, and our tolerance is `0.00001` dips off (not helped that 1/3 screen scale cannot be represented as decimal, even without FP error). This adds a small tolerance beyond just the pixel boundary, matching the logic in Fabric, which seems to resolve the issue. Changelog: [iOS][Fixed] - FP Tolerance in iOS Paper SafeAreaView debouncing Reviewed By: philIip Differential Revision: D51539091 fbshipit-source-id: 88bddc38c7cd8d93feef5f12da64b124af22f46d --- .../React/Views/SafeAreaView/RCTSafeAreaView.m | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/react-native/React/Views/SafeAreaView/RCTSafeAreaView.m b/packages/react-native/React/Views/SafeAreaView/RCTSafeAreaView.m index 41dc74b06b66be..eeb12da71bfb41 100644 --- a/packages/react-native/React/Views/SafeAreaView/RCTSafeAreaView.m +++ b/packages/react-native/React/Views/SafeAreaView/RCTSafeAreaView.m @@ -57,7 +57,12 @@ - (void)safeAreaInsetsDidChange - (void)setSafeAreaInsets:(UIEdgeInsets)safeAreaInsets { - if (UIEdgeInsetsEqualToEdgeInsetsWithThreshold(safeAreaInsets, _currentSafeAreaInsets, 1.0 / RCTScreenScale())) { + // Relayout with different padding may result in a close but slightly different result, amplified by Yoga rounding to + // physical pixel grid. To avoid infinite relayout, allow one physical pixel of difference, along with small amount of + // extra tolerance for FP error. + CGFloat tolerance = 1.0 / RCTScreenScale() + 0.01; + + if (UIEdgeInsetsEqualToEdgeInsetsWithThreshold(safeAreaInsets, _currentSafeAreaInsets, tolerance)) { return; } From d09b7b03828617c10063406e6aa8db325bcdd7c9 Mon Sep 17 00:00:00 2001 From: Nick Gerleman Date: Wed, 22 Nov 2023 22:43:41 -0800 Subject: [PATCH 071/162] Remove alias props for `inset`, `insetInline`, `insetBlock` (#41612) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41612 We never use the position edges for Yoga style. We should not keep extra props, and instead just parse directly into the Yoga style. Previously included in D50998164 Changelog: [Internal] Reviewed By: joevilches Differential Revision: D51508217 fbshipit-source-id: ff28cf7168446068b10901fbba258414b561f07f --- .../view/YogaLayoutableShadowNode.cpp | 9 ------ .../components/view/YogaStylableProps.cpp | 28 ++++--------------- .../components/view/YogaStylableProps.h | 7 ++--- .../components/view/propsConversions.h | 18 ++++++++++++ 4 files changed, 26 insertions(+), 36 deletions(-) diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/YogaLayoutableShadowNode.cpp b/packages/react-native/ReactCommon/react/renderer/components/view/YogaLayoutableShadowNode.cpp index 3bfa3a97f2394f..b19f51aa6769c3 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/YogaLayoutableShadowNode.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/view/YogaLayoutableShadowNode.cpp @@ -391,15 +391,6 @@ void YogaLayoutableShadowNode::updateYogaProps() { yoga::Style result{baseStyle}; // Aliases with precedence - if (!props.inset.isUndefined()) { - result.position()[YGEdgeAll] = props.inset; - } - if (!props.insetBlock.isUndefined()) { - result.position()[YGEdgeVertical] = props.insetBlock; - } - if (!props.insetInline.isUndefined()) { - result.position()[YGEdgeHorizontal] = props.insetInline; - } if (!props.insetInlineEnd.isUndefined()) { result.position()[YGEdgeEnd] = props.insetInlineEnd; } diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/YogaStylableProps.cpp b/packages/react-native/ReactCommon/react/renderer/components/view/YogaStylableProps.cpp index 607ed67c9d8be4..11c148f31b46d4 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/YogaStylableProps.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/view/YogaStylableProps.cpp @@ -227,7 +227,12 @@ static inline T const getFieldValue( REBUILD_YG_FIELD_SWITCH_CASE_INDEXED(position, YGEdgeRight, "right"); \ REBUILD_YG_FIELD_SWITCH_CASE_INDEXED(position, YGEdgeBottom, "bottom"); \ REBUILD_YG_FIELD_SWITCH_CASE_INDEXED(position, YGEdgeStart, "start"); \ - REBUILD_YG_FIELD_SWITCH_CASE_INDEXED(position, YGEdgeEnd, "end"); + REBUILD_YG_FIELD_SWITCH_CASE_INDEXED(position, YGEdgeEnd, "end"); \ + REBUILD_YG_FIELD_SWITCH_CASE_INDEXED( \ + position, YGEdgeHorizontal, "insetInline"); \ + REBUILD_YG_FIELD_SWITCH_CASE_INDEXED( \ + position, YGEdgeVertical, "insetBlock"); \ + REBUILD_YG_FIELD_SWITCH_CASE_INDEXED(position, YGEdgeAll, "inset"); void YogaStylableProps::setProp( const PropsParserContext& context, @@ -267,11 +272,8 @@ void YogaStylableProps::setProp( REBUILD_FIELD_YG_EDGES(border, "border", "Width"); // Aliases - RAW_SET_PROP_SWITCH_CASE(inset, "inset"); - RAW_SET_PROP_SWITCH_CASE(insetBlock, "insetBlock"); RAW_SET_PROP_SWITCH_CASE(insetBlockEnd, "insetBlockEnd"); RAW_SET_PROP_SWITCH_CASE(insetBlockStart, "insetBlockStart"); - RAW_SET_PROP_SWITCH_CASE(insetInline, "insetInline"); RAW_SET_PROP_SWITCH_CASE(insetInlineEnd, "insetInlineEnd"); RAW_SET_PROP_SWITCH_CASE(insetInlineStart, "insetInlineStart"); RAW_SET_PROP_SWITCH_CASE(marginInline, "marginInline"); @@ -387,18 +389,6 @@ void YogaStylableProps::convertRawPropAliases( const PropsParserContext& context, const YogaStylableProps& sourceProps, const RawProps& rawProps) { - inset = convertRawProp( - context, - rawProps, - "inset", - sourceProps.inset, - CompactValue::ofUndefined()); - insetBlock = convertRawProp( - context, - rawProps, - "insetBlock", - sourceProps.insetBlock, - CompactValue::ofUndefined()); insetBlockEnd = convertRawProp( context, rawProps, @@ -411,12 +401,6 @@ void YogaStylableProps::convertRawPropAliases( "insetBlockStart", sourceProps.insetBlockStart, CompactValue::ofUndefined()); - insetInline = convertRawProp( - context, - rawProps, - "insetInline", - sourceProps.insetInline, - CompactValue::ofUndefined()); insetInlineEnd = convertRawProp( context, rawProps, diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/YogaStylableProps.h b/packages/react-native/ReactCommon/react/renderer/components/view/YogaStylableProps.h index 6b529f7a7180fd..9114aa530e7ae8 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/YogaStylableProps.h +++ b/packages/react-native/ReactCommon/react/renderer/components/view/YogaStylableProps.h @@ -41,10 +41,8 @@ class YogaStylableProps : public Props { // Duplicates of existing properties with different names, taking // precedence. E.g. "marginBlock" instead of "marginVertical" - CompactValue inset; - CompactValue insetInline; - CompactValue insetInlineEnd; CompactValue insetInlineStart; + CompactValue insetInlineEnd; CompactValue marginInline; CompactValue marginInlineStart; @@ -59,9 +57,8 @@ class YogaStylableProps : public Props { // BlockEnd/BlockStart map to top/bottom (no writing mode), but we preserve // Yoga's precedence and prefer specific edges (e.g. top) to ones which are // flow relative (e.g. blockStart). - CompactValue insetBlock; - CompactValue insetBlockEnd; CompactValue insetBlockStart; + CompactValue insetBlockEnd; CompactValue marginBlockStart; CompactValue marginBlockEnd; diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/propsConversions.h b/packages/react-native/ReactCommon/react/renderer/components/view/propsConversions.h index db085aa2ae566d..6f9713ea64e22a 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/propsConversions.h +++ b/packages/react-native/ReactCommon/react/renderer/components/view/propsConversions.h @@ -143,6 +143,24 @@ static inline yoga::Style::Edges convertRawProp( "end", sourceValue[YGEdgeEnd], defaultValue[YGEdgeEnd]); + result[YGEdgeHorizontal] = convertRawProp( + context, + rawProps, + "insetInline", + sourceValue[YGEdgeHorizontal], + defaultValue[YGEdgeHorizontal]); + result[YGEdgeVertical] = convertRawProp( + context, + rawProps, + "insetBlock", + sourceValue[YGEdgeVertical], + defaultValue[YGEdgeVertical]); + result[YGEdgeAll] = convertRawProp( + context, + rawProps, + "inset", + sourceValue[YGEdgeAll], + defaultValue[YGEdgeAll]); return result; } From 5e920ff800fe4db69dac5f687bb1defedb5b0f71 Mon Sep 17 00:00:00 2001 From: Nick Gerleman Date: Wed, 22 Nov 2023 22:43:41 -0800 Subject: [PATCH 072/162] Inline yoga::Style::Edges convertRawProp (#41611) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41611 Aggregate edges will no longer be exposed. Inline the convertRawProp parsing functions for it. This is a little bit more code, but subjectively easier to reason about. Previously included in D50998164 Changelog: [Internal] Reviewed By: joevilches Differential Revision: D51510562 fbshipit-source-id: 30440e19422a3a3fb49a754b5ecd8279ce1521a2 --- .../components/view/propsConversions.h | 372 ++++++++++-------- 1 file changed, 210 insertions(+), 162 deletions(-) diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/propsConversions.h b/packages/react-native/ReactCommon/react/renderer/components/view/propsConversions.h index 6f9713ea64e22a..3ea67434e58946 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/propsConversions.h +++ b/packages/react-native/ReactCommon/react/renderer/components/view/propsConversions.h @@ -18,152 +18,6 @@ namespace facebook::react { // Nearly this entire file can be deleted when iterator-style Prop parsing // ships fully for View -static inline yoga::Style::Edges convertRawProp( - const PropsParserContext& context, - const RawProps& rawProps, - const char* prefix, - const char* suffix, - const yoga::Style::Edges& sourceValue, - const yoga::Style::Edges& defaultValue) { - auto result = defaultValue; - result[YGEdgeLeft] = convertRawProp( - context, - rawProps, - "Left", - sourceValue[YGEdgeLeft], - defaultValue[YGEdgeLeft], - prefix, - suffix); - result[YGEdgeTop] = convertRawProp( - context, - rawProps, - "Top", - sourceValue[YGEdgeTop], - defaultValue[YGEdgeTop], - prefix, - suffix); - result[YGEdgeRight] = convertRawProp( - context, - rawProps, - "Right", - sourceValue[YGEdgeRight], - defaultValue[YGEdgeRight], - prefix, - suffix); - result[YGEdgeBottom] = convertRawProp( - context, - rawProps, - "Bottom", - sourceValue[YGEdgeBottom], - defaultValue[YGEdgeBottom], - prefix, - suffix); - result[YGEdgeStart] = convertRawProp( - context, - rawProps, - "Start", - sourceValue[YGEdgeStart], - defaultValue[YGEdgeStart], - prefix, - suffix); - result[YGEdgeEnd] = convertRawProp( - context, - rawProps, - "End", - sourceValue[YGEdgeEnd], - defaultValue[YGEdgeEnd], - prefix, - suffix); - result[YGEdgeHorizontal] = convertRawProp( - context, - rawProps, - "Horizontal", - sourceValue[YGEdgeHorizontal], - defaultValue[YGEdgeHorizontal], - prefix, - suffix); - result[YGEdgeVertical] = convertRawProp( - context, - rawProps, - "Vertical", - sourceValue[YGEdgeVertical], - defaultValue[YGEdgeVertical], - prefix, - suffix); - result[YGEdgeAll] = convertRawProp( - context, - rawProps, - "", - sourceValue[YGEdgeAll], - defaultValue[YGEdgeAll], - prefix, - suffix); - return result; -} - -static inline yoga::Style::Edges convertRawProp( - const PropsParserContext& context, - const RawProps& rawProps, - const yoga::Style::Edges& sourceValue, - const yoga::Style::Edges& defaultValue) { - auto result = defaultValue; - result[YGEdgeLeft] = convertRawProp( - context, - rawProps, - "left", - sourceValue[YGEdgeLeft], - defaultValue[YGEdgeLeft]); - result[YGEdgeTop] = convertRawProp( - context, - rawProps, - "top", - sourceValue[YGEdgeTop], - defaultValue[YGEdgeTop]); - result[YGEdgeRight] = convertRawProp( - context, - rawProps, - "right", - sourceValue[YGEdgeRight], - defaultValue[YGEdgeRight]); - result[YGEdgeBottom] = convertRawProp( - context, - rawProps, - "bottom", - sourceValue[YGEdgeBottom], - defaultValue[YGEdgeBottom]); - result[YGEdgeStart] = convertRawProp( - context, - rawProps, - "start", - sourceValue[YGEdgeStart], - defaultValue[YGEdgeStart]); - result[YGEdgeEnd] = convertRawProp( - context, - rawProps, - "end", - sourceValue[YGEdgeEnd], - defaultValue[YGEdgeEnd]); - result[YGEdgeHorizontal] = convertRawProp( - context, - rawProps, - "insetInline", - sourceValue[YGEdgeHorizontal], - defaultValue[YGEdgeHorizontal]); - result[YGEdgeVertical] = convertRawProp( - context, - rawProps, - "insetBlock", - sourceValue[YGEdgeVertical], - defaultValue[YGEdgeVertical]); - result[YGEdgeAll] = convertRawProp( - context, - rawProps, - "inset", - sourceValue[YGEdgeAll], - defaultValue[YGEdgeAll]); - return result; -} - static inline yoga::Style convertRawProp( const PropsParserContext& context, const RawProps& rawProps, @@ -245,22 +99,170 @@ static inline yoga::Style convertRawProp( "flexBasis", sourceValue.flexBasis(), yogaStyle.flexBasis()); - yogaStyle.margin() = convertRawProp( + yogaStyle.margin()[YGEdgeLeft] = convertRawProp( + context, + rawProps, + "marginLeft", + sourceValue.margin()[YGEdgeLeft], + yogaStyle.margin()[YGEdgeLeft]); + yogaStyle.margin()[YGEdgeTop] = convertRawProp( + context, + rawProps, + "marginTop", + sourceValue.margin()[YGEdgeTop], + yogaStyle.margin()[YGEdgeTop]); + yogaStyle.margin()[YGEdgeRight] = convertRawProp( + context, + rawProps, + "marginRight", + sourceValue.margin()[YGEdgeRight], + yogaStyle.margin()[YGEdgeRight]); + yogaStyle.margin()[YGEdgeBottom] = convertRawProp( + context, + rawProps, + "marginBottom", + sourceValue.margin()[YGEdgeBottom], + yogaStyle.margin()[YGEdgeBottom]); + yogaStyle.margin()[YGEdgeStart] = convertRawProp( + context, + rawProps, + "marginStart", + sourceValue.margin()[YGEdgeStart], + yogaStyle.margin()[YGEdgeStart]); + yogaStyle.margin()[YGEdgeEnd] = convertRawProp( + context, + rawProps, + "marginEnd", + sourceValue.margin()[YGEdgeEnd], + yogaStyle.margin()[YGEdgeEnd]); + yogaStyle.margin()[YGEdgeHorizontal] = convertRawProp( + context, + rawProps, + "marginHorizontal", + sourceValue.margin()[YGEdgeHorizontal], + yogaStyle.margin()[YGEdgeHorizontal]); + yogaStyle.margin()[YGEdgeVertical] = convertRawProp( + context, + rawProps, + "marginVertical", + sourceValue.margin()[YGEdgeVertical], + yogaStyle.margin()[YGEdgeVertical]); + yogaStyle.margin()[YGEdgeAll] = convertRawProp( context, rawProps, "margin", - "", - sourceValue.margin(), - yogaStyle.margin()); - yogaStyle.position() = convertRawProp( - context, rawProps, sourceValue.position(), yogaStyle.position()); - yogaStyle.padding() = convertRawProp( + sourceValue.margin()[YGEdgeAll], + yogaStyle.margin()[YGEdgeAll]); + yogaStyle.position()[YGEdgeLeft] = convertRawProp( + context, + rawProps, + "left", + sourceValue.position()[YGEdgeLeft], + yogaStyle.position()[YGEdgeLeft]); + yogaStyle.position()[YGEdgeTop] = convertRawProp( + context, + rawProps, + "top", + sourceValue.position()[YGEdgeTop], + yogaStyle.position()[YGEdgeTop]); + + yogaStyle.position()[YGEdgeRight] = convertRawProp( + context, + rawProps, + "right", + sourceValue.position()[YGEdgeRight], + yogaStyle.position()[YGEdgeRight]); + yogaStyle.position()[YGEdgeBottom] = convertRawProp( + context, + rawProps, + "bottom", + sourceValue.position()[YGEdgeBottom], + yogaStyle.position()[YGEdgeBottom]); + yogaStyle.position()[YGEdgeStart] = convertRawProp( + context, + rawProps, + "start", + sourceValue.position()[YGEdgeStart], + yogaStyle.position()[YGEdgeStart]); + yogaStyle.position()[YGEdgeEnd] = convertRawProp( + context, + rawProps, + "end", + sourceValue.position()[YGEdgeEnd], + yogaStyle.position()[YGEdgeEnd]); + yogaStyle.position()[YGEdgeHorizontal] = convertRawProp( + context, + rawProps, + "insetInline", + sourceValue.position()[YGEdgeHorizontal], + yogaStyle.position()[YGEdgeHorizontal]); + + yogaStyle.position()[YGEdgeVertical] = convertRawProp( + context, + rawProps, + "insetBlock", + sourceValue.position()[YGEdgeVertical], + yogaStyle.position()[YGEdgeVertical]); + yogaStyle.position()[YGEdgeAll] = convertRawProp( + context, + rawProps, + "inset", + sourceValue.position()[YGEdgeAll], + yogaStyle.position()[YGEdgeAll]); + yogaStyle.padding()[YGEdgeLeft] = convertRawProp( + context, + rawProps, + "paddingLeft", + sourceValue.padding()[YGEdgeLeft], + yogaStyle.padding()[YGEdgeLeft]); + yogaStyle.padding()[YGEdgeTop] = convertRawProp( + context, + rawProps, + "paddingTop", + sourceValue.padding()[YGEdgeTop], + yogaStyle.padding()[YGEdgeTop]); + yogaStyle.padding()[YGEdgeRight] = convertRawProp( + context, + rawProps, + "paddingRight", + sourceValue.padding()[YGEdgeRight], + yogaStyle.padding()[YGEdgeRight]); + yogaStyle.padding()[YGEdgeBottom] = convertRawProp( + context, + rawProps, + "paddingBottom", + sourceValue.padding()[YGEdgeBottom], + yogaStyle.padding()[YGEdgeBottom]); + yogaStyle.padding()[YGEdgeStart] = convertRawProp( + context, + rawProps, + "paddingStart", + sourceValue.padding()[YGEdgeStart], + yogaStyle.padding()[YGEdgeStart]); + yogaStyle.padding()[YGEdgeEnd] = convertRawProp( + context, + rawProps, + "paddingEnd", + sourceValue.padding()[YGEdgeEnd], + yogaStyle.padding()[YGEdgeEnd]); + yogaStyle.padding()[YGEdgeHorizontal] = convertRawProp( + context, + rawProps, + "paddingHorizontal", + sourceValue.padding()[YGEdgeHorizontal], + yogaStyle.padding()[YGEdgeHorizontal]); + yogaStyle.padding()[YGEdgeVertical] = convertRawProp( + context, + rawProps, + "paddingVertical", + sourceValue.padding()[YGEdgeVertical], + yogaStyle.padding()[YGEdgeVertical]); + yogaStyle.padding()[YGEdgeAll] = convertRawProp( context, rawProps, "padding", - "", - sourceValue.padding(), - yogaStyle.padding()); + sourceValue.padding()[YGEdgeAll], + yogaStyle.padding()[YGEdgeAll]); yogaStyle.setGap( yoga::Gutter::Row, @@ -288,14 +290,60 @@ static inline yoga::Style convertRawProp( "gap", sourceValue.gap(yoga::Gutter::All), yogaStyle.gap(yoga::Gutter::All))); - - yogaStyle.border() = convertRawProp( + yogaStyle.border()[YGEdgeLeft] = convertRawProp( + context, + rawProps, + "borderLeftWidth", + sourceValue.border()[YGEdgeLeft], + yogaStyle.border()[YGEdgeLeft]); + yogaStyle.border()[YGEdgeTop] = convertRawProp( + context, + rawProps, + "borderTopWidth", + sourceValue.border()[YGEdgeTop], + yogaStyle.border()[YGEdgeTop]); + yogaStyle.border()[YGEdgeRight] = convertRawProp( + context, + rawProps, + "borderRightWidth", + sourceValue.border()[YGEdgeRight], + yogaStyle.border()[YGEdgeRight]); + yogaStyle.border()[YGEdgeBottom] = convertRawProp( + context, + rawProps, + "borderBottomWidth", + sourceValue.border()[YGEdgeBottom], + yogaStyle.border()[YGEdgeBottom]); + yogaStyle.border()[YGEdgeStart] = convertRawProp( + context, + rawProps, + "borderStartWidth", + sourceValue.border()[YGEdgeStart], + yogaStyle.border()[YGEdgeStart]); + yogaStyle.border()[YGEdgeEnd] = convertRawProp( + context, + rawProps, + "borderEndWidth", + sourceValue.border()[YGEdgeEnd], + yogaStyle.border()[YGEdgeEnd]); + yogaStyle.border()[YGEdgeHorizontal] = convertRawProp( + context, + rawProps, + "borderHorizontalWidth", + sourceValue.border()[YGEdgeHorizontal], + yogaStyle.border()[YGEdgeHorizontal]); + yogaStyle.border()[YGEdgeVertical] = convertRawProp( + context, + rawProps, + "borderVerticalWidth", + sourceValue.border()[YGEdgeVertical], + yogaStyle.border()[YGEdgeVertical]); + yogaStyle.border()[YGEdgeAll] = convertRawProp( context, rawProps, - "border", - "Width", - sourceValue.border(), - yogaStyle.border()); + "borderWidth", + sourceValue.border()[YGEdgeAll], + yogaStyle.border()[YGEdgeAll]); yogaStyle.setDimension( yoga::Dimension::Width, From 2d8ece4765a3490b627d1f8c0eeebcbaa15cdcf8 Mon Sep 17 00:00:00 2001 From: Nick Gerleman Date: Wed, 22 Nov 2023 22:43:41 -0800 Subject: [PATCH 073/162] Inline yoga::Style::Edges debugStringConvertibleItem (#41609) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41609 Aggregate edges will no longer be exposed. Inline debugStringConvertibleItem string printing for it. Previously included in D50998164 Changelog: [Internal] Reviewed By: joevilches Differential Revision: D51510790 fbshipit-source-id: aaabaa4fdd899bd9c602b9a5ab5dd35265c7269b --- .../components/view/YogaStylableProps.cpp | 144 +++++++++++++++++- .../renderer/components/view/conversions.h | 38 +---- 2 files changed, 142 insertions(+), 40 deletions(-) diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/YogaStylableProps.cpp b/packages/react-native/ReactCommon/react/renderer/components/view/YogaStylableProps.cpp index 11c148f31b46d4..4ae85c6c83955d 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/YogaStylableProps.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/view/YogaStylableProps.cpp @@ -346,13 +346,149 @@ SharedDebugStringConvertibleList YogaStylableProps::getDebugProps() const { debugStringConvertibleItem( "flexBasis", yogaStyle.flexBasis(), defaultYogaStyle.flexBasis()), debugStringConvertibleItem( - "margin", yogaStyle.margin(), defaultYogaStyle.margin()), + "marginLeft", + yogaStyle.margin()[YGEdgeLeft], + defaultYogaStyle.margin()[YGEdgeLeft]), debugStringConvertibleItem( - "position", yogaStyle.position(), defaultYogaStyle.position()), + "marginTop", + yogaStyle.margin()[YGEdgeTop], + defaultYogaStyle.margin()[YGEdgeTop]), debugStringConvertibleItem( - "padding", yogaStyle.padding(), defaultYogaStyle.padding()), + "marginRight", + yogaStyle.margin()[YGEdgeRight], + defaultYogaStyle.margin()[YGEdgeRight]), debugStringConvertibleItem( - "border", yogaStyle.border(), defaultYogaStyle.border()), + "marginBottom", + yogaStyle.margin()[YGEdgeBottom], + defaultYogaStyle.margin()[YGEdgeBottom]), + debugStringConvertibleItem( + "marginStart", + yogaStyle.margin()[YGEdgeStart], + defaultYogaStyle.margin()[YGEdgeStart]), + debugStringConvertibleItem( + "marginEnd", + yogaStyle.margin()[YGEdgeEnd], + defaultYogaStyle.margin()[YGEdgeEnd]), + debugStringConvertibleItem( + "marginHorizontal", + yogaStyle.margin()[YGEdgeHorizontal], + defaultYogaStyle.margin()[YGEdgeHorizontal]), + debugStringConvertibleItem( + "marginVertical", + yogaStyle.margin()[YGEdgeVertical], + defaultYogaStyle.margin()[YGEdgeVertical]), + debugStringConvertibleItem( + "margin", + yogaStyle.margin()[YGEdgeAll], + defaultYogaStyle.margin()[YGEdgeAll]), + debugStringConvertibleItem( + "left", + yogaStyle.position()[YGEdgeLeft], + defaultYogaStyle.position()[YGEdgeLeft]), + debugStringConvertibleItem( + "top", + yogaStyle.position()[YGEdgeTop], + defaultYogaStyle.position()[YGEdgeTop]), + debugStringConvertibleItem( + "right", + yogaStyle.position()[YGEdgeRight], + defaultYogaStyle.position()[YGEdgeRight]), + debugStringConvertibleItem( + "bottom", + yogaStyle.position()[YGEdgeBottom], + defaultYogaStyle.position()[YGEdgeBottom]), + debugStringConvertibleItem( + "start", + yogaStyle.position()[YGEdgeStart], + defaultYogaStyle.position()[YGEdgeStart]), + debugStringConvertibleItem( + "end", + yogaStyle.position()[YGEdgeEnd], + defaultYogaStyle.position()[YGEdgeEnd]), + debugStringConvertibleItem( + "inseInline", + yogaStyle.position()[YGEdgeHorizontal], + defaultYogaStyle.position()[YGEdgeHorizontal]), + debugStringConvertibleItem( + "insetBlock", + yogaStyle.position()[YGEdgeVertical], + defaultYogaStyle.position()[YGEdgeVertical]), + debugStringConvertibleItem( + "inset", + yogaStyle.position()[YGEdgeAll], + defaultYogaStyle.position()[YGEdgeAll]), + debugStringConvertibleItem( + "paddingLeft", + yogaStyle.padding()[YGEdgeLeft], + defaultYogaStyle.padding()[YGEdgeLeft]), + debugStringConvertibleItem( + "paddingTop", + yogaStyle.padding()[YGEdgeTop], + defaultYogaStyle.padding()[YGEdgeTop]), + debugStringConvertibleItem( + "paddingRight", + yogaStyle.padding()[YGEdgeRight], + defaultYogaStyle.padding()[YGEdgeRight]), + debugStringConvertibleItem( + "paddingBottom", + yogaStyle.padding()[YGEdgeBottom], + defaultYogaStyle.padding()[YGEdgeBottom]), + debugStringConvertibleItem( + "paddingStart", + yogaStyle.padding()[YGEdgeStart], + defaultYogaStyle.padding()[YGEdgeStart]), + debugStringConvertibleItem( + "paddingEnd", + yogaStyle.padding()[YGEdgeEnd], + defaultYogaStyle.padding()[YGEdgeEnd]), + debugStringConvertibleItem( + "paddingHorizontal", + yogaStyle.padding()[YGEdgeHorizontal], + defaultYogaStyle.padding()[YGEdgeHorizontal]), + debugStringConvertibleItem( + "paddingVertical", + yogaStyle.padding()[YGEdgeVertical], + defaultYogaStyle.padding()[YGEdgeVertical]), + debugStringConvertibleItem( + "padding", + yogaStyle.padding()[YGEdgeAll], + defaultYogaStyle.padding()[YGEdgeAll]), + debugStringConvertibleItem( + "borderLeftWidth", + yogaStyle.border()[YGEdgeLeft], + defaultYogaStyle.border()[YGEdgeLeft]), + debugStringConvertibleItem( + "borderTopWidth", + yogaStyle.border()[YGEdgeTop], + defaultYogaStyle.border()[YGEdgeTop]), + debugStringConvertibleItem( + "borderRightWidth", + yogaStyle.border()[YGEdgeRight], + defaultYogaStyle.border()[YGEdgeRight]), + debugStringConvertibleItem( + "borderBottomWidth", + yogaStyle.border()[YGEdgeBottom], + defaultYogaStyle.border()[YGEdgeBottom]), + debugStringConvertibleItem( + "borderStartWidth", + yogaStyle.border()[YGEdgeStart], + defaultYogaStyle.border()[YGEdgeStart]), + debugStringConvertibleItem( + "borderEndWidth", + yogaStyle.border()[YGEdgeEnd], + defaultYogaStyle.border()[YGEdgeEnd]), + debugStringConvertibleItem( + "borderHorizontalWidth", + yogaStyle.border()[YGEdgeHorizontal], + defaultYogaStyle.border()[YGEdgeHorizontal]), + debugStringConvertibleItem( + "borderVerticalWidth", + yogaStyle.border()[YGEdgeVertical], + defaultYogaStyle.border()[YGEdgeVertical]), + debugStringConvertibleItem( + "bordeWidth", + yogaStyle.border()[YGEdgeAll], + defaultYogaStyle.border()[YGEdgeAll]), debugStringConvertibleItem( "width", yogaStyle.dimension(yoga::Dimension::Width), diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/conversions.h b/packages/react-native/ReactCommon/react/renderer/components/view/conversions.h index c0edf7ce02dde9..2a82a16e85a1ce 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/conversions.h +++ b/packages/react-native/ReactCommon/react/renderer/components/view/conversions.h @@ -395,7 +395,7 @@ inline void fromRawValue( inline void fromRawValue( const PropsParserContext& context, const RawValue& value, - yoga::Style::ValueRepr& result) { + yoga::CompactValue& result) { if (value.hasType()) { result = yoga::CompactValue::ofMaybe((float)value); return; @@ -428,7 +428,7 @@ inline void fromRawValue( const PropsParserContext& context, const RawValue& value, YGValue& result) { - yoga::Style::ValueRepr ygValue{}; + yoga::CompactValue ygValue{}; fromRawValue(context, value, ygValue); result = ygValue; } @@ -778,40 +778,6 @@ inline std::string toString(const yoga::FloatOptional& value) { return folly::to(floatFromYogaFloat(value.unwrap())); } -inline std::string toString(const yoga::Style::Dimensions& value) { - return "{" + toString(value[0]) + ", " + toString(value[1]) + "}"; -} - -inline std::string toString(const yoga::Style::Edges& value) { - static std::array names = { - {"left", - "top", - "right", - "bottom", - "start", - "end", - "horizontal", - "vertical", - "all"}}; - - auto result = std::string{}; - auto separator = std::string{", "}; - - for (size_t i = 0; i < names.size(); i++) { - YGValue v = value[i]; - if (v.unit == YGUnitUndefined) { - continue; - } - result += names[i] + ": " + toString(v) + separator; - } - - if (!result.empty()) { - result.erase(result.length() - separator.length()); - } - - return "{" + result + "}"; -} - inline std::string toString(const LayoutConformance& value) { switch (value) { case LayoutConformance::Undefined: From 6b89dc1b97cdc326edc71b1a342bf6006aea239d Mon Sep 17 00:00:00 2001 From: Nick Gerleman Date: Wed, 22 Nov 2023 22:43:41 -0800 Subject: [PATCH 074/162] Do not expose aggregate style edges (#41610) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41610 X-link: https://github.com/facebook/yoga/pull/1477 A reland of the main change in D50998164, moving away from exposing compound edge arrays directly. Changelog: [Internal] Reviewed By: joevilches Differential Revision: D51512611 fbshipit-source-id: 2d4ceb89c9d76317feb9074aa271358a3abc0ee1 --- .../Text/RCTParagraphComponentViewTests.mm | 16 +- .../AndroidTextInputComponentDescriptor.h | 20 +- .../components/view/BaseViewProps.cpp | 18 +- .../components/view/ViewShadowNode.cpp | 2 +- .../view/YogaLayoutableShadowNode.cpp | 142 +++-- .../components/view/YogaStylableProps.cpp | 246 ++++---- .../view/YogaStylablePropsMapBuffer.cpp | 20 +- .../components/view/propsConversions.h | 538 +++++++++++------- .../components/view/tests/LayoutTest.cpp | 16 +- .../mounting/tests/StackingContextTest.cpp | 6 +- .../ReactCommon/yoga/yoga/YGNodeStyle.cpp | 47 +- .../yoga/yoga/algorithm/FlexDirection.h | 1 + .../yoga/yoga/debug/NodeToString.cpp | 47 +- .../ReactCommon/yoga/yoga/node/Node.cpp | 137 +++-- .../ReactCommon/yoga/yoga/node/Node.h | 15 +- .../ReactCommon/yoga/yoga/style/Style.h | 70 +-- 16 files changed, 681 insertions(+), 660 deletions(-) diff --git a/packages/react-native/React/Tests/Text/RCTParagraphComponentViewTests.mm b/packages/react-native/React/Tests/Text/RCTParagraphComponentViewTests.mm index da306ba8092441..0f5dc648ded670 100644 --- a/packages/react-native/React/Tests/Text/RCTParagraphComponentViewTests.mm +++ b/packages/react-native/React/Tests/Text/RCTParagraphComponentViewTests.mm @@ -134,8 +134,8 @@ - (void)setUp props.accessible = true; auto &yogaStyle = props.yogaStyle; yogaStyle.positionType() = yoga::PositionType::Absolute; - yogaStyle.position()[YGEdgeLeft] = YGValue{0, YGUnitPoint}; - yogaStyle.position()[YGEdgeTop] = YGValue{0, YGUnitPoint}; + yogaStyle.setPosition(YGEdgeLeft, yoga::CompactValue::of(0)); + yogaStyle.setPosition(YGEdgeTop, yoga::CompactValue::of(0)); yogaStyle.setDimension(yoga::Dimension::Width, yoga::CompactValue::of(200)); yogaStyle.setDimension(yoga::Dimension::Height, yoga::CompactValue::of(200)); return sharedProps; @@ -214,8 +214,8 @@ - (void)setUp props.accessible = true; auto &yogaStyle = props.yogaStyle; yogaStyle.positionType() = yoga::PositionType::Absolute; - yogaStyle.position()[YGEdgeLeft] = YGValue{0, YGUnitPoint}; - yogaStyle.position()[YGEdgeTop] = YGValue{30, YGUnitPoint}; + yogaStyle.setPosition(YGEdgeLeft, yoga::CompactValue::of(0)); + yogaStyle.setPosition(YGEdgeTop, yoga::CompactValue::of(30)); yogaStyle.setDimension(yoga::Dimension::Width, yoga::CompactValue::of(200)); yogaStyle.setDimension(yoga::Dimension::Height, yoga::CompactValue::of(50)); return sharedProps; @@ -258,8 +258,8 @@ - (void)setUp props.accessible = true; auto &yogaStyle = props.yogaStyle; yogaStyle.positionType() = yoga::PositionType::Absolute; - yogaStyle.position()[YGEdgeLeft] = YGValue{0, YGUnitPoint}; - yogaStyle.position()[YGEdgeTop] = YGValue{90, YGUnitPoint}; + yogaStyle.setPosition(YGEdgeLeft, yoga::CompactValue::of(0)); + yogaStyle.setPosition(YGEdgeTop, yoga::CompactValue::of(90)); yogaStyle.setDimension(yoga::Dimension::Width, yoga::CompactValue::of(200)); yogaStyle.setDimension(yoga::Dimension::Height, yoga::CompactValue::of(50)); return sharedProps; @@ -432,8 +432,8 @@ - (void)testEntireParagraphLink props.accessibilityTraits = AccessibilityTraits::Link; auto &yogaStyle = props.yogaStyle; yogaStyle.positionType() = yoga::PositionType::Absolute; - yogaStyle.position()[YGEdgeLeft] = YGValue{0, YGUnitPoint}; - yogaStyle.position()[YGEdgeTop] = YGValue{0, YGUnitPoint}; + yogaStyle.setPosition(YGEdgeLeft, yoga::CompactValue::of(0)); + yogaStyle.setPosition(YGEdgeTop, yoga::CompactValue::of(0)); yogaStyle.setDimension(yoga::Dimension::Width, yoga::CompactValue::of(200)); yogaStyle.setDimension(yoga::Dimension::Height, yoga::CompactValue::of(20)); return sharedProps; diff --git a/packages/react-native/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputComponentDescriptor.h b/packages/react-native/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputComponentDescriptor.h index 5ca2b167f65a94..553ba44389a8e1 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputComponentDescriptor.h +++ b/packages/react-native/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputComponentDescriptor.h @@ -106,27 +106,27 @@ class AndroidTextInputComponentDescriptor final !textInputProps.hasPaddingLeft && !textInputProps.hasPaddingHorizontal) { changedPadding = true; - style.padding()[YGEdgeStart] = - yoga::CompactValue::of(theme.start); + style.setPadding( + YGEdgeStart, yoga::CompactValue::of(theme.start)); } if (!textInputProps.hasPadding && !textInputProps.hasPaddingEnd && !textInputProps.hasPaddingRight && !textInputProps.hasPaddingHorizontal) { changedPadding = true; - style.padding()[YGEdgeEnd] = - yoga::CompactValue::of(theme.end); + style.setPadding( + YGEdgeEnd, yoga::CompactValue::of(theme.end)); } if (!textInputProps.hasPadding && !textInputProps.hasPaddingTop && !textInputProps.hasPaddingVertical) { changedPadding = true; - style.padding()[YGEdgeTop] = - yoga::CompactValue::of(theme.top); + style.setPadding( + YGEdgeTop, yoga::CompactValue::of(theme.top)); } if (!textInputProps.hasPadding && !textInputProps.hasPaddingBottom && !textInputProps.hasPaddingVertical) { changedPadding = true; - style.padding()[YGEdgeBottom] = - yoga::CompactValue::of(theme.bottom); + style.setPadding( + YGEdgeBottom, yoga::CompactValue::of(theme.bottom)); } // If the TextInput initially does not have paddingLeft or paddingStart, a @@ -137,12 +137,12 @@ class AndroidTextInputComponentDescriptor final if ((textInputProps.hasPadding || textInputProps.hasPaddingLeft || textInputProps.hasPaddingHorizontal) && !textInputProps.hasPaddingStart) { - style.padding()[YGEdgeStart] = yoga::CompactValue::ofUndefined(); + style.setPadding(YGEdgeStart, yoga::CompactValue::ofUndefined()); } if ((textInputProps.hasPadding || textInputProps.hasPaddingRight || textInputProps.hasPaddingHorizontal) && !textInputProps.hasPaddingEnd) { - style.padding()[YGEdgeEnd] = yoga::CompactValue::ofUndefined(); + style.setPadding(YGEdgeEnd, yoga::CompactValue::ofUndefined()); } // Note that this is expensive: on every adopt, we need to set the Yoga diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/BaseViewProps.cpp b/packages/react-native/ReactCommon/react/renderer/components/view/BaseViewProps.cpp index 58bb38b20385c1..790f14638e8622 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/BaseViewProps.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/view/BaseViewProps.cpp @@ -358,20 +358,20 @@ BorderMetrics BaseViewProps::resolveBorderMetrics( bool{layoutMetrics.layoutDirection == LayoutDirection::RightToLeft}; auto borderWidths = CascadedBorderWidths{ - /* .left = */ optionalFloatFromYogaValue(yogaStyle.border()[YGEdgeLeft]), - /* .top = */ optionalFloatFromYogaValue(yogaStyle.border()[YGEdgeTop]), + /* .left = */ optionalFloatFromYogaValue(yogaStyle.border(YGEdgeLeft)), + /* .top = */ optionalFloatFromYogaValue(yogaStyle.border(YGEdgeTop)), /* .right = */ - optionalFloatFromYogaValue(yogaStyle.border()[YGEdgeRight]), + optionalFloatFromYogaValue(yogaStyle.border(YGEdgeRight)), /* .bottom = */ - optionalFloatFromYogaValue(yogaStyle.border()[YGEdgeBottom]), + optionalFloatFromYogaValue(yogaStyle.border(YGEdgeBottom)), /* .start = */ - optionalFloatFromYogaValue(yogaStyle.border()[YGEdgeStart]), - /* .end = */ optionalFloatFromYogaValue(yogaStyle.border()[YGEdgeEnd]), + optionalFloatFromYogaValue(yogaStyle.border(YGEdgeStart)), + /* .end = */ optionalFloatFromYogaValue(yogaStyle.border(YGEdgeEnd)), /* .horizontal = */ - optionalFloatFromYogaValue(yogaStyle.border()[YGEdgeHorizontal]), + optionalFloatFromYogaValue(yogaStyle.border(YGEdgeHorizontal)), /* .vertical = */ - optionalFloatFromYogaValue(yogaStyle.border()[YGEdgeVertical]), - /* .all = */ optionalFloatFromYogaValue(yogaStyle.border()[YGEdgeAll]), + optionalFloatFromYogaValue(yogaStyle.border(YGEdgeVertical)), + /* .all = */ optionalFloatFromYogaValue(yogaStyle.border(YGEdgeAll)), }; return { diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/ViewShadowNode.cpp b/packages/react-native/ReactCommon/react/renderer/components/view/ViewShadowNode.cpp index ad22a350daef23..627128b1711a87 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/ViewShadowNode.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/view/ViewShadowNode.cpp @@ -41,7 +41,7 @@ void ViewShadowNode::initialize() noexcept { auto hasBorder = [&]() { for (auto edge : yoga::ordinals()) { - if (viewProps.yogaStyle.border()[yoga::unscopedEnum(edge)].isDefined()) { + if (viewProps.yogaStyle.border(yoga::unscopedEnum(edge)).isDefined()) { return true; } } diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/YogaLayoutableShadowNode.cpp b/packages/react-native/ReactCommon/react/renderer/components/view/YogaLayoutableShadowNode.cpp index b19f51aa6769c3..ac2e89a618aaab 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/YogaLayoutableShadowNode.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/view/YogaLayoutableShadowNode.cpp @@ -391,55 +391,55 @@ void YogaLayoutableShadowNode::updateYogaProps() { yoga::Style result{baseStyle}; // Aliases with precedence - if (!props.insetInlineEnd.isUndefined()) { - result.position()[YGEdgeEnd] = props.insetInlineEnd; + if (props.insetInlineEnd.isDefined()) { + result.setPosition(YGEdgeEnd, props.insetInlineEnd); } - if (!props.insetInlineStart.isUndefined()) { - result.position()[YGEdgeStart] = props.insetInlineStart; + if (props.insetInlineStart.isDefined()) { + result.setPosition(YGEdgeStart, props.insetInlineStart); } - if (!props.marginInline.isUndefined()) { - result.margin()[YGEdgeHorizontal] = props.marginInline; + if (props.marginInline.isDefined()) { + result.setMargin(YGEdgeHorizontal, props.marginInline); } - if (!props.marginInlineStart.isUndefined()) { - result.margin()[YGEdgeStart] = props.marginInlineStart; + if (props.marginInlineStart.isDefined()) { + result.setMargin(YGEdgeStart, props.marginInlineStart); } - if (!props.marginInlineEnd.isUndefined()) { - result.margin()[YGEdgeEnd] = props.marginInlineEnd; + if (props.marginInlineEnd.isDefined()) { + result.setMargin(YGEdgeEnd, props.marginInlineEnd); } - if (!props.marginBlock.isUndefined()) { - result.margin()[YGEdgeVertical] = props.marginBlock; + if (props.marginBlock.isDefined()) { + result.setMargin(YGEdgeVertical, props.marginBlock); } - if (!props.paddingInline.isUndefined()) { - result.padding()[YGEdgeHorizontal] = props.paddingInline; + if (props.paddingInline.isDefined()) { + result.setPadding(YGEdgeHorizontal, props.paddingInline); } - if (!props.paddingInlineStart.isUndefined()) { - result.padding()[YGEdgeStart] = props.paddingInlineStart; + if (props.paddingInlineStart.isDefined()) { + result.setPadding(YGEdgeStart, props.paddingInlineStart); } - if (!props.paddingInlineEnd.isUndefined()) { - result.padding()[YGEdgeEnd] = props.paddingInlineEnd; + if (props.paddingInlineEnd.isDefined()) { + result.setPadding(YGEdgeEnd, props.paddingInlineEnd); } - if (!props.paddingBlock.isUndefined()) { - result.padding()[YGEdgeVertical] = props.paddingBlock; + if (props.paddingBlock.isDefined()) { + result.setPadding(YGEdgeVertical, props.paddingBlock); } // Aliases without precedence - if (CompactValue(result.position()[YGEdgeBottom]).isUndefined()) { - result.position()[YGEdgeBottom] = props.insetBlockEnd; + if (result.position(YGEdgeBottom).isUndefined()) { + result.setPosition(YGEdgeBottom, props.insetBlockEnd); } - if (CompactValue(result.position()[YGEdgeTop]).isUndefined()) { - result.position()[YGEdgeTop] = props.insetBlockStart; + if (result.position(YGEdgeTop).isUndefined()) { + result.setPosition(YGEdgeTop, props.insetBlockStart); } - if (CompactValue(result.margin()[YGEdgeTop]).isUndefined()) { - result.margin()[YGEdgeTop] = props.marginBlockStart; + if (result.margin(YGEdgeTop).isUndefined()) { + result.setMargin(YGEdgeTop, props.marginBlockStart); } - if (CompactValue(result.margin()[YGEdgeBottom]).isUndefined()) { - result.margin()[YGEdgeBottom] = props.marginBlockEnd; + if (result.margin(YGEdgeBottom).isUndefined()) { + result.setMargin(YGEdgeBottom, props.marginBlockEnd); } - if (CompactValue(result.padding()[YGEdgeTop]).isUndefined()) { - result.padding()[YGEdgeTop] = props.paddingBlockStart; + if (result.padding(YGEdgeTop).isUndefined()) { + result.setPadding(YGEdgeTop, props.paddingBlockStart); } - if (CompactValue(result.padding()[YGEdgeBottom]).isUndefined()) { - result.padding()[YGEdgeBottom] = props.paddingBlockEnd; + if (result.padding(YGEdgeBottom).isUndefined()) { + result.setPadding(YGEdgeBottom, props.paddingBlockEnd); } return result; @@ -549,18 +549,18 @@ void YogaLayoutableShadowNode::setPadding(RectangleEdges padding) const { auto rightPadding = yoga::CompactValue::ofMaybe(padding.right); auto bottomPadding = yoga::CompactValue::ofMaybe(padding.bottom); - if (leftPadding != style.padding()[YGEdgeLeft] || - topPadding != style.padding()[YGEdgeTop] || - rightPadding != style.padding()[YGEdgeRight] || - bottomPadding != style.padding()[YGEdgeBottom]) { - style.padding()[YGEdgeTop] = - yoga::CompactValue::ofMaybe(padding.top); - style.padding()[YGEdgeLeft] = - yoga::CompactValue::ofMaybe(padding.left); - style.padding()[YGEdgeRight] = - yoga::CompactValue::ofMaybe(padding.right); - style.padding()[YGEdgeBottom] = - yoga::CompactValue::ofMaybe(padding.bottom); + if (leftPadding != style.padding(YGEdgeLeft) || + topPadding != style.padding(YGEdgeTop) || + rightPadding != style.padding(YGEdgeRight) || + bottomPadding != style.padding(YGEdgeBottom)) { + style.setPadding( + YGEdgeTop, yoga::CompactValue::ofMaybe(padding.top)); + style.setPadding( + YGEdgeLeft, yoga::CompactValue::ofMaybe(padding.left)); + style.setPadding( + YGEdgeRight, yoga::CompactValue::ofMaybe(padding.right)); + style.setPadding( + YGEdgeBottom, yoga::CompactValue::ofMaybe(padding.bottom)); yogaNode_.setStyle(style); yogaNode_.setDirty(true); } @@ -883,40 +883,36 @@ void YogaLayoutableShadowNode::swapLeftAndRightInYogaStyleProps( const YogaLayoutableShadowNode& shadowNode) { auto yogaStyle = shadowNode.yogaNode_.getStyle(); - const yoga::Style::Edges& position = yogaStyle.position(); - const yoga::Style::Edges& padding = yogaStyle.padding(); - const yoga::Style::Edges& margin = yogaStyle.margin(); - // Swap Yoga node values, position, padding and margin. - if (yogaStyle.position()[YGEdgeLeft] != YGValueUndefined) { - yogaStyle.position()[YGEdgeStart] = position[YGEdgeLeft]; - yogaStyle.position()[YGEdgeLeft] = YGValueUndefined; + if (yogaStyle.position(YGEdgeLeft).isDefined()) { + yogaStyle.setPosition(YGEdgeStart, yogaStyle.position(YGEdgeLeft)); + yogaStyle.setPosition(YGEdgeLeft, yoga::CompactValue::ofUndefined()); } - if (yogaStyle.position()[YGEdgeRight] != YGValueUndefined) { - yogaStyle.position()[YGEdgeEnd] = position[YGEdgeRight]; - yogaStyle.position()[YGEdgeRight] = YGValueUndefined; + if (yogaStyle.position(YGEdgeRight).isDefined()) { + yogaStyle.setPosition(YGEdgeEnd, yogaStyle.position(YGEdgeRight)); + yogaStyle.setPosition(YGEdgeRight, yoga::CompactValue::ofUndefined()); } - if (yogaStyle.padding()[YGEdgeLeft] != YGValueUndefined) { - yogaStyle.padding()[YGEdgeStart] = padding[YGEdgeLeft]; - yogaStyle.padding()[YGEdgeLeft] = YGValueUndefined; + if (yogaStyle.padding(YGEdgeLeft).isDefined()) { + yogaStyle.setPadding(YGEdgeStart, yogaStyle.padding(YGEdgeLeft)); + yogaStyle.setPadding(YGEdgeLeft, yoga::CompactValue::ofUndefined()); } - if (yogaStyle.padding()[YGEdgeRight] != YGValueUndefined) { - yogaStyle.padding()[YGEdgeEnd] = padding[YGEdgeRight]; - yogaStyle.padding()[YGEdgeRight] = YGValueUndefined; + if (yogaStyle.padding(YGEdgeRight).isDefined()) { + yogaStyle.setPadding(YGEdgeEnd, yogaStyle.padding(YGEdgeRight)); + yogaStyle.setPadding(YGEdgeRight, yoga::CompactValue::ofUndefined()); } - if (yogaStyle.margin()[YGEdgeLeft] != YGValueUndefined) { - yogaStyle.margin()[YGEdgeStart] = margin[YGEdgeLeft]; - yogaStyle.margin()[YGEdgeLeft] = YGValueUndefined; + if (yogaStyle.margin(YGEdgeLeft).isDefined()) { + yogaStyle.setMargin(YGEdgeStart, yogaStyle.margin(YGEdgeLeft)); + yogaStyle.setMargin(YGEdgeLeft, yoga::CompactValue::ofUndefined()); } - if (yogaStyle.margin()[YGEdgeRight] != YGValueUndefined) { - yogaStyle.margin()[YGEdgeEnd] = margin[YGEdgeRight]; - yogaStyle.margin()[YGEdgeRight] = YGValueUndefined; + if (yogaStyle.margin(YGEdgeRight).isDefined()) { + yogaStyle.setMargin(YGEdgeEnd, yogaStyle.margin(YGEdgeRight)); + yogaStyle.setMargin(YGEdgeRight, yoga::CompactValue::ofUndefined()); } shadowNode.yogaNode_.setStyle(yogaStyle); @@ -969,16 +965,14 @@ void YogaLayoutableShadowNode::swapLeftAndRightInViewProps( props.borderStyles.right.reset(); } - const yoga::Style::Edges& border = props.yogaStyle.border(); - - if (props.yogaStyle.border()[YGEdgeLeft] != YGValueUndefined) { - props.yogaStyle.border()[YGEdgeStart] = border[YGEdgeLeft]; - props.yogaStyle.border()[YGEdgeLeft] = YGValueUndefined; + if (props.yogaStyle.border(YGEdgeLeft).isDefined()) { + props.yogaStyle.setBorder(YGEdgeStart, props.yogaStyle.border(YGEdgeLeft)); + props.yogaStyle.setBorder(YGEdgeLeft, yoga::CompactValue::ofUndefined()); } - if (props.yogaStyle.border()[YGEdgeRight] != YGValueUndefined) { - props.yogaStyle.border()[YGEdgeEnd] = border[YGEdgeRight]; - props.yogaStyle.border()[YGEdgeRight] = YGValueUndefined; + if (props.yogaStyle.border(YGEdgeRight).isDefined()) { + props.yogaStyle.setBorder(YGEdgeEnd, props.yogaStyle.border(YGEdgeRight)); + props.yogaStyle.setBorder(YGEdgeRight, yoga::CompactValue::ofUndefined()); } } diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/YogaStylableProps.cpp b/packages/react-native/ReactCommon/react/renderer/components/view/YogaStylableProps.cpp index 4ae85c6c83955d..f8a7f360008d27 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/YogaStylableProps.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/view/YogaStylableProps.cpp @@ -174,65 +174,67 @@ static inline T const getFieldValue( #define REBUILD_FIELD_SWITCH_CASE_YSP(field) \ REBUILD_FIELD_SWITCH_CASE2(field, #field) -#define REBUILD_YG_FIELD_SWITCH_CASE_INDEXED(field, index, fieldName) \ - case CONSTEXPR_RAW_PROPS_KEY_HASH(fieldName): { \ - yogaStyle.field()[index] = \ - getFieldValue(context, value, ygDefaults.field()[index]); \ - return; \ - } - -#define REBUILD_YG_FIELD_SWITCH_CASE_INDEXED_SETTER( \ - field, setter, index, fieldName) \ - case CONSTEXPR_RAW_PROPS_KEY_HASH(fieldName): { \ - yogaStyle.setter( \ - index, getFieldValue(context, value, ygDefaults.field(index))); \ - return; \ +#define REBUILD_YG_FIELD_SWITCH_CASE_INDEXED(field, setter, index, fieldName) \ + case CONSTEXPR_RAW_PROPS_KEY_HASH(fieldName): { \ + yogaStyle.setter( \ + index, getFieldValue(context, value, ygDefaults.field(index))); \ + return; \ } #define REBUILD_FIELD_YG_DIMENSION(field, setter, widthStr, heightStr) \ - REBUILD_YG_FIELD_SWITCH_CASE_INDEXED_SETTER( \ + REBUILD_YG_FIELD_SWITCH_CASE_INDEXED( \ field, setter, yoga::Dimension::Width, widthStr); \ - REBUILD_YG_FIELD_SWITCH_CASE_INDEXED_SETTER( \ + REBUILD_YG_FIELD_SWITCH_CASE_INDEXED( \ field, setter, yoga::Dimension::Height, heightStr); #define REBUILD_FIELD_YG_GUTTER( \ field, setter, rowGapStr, columnGapStr, gapStr) \ - REBUILD_YG_FIELD_SWITCH_CASE_INDEXED_SETTER( \ + REBUILD_YG_FIELD_SWITCH_CASE_INDEXED( \ field, setter, yoga::Gutter::Row, rowGapStr); \ - REBUILD_YG_FIELD_SWITCH_CASE_INDEXED_SETTER( \ + REBUILD_YG_FIELD_SWITCH_CASE_INDEXED( \ field, setter, yoga::Gutter::Column, columnGapStr); \ - REBUILD_YG_FIELD_SWITCH_CASE_INDEXED_SETTER( \ + REBUILD_YG_FIELD_SWITCH_CASE_INDEXED( \ field, setter, yoga::Gutter::All, gapStr); -#define REBUILD_FIELD_YG_EDGES(field, prefix, suffix) \ - REBUILD_YG_FIELD_SWITCH_CASE_INDEXED( \ - field, YGEdgeLeft, prefix "Left" suffix); \ - REBUILD_YG_FIELD_SWITCH_CASE_INDEXED(field, YGEdgeTop, prefix "Top" suffix); \ - REBUILD_YG_FIELD_SWITCH_CASE_INDEXED( \ - field, YGEdgeRight, prefix "Right" suffix); \ - REBUILD_YG_FIELD_SWITCH_CASE_INDEXED( \ - field, YGEdgeBottom, prefix "Bottom" suffix); \ - REBUILD_YG_FIELD_SWITCH_CASE_INDEXED( \ - field, YGEdgeStart, prefix "Start" suffix); \ - REBUILD_YG_FIELD_SWITCH_CASE_INDEXED(field, YGEdgeEnd, prefix "End" suffix); \ - REBUILD_YG_FIELD_SWITCH_CASE_INDEXED( \ - field, YGEdgeHorizontal, prefix "Horizontal" suffix); \ - REBUILD_YG_FIELD_SWITCH_CASE_INDEXED( \ - field, YGEdgeVertical, prefix "Vertical" suffix); \ - REBUILD_YG_FIELD_SWITCH_CASE_INDEXED(field, YGEdgeAll, prefix "" suffix); - -#define REBUILD_FIELD_YG_EDGES_POSITION() \ - REBUILD_YG_FIELD_SWITCH_CASE_INDEXED(position, YGEdgeLeft, "left"); \ - REBUILD_YG_FIELD_SWITCH_CASE_INDEXED(position, YGEdgeTop, "top"); \ - REBUILD_YG_FIELD_SWITCH_CASE_INDEXED(position, YGEdgeRight, "right"); \ - REBUILD_YG_FIELD_SWITCH_CASE_INDEXED(position, YGEdgeBottom, "bottom"); \ - REBUILD_YG_FIELD_SWITCH_CASE_INDEXED(position, YGEdgeStart, "start"); \ - REBUILD_YG_FIELD_SWITCH_CASE_INDEXED(position, YGEdgeEnd, "end"); \ - REBUILD_YG_FIELD_SWITCH_CASE_INDEXED( \ - position, YGEdgeHorizontal, "insetInline"); \ - REBUILD_YG_FIELD_SWITCH_CASE_INDEXED( \ - position, YGEdgeVertical, "insetBlock"); \ - REBUILD_YG_FIELD_SWITCH_CASE_INDEXED(position, YGEdgeAll, "inset"); +#define REBUILD_FIELD_YG_EDGES(field, setter, prefix, suffix) \ + REBUILD_YG_FIELD_SWITCH_CASE_INDEXED( \ + field, setter, YGEdgeLeft, prefix "Left" suffix); \ + REBUILD_YG_FIELD_SWITCH_CASE_INDEXED( \ + field, setter, YGEdgeTop, prefix "Top" suffix); \ + REBUILD_YG_FIELD_SWITCH_CASE_INDEXED( \ + field, setter, YGEdgeRight, prefix "Right" suffix); \ + REBUILD_YG_FIELD_SWITCH_CASE_INDEXED( \ + field, setter, YGEdgeBottom, prefix "Bottom" suffix); \ + REBUILD_YG_FIELD_SWITCH_CASE_INDEXED( \ + field, setter, YGEdgeStart, prefix "Start" suffix); \ + REBUILD_YG_FIELD_SWITCH_CASE_INDEXED( \ + field, setter, YGEdgeEnd, prefix "End" suffix); \ + REBUILD_YG_FIELD_SWITCH_CASE_INDEXED( \ + field, setter, YGEdgeHorizontal, prefix "Horizontal" suffix); \ + REBUILD_YG_FIELD_SWITCH_CASE_INDEXED( \ + field, setter, YGEdgeVertical, prefix "Vertical" suffix); \ + REBUILD_YG_FIELD_SWITCH_CASE_INDEXED( \ + field, setter, YGEdgeAll, prefix "" suffix); + +#define REBUILD_FIELD_YG_EDGES_POSITION() \ + REBUILD_YG_FIELD_SWITCH_CASE_INDEXED( \ + position, setPosition, YGEdgeLeft, "left"); \ + REBUILD_YG_FIELD_SWITCH_CASE_INDEXED( \ + position, setPosition, YGEdgeTop, "top"); \ + REBUILD_YG_FIELD_SWITCH_CASE_INDEXED( \ + position, setPosition, YGEdgeRight, "right"); \ + REBUILD_YG_FIELD_SWITCH_CASE_INDEXED( \ + position, setPosition, YGEdgeBottom, "bottom"); \ + REBUILD_YG_FIELD_SWITCH_CASE_INDEXED( \ + position, setPosition, YGEdgeStart, "start"); \ + REBUILD_YG_FIELD_SWITCH_CASE_INDEXED( \ + position, setPosition, YGEdgeEnd, "end"); \ + REBUILD_YG_FIELD_SWITCH_CASE_INDEXED( \ + position, setPosition, YGEdgeHorizontal, "insetInline"); \ + REBUILD_YG_FIELD_SWITCH_CASE_INDEXED( \ + position, setPosition, YGEdgeVertical, "insetBlock"); \ + REBUILD_YG_FIELD_SWITCH_CASE_INDEXED( \ + position, setPosition, YGEdgeAll, "inset"); void YogaStylableProps::setProp( const PropsParserContext& context, @@ -267,9 +269,9 @@ void YogaStylableProps::setProp( REBUILD_FIELD_YG_DIMENSION( maxDimension, setMaxDimension, "maxWidth", "maxHeight"); REBUILD_FIELD_YG_EDGES_POSITION(); - REBUILD_FIELD_YG_EDGES(margin, "margin", ""); - REBUILD_FIELD_YG_EDGES(padding, "padding", ""); - REBUILD_FIELD_YG_EDGES(border, "border", "Width"); + REBUILD_FIELD_YG_EDGES(margin, setMargin, "margin", ""); + REBUILD_FIELD_YG_EDGES(padding, setPadding, "padding", ""); + REBUILD_FIELD_YG_EDGES(border, setBorder, "border", "Width"); // Aliases RAW_SET_PROP_SWITCH_CASE(insetBlockEnd, "insetBlockEnd"); @@ -347,148 +349,148 @@ SharedDebugStringConvertibleList YogaStylableProps::getDebugProps() const { "flexBasis", yogaStyle.flexBasis(), defaultYogaStyle.flexBasis()), debugStringConvertibleItem( "marginLeft", - yogaStyle.margin()[YGEdgeLeft], - defaultYogaStyle.margin()[YGEdgeLeft]), + yogaStyle.margin(YGEdgeLeft), + defaultYogaStyle.margin(YGEdgeLeft)), debugStringConvertibleItem( "marginTop", - yogaStyle.margin()[YGEdgeTop], - defaultYogaStyle.margin()[YGEdgeTop]), + yogaStyle.margin(YGEdgeTop), + defaultYogaStyle.margin(YGEdgeTop)), debugStringConvertibleItem( "marginRight", - yogaStyle.margin()[YGEdgeRight], - defaultYogaStyle.margin()[YGEdgeRight]), + yogaStyle.margin(YGEdgeRight), + defaultYogaStyle.margin(YGEdgeRight)), debugStringConvertibleItem( "marginBottom", - yogaStyle.margin()[YGEdgeBottom], - defaultYogaStyle.margin()[YGEdgeBottom]), + yogaStyle.margin(YGEdgeBottom), + defaultYogaStyle.margin(YGEdgeBottom)), debugStringConvertibleItem( "marginStart", - yogaStyle.margin()[YGEdgeStart], - defaultYogaStyle.margin()[YGEdgeStart]), + yogaStyle.margin(YGEdgeStart), + defaultYogaStyle.margin(YGEdgeStart)), debugStringConvertibleItem( "marginEnd", - yogaStyle.margin()[YGEdgeEnd], - defaultYogaStyle.margin()[YGEdgeEnd]), + yogaStyle.margin(YGEdgeEnd), + defaultYogaStyle.margin(YGEdgeEnd)), debugStringConvertibleItem( "marginHorizontal", - yogaStyle.margin()[YGEdgeHorizontal], - defaultYogaStyle.margin()[YGEdgeHorizontal]), + yogaStyle.margin(YGEdgeHorizontal), + defaultYogaStyle.margin(YGEdgeHorizontal)), debugStringConvertibleItem( "marginVertical", - yogaStyle.margin()[YGEdgeVertical], - defaultYogaStyle.margin()[YGEdgeVertical]), + yogaStyle.margin(YGEdgeVertical), + defaultYogaStyle.margin(YGEdgeVertical)), debugStringConvertibleItem( "margin", - yogaStyle.margin()[YGEdgeAll], - defaultYogaStyle.margin()[YGEdgeAll]), + yogaStyle.margin(YGEdgeAll), + defaultYogaStyle.margin(YGEdgeAll)), debugStringConvertibleItem( "left", - yogaStyle.position()[YGEdgeLeft], - defaultYogaStyle.position()[YGEdgeLeft]), + yogaStyle.position(YGEdgeLeft), + defaultYogaStyle.position(YGEdgeLeft)), debugStringConvertibleItem( "top", - yogaStyle.position()[YGEdgeTop], - defaultYogaStyle.position()[YGEdgeTop]), + yogaStyle.position(YGEdgeTop), + defaultYogaStyle.position(YGEdgeTop)), debugStringConvertibleItem( "right", - yogaStyle.position()[YGEdgeRight], - defaultYogaStyle.position()[YGEdgeRight]), + yogaStyle.position(YGEdgeRight), + defaultYogaStyle.position(YGEdgeRight)), debugStringConvertibleItem( "bottom", - yogaStyle.position()[YGEdgeBottom], - defaultYogaStyle.position()[YGEdgeBottom]), + yogaStyle.position(YGEdgeBottom), + defaultYogaStyle.position(YGEdgeBottom)), debugStringConvertibleItem( "start", - yogaStyle.position()[YGEdgeStart], - defaultYogaStyle.position()[YGEdgeStart]), + yogaStyle.position(YGEdgeStart), + defaultYogaStyle.position(YGEdgeStart)), debugStringConvertibleItem( "end", - yogaStyle.position()[YGEdgeEnd], - defaultYogaStyle.position()[YGEdgeEnd]), + yogaStyle.position(YGEdgeEnd), + defaultYogaStyle.position(YGEdgeEnd)), debugStringConvertibleItem( "inseInline", - yogaStyle.position()[YGEdgeHorizontal], - defaultYogaStyle.position()[YGEdgeHorizontal]), + yogaStyle.position(YGEdgeHorizontal), + defaultYogaStyle.position(YGEdgeHorizontal)), debugStringConvertibleItem( "insetBlock", - yogaStyle.position()[YGEdgeVertical], - defaultYogaStyle.position()[YGEdgeVertical]), + yogaStyle.position(YGEdgeVertical), + defaultYogaStyle.position(YGEdgeVertical)), debugStringConvertibleItem( "inset", - yogaStyle.position()[YGEdgeAll], - defaultYogaStyle.position()[YGEdgeAll]), + yogaStyle.position(YGEdgeAll), + defaultYogaStyle.position(YGEdgeAll)), debugStringConvertibleItem( "paddingLeft", - yogaStyle.padding()[YGEdgeLeft], - defaultYogaStyle.padding()[YGEdgeLeft]), + yogaStyle.padding(YGEdgeLeft), + defaultYogaStyle.padding(YGEdgeLeft)), debugStringConvertibleItem( "paddingTop", - yogaStyle.padding()[YGEdgeTop], - defaultYogaStyle.padding()[YGEdgeTop]), + yogaStyle.padding(YGEdgeTop), + defaultYogaStyle.padding(YGEdgeTop)), debugStringConvertibleItem( "paddingRight", - yogaStyle.padding()[YGEdgeRight], - defaultYogaStyle.padding()[YGEdgeRight]), + yogaStyle.padding(YGEdgeRight), + defaultYogaStyle.padding(YGEdgeRight)), debugStringConvertibleItem( "paddingBottom", - yogaStyle.padding()[YGEdgeBottom], - defaultYogaStyle.padding()[YGEdgeBottom]), + yogaStyle.padding(YGEdgeBottom), + defaultYogaStyle.padding(YGEdgeBottom)), debugStringConvertibleItem( "paddingStart", - yogaStyle.padding()[YGEdgeStart], - defaultYogaStyle.padding()[YGEdgeStart]), + yogaStyle.padding(YGEdgeStart), + defaultYogaStyle.padding(YGEdgeStart)), debugStringConvertibleItem( "paddingEnd", - yogaStyle.padding()[YGEdgeEnd], - defaultYogaStyle.padding()[YGEdgeEnd]), + yogaStyle.padding(YGEdgeEnd), + defaultYogaStyle.padding(YGEdgeEnd)), debugStringConvertibleItem( "paddingHorizontal", - yogaStyle.padding()[YGEdgeHorizontal], - defaultYogaStyle.padding()[YGEdgeHorizontal]), + yogaStyle.padding(YGEdgeHorizontal), + defaultYogaStyle.padding(YGEdgeHorizontal)), debugStringConvertibleItem( "paddingVertical", - yogaStyle.padding()[YGEdgeVertical], - defaultYogaStyle.padding()[YGEdgeVertical]), + yogaStyle.padding(YGEdgeVertical), + defaultYogaStyle.padding(YGEdgeVertical)), debugStringConvertibleItem( "padding", - yogaStyle.padding()[YGEdgeAll], - defaultYogaStyle.padding()[YGEdgeAll]), + yogaStyle.padding(YGEdgeAll), + defaultYogaStyle.padding(YGEdgeAll)), debugStringConvertibleItem( "borderLeftWidth", - yogaStyle.border()[YGEdgeLeft], - defaultYogaStyle.border()[YGEdgeLeft]), + yogaStyle.border(YGEdgeLeft), + defaultYogaStyle.border(YGEdgeLeft)), debugStringConvertibleItem( "borderTopWidth", - yogaStyle.border()[YGEdgeTop], - defaultYogaStyle.border()[YGEdgeTop]), + yogaStyle.border(YGEdgeTop), + defaultYogaStyle.border(YGEdgeTop)), debugStringConvertibleItem( "borderRightWidth", - yogaStyle.border()[YGEdgeRight], - defaultYogaStyle.border()[YGEdgeRight]), + yogaStyle.border(YGEdgeRight), + defaultYogaStyle.border(YGEdgeRight)), debugStringConvertibleItem( "borderBottomWidth", - yogaStyle.border()[YGEdgeBottom], - defaultYogaStyle.border()[YGEdgeBottom]), + yogaStyle.border(YGEdgeBottom), + defaultYogaStyle.border(YGEdgeBottom)), debugStringConvertibleItem( "borderStartWidth", - yogaStyle.border()[YGEdgeStart], - defaultYogaStyle.border()[YGEdgeStart]), + yogaStyle.border(YGEdgeStart), + defaultYogaStyle.border(YGEdgeStart)), debugStringConvertibleItem( "borderEndWidth", - yogaStyle.border()[YGEdgeEnd], - defaultYogaStyle.border()[YGEdgeEnd]), + yogaStyle.border(YGEdgeEnd), + defaultYogaStyle.border(YGEdgeEnd)), debugStringConvertibleItem( "borderHorizontalWidth", - yogaStyle.border()[YGEdgeHorizontal], - defaultYogaStyle.border()[YGEdgeHorizontal]), + yogaStyle.border(YGEdgeHorizontal), + defaultYogaStyle.border(YGEdgeHorizontal)), debugStringConvertibleItem( "borderVerticalWidth", - yogaStyle.border()[YGEdgeVertical], - defaultYogaStyle.border()[YGEdgeVertical]), + yogaStyle.border(YGEdgeVertical), + defaultYogaStyle.border(YGEdgeVertical)), debugStringConvertibleItem( "bordeWidth", - yogaStyle.border()[YGEdgeAll], - defaultYogaStyle.border()[YGEdgeAll]), + yogaStyle.border(YGEdgeAll), + defaultYogaStyle.border(YGEdgeAll)), debugStringConvertibleItem( "width", yogaStyle.dimension(yoga::Dimension::Width), diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/platform/android/react/renderer/components/view/YogaStylablePropsMapBuffer.cpp b/packages/react-native/ReactCommon/react/renderer/components/view/platform/android/react/renderer/components/view/YogaStylablePropsMapBuffer.cpp index 315f8b99eeda4c..f23fccf8913738 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/platform/android/react/renderer/components/view/YogaStylablePropsMapBuffer.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/view/platform/android/react/renderer/components/view/YogaStylablePropsMapBuffer.cpp @@ -16,27 +16,25 @@ namespace facebook::react { MapBuffer convertBorderWidths(const yoga::Style& style) { MapBufferBuilder builder(7); putOptionalFloat( - builder, EDGE_TOP, optionalFloatFromYogaValue(style.border()[YGEdgeTop])); + builder, EDGE_TOP, optionalFloatFromYogaValue(style.border(YGEdgeTop))); putOptionalFloat( builder, EDGE_RIGHT, - optionalFloatFromYogaValue(style.border()[YGEdgeRight])); + optionalFloatFromYogaValue(style.border(YGEdgeRight))); putOptionalFloat( builder, EDGE_BOTTOM, - optionalFloatFromYogaValue(style.border()[YGEdgeBottom])); + optionalFloatFromYogaValue(style.border(YGEdgeBottom))); putOptionalFloat( - builder, - EDGE_LEFT, - optionalFloatFromYogaValue(style.border()[YGEdgeLeft])); + builder, EDGE_LEFT, optionalFloatFromYogaValue(style.border(YGEdgeLeft))); putOptionalFloat( builder, EDGE_START, - optionalFloatFromYogaValue(style.border()[YGEdgeStart])); + optionalFloatFromYogaValue(style.border(YGEdgeStart))); putOptionalFloat( - builder, EDGE_END, optionalFloatFromYogaValue(style.border()[YGEdgeEnd])); + builder, EDGE_END, optionalFloatFromYogaValue(style.border(YGEdgeEnd))); putOptionalFloat( - builder, EDGE_ALL, optionalFloatFromYogaValue(style.border()[YGEdgeAll])); + builder, EDGE_ALL, optionalFloatFromYogaValue(style.border(YGEdgeAll))); return builder.build(); } @@ -64,8 +62,8 @@ void YogaStylableProps::propsDiffMapBuffer( bool areBordersEqual = true; for (auto edge : yoga::ordinals()) { - if (oldStyle.border()[yoga::unscopedEnum(edge)] != - newStyle.border()[yoga::unscopedEnum(edge)]) { + if (oldStyle.border(yoga::unscopedEnum(edge)) != + newStyle.border(yoga::unscopedEnum(edge))) { areBordersEqual = false; break; } diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/propsConversions.h b/packages/react-native/ReactCommon/react/renderer/components/view/propsConversions.h index 3ea67434e58946..13af58193c4289 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/propsConversions.h +++ b/packages/react-native/ReactCommon/react/renderer/components/view/propsConversions.h @@ -99,170 +99,249 @@ static inline yoga::Style convertRawProp( "flexBasis", sourceValue.flexBasis(), yogaStyle.flexBasis()); - yogaStyle.margin()[YGEdgeLeft] = convertRawProp( - context, - rawProps, - "marginLeft", - sourceValue.margin()[YGEdgeLeft], - yogaStyle.margin()[YGEdgeLeft]); - yogaStyle.margin()[YGEdgeTop] = convertRawProp( - context, - rawProps, - "marginTop", - sourceValue.margin()[YGEdgeTop], - yogaStyle.margin()[YGEdgeTop]); - yogaStyle.margin()[YGEdgeRight] = convertRawProp( - context, - rawProps, - "marginRight", - sourceValue.margin()[YGEdgeRight], - yogaStyle.margin()[YGEdgeRight]); - yogaStyle.margin()[YGEdgeBottom] = convertRawProp( - context, - rawProps, - "marginBottom", - sourceValue.margin()[YGEdgeBottom], - yogaStyle.margin()[YGEdgeBottom]); - yogaStyle.margin()[YGEdgeStart] = convertRawProp( - context, - rawProps, - "marginStart", - sourceValue.margin()[YGEdgeStart], - yogaStyle.margin()[YGEdgeStart]); - yogaStyle.margin()[YGEdgeEnd] = convertRawProp( - context, - rawProps, - "marginEnd", - sourceValue.margin()[YGEdgeEnd], - yogaStyle.margin()[YGEdgeEnd]); - yogaStyle.margin()[YGEdgeHorizontal] = convertRawProp( - context, - rawProps, - "marginHorizontal", - sourceValue.margin()[YGEdgeHorizontal], - yogaStyle.margin()[YGEdgeHorizontal]); - yogaStyle.margin()[YGEdgeVertical] = convertRawProp( - context, - rawProps, - "marginVertical", - sourceValue.margin()[YGEdgeVertical], - yogaStyle.margin()[YGEdgeVertical]); - yogaStyle.margin()[YGEdgeAll] = convertRawProp( - context, - rawProps, - "margin", - sourceValue.margin()[YGEdgeAll], - yogaStyle.margin()[YGEdgeAll]); - yogaStyle.position()[YGEdgeLeft] = convertRawProp( - context, - rawProps, - "left", - sourceValue.position()[YGEdgeLeft], - yogaStyle.position()[YGEdgeLeft]); - yogaStyle.position()[YGEdgeTop] = convertRawProp( - context, - rawProps, - "top", - sourceValue.position()[YGEdgeTop], - yogaStyle.position()[YGEdgeTop]); - yogaStyle.position()[YGEdgeRight] = convertRawProp( - context, - rawProps, - "right", - sourceValue.position()[YGEdgeRight], - yogaStyle.position()[YGEdgeRight]); - yogaStyle.position()[YGEdgeBottom] = convertRawProp( - context, - rawProps, - "bottom", - sourceValue.position()[YGEdgeBottom], - yogaStyle.position()[YGEdgeBottom]); - yogaStyle.position()[YGEdgeStart] = convertRawProp( - context, - rawProps, - "start", - sourceValue.position()[YGEdgeStart], - yogaStyle.position()[YGEdgeStart]); - yogaStyle.position()[YGEdgeEnd] = convertRawProp( - context, - rawProps, - "end", - sourceValue.position()[YGEdgeEnd], - yogaStyle.position()[YGEdgeEnd]); - yogaStyle.position()[YGEdgeHorizontal] = convertRawProp( - context, - rawProps, - "insetInline", - sourceValue.position()[YGEdgeHorizontal], - yogaStyle.position()[YGEdgeHorizontal]); + yogaStyle.setMargin( + YGEdgeLeft, + convertRawProp( + context, + rawProps, + "marginLeft", + sourceValue.margin(YGEdgeLeft), + yogaStyle.margin(YGEdgeLeft))); - yogaStyle.position()[YGEdgeVertical] = convertRawProp( - context, - rawProps, - "insetBlock", - sourceValue.position()[YGEdgeVertical], - yogaStyle.position()[YGEdgeVertical]); - yogaStyle.position()[YGEdgeAll] = convertRawProp( - context, - rawProps, - "inset", - sourceValue.position()[YGEdgeAll], - yogaStyle.position()[YGEdgeAll]); - yogaStyle.padding()[YGEdgeLeft] = convertRawProp( - context, - rawProps, - "paddingLeft", - sourceValue.padding()[YGEdgeLeft], - yogaStyle.padding()[YGEdgeLeft]); - yogaStyle.padding()[YGEdgeTop] = convertRawProp( - context, - rawProps, - "paddingTop", - sourceValue.padding()[YGEdgeTop], - yogaStyle.padding()[YGEdgeTop]); - yogaStyle.padding()[YGEdgeRight] = convertRawProp( - context, - rawProps, - "paddingRight", - sourceValue.padding()[YGEdgeRight], - yogaStyle.padding()[YGEdgeRight]); - yogaStyle.padding()[YGEdgeBottom] = convertRawProp( - context, - rawProps, - "paddingBottom", - sourceValue.padding()[YGEdgeBottom], - yogaStyle.padding()[YGEdgeBottom]); - yogaStyle.padding()[YGEdgeStart] = convertRawProp( - context, - rawProps, - "paddingStart", - sourceValue.padding()[YGEdgeStart], - yogaStyle.padding()[YGEdgeStart]); - yogaStyle.padding()[YGEdgeEnd] = convertRawProp( - context, - rawProps, - "paddingEnd", - sourceValue.padding()[YGEdgeEnd], - yogaStyle.padding()[YGEdgeEnd]); - yogaStyle.padding()[YGEdgeHorizontal] = convertRawProp( - context, - rawProps, - "paddingHorizontal", - sourceValue.padding()[YGEdgeHorizontal], - yogaStyle.padding()[YGEdgeHorizontal]); - yogaStyle.padding()[YGEdgeVertical] = convertRawProp( - context, - rawProps, - "paddingVertical", - sourceValue.padding()[YGEdgeVertical], - yogaStyle.padding()[YGEdgeVertical]); - yogaStyle.padding()[YGEdgeAll] = convertRawProp( - context, - rawProps, - "padding", - sourceValue.padding()[YGEdgeAll], - yogaStyle.padding()[YGEdgeAll]); + yogaStyle.setMargin( + YGEdgeTop, + convertRawProp( + context, + rawProps, + "marginTop", + sourceValue.margin(YGEdgeTop), + yogaStyle.margin(YGEdgeTop))); + + yogaStyle.setMargin( + YGEdgeRight, + convertRawProp( + context, + rawProps, + "marginRight", + sourceValue.margin(YGEdgeRight), + yogaStyle.margin(YGEdgeRight))); + + yogaStyle.setMargin( + YGEdgeBottom, + convertRawProp( + context, + rawProps, + "marginBottom", + sourceValue.margin(YGEdgeBottom), + yogaStyle.margin(YGEdgeBottom))); + + yogaStyle.setMargin( + YGEdgeStart, + convertRawProp( + context, + rawProps, + "marginStart", + sourceValue.margin(YGEdgeStart), + yogaStyle.margin(YGEdgeStart))); + + yogaStyle.setMargin( + YGEdgeEnd, + convertRawProp( + context, + rawProps, + "marginEnd", + sourceValue.margin(YGEdgeEnd), + yogaStyle.margin(YGEdgeEnd))); + + yogaStyle.setMargin( + YGEdgeHorizontal, + convertRawProp( + context, + rawProps, + "marginHorizontal", + sourceValue.margin(YGEdgeHorizontal), + yogaStyle.margin(YGEdgeHorizontal))); + + yogaStyle.setMargin( + YGEdgeVertical, + convertRawProp( + context, + rawProps, + "marginVertical", + sourceValue.margin(YGEdgeVertical), + yogaStyle.margin(YGEdgeVertical))); + + yogaStyle.setMargin( + YGEdgeAll, + convertRawProp( + context, + rawProps, + "margin", + sourceValue.margin(YGEdgeAll), + yogaStyle.margin(YGEdgeAll))); + + yogaStyle.setPosition( + YGEdgeLeft, + convertRawProp( + context, + rawProps, + "left", + sourceValue.position(YGEdgeLeft), + yogaStyle.position(YGEdgeLeft))); + + yogaStyle.setPosition( + YGEdgeTop, + convertRawProp( + context, + rawProps, + "top", + sourceValue.position(YGEdgeTop), + yogaStyle.position(YGEdgeTop))); + + yogaStyle.setPosition( + YGEdgeRight, + convertRawProp( + context, + rawProps, + "right", + sourceValue.position(YGEdgeRight), + yogaStyle.position(YGEdgeRight))); + + yogaStyle.setPosition( + YGEdgeBottom, + convertRawProp( + context, + rawProps, + "bottom", + sourceValue.position(YGEdgeBottom), + yogaStyle.position(YGEdgeBottom))); + + yogaStyle.setPosition( + YGEdgeStart, + convertRawProp( + context, + rawProps, + "start", + sourceValue.position(YGEdgeStart), + yogaStyle.position(YGEdgeStart))); + + yogaStyle.setPosition( + YGEdgeEnd, + convertRawProp( + context, + rawProps, + "end", + sourceValue.position(YGEdgeEnd), + yogaStyle.position(YGEdgeEnd))); + + yogaStyle.setPosition( + YGEdgeHorizontal, + convertRawProp( + context, + rawProps, + "insetInline", + sourceValue.position(YGEdgeHorizontal), + yogaStyle.position(YGEdgeHorizontal))); + + yogaStyle.setPosition( + YGEdgeVertical, + convertRawProp( + context, + rawProps, + "insetBlock", + sourceValue.position(YGEdgeVertical), + yogaStyle.position(YGEdgeVertical))); + + yogaStyle.setPosition( + YGEdgeAll, + convertRawProp( + context, + rawProps, + "inset", + sourceValue.position(YGEdgeAll), + yogaStyle.position(YGEdgeAll))); + + yogaStyle.setPadding( + YGEdgeLeft, + convertRawProp( + context, + rawProps, + "paddingLeft", + sourceValue.padding(YGEdgeLeft), + yogaStyle.padding(YGEdgeLeft))); + + yogaStyle.setPadding( + YGEdgeTop, + convertRawProp( + context, + rawProps, + "paddingTop", + sourceValue.padding(YGEdgeTop), + yogaStyle.padding(YGEdgeTop))); + + yogaStyle.setPadding( + YGEdgeRight, + convertRawProp( + context, + rawProps, + "paddingRight", + sourceValue.padding(YGEdgeRight), + yogaStyle.padding(YGEdgeRight))); + + yogaStyle.setPadding( + YGEdgeBottom, + convertRawProp( + context, + rawProps, + "paddingBottom", + sourceValue.padding(YGEdgeBottom), + yogaStyle.padding(YGEdgeBottom))); + + yogaStyle.setPadding( + YGEdgeStart, + convertRawProp( + context, + rawProps, + "paddingStart", + sourceValue.padding(YGEdgeStart), + yogaStyle.padding(YGEdgeStart))); + + yogaStyle.setPadding( + YGEdgeEnd, + convertRawProp( + context, + rawProps, + "paddingEnd", + sourceValue.padding(YGEdgeEnd), + yogaStyle.padding(YGEdgeEnd))); + + yogaStyle.setPadding( + YGEdgeHorizontal, + convertRawProp( + context, + rawProps, + "paddingHorizontal", + sourceValue.padding(YGEdgeHorizontal), + yogaStyle.padding(YGEdgeHorizontal))); + + yogaStyle.setPadding( + YGEdgeVertical, + convertRawProp( + context, + rawProps, + "paddingVertical", + sourceValue.padding(YGEdgeVertical), + yogaStyle.padding(YGEdgeVertical))); + + yogaStyle.setPadding( + YGEdgeAll, + convertRawProp( + context, + rawProps, + "padding", + sourceValue.padding(YGEdgeAll), + yogaStyle.padding(YGEdgeAll))); yogaStyle.setGap( yoga::Gutter::Row, @@ -290,60 +369,87 @@ static inline yoga::Style convertRawProp( "gap", sourceValue.gap(yoga::Gutter::All), yogaStyle.gap(yoga::Gutter::All))); - yogaStyle.border()[YGEdgeLeft] = convertRawProp( - context, - rawProps, - "borderLeftWidth", - sourceValue.border()[YGEdgeLeft], - yogaStyle.border()[YGEdgeLeft]); - yogaStyle.border()[YGEdgeTop] = convertRawProp( - context, - rawProps, - "borderTopWidth", - sourceValue.border()[YGEdgeTop], - yogaStyle.border()[YGEdgeTop]); - yogaStyle.border()[YGEdgeRight] = convertRawProp( - context, - rawProps, - "borderRightWidth", - sourceValue.border()[YGEdgeRight], - yogaStyle.border()[YGEdgeRight]); - yogaStyle.border()[YGEdgeBottom] = convertRawProp( - context, - rawProps, - "borderBottomWidth", - sourceValue.border()[YGEdgeBottom], - yogaStyle.border()[YGEdgeBottom]); - yogaStyle.border()[YGEdgeStart] = convertRawProp( - context, - rawProps, - "borderStartWidth", - sourceValue.border()[YGEdgeStart], - yogaStyle.border()[YGEdgeStart]); - yogaStyle.border()[YGEdgeEnd] = convertRawProp( - context, - rawProps, - "borderEndWidth", - sourceValue.border()[YGEdgeEnd], - yogaStyle.border()[YGEdgeEnd]); - yogaStyle.border()[YGEdgeHorizontal] = convertRawProp( - context, - rawProps, - "borderHorizontalWidth", - sourceValue.border()[YGEdgeHorizontal], - yogaStyle.border()[YGEdgeHorizontal]); - yogaStyle.border()[YGEdgeVertical] = convertRawProp( - context, - rawProps, - "borderVerticalWidth", - sourceValue.border()[YGEdgeVertical], - yogaStyle.border()[YGEdgeVertical]); - yogaStyle.border()[YGEdgeAll] = convertRawProp( - context, - rawProps, - "borderWidth", - sourceValue.border()[YGEdgeAll], - yogaStyle.border()[YGEdgeAll]); + + yogaStyle.setBorder( + YGEdgeLeft, + convertRawProp( + context, + rawProps, + "borderLeftWidth", + sourceValue.border(YGEdgeLeft), + yogaStyle.border(YGEdgeLeft))); + + yogaStyle.setBorder( + YGEdgeTop, + convertRawProp( + context, + rawProps, + "borderTopWidth", + sourceValue.border(YGEdgeTop), + yogaStyle.border(YGEdgeTop))); + + yogaStyle.setBorder( + YGEdgeRight, + convertRawProp( + context, + rawProps, + "borderRightWidth", + sourceValue.border(YGEdgeRight), + yogaStyle.border(YGEdgeRight))); + + yogaStyle.setBorder( + YGEdgeBottom, + convertRawProp( + context, + rawProps, + "borderBottomWidth", + sourceValue.border(YGEdgeBottom), + yogaStyle.border(YGEdgeBottom))); + + yogaStyle.setBorder( + YGEdgeStart, + convertRawProp( + context, + rawProps, + "borderStartWidth", + sourceValue.border(YGEdgeStart), + yogaStyle.border(YGEdgeStart))); + + yogaStyle.setBorder( + YGEdgeEnd, + convertRawProp( + context, + rawProps, + "borderEndWidth", + sourceValue.border(YGEdgeEnd), + yogaStyle.border(YGEdgeEnd))); + + yogaStyle.setBorder( + YGEdgeHorizontal, + convertRawProp( + context, + rawProps, + "borderHorizontalWidth", + sourceValue.border(YGEdgeHorizontal), + yogaStyle.border(YGEdgeHorizontal))); + + yogaStyle.setBorder( + YGEdgeVertical, + convertRawProp( + context, + rawProps, + "borderVerticalWidth", + sourceValue.border(YGEdgeVertical), + yogaStyle.border(YGEdgeVertical))); + + yogaStyle.setBorder( + YGEdgeAll, + convertRawProp( + context, + rawProps, + "borderWidth", + sourceValue.border(YGEdgeAll), + yogaStyle.border(YGEdgeAll))); yogaStyle.setDimension( yoga::Dimension::Width, diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/tests/LayoutTest.cpp b/packages/react-native/ReactCommon/react/renderer/components/view/tests/LayoutTest.cpp index 0e53f62e809bc4..b0be9bc7f1e32d 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/tests/LayoutTest.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/view/tests/LayoutTest.cpp @@ -103,8 +103,8 @@ class LayoutTest : public ::testing::Test { auto &props = *sharedProps; auto &yogaStyle = props.yogaStyle; yogaStyle.positionType() = yoga::PositionType::Absolute; - yogaStyle.position()[YGEdgeLeft] = YGValue{10, YGUnitPoint}; - yogaStyle.position()[YGEdgeTop] = YGValue{10, YGUnitPoint}; + yogaStyle.setPosition(YGEdgeLeft, yoga::CompactValue::of(10)); + yogaStyle.setPosition(YGEdgeTop, yoga::CompactValue::of(10)); yogaStyle.setDimension(yoga::Dimension::Width, yoga::CompactValue::of(30)); yogaStyle.setDimension(yoga::Dimension::Height, yoga::CompactValue::of(90)); @@ -136,8 +136,8 @@ class LayoutTest : public ::testing::Test { } yogaStyle.positionType() = yoga::PositionType::Absolute; - yogaStyle.position()[YGEdgeLeft] = YGValue{10, YGUnitPoint}; - yogaStyle.position()[YGEdgeTop] = YGValue{10, YGUnitPoint}; + yogaStyle.setPosition(YGEdgeLeft, yoga::CompactValue::of(10)); + yogaStyle.setPosition(YGEdgeTop, yoga::CompactValue::of(10)); yogaStyle.setDimension(yoga::Dimension::Width, yoga::CompactValue::of(110)); yogaStyle.setDimension(yoga::Dimension::Height, yoga::CompactValue::of(20)); return sharedProps; @@ -151,8 +151,8 @@ class LayoutTest : public ::testing::Test { auto &props = *sharedProps; auto &yogaStyle = props.yogaStyle; yogaStyle.positionType() = yoga::PositionType::Absolute; - yogaStyle.position()[YGEdgeLeft] = YGValue{70, YGUnitPoint}; - yogaStyle.position()[YGEdgeTop] = YGValue{-50, YGUnitPoint}; + yogaStyle.setPosition(YGEdgeLeft, yoga::CompactValue::of(70)); + yogaStyle.setPosition(YGEdgeTop, yoga::CompactValue::of(-50)); yogaStyle.setDimension(yoga::Dimension::Width, yoga::CompactValue::of(30)); yogaStyle.setDimension(yoga::Dimension::Height, yoga::CompactValue::of(60)); return sharedProps; @@ -166,8 +166,8 @@ class LayoutTest : public ::testing::Test { auto &props = *sharedProps; auto &yogaStyle = props.yogaStyle; yogaStyle.positionType() = yoga::PositionType::Absolute; - yogaStyle.position()[YGEdgeLeft] = YGValue{-60, YGUnitPoint}; - yogaStyle.position()[YGEdgeTop] = YGValue{50, YGUnitPoint}; + yogaStyle.setPosition(YGEdgeLeft, yoga::CompactValue::of(-60)); + yogaStyle.setPosition(YGEdgeTop, yoga::CompactValue::of(50)); yogaStyle.setDimension(yoga::Dimension::Width, yoga::CompactValue::of(70)); yogaStyle.setDimension(yoga::Dimension::Height, yoga::CompactValue::of(20)); return sharedProps; diff --git a/packages/react-native/ReactCommon/react/renderer/mounting/tests/StackingContextTest.cpp b/packages/react-native/ReactCommon/react/renderer/mounting/tests/StackingContextTest.cpp index 262e7e10c2f541..ab06e2f8ccce76 100644 --- a/packages/react-native/ReactCommon/react/renderer/mounting/tests/StackingContextTest.cpp +++ b/packages/react-native/ReactCommon/react/renderer/mounting/tests/StackingContextTest.cpp @@ -251,8 +251,8 @@ TEST_F(StackingContextTest, mostPropsDoNotForceViewsToMaterialize) { mutateViewShadowNodeProps_(nodeAA_, [](ViewProps& props) { auto& yogaStyle = props.yogaStyle; - yogaStyle.padding()[YGEdgeAll] = YGValue{42, YGUnitPoint}; - yogaStyle.margin()[YGEdgeAll] = YGValue{42, YGUnitPoint}; + yogaStyle.setPadding(YGEdgeAll, yoga::CompactValue::of(42)); + yogaStyle.setMargin(YGEdgeAll, yoga::CompactValue::of(42)); yogaStyle.positionType() = yoga::PositionType::Absolute; props.shadowRadius = 42; props.shadowOffset = Size{42, 42}; @@ -262,7 +262,7 @@ TEST_F(StackingContextTest, mostPropsDoNotForceViewsToMaterialize) { mutateViewShadowNodeProps_(nodeBA_, [](ViewProps& props) { auto& yogaStyle = props.yogaStyle; props.zIndex = 42; - yogaStyle.margin()[YGEdgeAll] = YGValue{42, YGUnitPoint}; + yogaStyle.setMargin(YGEdgeAll, yoga::CompactValue::of(42)); props.shadowColor = clearColor(); props.shadowOpacity = 0.42; }); diff --git a/packages/react-native/ReactCommon/yoga/yoga/YGNodeStyle.cpp b/packages/react-native/ReactCommon/yoga/yoga/YGNodeStyle.cpp index 57d352cd01685d..38a55f2c8c8a31 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/YGNodeStyle.cpp +++ b/packages/react-native/ReactCommon/yoga/yoga/YGNodeStyle.cpp @@ -35,19 +35,6 @@ void updateStyle(YGNodeRef node, Ref (Style::*prop)(), T value) { [prop](Style& s, T x) { (s.*prop)() = x; }); } -template -void updateIndexedStyleProp( - YGNodeRef node, - Ref (Style::*prop)(), - Idx idx, - CompactValue value) { - updateStyle( - resolveRef(node), - value, - [idx, prop](Style& s, CompactValue x) { return (s.*prop)()[idx] != x; }, - [idx, prop](Style& s, CompactValue x) { (s.*prop)()[idx] = x; }); -} - template void updateIndexedStyleProp(YGNodeRef node, IdxT idx, CompactValue value) { updateStyle( @@ -237,53 +224,53 @@ YGValue YGNodeStyleGetFlexBasis(const YGNodeConstRef node) { void YGNodeStyleSetPosition(YGNodeRef node, YGEdge edge, float points) { auto value = CompactValue::ofMaybe(points); - updateIndexedStyleProp( - node, &Style::position, edge, value); + updateIndexedStyleProp<&Style::position, &Style::setPosition>( + node, edge, value); } void YGNodeStyleSetPositionPercent(YGNodeRef node, YGEdge edge, float percent) { auto value = CompactValue::ofMaybe(percent); - updateIndexedStyleProp( - node, &Style::position, edge, value); + updateIndexedStyleProp<&Style::position, &Style::setPosition>( + node, edge, value); } YGValue YGNodeStyleGetPosition(YGNodeConstRef node, YGEdge edge) { - return resolveRef(node)->getStyle().position()[edge]; + return resolveRef(node)->getStyle().position(edge); } void YGNodeStyleSetMargin(YGNodeRef node, YGEdge edge, float points) { auto value = CompactValue::ofMaybe(points); - updateIndexedStyleProp(node, &Style::margin, edge, value); + updateIndexedStyleProp<&Style::margin, &Style::setMargin>(node, edge, value); } void YGNodeStyleSetMarginPercent(YGNodeRef node, YGEdge edge, float percent) { auto value = CompactValue::ofMaybe(percent); - updateIndexedStyleProp(node, &Style::margin, edge, value); + updateIndexedStyleProp<&Style::margin, &Style::setMargin>(node, edge, value); } void YGNodeStyleSetMarginAuto(YGNodeRef node, YGEdge edge) { - updateIndexedStyleProp( - node, &Style::margin, edge, CompactValue::ofAuto()); + updateIndexedStyleProp<&Style::margin, &Style::setMargin>( + node, edge, CompactValue::ofAuto()); } YGValue YGNodeStyleGetMargin(YGNodeConstRef node, YGEdge edge) { - return resolveRef(node)->getStyle().margin()[edge]; + return resolveRef(node)->getStyle().margin(edge); } void YGNodeStyleSetPadding(YGNodeRef node, YGEdge edge, float points) { auto value = CompactValue::ofMaybe(points); - updateIndexedStyleProp( - node, &Style::padding, edge, value); + updateIndexedStyleProp<&Style::padding, &Style::setPadding>( + node, edge, value); } void YGNodeStyleSetPaddingPercent(YGNodeRef node, YGEdge edge, float percent) { auto value = CompactValue::ofMaybe(percent); - updateIndexedStyleProp( - node, &Style::padding, edge, value); + updateIndexedStyleProp<&Style::padding, &Style::setPadding>( + node, edge, value); } YGValue YGNodeStyleGetPadding(YGNodeConstRef node, YGEdge edge) { - return resolveRef(node)->getStyle().padding()[edge]; + return resolveRef(node)->getStyle().padding(edge); } void YGNodeStyleSetBorder( @@ -291,11 +278,11 @@ void YGNodeStyleSetBorder( const YGEdge edge, const float border) { auto value = CompactValue::ofMaybe(border); - updateIndexedStyleProp(node, &Style::border, edge, value); + updateIndexedStyleProp<&Style::border, &Style::setBorder>(node, edge, value); } float YGNodeStyleGetBorder(const YGNodeConstRef node, const YGEdge edge) { - auto border = resolveRef(node)->getStyle().border()[edge]; + auto border = resolveRef(node)->getStyle().border(edge); if (border.isUndefined() || border.isAuto()) { return YGUndefined; } diff --git a/packages/react-native/ReactCommon/yoga/yoga/algorithm/FlexDirection.h b/packages/react-native/ReactCommon/yoga/yoga/algorithm/FlexDirection.h index 3770783b7e7d71..a8ee7586aeb849 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/algorithm/FlexDirection.h +++ b/packages/react-native/ReactCommon/yoga/yoga/algorithm/FlexDirection.h @@ -11,6 +11,7 @@ #include #include +#include #include namespace facebook::yoga { diff --git a/packages/react-native/ReactCommon/yoga/yoga/debug/NodeToString.cpp b/packages/react-native/ReactCommon/yoga/yoga/debug/NodeToString.cpp index a2bf467bede115..ef55ea1d215e9d 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/debug/NodeToString.cpp +++ b/packages/react-native/ReactCommon/yoga/yoga/debug/NodeToString.cpp @@ -23,12 +23,6 @@ static void indent(std::string& base, uint32_t level) { } } -static bool areFourValuesEqual(const Style::Edges& four) { - return yoga::inexactEquals(four[0], four[1]) && - yoga::inexactEquals(four[0], four[2]) && - yoga::inexactEquals(four[0], four[3]); -} - static void appendFormattedString(std::string& str, const char* fmt, ...) { va_list args; va_start(args, fmt); @@ -86,33 +80,15 @@ static void appendNumberIfNotZero( } } -static void appendEdges( - std::string& base, - const std::string& key, - const Style::Edges& edges) { - if (areFourValuesEqual(edges)) { - auto edgeValue = yoga::Node::computeEdgeValueForColumn(edges, YGEdgeLeft); - appendNumberIfNotUndefined(base, key, edgeValue); - } else { - for (int edge = YGEdgeLeft; edge != YGEdgeAll; ++edge) { - std::string str = key + "-" + YGEdgeToString(static_cast(edge)); - appendNumberIfNotZero(base, str, edges[static_cast(edge)]); - } +template +static void +appendEdges(std::string& base, const std::string& key, const Style& style) { + for (auto edge : ordinals()) { + std::string str = key + "-" + toString(edge); + appendNumberIfNotZero(base, str, (style.*Field)(unscopedEnum(edge))); } } -static void appendEdgeIfNotUndefined( - std::string& base, - const std::string& str, - const Style::Edges& edges, - const YGEdge edge) { - // TODO: this doesn't take RTL / YGEdgeStart / YGEdgeEnd into account - auto value = (edge == YGEdgeLeft || edge == YGEdgeRight) - ? yoga::Node::computeEdgeValueForRow(edges, edge, edge) - : yoga::Node::computeEdgeValueForColumn(edges, edge); - appendNumberIfNotUndefined(base, str, value); -} - void nodeToString( std::string& str, const yoga::Node* node, @@ -173,9 +149,9 @@ void nodeToString( if (style.display() != yoga::Node{}.getStyle().display()) { appendFormattedString(str, "display: %s; ", toString(style.display())); } - appendEdges(str, "margin", style.margin()); - appendEdges(str, "padding", style.padding()); - appendEdges(str, "border", style.border()); + appendEdges<&Style::margin>(str, "margin", style); + appendEdges<&Style::padding>(str, "padding", style); + appendEdges<&Style::border>(str, "border", style); if (style.gap(Gutter::All).isDefined()) { appendNumberIfNotUndefined(str, "gap", style.gap(Gutter::All)); @@ -200,10 +176,7 @@ void nodeToString( str, "position: %s; ", toString(style.positionType())); } - appendEdgeIfNotUndefined(str, "left", style.position(), YGEdgeLeft); - appendEdgeIfNotUndefined(str, "right", style.position(), YGEdgeRight); - appendEdgeIfNotUndefined(str, "top", style.position(), YGEdgeTop); - appendEdgeIfNotUndefined(str, "bottom", style.position(), YGEdgeBottom); + appendEdges<&Style::position>(str, "position", style); appendFormattedString(str, "\" "); if (node->hasMeasureFunc()) { diff --git a/packages/react-native/ReactCommon/yoga/yoga/node/Node.cpp b/packages/react-native/ReactCommon/yoga/yoga/node/Node.cpp index e69c96f5aeddee..e5100ee2815137 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/node/Node.cpp +++ b/packages/react-native/ReactCommon/yoga/yoga/node/Node.cpp @@ -56,30 +56,29 @@ void Node::print() { } } -CompactValue Node::computeEdgeValueForRow( - const Style::Edges& edges, - YGEdge rowEdge, - YGEdge edge) { - if (edges[rowEdge].isDefined()) { - return edges[rowEdge]; - } else if (edges[edge].isDefined()) { - return edges[edge]; - } else if (edges[YGEdgeHorizontal].isDefined()) { - return edges[YGEdgeHorizontal]; +// TODO: Edge value resolution should be moved to `yoga::Style` +template +CompactValue Node::computeEdgeValueForRow(YGEdge rowEdge, YGEdge edge) const { + if ((style_.*Field)(rowEdge).isDefined()) { + return (style_.*Field)(rowEdge); + } else if ((style_.*Field)(edge).isDefined()) { + return (style_.*Field)(edge); + } else if ((style_.*Field)(YGEdgeHorizontal).isDefined()) { + return (style_.*Field)(YGEdgeHorizontal); } else { - return edges[YGEdgeAll]; + return (style_.*Field)(YGEdgeAll); } } -CompactValue Node::computeEdgeValueForColumn( - const Style::Edges& edges, - YGEdge edge) { - if (edges[edge].isDefined()) { - return edges[edge]; - } else if (edges[YGEdgeVertical].isDefined()) { - return edges[YGEdgeVertical]; +// TODO: Edge value resolution should be moved to `yoga::Style` +template +CompactValue Node::computeEdgeValueForColumn(YGEdge edge) const { + if ((style_.*Field)(edge).isDefined()) { + return (style_.*Field)(edge); + } else if ((style_.*Field)(YGEdgeVertical).isDefined()) { + return (style_.*Field)(YGEdgeVertical); } else { - return edges[YGEdgeAll]; + return (style_.*Field)(YGEdgeAll); } } @@ -102,8 +101,8 @@ YGEdge Node::getInlineEndEdgeUsingErrata( bool Node::isFlexStartPositionDefined(FlexDirection axis) const { const YGEdge startEdge = flexStartEdge(axis); auto leadingPosition = isRow(axis) - ? computeEdgeValueForRow(style_.position(), YGEdgeStart, startEdge) - : computeEdgeValueForColumn(style_.position(), startEdge); + ? computeEdgeValueForRow<&Style::position>(YGEdgeStart, startEdge) + : computeEdgeValueForColumn<&Style::position>(startEdge); return leadingPosition.isDefined(); } @@ -112,8 +111,8 @@ bool Node::isInlineStartPositionDefined(FlexDirection axis, Direction direction) const { const YGEdge startEdge = getInlineStartEdgeUsingErrata(axis, direction); auto leadingPosition = isRow(axis) - ? computeEdgeValueForRow(style_.position(), YGEdgeStart, startEdge) - : computeEdgeValueForColumn(style_.position(), startEdge); + ? computeEdgeValueForRow<&Style::position>(YGEdgeStart, startEdge) + : computeEdgeValueForColumn<&Style::position>(startEdge); return leadingPosition.isDefined(); } @@ -121,8 +120,8 @@ bool Node::isInlineStartPositionDefined(FlexDirection axis, Direction direction) bool Node::isFlexEndPositionDefined(FlexDirection axis) const { const YGEdge endEdge = flexEndEdge(axis); auto trailingPosition = isRow(axis) - ? computeEdgeValueForRow(style_.position(), YGEdgeEnd, endEdge) - : computeEdgeValueForColumn(style_.position(), endEdge); + ? computeEdgeValueForRow<&Style::position>(YGEdgeEnd, endEdge) + : computeEdgeValueForColumn<&Style::position>(endEdge); return !trailingPosition.isUndefined(); } @@ -131,8 +130,8 @@ bool Node::isInlineEndPositionDefined(FlexDirection axis, Direction direction) const { const YGEdge endEdge = getInlineEndEdgeUsingErrata(axis, direction); auto trailingPosition = isRow(axis) - ? computeEdgeValueForRow(style_.position(), YGEdgeEnd, endEdge) - : computeEdgeValueForColumn(style_.position(), endEdge); + ? computeEdgeValueForRow<&Style::position>(YGEdgeEnd, endEdge) + : computeEdgeValueForColumn<&Style::position>(endEdge); return trailingPosition.isDefined(); } @@ -140,8 +139,8 @@ bool Node::isInlineEndPositionDefined(FlexDirection axis, Direction direction) float Node::getFlexStartPosition(FlexDirection axis, float axisSize) const { const YGEdge startEdge = flexStartEdge(axis); auto leadingPosition = isRow(axis) - ? computeEdgeValueForRow(style_.position(), YGEdgeStart, startEdge) - : computeEdgeValueForColumn(style_.position(), startEdge); + ? computeEdgeValueForRow<&Style::position>(YGEdgeStart, startEdge) + : computeEdgeValueForColumn<&Style::position>(startEdge); return resolveValue(leadingPosition, axisSize).unwrapOrDefault(0.0f); } @@ -152,8 +151,8 @@ float Node::getInlineStartPosition( float axisSize) const { const YGEdge startEdge = getInlineStartEdgeUsingErrata(axis, direction); auto leadingPosition = isRow(axis) - ? computeEdgeValueForRow(style_.position(), YGEdgeStart, startEdge) - : computeEdgeValueForColumn(style_.position(), startEdge); + ? computeEdgeValueForRow<&Style::position>(YGEdgeStart, startEdge) + : computeEdgeValueForColumn<&Style::position>(startEdge); return resolveValue(leadingPosition, axisSize).unwrapOrDefault(0.0f); } @@ -161,8 +160,8 @@ float Node::getInlineStartPosition( float Node::getFlexEndPosition(FlexDirection axis, float axisSize) const { const YGEdge endEdge = flexEndEdge(axis); auto trailingPosition = isRow(axis) - ? computeEdgeValueForRow(style_.position(), YGEdgeEnd, endEdge) - : computeEdgeValueForColumn(style_.position(), endEdge); + ? computeEdgeValueForRow<&Style::position>(YGEdgeEnd, endEdge) + : computeEdgeValueForColumn<&Style::position>(endEdge); return resolveValue(trailingPosition, axisSize).unwrapOrDefault(0.0f); } @@ -173,8 +172,8 @@ float Node::getInlineEndPosition( float axisSize) const { const YGEdge endEdge = getInlineEndEdgeUsingErrata(axis, direction); auto trailingPosition = isRow(axis) - ? computeEdgeValueForRow(style_.position(), YGEdgeEnd, endEdge) - : computeEdgeValueForColumn(style_.position(), endEdge); + ? computeEdgeValueForRow<&Style::position>(YGEdgeEnd, endEdge) + : computeEdgeValueForColumn<&Style::position>(endEdge); return resolveValue(trailingPosition, axisSize).unwrapOrDefault(0.0f); } @@ -182,8 +181,8 @@ float Node::getInlineEndPosition( float Node::getFlexStartMargin(FlexDirection axis, float widthSize) const { const YGEdge startEdge = flexStartEdge(axis); auto leadingMargin = isRow(axis) - ? computeEdgeValueForRow(style_.margin(), YGEdgeStart, startEdge) - : computeEdgeValueForColumn(style_.margin(), startEdge); + ? computeEdgeValueForRow<&Style::margin>(YGEdgeStart, startEdge) + : computeEdgeValueForColumn<&Style::margin>(startEdge); return resolveValue(leadingMargin, widthSize).unwrapOrDefault(0.0f); } @@ -194,8 +193,8 @@ float Node::getInlineStartMargin( float widthSize) const { const YGEdge startEdge = getInlineStartEdgeUsingErrata(axis, direction); auto leadingMargin = isRow(axis) - ? computeEdgeValueForRow(style_.margin(), YGEdgeStart, startEdge) - : computeEdgeValueForColumn(style_.margin(), startEdge); + ? computeEdgeValueForRow<&Style::margin>(YGEdgeStart, startEdge) + : computeEdgeValueForColumn<&Style::margin>(startEdge); return resolveValue(leadingMargin, widthSize).unwrapOrDefault(0.0f); } @@ -203,8 +202,8 @@ float Node::getInlineStartMargin( float Node::getFlexEndMargin(FlexDirection axis, float widthSize) const { const YGEdge endEdge = flexEndEdge(axis); auto trailingMargin = isRow(axis) - ? computeEdgeValueForRow(style_.margin(), YGEdgeEnd, endEdge) - : computeEdgeValueForColumn(style_.margin(), endEdge); + ? computeEdgeValueForRow<&Style::margin>(YGEdgeEnd, endEdge) + : computeEdgeValueForColumn<&Style::margin>(endEdge); return resolveValue(trailingMargin, widthSize).unwrapOrDefault(0.0f); } @@ -215,8 +214,8 @@ float Node::getInlineEndMargin( float widthSize) const { const YGEdge endEdge = getInlineEndEdgeUsingErrata(axis, direction); auto trailingMargin = isRow(axis) - ? computeEdgeValueForRow(style_.margin(), YGEdgeEnd, endEdge) - : computeEdgeValueForColumn(style_.margin(), endEdge); + ? computeEdgeValueForRow<&Style::margin>(YGEdgeEnd, endEdge) + : computeEdgeValueForColumn<&Style::margin>(endEdge); return resolveValue(trailingMargin, widthSize).unwrapOrDefault(0.0f); } @@ -225,8 +224,8 @@ float Node::getInlineStartBorder(FlexDirection axis, Direction direction) const { const YGEdge startEdge = getInlineStartEdgeUsingErrata(axis, direction); YGValue leadingBorder = isRow(axis) - ? computeEdgeValueForRow(style_.border(), YGEdgeStart, startEdge) - : computeEdgeValueForColumn(style_.border(), startEdge); + ? computeEdgeValueForRow<&Style::border>(YGEdgeStart, startEdge) + : computeEdgeValueForColumn<&Style::border>(startEdge); return maxOrDefined(leadingBorder.value, 0.0f); } @@ -235,9 +234,9 @@ float Node::getFlexStartBorder(FlexDirection axis, Direction direction) const { const YGEdge leadRelativeFlexItemEdge = flexStartRelativeEdge(axis, direction); YGValue leadingBorder = isRow(axis) - ? computeEdgeValueForRow( - style_.border(), leadRelativeFlexItemEdge, flexStartEdge(axis)) - : computeEdgeValueForColumn(style_.border(), flexStartEdge(axis)); + ? computeEdgeValueForRow<&Style::border>( + leadRelativeFlexItemEdge, flexStartEdge(axis)) + : computeEdgeValueForColumn<&Style::border>(flexStartEdge(axis)); return maxOrDefined(leadingBorder.value, 0.0f); } @@ -245,8 +244,8 @@ float Node::getFlexStartBorder(FlexDirection axis, Direction direction) const { float Node::getInlineEndBorder(FlexDirection axis, Direction direction) const { const YGEdge endEdge = getInlineEndEdgeUsingErrata(axis, direction); YGValue trailingBorder = isRow(axis) - ? computeEdgeValueForRow(style_.border(), YGEdgeEnd, endEdge) - : computeEdgeValueForColumn(style_.border(), endEdge); + ? computeEdgeValueForRow<&Style::border>(YGEdgeEnd, endEdge) + : computeEdgeValueForColumn<&Style::border>(endEdge); return maxOrDefined(trailingBorder.value, 0.0f); } @@ -254,9 +253,9 @@ float Node::getInlineEndBorder(FlexDirection axis, Direction direction) const { float Node::getFlexEndBorder(FlexDirection axis, Direction direction) const { const YGEdge trailRelativeFlexItemEdge = flexEndRelativeEdge(axis, direction); YGValue trailingBorder = isRow(axis) - ? computeEdgeValueForRow( - style_.border(), trailRelativeFlexItemEdge, flexEndEdge(axis)) - : computeEdgeValueForColumn(style_.border(), flexEndEdge(axis)); + ? computeEdgeValueForRow<&Style::border>( + trailRelativeFlexItemEdge, flexEndEdge(axis)) + : computeEdgeValueForColumn<&Style::border>(flexEndEdge(axis)); return maxOrDefined(trailingBorder.value, 0.0f); } @@ -267,8 +266,8 @@ float Node::getInlineStartPadding( float widthSize) const { const YGEdge startEdge = getInlineStartEdgeUsingErrata(axis, direction); auto leadingPadding = isRow(axis) - ? computeEdgeValueForRow(style_.padding(), YGEdgeStart, startEdge) - : computeEdgeValueForColumn(style_.padding(), startEdge); + ? computeEdgeValueForRow<&Style::padding>(YGEdgeStart, startEdge) + : computeEdgeValueForColumn<&Style::padding>(startEdge); return maxOrDefined(resolveValue(leadingPadding, widthSize).unwrap(), 0.0f); } @@ -280,9 +279,9 @@ float Node::getFlexStartPadding( const YGEdge leadRelativeFlexItemEdge = flexStartRelativeEdge(axis, direction); auto leadingPadding = isRow(axis) - ? computeEdgeValueForRow( - style_.padding(), leadRelativeFlexItemEdge, flexStartEdge(axis)) - : computeEdgeValueForColumn(style_.padding(), flexStartEdge(axis)); + ? computeEdgeValueForRow<&Style::padding>( + leadRelativeFlexItemEdge, flexStartEdge(axis)) + : computeEdgeValueForColumn<&Style::padding>(flexStartEdge(axis)); return maxOrDefined(resolveValue(leadingPadding, widthSize).unwrap(), 0.0f); } @@ -293,8 +292,8 @@ float Node::getInlineEndPadding( float widthSize) const { const YGEdge endEdge = getInlineEndEdgeUsingErrata(axis, direction); auto trailingPadding = isRow(axis) - ? computeEdgeValueForRow(style_.padding(), YGEdgeEnd, endEdge) - : computeEdgeValueForColumn(style_.padding(), endEdge); + ? computeEdgeValueForRow<&Style::padding>(YGEdgeEnd, endEdge) + : computeEdgeValueForColumn<&Style::padding>(endEdge); return maxOrDefined(resolveValue(trailingPadding, widthSize).unwrap(), 0.0f); } @@ -305,9 +304,9 @@ float Node::getFlexEndPadding( float widthSize) const { const YGEdge trailRelativeFlexItemEdge = flexEndRelativeEdge(axis, direction); auto trailingPadding = isRow(axis) - ? computeEdgeValueForRow( - style_.padding(), trailRelativeFlexItemEdge, flexEndEdge(axis)) - : computeEdgeValueForColumn(style_.padding(), flexEndEdge(axis)); + ? computeEdgeValueForRow<&Style::padding>( + trailRelativeFlexItemEdge, flexEndEdge(axis)) + : computeEdgeValueForColumn<&Style::padding>(flexEndEdge(axis)); return maxOrDefined(resolveValue(trailingPadding, widthSize).unwrap(), 0.0f); } @@ -565,18 +564,18 @@ void Node::setPosition( } YGValue Node::getFlexStartMarginValue(FlexDirection axis) const { - if (isRow(axis) && style_.margin()[YGEdgeStart].isDefined()) { - return style_.margin()[YGEdgeStart]; + if (isRow(axis) && style_.margin(YGEdgeStart).isDefined()) { + return style_.margin(YGEdgeStart); } else { - return style_.margin()[flexStartEdge(axis)]; + return style_.margin(flexStartEdge(axis)); } } YGValue Node::marginTrailingValue(FlexDirection axis) const { - if (isRow(axis) && style_.margin()[YGEdgeEnd].isDefined()) { - return style_.margin()[YGEdgeEnd]; + if (isRow(axis) && style_.margin(YGEdgeEnd).isDefined()) { + return style_.margin(YGEdgeEnd); } else { - return style_.margin()[flexEndEdge(axis)]; + return style_.margin(flexEndEdge(axis)); } } diff --git a/packages/react-native/ReactCommon/yoga/yoga/node/Node.h b/packages/react-native/ReactCommon/yoga/yoga/node/Node.h index 601e153fea8a99..9fefcf15aa0b99 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/node/Node.h +++ b/packages/react-native/ReactCommon/yoga/yoga/node/Node.h @@ -65,6 +65,12 @@ class YG_EXPORT Node : public ::YGNode { style_.alignContent() = Align::Stretch; } + template + CompactValue computeEdgeValueForColumn(YGEdge edge) const; + + template + CompactValue computeEdgeValueForRow(YGEdge rowEdge, YGEdge edge) const; + // DANGER DANGER DANGER! // If the node assigned to has children, we'd either have to deallocate // them (potentially incorrect) or ignore them (danger of leaks). Only ever @@ -189,15 +195,6 @@ class YG_EXPORT Node : public ::YGNode { return resolvedDimensions_[static_cast(dimension)]; } - static CompactValue computeEdgeValueForColumn( - const Style::Edges& edges, - YGEdge edge); - - static CompactValue computeEdgeValueForRow( - const Style::Edges& edges, - YGEdge rowEdge, - YGEdge edge); - // Methods related to positions, margin, padding and border bool isFlexStartPositionDefined(FlexDirection axis) const; bool isInlineStartPositionDefined(FlexDirection axis, Direction direction) diff --git a/packages/react-native/ReactCommon/yoga/yoga/style/Style.h b/packages/react-native/ReactCommon/yoga/yoga/style/Style.h index 2df44a75ab7c89..d7dbf2f1886b05 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/style/Style.h +++ b/packages/react-native/ReactCommon/yoga/yoga/style/Style.h @@ -35,11 +35,11 @@ class YG_EXPORT Style { template using Values = std::array()>; - public: using Dimensions = Values; using Edges = Values; using Gutters = Values; + public: static constexpr float DefaultFlexGrow = 0.0f; static constexpr float DefaultFlexShrink = 0.0f; static constexpr float WebDefaultFlexShrink = 1.0f; @@ -69,39 +69,6 @@ class YG_EXPORT Style { } }; - template Style::*Prop> - struct IdxRef { - struct Ref { - Style& style; - Idx idx; - operator CompactValue() const { - return (style.*Prop)[idx]; - } - operator YGValue() const { - return (style.*Prop)[idx]; - } - Ref& operator=(CompactValue value) { - (style.*Prop)[idx] = value; - return *this; - } - }; - - Style& style; - IdxRef& operator=(const Values& values) { - style.*Prop = values; - return *this; - } - operator const Values&() const { - return style.*Prop; - } - Ref operator[](Idx idx) { - return {style, idx}; - } - CompactValue operator[](Idx idx) const { - return (style.*Prop)[idx]; - } - }; - Style() { alignContent() = Align::FlexStart; alignItems() = Align::Stretch; @@ -147,9 +114,6 @@ class YG_EXPORT Style { FloatOptional aspectRatio_ = {}; public: - // for library users needing a type - using ValueRepr = std::remove_reference::type; - Direction direction() const { return getEnumData(flags, directionOffset); } @@ -248,32 +212,32 @@ class YG_EXPORT Style { return {*this}; } - const Edges& margin() const { - return margin_; + CompactValue margin(YGEdge edge) const { + return margin_[edge]; } - IdxRef margin() { - return {*this}; + void setMargin(YGEdge edge, CompactValue value) { + margin_[edge] = value; } - const Edges& position() const { - return position_; + CompactValue position(YGEdge edge) const { + return position_[edge]; } - IdxRef position() { - return {*this}; + void setPosition(YGEdge edge, CompactValue value) { + position_[edge] = value; } - const Edges& padding() const { - return padding_; + CompactValue padding(YGEdge edge) const { + return padding_[edge]; } - IdxRef padding() { - return {*this}; + void setPadding(YGEdge edge, CompactValue value) { + padding_[edge] = value; } - const Edges& border() const { - return border_; + CompactValue border(YGEdge edge) const { + return border_[edge]; } - IdxRef border() { - return {*this}; + void setBorder(YGEdge edge, CompactValue value) { + border_[edge] = value; } CompactValue gap(Gutter gutter) const { From 1e68e48534aedf1533327bf65f26e5cf5b80127b Mon Sep 17 00:00:00 2001 From: Jakub Grzywacz Date: Thu, 23 Nov 2023 05:34:24 -0800 Subject: [PATCH 075/162] feat: selectionHandleColor prop on Android (#41092) Summary: This PR addresses the problem raised in the https://github.com/facebook/react-native/issues/41004 issue. The current logic is that `selectionColor` on iOS sets the color of the selection, handles, and cursor. On Android it looks similar, while it doesn't change the color of the handles if the API level is higher than 27. In addition, on Android there was an option to set the color of the cursor by `cursorColor` prop, but it didn't work if the `selectionCursor` was set. ## Changelog: [GENERAL] [ADDED] - Make same behavior of the `selectionColor` prop on Android as iOS [ANDROID] [ADDED] - Introduced `selectionHandleColor` as a separate prop [ANDROID] [CHANGED] - Allowing `cursorColor` and `selectionHandleColor` to override `selectionColor` on Android Pull Request resolved: https://github.com/facebook/react-native/pull/41092 Test Plan: Manual tests in rn-tester: ### `selectionColor` same as iOS, sets selection, handles and cursor color _There is a way to set only "rectangle" color by setting other props as null_ ![image](https://github.com/facebook/react-native/assets/39670088/9cba34c2-c9fc-4d84-a9cb-3b28a754671d) ### `selectionHandleColor` ![image](https://github.com/facebook/react-native/assets/39670088/8a7e488e-0e35-4646-9efe-4783420b41fa) ### `cursorColor` ![image](https://github.com/facebook/react-native/assets/39670088/06798b8a-851f-44c7-979e-a4e74681b29a) Reviewed By: NickGerleman Differential Revision: D51253298 Pulled By: javache fbshipit-source-id: 290284aa38c6ba0aa6998b937258788ce6376431 --- .../AndroidTextInputNativeComponent.js | 8 ++ .../Components/TextInput/TextInput.d.ts | 8 ++ .../Components/TextInput/TextInput.flow.js | 8 ++ .../Components/TextInput/TextInput.js | 20 ++- .../textinput/ReactTextInputManager.java | 131 ++++++++++++------ .../AndroidTextInputProps.cpp | 6 + .../androidtextinput/AndroidTextInputProps.h | 1 + .../iostextinput/TextInputProps.cpp | 6 + .../components/iostextinput/TextInputProps.h | 1 + .../TextInput/TextInputExample.android.js | 16 ++- 10 files changed, 161 insertions(+), 44 deletions(-) diff --git a/packages/react-native/Libraries/Components/TextInput/AndroidTextInputNativeComponent.js b/packages/react-native/Libraries/Components/TextInput/AndroidTextInputNativeComponent.js index 55b770d26a35ef..f5d06e24595213 100644 --- a/packages/react-native/Libraries/Components/TextInput/AndroidTextInputNativeComponent.js +++ b/packages/react-native/Libraries/Components/TextInput/AndroidTextInputNativeComponent.js @@ -485,6 +485,11 @@ export type NativeProps = $ReadOnly<{| */ selectionColor?: ?ColorValue, + /** + * The text selection handle color. + */ + selectionHandleColor?: ?ColorValue, + /** * The start and end of the text input's selection. Set start and end to * the same value to position the cursor. @@ -692,6 +697,9 @@ export const __INTERNAL_VIEW_CONFIG: PartialViewConfig = { fontStyle: true, textShadowOffset: true, selectionColor: {process: require('../../StyleSheet/processColor').default}, + selectionHandleColor: { + process: require('../../StyleSheet/processColor').default, + }, placeholderTextColor: { process: require('../../StyleSheet/processColor').default, }, diff --git a/packages/react-native/Libraries/Components/TextInput/TextInput.d.ts b/packages/react-native/Libraries/Components/TextInput/TextInput.d.ts index 80db8f0a652225..7234cbb3c325c5 100644 --- a/packages/react-native/Libraries/Components/TextInput/TextInput.d.ts +++ b/packages/react-native/Libraries/Components/TextInput/TextInput.d.ts @@ -336,6 +336,14 @@ export interface TextInputAndroidProps { */ cursorColor?: ColorValue | null | undefined; + /** + * When provided it will set the color of the selection handles when highlighting text. + * Unlike the behavior of `selectionColor` the handle color will be set independently + * from the color of the text selection box. + * @platform android + */ + selectionHandleColor?: ColorValue | null | undefined; + /** * Determines whether the individual fields in your app should be included in a * view structure for autofill purposes on Android API Level 26+. Defaults to auto. diff --git a/packages/react-native/Libraries/Components/TextInput/TextInput.flow.js b/packages/react-native/Libraries/Components/TextInput/TextInput.flow.js index 0eb8f578d65879..638acd7c7925a2 100644 --- a/packages/react-native/Libraries/Components/TextInput/TextInput.flow.js +++ b/packages/react-native/Libraries/Components/TextInput/TextInput.flow.js @@ -332,6 +332,14 @@ type AndroidProps = $ReadOnly<{| */ cursorColor?: ?ColorValue, + /** + * When provided it will set the color of the selection handles when highlighting text. + * Unlike the behavior of `selectionColor` the handle color will be set independently + * from the color of the text selection box. + * @platform android + */ + selectionHandleColor?: ?ColorValue, + /** * When `false`, if there is a small amount of space available around a text input * (e.g. landscape orientation on a phone), the OS may choose to have the user edit diff --git a/packages/react-native/Libraries/Components/TextInput/TextInput.js b/packages/react-native/Libraries/Components/TextInput/TextInput.js index 3e0d8bf7681dd3..0162f2bb007b02 100644 --- a/packages/react-native/Libraries/Components/TextInput/TextInput.js +++ b/packages/react-native/Libraries/Components/TextInput/TextInput.js @@ -917,6 +917,12 @@ export type Props = $ReadOnly<{| */ selectionColor?: ?ColorValue, + /** + * The text selection handle color. + * @platform android + */ + selectionHandleColor?: ?ColorValue, + /** * If `true`, all text will automatically be selected on focus. */ @@ -1111,6 +1117,9 @@ function InternalTextInput(props: Props): React.Node { id, tabIndex, selection: propsSelection, + selectionColor, + selectionHandleColor, + cursorColor, ...otherProps } = props; @@ -1506,7 +1515,15 @@ function InternalTextInput(props: Props): React.Node { if (childCount > 1) { children = {children}; } - + // For consistency with iOS set cursor/selectionHandle color as selectionColor + const colorProps = { + selectionColor, + selectionHandleColor: + selectionHandleColor === undefined + ? selectionColor + : selectionHandleColor, + cursorColor: cursorColor === undefined ? selectionColor : cursorColor, + }; textInput = ( /* $FlowFixMe[prop-missing] the types for AndroidTextInput don't match up * exactly with the props for TextInput. This will need to get fixed */ @@ -1520,6 +1537,7 @@ function InternalTextInput(props: Props): React.Node { // $FlowFixMe[incompatible-type] - Figure out imperative + forward refs. ref={ref} {...otherProps} + {...colorProps} {...eventHandlers} accessibilityState={_accessibilityState} accessibilityLabelledBy={_accessibilityLabelledBy} diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java index 8496a7d059e4c8..0816eeb102e4f4 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java @@ -168,14 +168,11 @@ public class ReactTextInputManager extends BaseViewManager= Build.VERSION_CODES.Q) { - Drawable cursorDrawable = view.getTextCursorDrawable(); - if (cursorDrawable != null) { - cursorDrawable.setColorFilter(new BlendModeColorFilter(color, BlendMode.SRC_IN)); - view.setTextCursorDrawable(cursorDrawable); + Drawable drawableCenter = view.getTextSelectHandle().mutate(); + Drawable drawableLeft = view.getTextSelectHandleLeft().mutate(); + Drawable drawableRight = view.getTextSelectHandleRight().mutate(); + if (color != null) { + BlendModeColorFilter filter = new BlendModeColorFilter(color, BlendMode.SRC_IN); + drawableCenter.setColorFilter(filter); + drawableLeft.setColorFilter(filter); + drawableRight.setColorFilter(filter); + } else { + drawableCenter.clearColorFilter(); + drawableLeft.clearColorFilter(); + drawableRight.clearColorFilter(); } + view.setTextSelectHandle(drawableCenter); + view.setTextSelectHandleLeft(drawableLeft); + view.setTextSelectHandleRight(drawableRight); return; } + // Based on https://github.com/facebook/react-native/pull/31007 if (Build.VERSION.SDK_INT == Build.VERSION_CODES.P) { - // Pre-Android 10, there was no supported API to change the cursor color programmatically. - // In Android 9.0, they changed the underlying implementation, - // but also "dark greylisted" the new field, rendering it unusable. return; } - // The evil code that follows uses reflection to achieve this on Android 8.1 and below. - // Based on https://tinyurl.com/3vff8lyu https://tinyurl.com/vehggzs9 - for (int i = 0; i < DRAWABLE_RESOURCES.length; i++) { + // The following code uses reflection to change handles color on Android 8.1 and below. + for (int i = 0; i < DRAWABLE_HANDLE_RESOURCES.length; i++) { try { - Field drawableResourceField = TextView.class.getDeclaredField(DRAWABLE_RESOURCES[i]); + Field drawableResourceField = + view.getClass().getDeclaredField(DRAWABLE_HANDLE_RESOURCES[i]); drawableResourceField.setAccessible(true); int resourceId = drawableResourceField.getInt(view); - // The view has no cursor drawable. + // The view has no handle drawable. if (resourceId == 0) { return; } - Drawable drawable = ContextCompat.getDrawable(view.getContext(), resourceId); - - Drawable drawableCopy = drawable.mutate(); - drawableCopy.setColorFilter(color, PorterDuff.Mode.SRC_IN); + Drawable drawable = ContextCompat.getDrawable(view.getContext(), resourceId).mutate(); + if (color != null) { + drawable.setColorFilter(color, PorterDuff.Mode.SRC_IN); + } else { + drawable.clearColorFilter(); + } Field editorField = TextView.class.getDeclaredField("mEditor"); editorField.setAccessible(true); Object editor = editorField.get(view); - Field cursorDrawableField = editor.getClass().getDeclaredField(DRAWABLE_FIELDS[i]); + Field cursorDrawableField = editor.getClass().getDeclaredField(DRAWABLE_HANDLE_FIELDS[i]); cursorDrawableField.setAccessible(true); - if (DRAWABLE_RESOURCES[i] == "mCursorDrawableRes") { - Drawable[] drawables = {drawableCopy, drawableCopy}; - cursorDrawableField.set(editor, drawables); - } else { - cursorDrawableField.set(editor, drawableCopy); - } + cursorDrawableField.set(editor, drawable); } catch (NoSuchFieldException ex) { - // Ignore errors to avoid crashing if these private fields don't exist on modified - // or future android versions. } catch (IllegalAccessException ex) { } } } + @ReactProp(name = "cursorColor", customType = "Color") + public void setCursorColor(ReactEditText view, @Nullable Integer color) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + Drawable cursorDrawable = view.getTextCursorDrawable(); + if (cursorDrawable != null) { + if (color != null) { + cursorDrawable.setColorFilter(new BlendModeColorFilter(color, BlendMode.SRC_IN)); + } else { + cursorDrawable.clearColorFilter(); + } + view.setTextCursorDrawable(cursorDrawable); + } + return; + } + + if (Build.VERSION.SDK_INT == Build.VERSION_CODES.P) { + // Pre-Android 10, there was no supported API to change the cursor color programmatically. + // In Android 9.0, they changed the underlying implementation, + // but also "dark greylisted" the new field, rendering it unusable. + return; + } + + // The evil code that follows uses reflection to achieve this on Android 8.1 and below. + // Based on https://tinyurl.com/3vff8lyu https://tinyurl.com/vehggzs9 + try { + Field drawableCursorField = view.getClass().getDeclaredField("mCursorDrawableRes"); + drawableCursorField.setAccessible(true); + int resourceId = drawableCursorField.getInt(view); + + // The view has no cursor drawable. + if (resourceId == 0) { + return; + } + + Drawable drawable = ContextCompat.getDrawable(view.getContext(), resourceId).mutate(); + if (color != null) { + drawable.setColorFilter(color, PorterDuff.Mode.SRC_IN); + } else { + drawable.clearColorFilter(); + } + + Field editorField = TextView.class.getDeclaredField("mEditor"); + editorField.setAccessible(true); + Object editor = editorField.get(view); + + Field cursorDrawableField = editor.getClass().getDeclaredField("mCursorDrawable"); + cursorDrawableField.setAccessible(true); + Drawable[] drawables = {drawable, drawable}; + cursorDrawableField.set(editor, drawables); + } catch (NoSuchFieldException ex) { + // Ignore errors to avoid crashing if these private fields don't exist on modified + // or future android versions. + } catch (IllegalAccessException ex) { + } + } + private static boolean shouldHideCursorForEmailTextInput() { String manufacturer = Build.MANUFACTURER.toLowerCase(Locale.ROOT); return (Build.VERSION.SDK_INT == Build.VERSION_CODES.Q && manufacturer.contains("xiaomi")); diff --git a/packages/react-native/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputProps.cpp b/packages/react-native/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputProps.cpp index 116284f1c6bcaa..2687d64cb3f86f 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputProps.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputProps.cpp @@ -134,6 +134,10 @@ AndroidTextInputProps::AndroidTextInputProps( "selectionColor", sourceProps.selectionColor, {})), + selectionHandleColor(CoreFeatures::enablePropIteratorSetter? sourceProps.selectionHandleColor : convertRawProp(context, rawProps, + "selectionHandleColor", + sourceProps.selectionHandleColor, + {})), value(CoreFeatures::enablePropIteratorSetter? sourceProps.value : convertRawProp(context, rawProps, "value", sourceProps.value, {})), defaultValue(CoreFeatures::enablePropIteratorSetter? sourceProps.defaultValue : convertRawProp(context, rawProps, "defaultValue", @@ -347,6 +351,7 @@ void AndroidTextInputProps::setProp( RAW_SET_PROP_SWITCH_CASE_BASIC(placeholderTextColor); RAW_SET_PROP_SWITCH_CASE_BASIC(secureTextEntry); RAW_SET_PROP_SWITCH_CASE_BASIC(selectionColor); + RAW_SET_PROP_SWITCH_CASE_BASIC(selectionHandleColor); RAW_SET_PROP_SWITCH_CASE_BASIC(defaultValue); RAW_SET_PROP_SWITCH_CASE_BASIC(selectTextOnFocus); RAW_SET_PROP_SWITCH_CASE_BASIC(submitBehavior); @@ -446,6 +451,7 @@ folly::dynamic AndroidTextInputProps::getDynamic() const { props["placeholderTextColor"] = toAndroidRepr(placeholderTextColor); props["secureTextEntry"] = secureTextEntry; props["selectionColor"] = toAndroidRepr(selectionColor); + props["selectionHandleColor"] = toAndroidRepr(selectionHandleColor); props["value"] = value; props["defaultValue"] = defaultValue; props["selectTextOnFocus"] = selectTextOnFocus; diff --git a/packages/react-native/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputProps.h b/packages/react-native/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputProps.h index a690816906ae2f..82fb75ea1028e4 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputProps.h +++ b/packages/react-native/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputProps.h @@ -100,6 +100,7 @@ class AndroidTextInputProps final : public ViewProps, public BaseTextProps { SharedColor placeholderTextColor{}; bool secureTextEntry{false}; SharedColor selectionColor{}; + SharedColor selectionHandleColor{}; std::string value{}; std::string defaultValue{}; bool selectTextOnFocus{false}; diff --git a/packages/react-native/ReactCommon/react/renderer/components/textinput/iostextinput/react/renderer/components/iostextinput/TextInputProps.cpp b/packages/react-native/ReactCommon/react/renderer/components/textinput/iostextinput/react/renderer/components/iostextinput/TextInputProps.cpp index 3e4b712e91d06c..a825971ddbe8c8 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/textinput/iostextinput/react/renderer/components/iostextinput/TextInputProps.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/textinput/iostextinput/react/renderer/components/iostextinput/TextInputProps.cpp @@ -62,6 +62,12 @@ TextInputProps::TextInputProps( "selectionColor", sourceProps.selectionColor, {})), + selectionHandleColor(convertRawProp( + context, + rawProps, + "selectionHandleColor", + sourceProps.selectionHandleColor, + {})), underlineColorAndroid(convertRawProp( context, rawProps, diff --git a/packages/react-native/ReactCommon/react/renderer/components/textinput/iostextinput/react/renderer/components/iostextinput/TextInputProps.h b/packages/react-native/ReactCommon/react/renderer/components/textinput/iostextinput/react/renderer/components/iostextinput/TextInputProps.h index 203f762ede10ab..e3db155099c78e 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/textinput/iostextinput/react/renderer/components/iostextinput/TextInputProps.h +++ b/packages/react-native/ReactCommon/react/renderer/components/textinput/iostextinput/react/renderer/components/iostextinput/TextInputProps.h @@ -53,6 +53,7 @@ class TextInputProps final : public ViewProps, public BaseTextProps { */ const SharedColor cursorColor{}; const SharedColor selectionColor{}; + const SharedColor selectionHandleColor{}; // TODO: Rename to `tintColor` and make universal. const SharedColor underlineColorAndroid{}; diff --git a/packages/rn-tester/js/examples/TextInput/TextInputExample.android.js b/packages/rn-tester/js/examples/TextInput/TextInputExample.android.js index d0ad866155858d..35347b720cedc6 100644 --- a/packages/rn-tester/js/examples/TextInput/TextInputExample.android.js +++ b/packages/rn-tester/js/examples/TextInput/TextInputExample.android.js @@ -196,10 +196,20 @@ const examples: Array = [ + + ); }, @@ -470,7 +480,7 @@ const examples: Array = [ 'next', ]; const returnKeyLabels = ['Compile', 'React Native']; - const examples = returnKeyTypes.map(type => { + const returnKeyExamples = returnKeyTypes.map(type => { return ( = [ }); return ( - {examples} + {returnKeyExamples} {types} ); From 8a62d6135f5ac8c01aa8103ddd91f94973dd6cd3 Mon Sep 17 00:00:00 2001 From: Dmitry Rykun Date: Thu, 23 Nov 2023 06:07:28 -0800 Subject: [PATCH 076/162] Refactor generate-artifacts-executor.js: remove configFileDir CLI argument, use node resolution instead (#41557) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41557 The `configFileDir` CLI argument is used to help to find paths to the 3rd party dependencies of the app. Since we only care about dependencies listed in the root `package.json`, we can use `node` resolution instead of having to construct paths manually. In that case `configFileDir` becomes redundant. Changelog: [iOS][Breaking] - Delete configFileDir CLI argument. Reviewed By: cipolleschi Differential Revision: D51303793 fbshipit-source-id: 46cb61197ddf51515af634c8fc6b85a8d218c51e --- .../generate-artifacts-executor-test.js | 7 +--- .../codegen/generate-artifacts-executor.js | 41 ++++++++----------- .../scripts/generate-codegen-artifacts.js | 8 +--- .../__tests__/script_phases.snap.rb | 2 - .../react_native_pods_utils/script_phases.rb | 1 - .../react_native_pods_utils/script_phases.sh | 2 +- 6 files changed, 21 insertions(+), 40 deletions(-) diff --git a/packages/react-native/scripts/codegen/__tests__/generate-artifacts-executor-test.js b/packages/react-native/scripts/codegen/__tests__/generate-artifacts-executor-test.js index d5e45257fc270e..f195b66f8210f3 100644 --- a/packages/react-native/scripts/codegen/__tests__/generate-artifacts-executor-test.js +++ b/packages/react-native/scripts/codegen/__tests__/generate-artifacts-executor-test.js @@ -173,12 +173,7 @@ describe('findCodegenEnabledLibraries', () => { }, })); - const libraries = findCodegenEnabledLibraries( - `${projectDir}/app`, - baseCodegenConfigFileDir, - `package.json`, - 'codegenConfig', - ); + const libraries = findCodegenEnabledLibraries(`${projectDir}/app`); expect(libraries).toEqual([ { diff --git a/packages/react-native/scripts/codegen/generate-artifacts-executor.js b/packages/react-native/scripts/codegen/generate-artifacts-executor.js index a4c07c487200f9..d72d427c89b66a 100644 --- a/packages/react-native/scripts/codegen/generate-artifacts-executor.js +++ b/packages/react-native/scripts/codegen/generate-artifacts-executor.js @@ -151,32 +151,32 @@ function handleReactNativeCoreLibraries() { ); } -function handleThirdPartyLibraries(baseCodegenConfigFileDir, dependencies) { +function handleThirdPartyLibraries(pkgJson) { + const dependencies = {...pkgJson.dependencies, ...pkgJson.devDependencies}; // Determine which of these are codegen-enabled libraries - const configDir = - baseCodegenConfigFileDir || - path.join(REACT_NATIVE_PACKAGE_ROOT_FOLDER, '..'); console.log( - `\n\n[Codegen] >>>>> Searching for codegen-enabled libraries in ${configDir}`, + '\n\n[Codegen] >>>>> Searching for codegen-enabled libraries in the project dependencies.', ); - // Handle third-party libraries return Object.keys(dependencies).flatMap(dependency => { if (dependency === REACT_NATIVE) { // react-native should already be added. return []; } - let configFile; try { - configFile = readPkgJsonInDirectory(codegenConfigFileDir); - } catch { + const configFilePath = require.resolve( + path.join(dependency, 'package.json'), + ); + const configFile = JSON.parse(fs.readFileSync(configFilePath)); + const codegenConfigFileDir = path.dirname(configFilePath); + return extractLibrariesFromJSON( + configFile, + dependency, + codegenConfigFileDir, + ); + } catch (e) { return []; } - return extractLibrariesFromJSON( - configFile, - dependency, - codegenConfigFileDir, - ); }); } @@ -338,12 +338,11 @@ function createComponentProvider(schemas) { console.log(`Generated provider in: ${outputDir}`); } -function findCodegenEnabledLibraries(appRootDir, baseCodegenConfigFileDir) { +function findCodegenEnabledLibraries(appRootDir) { const pkgJson = readPkgJsonInDirectory(appRootDir); - const dependencies = {...pkgJson.dependencies, ...pkgJson.devDependencies}; return [ ...handleReactNativeCoreLibraries(), - ...handleThirdPartyLibraries(baseCodegenConfigFileDir, dependencies), + ...handleThirdPartyLibraries(pkgJson), ...handleLibrariesFromReactNativeConfig(appRootDir), ...handleInAppLibraries(pkgJson, appRootDir), ]; @@ -393,12 +392,11 @@ function cleanupEmptyFilesAndFolders(filepath) { * * @parameter appRootDir: the directory with the app source code, where the package.json lives. * @parameter outputPath: the base output path for the CodeGen. - * @parameter baseCodegenConfigFileDir: the directory of the codeGenConfigFile. * @throws If it can't find a config file for react-native. * @throws If it can't find a CodeGen configuration in the file. * @throws If it can't find a cli for the CodeGen. */ -function execute(appRootDir, outputPath, baseCodegenConfigFileDir) { +function execute(appRootDir, outputPath) { if (!isAppRootValid(appRootDir)) { return; } @@ -406,10 +404,7 @@ function execute(appRootDir, outputPath, baseCodegenConfigFileDir) { buildCodegenIfNeeded(); try { - const libraries = findCodegenEnabledLibraries( - appRootDir, - baseCodegenConfigFileDir, - ); + const libraries = findCodegenEnabledLibraries(appRootDir); if (libraries.length === 0) { console.log('[Codegen] No codegen-enabled libraries found.'); diff --git a/packages/react-native/scripts/generate-codegen-artifacts.js b/packages/react-native/scripts/generate-codegen-artifacts.js index bcbc8aaf039f28..186c1f39c32dbc 100644 --- a/packages/react-native/scripts/generate-codegen-artifacts.js +++ b/packages/react-native/scripts/generate-codegen-artifacts.js @@ -21,13 +21,7 @@ const argv = yargs alias: 'outputPath', description: 'Path where generated artifacts will be output to', }) - .option('c', { - alias: 'configFileDir', - default: '', - description: - 'Path where codegen config files are located (e.g. node_modules dir).', - }) .usage('Usage: $0 -p [path to app]') .demandOption(['p']).argv; -executor.execute(argv.path, argv.outputPath, argv.configFileDir); +executor.execute(argv.path, argv.outputPath); diff --git a/packages/react-native/scripts/react_native_pods_utils/__tests__/script_phases.snap.rb b/packages/react-native/scripts/react_native_pods_utils/__tests__/script_phases.snap.rb index ff4604b259bef4..bc216b1315d90a 100644 --- a/packages/react-native/scripts/react_native_pods_utils/__tests__/script_phases.snap.rb +++ b/packages/react-native/scripts/react_native_pods_utils/__tests__/script_phases.snap.rb @@ -11,7 +11,6 @@ def snap_get_script_phases_with_codegen_discovery_with_config_file_dir() export RCT_SCRIPT_RN_DIR=$RCT_SCRIPT_POD_INSTALLATION_ROOT/../.. export RCT_SCRIPT_APP_PATH=$RCT_SCRIPT_POD_INSTALLATION_ROOT/ - export RCT_SCRIPT_CONFIG_FILE_DIR=$RCT_SCRIPT_POD_INSTALLATION_ROOT/node_modules export RCT_SCRIPT_OUTPUT_DIR=$RCT_SCRIPT_POD_INSTALLATION_ROOT export RCT_SCRIPT_TYPE=withCodegenDiscovery @@ -29,7 +28,6 @@ def snap_get_script_phases_with_codegen_discovery_without_config_file_dir() export RCT_SCRIPT_RN_DIR=$RCT_SCRIPT_POD_INSTALLATION_ROOT/../.. export RCT_SCRIPT_APP_PATH=$RCT_SCRIPT_POD_INSTALLATION_ROOT/ - export RCT_SCRIPT_CONFIG_FILE_DIR= export RCT_SCRIPT_OUTPUT_DIR=$RCT_SCRIPT_POD_INSTALLATION_ROOT export RCT_SCRIPT_TYPE=withCodegenDiscovery diff --git a/packages/react-native/scripts/react_native_pods_utils/script_phases.rb b/packages/react-native/scripts/react_native_pods_utils/script_phases.rb index 78a381c403a31b..f5dd2ed708312f 100644 --- a/packages/react-native/scripts/react_native_pods_utils/script_phases.rb +++ b/packages/react-native/scripts/react_native_pods_utils/script_phases.rb @@ -11,7 +11,6 @@ def get_script_phases_with_codegen_discovery(options) export_vars = { 'RCT_SCRIPT_RN_DIR' => "$RCT_SCRIPT_POD_INSTALLATION_ROOT/#{options[:react_native_path]}", 'RCT_SCRIPT_APP_PATH' => "$RCT_SCRIPT_POD_INSTALLATION_ROOT/#{options[:relative_app_root]}", - 'RCT_SCRIPT_CONFIG_FILE_DIR' => "#{options[:relative_config_file_dir] != '' ? "$RCT_SCRIPT_POD_INSTALLATION_ROOT/#{options[:relative_config_file_dir]}" : ''}", 'RCT_SCRIPT_OUTPUT_DIR' => "$RCT_SCRIPT_POD_INSTALLATION_ROOT", 'RCT_SCRIPT_TYPE' => "withCodegenDiscovery", } diff --git a/packages/react-native/scripts/react_native_pods_utils/script_phases.sh b/packages/react-native/scripts/react_native_pods_utils/script_phases.sh index aff355264ff7bc..847702fdb0dabd 100755 --- a/packages/react-native/scripts/react_native_pods_utils/script_phases.sh +++ b/packages/react-native/scripts/react_native_pods_utils/script_phases.sh @@ -96,7 +96,7 @@ generateCodegenArtifactsFromSchema () { generateArtifacts () { describe "Generating codegen artifacts" pushd "$RCT_SCRIPT_RN_DIR" >/dev/null || exit 1 - "$NODE_BINARY" "scripts/generate-codegen-artifacts.js" --path "$RCT_SCRIPT_APP_PATH" --outputPath "$TEMP_OUTPUT_DIR" --configFileDir "$RCT_SCRIPT_CONFIG_FILE_DIR" + "$NODE_BINARY" "scripts/generate-codegen-artifacts.js" --path "$RCT_SCRIPT_APP_PATH" --outputPath "$TEMP_OUTPUT_DIR" popd >/dev/null || exit 1 } From 5ec2c016972400cf6e26d987acec6feee46ba6e6 Mon Sep 17 00:00:00 2001 From: Nicola Corti Date: Thu, 23 Nov 2023 06:59:18 -0800 Subject: [PATCH 077/162] Fix projects being broken on dependencies starting with `a..` (#41621) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41621 Currently, if you have a dependency that is alphabetically smaller than `app`, it's evaluation will happen before `app`. This means that the namespace auto-discovery and the JVM toolchain configuration won't be working and the project will fail to buid. This fixes it by introducing a root-project Gradle Plugin that takes care of enforcing the evaluation order on the `app` project. Fixes #41620 Changelog: [Android] [Fixed] - Fix projects being broken on dependencies starting with `a..` Reviewed By: huntie Differential Revision: D51547294 fbshipit-source-id: 65df7149548b7087dd8928e556fb803b3baf7b79 --- .../build.gradle.kts | 4 +++ .../facebook/react/ReactRootProjectPlugin.kt | 30 +++++++++++++++++++ .../template/android/build.gradle | 4 +-- 3 files changed, 36 insertions(+), 2 deletions(-) create mode 100644 packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/ReactRootProjectPlugin.kt diff --git a/packages/react-native-gradle-plugin/build.gradle.kts b/packages/react-native-gradle-plugin/build.gradle.kts index c4a31beb010e19..9346508f497062 100644 --- a/packages/react-native-gradle-plugin/build.gradle.kts +++ b/packages/react-native-gradle-plugin/build.gradle.kts @@ -26,6 +26,10 @@ gradlePlugin { id = "com.facebook.react" implementationClass = "com.facebook.react.ReactPlugin" } + create("reactrootproject") { + id = "com.facebook.react.rootproject" + implementationClass = "com.facebook.react.ReactRootProjectPlugin" + } } } diff --git a/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/ReactRootProjectPlugin.kt b/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/ReactRootProjectPlugin.kt new file mode 100644 index 00000000000000..5f232cd0e581a5 --- /dev/null +++ b/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/ReactRootProjectPlugin.kt @@ -0,0 +1,30 @@ +/* + * Copyright (c) Meta Platforms, Inc. and 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 + +import org.gradle.api.Plugin +import org.gradle.api.Project + +/** + * Gradle plugin applied to the `android/build.gradle` file. + * + * This plugin allows to specify project wide configurations that can be applied to both apps and + * libraries before they're evaluated. + */ +class ReactRootProjectPlugin : Plugin { + override fun apply(project: Project) { + project.subprojects { + // As the :app project (i.e. ReactPlugin) configures both namespaces and JVM toolchains + // for libraries, its evaluation must happen before the libraries' evaluation. + // Eventually the configuration of namespace/JVM toolchain can be moved inside this plugin. + if (it.path != ":app") { + it.evaluationDependsOn(":app") + } + } + } +} diff --git a/packages/react-native/template/android/build.gradle b/packages/react-native/template/android/build.gradle index 8012362ce17b77..a61601bb05dbf6 100644 --- a/packages/react-native/template/android/build.gradle +++ b/packages/react-native/template/android/build.gradle @@ -1,5 +1,3 @@ -// Top-level build file where you can add configuration options common to all sub-projects/modules. - buildscript { ext { buildToolsVersion = "34.0.0" @@ -19,3 +17,5 @@ buildscript { classpath("org.jetbrains.kotlin:kotlin-gradle-plugin") } } + +apply plugin: "com.facebook.react.rootproject" From fd35c1db2810c7c147c28ad067194744bf378069 Mon Sep 17 00:00:00 2001 From: Frieder Bluemle Date: Thu, 23 Nov 2023 07:49:14 -0800 Subject: [PATCH 078/162] Update pkg/repo names in deprecation messages (#41618) Summary: Several deprecation warning messages related to components that were removed from `react-native` were outdated. Some repositories have been moved, some packages were renamed/re-published under new names. A couple **never existed** (`react-native-community/segmented-checkbox` and `react-native-community/react-native-image-picker`). This updates all messages to include links to the latest repositories and references to npm packages. Because `react-native-community/art` is deprecated I've also slightly amended the message with the suggestion from its [repo readme](https://github.com/react-native-art/art#deprecated---this-package-is-deprecated-if-you-need-a-similar-package-please-consider-using-react-native-svg). ## Changelog: [GENERAL] [FIXED] - Update pkg/repo names in deprecation messages Pull Request resolved: https://github.com/facebook/react-native/pull/41618 Test Plan: No code change, just documentation/text. Reviewed By: cipolleschi Differential Revision: D51546345 Pulled By: cortinico fbshipit-source-id: 5d7176a70d94c8b1e8111f4d84fba89eacde456a --- packages/react-native/index.js | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/packages/react-native/index.js b/packages/react-native/index.js index 0e4376a60f76db..3e0a2396cff6cd 100644 --- a/packages/react-native/index.js +++ b/packages/react-native/index.js @@ -285,7 +285,7 @@ module.exports = { 'pushNotificationIOS-moved', 'PushNotificationIOS has been extracted from react-native core and will be removed in a future release. ' + "It can now be installed and imported from '@react-native-community/push-notification-ios' instead of 'react-native'. " + - 'See https://github.com/react-native-push-notification-ios/push-notification-ios', + 'See https://github.com/react-native-push-notification/ios', ); return require('./Libraries/PushNotificationIOS/PushNotificationIOS'); }, @@ -429,7 +429,8 @@ if (__DEV__) { invariant( false, 'ART has been removed from React Native. ' + - "It can now be installed and imported from '@react-native-community/art' instead of 'react-native'. " + + "Please upgrade to use either 'react-native-svg' or a similar package. " + + "If you cannot upgrade to a different library, please install the deprecated '@react-native-community/art' package. " + 'See https://github.com/react-native-art/art', ); }, @@ -509,7 +510,7 @@ if (__DEV__) { invariant( false, 'CameraRoll has been removed from React Native. ' + - "It can now be installed and imported from '@react-native-community/cameraroll' instead of 'react-native'. " + + "It can now be installed and imported from '@react-native-camera-roll/camera-roll' instead of 'react-native'. " + 'See https://github.com/react-native-cameraroll/react-native-cameraroll', ); }, @@ -622,7 +623,7 @@ if (__DEV__) { invariant( false, 'SegmentedControlIOS has been removed from React Native. ' + - "It can now be installed and imported from '@react-native-community/segmented-checkbox' instead of 'react-native'." + + "It can now be installed and imported from '@react-native-segmented-control/segmented-control' instead of 'react-native'." + 'See https://github.com/react-native-segmented-control/segmented-control', ); }, @@ -700,7 +701,7 @@ if (__DEV__) { invariant( false, 'MaskedViewIOS has been removed from React Native. ' + - "It can now be installed and imported from '@react-native-community/react-native-masked-view' instead of 'react-native'. " + + "It can now be installed and imported from '@react-native-masked-view/masked-view' instead of 'react-native'. " + 'See https://github.com/react-native-masked-view/masked-view', ); }, @@ -730,7 +731,7 @@ if (__DEV__) { invariant( false, 'ImagePickerIOS has been removed from React Native. ' + - "Please upgrade to use either '@react-native-community/react-native-image-picker' or 'expo-image-picker'. " + + "Please upgrade to use either 'react-native-image-picker' or 'expo-image-picker'. " + "If you cannot upgrade to a different library, please install the deprecated '@react-native-community/image-picker-ios' package. " + 'See https://github.com/rnc-archive/react-native-image-picker-ios', ); From 758e59f1d9752cf051b2dee900c5182ee52c4189 Mon Sep 17 00:00:00 2001 From: Ruslan Lesiutin Date: Thu, 23 Nov 2023 07:53:24 -0800 Subject: [PATCH 079/162] feat[TraceUpdateOverlay]: add iOS native component (#41563) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41563 Changelog: [iOS][Added] - support "highlighting updates when components render" feature from React DevTools Reviewed By: javache Differential Revision: D51470012 fbshipit-source-id: ba4094ae24d14f58ad08acbb90333bbe49e043c9 --- .../TraceUpdateOverlay/TraceUpdateOverlay.js | 10 ++- .../RCTFabricComponentsPlugins.h | 1 + .../RCTFabricComponentsPlugins.mm | 1 + .../RCTTraceUpdateOverlayComponentView.h | 16 +++++ .../RCTTraceUpdateOverlayComponentView.mm | 65 +++++++++++++++++++ .../React/Views/RCTTraceUpdateOverlay.h | 16 +++++ .../React/Views/RCTTraceUpdateOverlay.m | 57 ++++++++++++++++ .../Views/RCTTraceUpdateOverlayManager.h | 12 ++++ .../Views/RCTTraceUpdateOverlayManager.m | 38 +++++++++++ 9 files changed, 210 insertions(+), 6 deletions(-) create mode 100644 packages/react-native/React/Fabric/Mounting/ComponentViews/TraceUpdateOverlay/RCTTraceUpdateOverlayComponentView.h create mode 100644 packages/react-native/React/Fabric/Mounting/ComponentViews/TraceUpdateOverlay/RCTTraceUpdateOverlayComponentView.mm create mode 100644 packages/react-native/React/Views/RCTTraceUpdateOverlay.h create mode 100644 packages/react-native/React/Views/RCTTraceUpdateOverlay.m create mode 100644 packages/react-native/React/Views/RCTTraceUpdateOverlayManager.h create mode 100644 packages/react-native/React/Views/RCTTraceUpdateOverlayManager.m diff --git a/packages/react-native/Libraries/Components/TraceUpdateOverlay/TraceUpdateOverlay.js b/packages/react-native/Libraries/Components/TraceUpdateOverlay/TraceUpdateOverlay.js index 57c70fd5f28c75..97a4426e11fd42 100644 --- a/packages/react-native/Libraries/Components/TraceUpdateOverlay/TraceUpdateOverlay.js +++ b/packages/react-native/Libraries/Components/TraceUpdateOverlay/TraceUpdateOverlay.js @@ -17,7 +17,6 @@ import type {Overlay} from './TraceUpdateOverlayNativeComponent'; import UIManager from '../../ReactNative/UIManager'; import processColor from '../../StyleSheet/processColor'; import StyleSheet from '../../StyleSheet/StyleSheet'; -import Platform from '../../Utilities/Platform'; import View from '../View/View'; import TraceUpdateOverlayNativeComponent, { Commands, @@ -26,7 +25,6 @@ import * as React from 'react'; const {useEffect, useRef, useState} = React; const isNativeComponentReady = - Platform.OS === 'android' && UIManager.hasViewManagerConfig('TraceUpdateOverlay'); type Props = { @@ -39,13 +37,13 @@ export default function TraceUpdateOverlay({ const [overlayDisabled, setOverlayDisabled] = useState(false); useEffect(() => { - if (!isNativeComponentReady) { - return; - } - const drawTraceUpdates = ( nodesToDraw: Array<{node: InstanceFromReactDevTools, color: string}> = [], ) => { + if (!isNativeComponentReady) { + return; + } + // If overlay is disabled before, now it's enabled. setOverlayDisabled(false); diff --git a/packages/react-native/React/Fabric/Mounting/ComponentViews/RCTFabricComponentsPlugins.h b/packages/react-native/React/Fabric/Mounting/ComponentViews/RCTFabricComponentsPlugins.h index ca5f395c3141a8..51912e25dcd143 100644 --- a/packages/react-native/React/Fabric/Mounting/ComponentViews/RCTFabricComponentsPlugins.h +++ b/packages/react-native/React/Fabric/Mounting/ComponentViews/RCTFabricComponentsPlugins.h @@ -38,6 +38,7 @@ Class RCTSafeAreaViewCls(void) __attribute__((used)); Class RCTScrollViewCls(void) __attribute__((used)); Class RCTSwitchCls(void) __attribute__((used)); Class RCTTextInputCls(void) __attribute__((used)); +Class RCTTraceUpdateOverlayCls(void) __attribute__((used)); Class RCTUnimplementedNativeViewCls(void) __attribute__((used)); Class RCTViewCls(void) __attribute__((used)); Class RCTImageCls(void) __attribute__((used)); diff --git a/packages/react-native/React/Fabric/Mounting/ComponentViews/RCTFabricComponentsPlugins.mm b/packages/react-native/React/Fabric/Mounting/ComponentViews/RCTFabricComponentsPlugins.mm index 02d1dc1a125af7..dff4412f48ab38 100644 --- a/packages/react-native/React/Fabric/Mounting/ComponentViews/RCTFabricComponentsPlugins.mm +++ b/packages/react-native/React/Fabric/Mounting/ComponentViews/RCTFabricComponentsPlugins.mm @@ -26,6 +26,7 @@ {"ScrollView", RCTScrollViewCls}, {"Switch", RCTSwitchCls}, {"TextInput", RCTTextInputCls}, + {"TraceUpdateOverlay", RCTTraceUpdateOverlayCls}, {"UnimplementedNativeView", RCTUnimplementedNativeViewCls}, {"View", RCTViewCls}, {"Image", RCTImageCls}, diff --git a/packages/react-native/React/Fabric/Mounting/ComponentViews/TraceUpdateOverlay/RCTTraceUpdateOverlayComponentView.h b/packages/react-native/React/Fabric/Mounting/ComponentViews/TraceUpdateOverlay/RCTTraceUpdateOverlayComponentView.h new file mode 100644 index 00000000000000..d6aa304ef5725b --- /dev/null +++ b/packages/react-native/React/Fabric/Mounting/ComponentViews/TraceUpdateOverlay/RCTTraceUpdateOverlayComponentView.h @@ -0,0 +1,16 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import + +#import + +#import + +@interface RCTTraceUpdateOverlayComponentView : RCTViewComponentView + +@end diff --git a/packages/react-native/React/Fabric/Mounting/ComponentViews/TraceUpdateOverlay/RCTTraceUpdateOverlayComponentView.mm b/packages/react-native/React/Fabric/Mounting/ComponentViews/TraceUpdateOverlay/RCTTraceUpdateOverlayComponentView.mm new file mode 100644 index 00000000000000..6bf68de14e15a8 --- /dev/null +++ b/packages/react-native/React/Fabric/Mounting/ComponentViews/TraceUpdateOverlay/RCTTraceUpdateOverlayComponentView.mm @@ -0,0 +1,65 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import "RCTTraceUpdateOverlayComponentView.h" + +#import +#import +#import + +#import +#import +#import +#import + +#import "RCTFabricComponentsPlugins.h" + +using namespace facebook::react; + +@implementation RCTTraceUpdateOverlayComponentView { + RCTTraceUpdateOverlay *_overlay; +} + +- (instancetype)initWithFrame:(CGRect)frame +{ + if (self = [super initWithFrame:frame]) { + static const auto defaultProps = std::make_shared(); + _props = defaultProps; + + _overlay = [[RCTTraceUpdateOverlay alloc] initWithFrame:self.bounds]; + + self.contentView = _overlay; + } + + return self; +} + +#pragma mark - RCTComponentViewProtocol + ++ (ComponentDescriptorProvider)componentDescriptorProvider +{ + return concreteComponentDescriptorProvider(); +} + +#pragma mark - Native commands + +- (void)handleCommand:(const NSString *)commandName args:(const NSArray *)args +{ + RCTTraceUpdateOverlayHandleCommand(self, commandName, args); +} + +- (void)draw:(NSString *)overlays +{ + [_overlay draw:overlays]; +} + +@end + +Class RCTTraceUpdateOverlayCls(void) +{ + return RCTTraceUpdateOverlayComponentView.class; +} diff --git a/packages/react-native/React/Views/RCTTraceUpdateOverlay.h b/packages/react-native/React/Views/RCTTraceUpdateOverlay.h new file mode 100644 index 00000000000000..480883044d2e49 --- /dev/null +++ b/packages/react-native/React/Views/RCTTraceUpdateOverlay.h @@ -0,0 +1,16 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import + +#import + +@interface RCTTraceUpdateOverlay : RCTView + +- (void)draw:(NSString *)serializedNodes; + +@end diff --git a/packages/react-native/React/Views/RCTTraceUpdateOverlay.m b/packages/react-native/React/Views/RCTTraceUpdateOverlay.m new file mode 100644 index 00000000000000..198f46b94429b6 --- /dev/null +++ b/packages/react-native/React/Views/RCTTraceUpdateOverlay.m @@ -0,0 +1,57 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import "RCTTraceUpdateOverlay.h" + +#import +#import +#import + +@implementation RCTTraceUpdateOverlay + +- (void)draw:(NSString *)serializedNodes +{ + NSArray *subViewsToRemove = [self subviews]; + for (UIView *v in subViewsToRemove) { + [v removeFromSuperview]; + } + + NSError *error = nil; + id deserializedNodes = RCTJSONParse(serializedNodes, &error); + + if (error) { + RCTLogError(@"Failed to parse serialized nodes passed to RCTTraceUpdatesOverlay"); + return; + } + + if (![deserializedNodes isKindOfClass:[NSArray class]]) { + RCTLogError(@"Expected to receive nodes as an array, got %@", NSStringFromClass([deserializedNodes class])); + return; + } + + for (NSDictionary *node in deserializedNodes) { + NSDictionary *nodeRectangle = node[@"rect"]; + NSNumber *nodeColor = node[@"color"]; + + NSNumber *x = nodeRectangle[@"left"]; + NSNumber *y = nodeRectangle[@"top"]; + NSNumber *width = nodeRectangle[@"width"]; + NSNumber *height = nodeRectangle[@"height"]; + + CGRect rect = CGRectMake(x.doubleValue, y.doubleValue, width.doubleValue, height.doubleValue); + + UIView *box = [[UIView alloc] initWithFrame:rect]; + box.backgroundColor = [UIColor clearColor]; + + box.layer.borderWidth = 2.0f; + box.layer.borderColor = [RCTConvert UIColor:nodeColor].CGColor; + + [self addSubview:box]; + } +} + +@end diff --git a/packages/react-native/React/Views/RCTTraceUpdateOverlayManager.h b/packages/react-native/React/Views/RCTTraceUpdateOverlayManager.h new file mode 100644 index 00000000000000..f50680420dc332 --- /dev/null +++ b/packages/react-native/React/Views/RCTTraceUpdateOverlayManager.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import + +@interface RCTTraceUpdateOverlayManager : RCTViewManager + +@end diff --git a/packages/react-native/React/Views/RCTTraceUpdateOverlayManager.m b/packages/react-native/React/Views/RCTTraceUpdateOverlayManager.m new file mode 100644 index 00000000000000..8386b94941d997 --- /dev/null +++ b/packages/react-native/React/Views/RCTTraceUpdateOverlayManager.m @@ -0,0 +1,38 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import "RCTTraceUpdateOverlayManager.h" +#import "RCTTraceUpdateOverlay.h" + +#import +#import + +#import "RCTBridge.h" + +@implementation RCTTraceUpdateOverlayManager + +RCT_EXPORT_MODULE(TraceUpdateOverlay) + +- (UIView *)view +{ + return [RCTTraceUpdateOverlay new]; +} + +RCT_EXPORT_METHOD(draw : (nonnull NSNumber *)viewTag nodes : (NSString *)serializedNodes) +{ + [self.bridge.uiManager addUIBlock:^(RCTUIManager *uiManager, NSDictionary *viewRegistry) { + UIView *view = viewRegistry[viewTag]; + + if ([view isKindOfClass:[RCTTraceUpdateOverlay class]]) { + [(RCTTraceUpdateOverlay *)view draw:serializedNodes]; + } else { + RCTLogError(@"Expected view to be RCTTraceUpdateOverlay, got %@", NSStringFromClass([view class])); + } + }]; +} + +@end From ed1056e1c7ec8313955a46f783e631dd90a6db03 Mon Sep 17 00:00:00 2001 From: Ruslan Lesiutin Date: Thu, 23 Nov 2023 07:53:24 -0800 Subject: [PATCH 080/162] refactor: TraceUpdates native component -> DebuggingOverlay (#41562) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41562 Changelog: [Internal] We will use this native component as a single layer for drawing debugging information: both for trace updates and inspected components from React DevTools. Reviewed By: javache Differential Revision: D51470789 fbshipit-source-id: 6c4633d2b70c2c2635a2bbfcd7adf1c727b73585 --- .../TraceUpdateOverlay/TraceUpdateOverlay.js | 14 ++++++------- .../DebuggingOverlayNativeComponent.js} | 16 +++++++-------- .../RCTDebuggingOverlayComponentView.h} | 2 +- .../RCTDebuggingOverlayComponentView.mm} | 20 +++++++++---------- .../RCTFabricComponentsPlugins.h | 2 +- .../RCTFabricComponentsPlugins.mm | 2 +- ...eUpdateOverlay.h => RCTDebuggingOverlay.h} | 2 +- ...eUpdateOverlay.m => RCTDebuggingOverlay.m} | 6 +++--- ...Manager.h => RCTDebuggingOverlayManager.h} | 2 +- ...Manager.m => RCTDebuggingOverlayManager.m} | 16 +++++++-------- .../com/facebook/react/DebugCorePackage.java | 5 ++--- .../DebuggingOverlay.java} | 6 +++--- .../DebuggingOverlayManager.java} | 20 +++++++++---------- .../react/fabric/CoreComponentsRegistry.cpp | 2 +- 14 files changed, 57 insertions(+), 58 deletions(-) rename packages/react-native/Libraries/{Components/TraceUpdateOverlay/TraceUpdateOverlayNativeComponent.js => Debugging/DebuggingOverlayNativeComponent.js} (62%) rename packages/react-native/React/Fabric/Mounting/ComponentViews/{TraceUpdateOverlay/RCTTraceUpdateOverlayComponentView.h => DebuggingOverlay/RCTDebuggingOverlayComponentView.h} (75%) rename packages/react-native/React/Fabric/Mounting/ComponentViews/{TraceUpdateOverlay/RCTTraceUpdateOverlayComponentView.mm => DebuggingOverlay/RCTDebuggingOverlayComponentView.mm} (63%) rename packages/react-native/React/Views/{RCTTraceUpdateOverlay.h => RCTDebuggingOverlay.h} (87%) rename packages/react-native/React/Views/{RCTTraceUpdateOverlay.m => RCTDebuggingOverlay.m} (93%) rename packages/react-native/React/Views/{RCTTraceUpdateOverlayManager.h => RCTDebuggingOverlayManager.h} (80%) rename packages/react-native/React/Views/{RCTTraceUpdateOverlayManager.m => RCTDebuggingOverlayManager.m} (57%) rename packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/{traceupdateoverlay/TraceUpdateOverlay.java => debuggingoverlay/DebuggingOverlay.java} (92%) rename packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/{traceupdateoverlay/TraceUpdateOverlayManager.java => debuggingoverlay/DebuggingOverlayManager.java} (76%) diff --git a/packages/react-native/Libraries/Components/TraceUpdateOverlay/TraceUpdateOverlay.js b/packages/react-native/Libraries/Components/TraceUpdateOverlay/TraceUpdateOverlay.js index 97a4426e11fd42..94ded259e1249e 100644 --- a/packages/react-native/Libraries/Components/TraceUpdateOverlay/TraceUpdateOverlay.js +++ b/packages/react-native/Libraries/Components/TraceUpdateOverlay/TraceUpdateOverlay.js @@ -8,24 +8,24 @@ * @format */ +import type {Overlay} from '../../Debugging/DebuggingOverlayNativeComponent'; import type { InstanceFromReactDevTools, ReactDevToolsAgent, } from '../../Types/ReactDevToolsTypes'; -import type {Overlay} from './TraceUpdateOverlayNativeComponent'; +import DebuggingOverlayNativeComponent, { + Commands, +} from '../../Debugging/DebuggingOverlayNativeComponent'; import UIManager from '../../ReactNative/UIManager'; import processColor from '../../StyleSheet/processColor'; import StyleSheet from '../../StyleSheet/StyleSheet'; import View from '../View/View'; -import TraceUpdateOverlayNativeComponent, { - Commands, -} from './TraceUpdateOverlayNativeComponent'; import * as React from 'react'; const {useEffect, useRef, useState} = React; const isNativeComponentReady = - UIManager.hasViewManagerConfig('TraceUpdateOverlay'); + UIManager.hasViewManagerConfig('DebuggingOverlay'); type Props = { reactDevToolsAgent: ReactDevToolsAgent, @@ -111,13 +111,13 @@ export default function TraceUpdateOverlay({ }, [reactDevToolsAgent]); const nativeComponentRef = - useRef>(null); + useRef>(null); return ( !overlayDisabled && isNativeComponentReady && ( - diff --git a/packages/react-native/Libraries/Components/TraceUpdateOverlay/TraceUpdateOverlayNativeComponent.js b/packages/react-native/Libraries/Debugging/DebuggingOverlayNativeComponent.js similarity index 62% rename from packages/react-native/Libraries/Components/TraceUpdateOverlay/TraceUpdateOverlayNativeComponent.js rename to packages/react-native/Libraries/Debugging/DebuggingOverlayNativeComponent.js index 837223e3774b2d..0e2f95514583e9 100644 --- a/packages/react-native/Libraries/Components/TraceUpdateOverlay/TraceUpdateOverlayNativeComponent.js +++ b/packages/react-native/Libraries/Debugging/DebuggingOverlayNativeComponent.js @@ -8,18 +8,18 @@ * @format */ -import type {HostComponent} from '../../Renderer/shims/ReactNativeTypes'; -import type {ProcessedColorValue} from '../../StyleSheet/processColor'; -import type {ViewProps} from '../View/ViewPropTypes'; +import type {ViewProps} from '../Components/View/ViewPropTypes'; +import type {HostComponent} from '../Renderer/shims/ReactNativeTypes'; +import type {ProcessedColorValue} from '../StyleSheet/processColor'; -import codegenNativeCommands from '../../Utilities/codegenNativeCommands'; -import codegenNativeComponent from '../../Utilities/codegenNativeComponent'; +import codegenNativeCommands from '../Utilities/codegenNativeCommands'; +import codegenNativeComponent from '../Utilities/codegenNativeComponent'; import * as React from 'react'; type NativeProps = $ReadOnly<{| ...ViewProps, |}>; -export type TraceUpdateOverlayNativeComponentType = HostComponent; +export type DebuggingOverlayNativeComponentType = HostComponent; export type Overlay = { rect: {left: number, top: number, width: number, height: number}, color: ?ProcessedColorValue, @@ -27,7 +27,7 @@ export type Overlay = { interface NativeCommands { +draw: ( - viewRef: React.ElementRef, + viewRef: React.ElementRef, // TODO(T144046177): Ideally we can pass array of Overlay, but currently // Array type is not supported in RN codegen for building native commands. overlays: string, @@ -39,5 +39,5 @@ export const Commands: NativeCommands = codegenNativeCommands({ }); export default (codegenNativeComponent( - 'TraceUpdateOverlay', + 'DebuggingOverlay', ): HostComponent); diff --git a/packages/react-native/React/Fabric/Mounting/ComponentViews/TraceUpdateOverlay/RCTTraceUpdateOverlayComponentView.h b/packages/react-native/React/Fabric/Mounting/ComponentViews/DebuggingOverlay/RCTDebuggingOverlayComponentView.h similarity index 75% rename from packages/react-native/React/Fabric/Mounting/ComponentViews/TraceUpdateOverlay/RCTTraceUpdateOverlayComponentView.h rename to packages/react-native/React/Fabric/Mounting/ComponentViews/DebuggingOverlay/RCTDebuggingOverlayComponentView.h index d6aa304ef5725b..9ee08512265621 100644 --- a/packages/react-native/React/Fabric/Mounting/ComponentViews/TraceUpdateOverlay/RCTTraceUpdateOverlayComponentView.h +++ b/packages/react-native/React/Fabric/Mounting/ComponentViews/DebuggingOverlay/RCTDebuggingOverlayComponentView.h @@ -11,6 +11,6 @@ #import -@interface RCTTraceUpdateOverlayComponentView : RCTViewComponentView +@interface RCTDebuggingOverlayComponentView : RCTViewComponentView @end diff --git a/packages/react-native/React/Fabric/Mounting/ComponentViews/TraceUpdateOverlay/RCTTraceUpdateOverlayComponentView.mm b/packages/react-native/React/Fabric/Mounting/ComponentViews/DebuggingOverlay/RCTDebuggingOverlayComponentView.mm similarity index 63% rename from packages/react-native/React/Fabric/Mounting/ComponentViews/TraceUpdateOverlay/RCTTraceUpdateOverlayComponentView.mm rename to packages/react-native/React/Fabric/Mounting/ComponentViews/DebuggingOverlay/RCTDebuggingOverlayComponentView.mm index 6bf68de14e15a8..31d1dcb5f77962 100644 --- a/packages/react-native/React/Fabric/Mounting/ComponentViews/TraceUpdateOverlay/RCTTraceUpdateOverlayComponentView.mm +++ b/packages/react-native/React/Fabric/Mounting/ComponentViews/DebuggingOverlay/RCTDebuggingOverlayComponentView.mm @@ -5,11 +5,11 @@ * LICENSE file in the root directory of this source tree. */ -#import "RCTTraceUpdateOverlayComponentView.h" +#import "RCTDebuggingOverlayComponentView.h" +#import #import #import -#import #import #import @@ -20,17 +20,17 @@ using namespace facebook::react; -@implementation RCTTraceUpdateOverlayComponentView { - RCTTraceUpdateOverlay *_overlay; +@implementation RCTDebuggingOverlayComponentView { + RCTDebuggingOverlay *_overlay; } - (instancetype)initWithFrame:(CGRect)frame { if (self = [super initWithFrame:frame]) { - static const auto defaultProps = std::make_shared(); + static const auto defaultProps = std::make_shared(); _props = defaultProps; - _overlay = [[RCTTraceUpdateOverlay alloc] initWithFrame:self.bounds]; + _overlay = [[RCTDebuggingOverlay alloc] initWithFrame:self.bounds]; self.contentView = _overlay; } @@ -42,14 +42,14 @@ - (instancetype)initWithFrame:(CGRect)frame + (ComponentDescriptorProvider)componentDescriptorProvider { - return concreteComponentDescriptorProvider(); + return concreteComponentDescriptorProvider(); } #pragma mark - Native commands - (void)handleCommand:(const NSString *)commandName args:(const NSArray *)args { - RCTTraceUpdateOverlayHandleCommand(self, commandName, args); + RCTDebuggingOverlayHandleCommand(self, commandName, args); } - (void)draw:(NSString *)overlays @@ -59,7 +59,7 @@ - (void)draw:(NSString *)overlays @end -Class RCTTraceUpdateOverlayCls(void) +Class RCTDebuggingOverlayCls(void) { - return RCTTraceUpdateOverlayComponentView.class; + return RCTDebuggingOverlayComponentView.class; } diff --git a/packages/react-native/React/Fabric/Mounting/ComponentViews/RCTFabricComponentsPlugins.h b/packages/react-native/React/Fabric/Mounting/ComponentViews/RCTFabricComponentsPlugins.h index 51912e25dcd143..54936a93de7c5c 100644 --- a/packages/react-native/React/Fabric/Mounting/ComponentViews/RCTFabricComponentsPlugins.h +++ b/packages/react-native/React/Fabric/Mounting/ComponentViews/RCTFabricComponentsPlugins.h @@ -31,6 +31,7 @@ Class RCTFabricComponentsProvider(const char *name); // Lookup functions Class RCTActivityIndicatorViewCls(void) __attribute__((used)); +Class RCTDebuggingOverlayCls(void) __attribute__((used)); Class RCTInputAccessoryCls(void) __attribute__((used)); Class RCTParagraphCls(void) __attribute__((used)); Class RCTPullToRefreshViewCls(void) __attribute__((used)); @@ -38,7 +39,6 @@ Class RCTSafeAreaViewCls(void) __attribute__((used)); Class RCTScrollViewCls(void) __attribute__((used)); Class RCTSwitchCls(void) __attribute__((used)); Class RCTTextInputCls(void) __attribute__((used)); -Class RCTTraceUpdateOverlayCls(void) __attribute__((used)); Class RCTUnimplementedNativeViewCls(void) __attribute__((used)); Class RCTViewCls(void) __attribute__((used)); Class RCTImageCls(void) __attribute__((used)); diff --git a/packages/react-native/React/Fabric/Mounting/ComponentViews/RCTFabricComponentsPlugins.mm b/packages/react-native/React/Fabric/Mounting/ComponentViews/RCTFabricComponentsPlugins.mm index dff4412f48ab38..f07b0301cd28a5 100644 --- a/packages/react-native/React/Fabric/Mounting/ComponentViews/RCTFabricComponentsPlugins.mm +++ b/packages/react-native/React/Fabric/Mounting/ComponentViews/RCTFabricComponentsPlugins.mm @@ -19,6 +19,7 @@ Class RCTFabricComponentsProvider(const char *name) { static std::unordered_map sFabricComponentsClassMap = { {"ActivityIndicatorView", RCTActivityIndicatorViewCls}, + {"DebuggingOverlay", RCTDebuggingOverlayCls}, {"InputAccessoryView", RCTInputAccessoryCls}, {"Paragraph", RCTParagraphCls}, {"PullToRefreshView", RCTPullToRefreshViewCls}, @@ -26,7 +27,6 @@ {"ScrollView", RCTScrollViewCls}, {"Switch", RCTSwitchCls}, {"TextInput", RCTTextInputCls}, - {"TraceUpdateOverlay", RCTTraceUpdateOverlayCls}, {"UnimplementedNativeView", RCTUnimplementedNativeViewCls}, {"View", RCTViewCls}, {"Image", RCTImageCls}, diff --git a/packages/react-native/React/Views/RCTTraceUpdateOverlay.h b/packages/react-native/React/Views/RCTDebuggingOverlay.h similarity index 87% rename from packages/react-native/React/Views/RCTTraceUpdateOverlay.h rename to packages/react-native/React/Views/RCTDebuggingOverlay.h index 480883044d2e49..64b7d1feb03e45 100644 --- a/packages/react-native/React/Views/RCTTraceUpdateOverlay.h +++ b/packages/react-native/React/Views/RCTDebuggingOverlay.h @@ -9,7 +9,7 @@ #import -@interface RCTTraceUpdateOverlay : RCTView +@interface RCTDebuggingOverlay : RCTView - (void)draw:(NSString *)serializedNodes; diff --git a/packages/react-native/React/Views/RCTTraceUpdateOverlay.m b/packages/react-native/React/Views/RCTDebuggingOverlay.m similarity index 93% rename from packages/react-native/React/Views/RCTTraceUpdateOverlay.m rename to packages/react-native/React/Views/RCTDebuggingOverlay.m index 198f46b94429b6..992862bd5ec2f0 100644 --- a/packages/react-native/React/Views/RCTTraceUpdateOverlay.m +++ b/packages/react-native/React/Views/RCTDebuggingOverlay.m @@ -5,13 +5,13 @@ * LICENSE file in the root directory of this source tree. */ -#import "RCTTraceUpdateOverlay.h" +#import "RCTDebuggingOverlay.h" #import #import #import -@implementation RCTTraceUpdateOverlay +@implementation RCTDebuggingOverlay - (void)draw:(NSString *)serializedNodes { @@ -24,7 +24,7 @@ - (void)draw:(NSString *)serializedNodes id deserializedNodes = RCTJSONParse(serializedNodes, &error); if (error) { - RCTLogError(@"Failed to parse serialized nodes passed to RCTTraceUpdatesOverlay"); + RCTLogError(@"Failed to parse serialized nodes passed to RCTDebuggingOverlay"); return; } diff --git a/packages/react-native/React/Views/RCTTraceUpdateOverlayManager.h b/packages/react-native/React/Views/RCTDebuggingOverlayManager.h similarity index 80% rename from packages/react-native/React/Views/RCTTraceUpdateOverlayManager.h rename to packages/react-native/React/Views/RCTDebuggingOverlayManager.h index f50680420dc332..a852cc81883e19 100644 --- a/packages/react-native/React/Views/RCTTraceUpdateOverlayManager.h +++ b/packages/react-native/React/Views/RCTDebuggingOverlayManager.h @@ -7,6 +7,6 @@ #import -@interface RCTTraceUpdateOverlayManager : RCTViewManager +@interface RCTDebuggingOverlayManager : RCTViewManager @end diff --git a/packages/react-native/React/Views/RCTTraceUpdateOverlayManager.m b/packages/react-native/React/Views/RCTDebuggingOverlayManager.m similarity index 57% rename from packages/react-native/React/Views/RCTTraceUpdateOverlayManager.m rename to packages/react-native/React/Views/RCTDebuggingOverlayManager.m index 8386b94941d997..ae00c27ac2e23a 100644 --- a/packages/react-native/React/Views/RCTTraceUpdateOverlayManager.m +++ b/packages/react-native/React/Views/RCTDebuggingOverlayManager.m @@ -5,21 +5,21 @@ * LICENSE file in the root directory of this source tree. */ -#import "RCTTraceUpdateOverlayManager.h" -#import "RCTTraceUpdateOverlay.h" +#import "RCTDebuggingOverlayManager.h" +#import "RCTDebuggingOverlay.h" #import #import #import "RCTBridge.h" -@implementation RCTTraceUpdateOverlayManager +@implementation RCTDebuggingOverlayManager -RCT_EXPORT_MODULE(TraceUpdateOverlay) +RCT_EXPORT_MODULE(DebuggingOverlay) - (UIView *)view { - return [RCTTraceUpdateOverlay new]; + return [RCTDebuggingOverlay new]; } RCT_EXPORT_METHOD(draw : (nonnull NSNumber *)viewTag nodes : (NSString *)serializedNodes) @@ -27,10 +27,10 @@ - (UIView *)view [self.bridge.uiManager addUIBlock:^(RCTUIManager *uiManager, NSDictionary *viewRegistry) { UIView *view = viewRegistry[viewTag]; - if ([view isKindOfClass:[RCTTraceUpdateOverlay class]]) { - [(RCTTraceUpdateOverlay *)view draw:serializedNodes]; + if ([view isKindOfClass:[RCTDebuggingOverlay class]]) { + [(RCTDebuggingOverlay *)view draw:serializedNodes]; } else { - RCTLogError(@"Expected view to be RCTTraceUpdateOverlay, got %@", NSStringFromClass([view class])); + RCTLogError(@"Expected view to be RCTDebuggingOverlay, got %@", NSStringFromClass([view class])); } }]; } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/DebugCorePackage.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/DebugCorePackage.java index 398b69ac1a5684..69471937ab8501 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/DebugCorePackage.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/DebugCorePackage.java @@ -19,7 +19,7 @@ import com.facebook.react.module.model.ReactModuleInfoProvider; import com.facebook.react.uimanager.UIManagerModule; import com.facebook.react.uimanager.ViewManager; -import com.facebook.react.views.traceupdateoverlay.TraceUpdateOverlayManager; +import com.facebook.react.views.debuggingoverlay.DebuggingOverlayManager; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; @@ -96,8 +96,7 @@ private static void appendMap( private Map getViewManagersMap() { if (mViewManagers == null) { Map viewManagers = new HashMap<>(); - appendMap( - viewManagers, TraceUpdateOverlayManager.REACT_CLASS, TraceUpdateOverlayManager::new); + appendMap(viewManagers, DebuggingOverlayManager.REACT_CLASS, DebuggingOverlayManager::new); mViewManagers = viewManagers; } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/traceupdateoverlay/TraceUpdateOverlay.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/debuggingoverlay/DebuggingOverlay.java similarity index 92% rename from packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/traceupdateoverlay/TraceUpdateOverlay.java rename to packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/debuggingoverlay/DebuggingOverlay.java index 6799848284828f..0ebaf4b8743866 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/traceupdateoverlay/TraceUpdateOverlay.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/debuggingoverlay/DebuggingOverlay.java @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -package com.facebook.react.views.traceupdateoverlay; +package com.facebook.react.views.debuggingoverlay; import android.content.Context; import android.graphics.Canvas; @@ -17,7 +17,7 @@ import java.util.ArrayList; import java.util.List; -public class TraceUpdateOverlay extends View { +public class DebuggingOverlay extends View { private final Paint mOverlayPaint = new Paint(); private List mOverlays = new ArrayList(); @@ -43,7 +43,7 @@ public RectF getPixelRect() { } } - public TraceUpdateOverlay(Context context) { + public DebuggingOverlay(Context context) { super(context); mOverlayPaint.setStyle(Paint.Style.STROKE); mOverlayPaint.setStrokeWidth(6); diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/traceupdateoverlay/TraceUpdateOverlayManager.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/debuggingoverlay/DebuggingOverlayManager.java similarity index 76% rename from packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/traceupdateoverlay/TraceUpdateOverlayManager.java rename to packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/debuggingoverlay/DebuggingOverlayManager.java index 434be098b1a2fa..cacdd5c4dbfeda 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/traceupdateoverlay/TraceUpdateOverlayManager.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/debuggingoverlay/DebuggingOverlayManager.java @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -package com.facebook.react.views.traceupdateoverlay; +package com.facebook.react.views.debuggingoverlay; import android.graphics.RectF; import androidx.annotation.Nullable; @@ -16,22 +16,22 @@ import com.facebook.react.module.annotations.ReactModule; import com.facebook.react.uimanager.SimpleViewManager; import com.facebook.react.uimanager.ThemedReactContext; -import com.facebook.react.views.traceupdateoverlay.TraceUpdateOverlay.Overlay; +import com.facebook.react.views.debuggingoverlay.DebuggingOverlay.Overlay; import java.util.ArrayList; import java.util.List; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; -@ReactModule(name = TraceUpdateOverlayManager.REACT_CLASS) -public class TraceUpdateOverlayManager extends SimpleViewManager { - public static final String REACT_CLASS = "TraceUpdateOverlay"; +@ReactModule(name = DebuggingOverlayManager.REACT_CLASS) +public class DebuggingOverlayManager extends SimpleViewManager { + public static final String REACT_CLASS = "DebuggingOverlay"; - public TraceUpdateOverlayManager() {} + public DebuggingOverlayManager() {} @Override public void receiveCommand( - TraceUpdateOverlay view, String commandId, @Nullable ReadableArray args) { + DebuggingOverlay view, String commandId, @Nullable ReadableArray args) { switch (commandId) { case "draw": if (args == null) { @@ -67,13 +67,13 @@ public void receiveCommand( ReactSoftExceptionLogger.logSoftException( REACT_CLASS, new ReactNoCrashSoftException( - "Received unexpected command in TraceUpdateOverlayManager")); + "Received unexpected command in DebuggingOverlayManager")); } } @Override - public TraceUpdateOverlay createViewInstance(ThemedReactContext context) { - return new TraceUpdateOverlay(context); + public DebuggingOverlay createViewInstance(ThemedReactContext context) { + return new DebuggingOverlay(context); } @Override diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/fabric/CoreComponentsRegistry.cpp b/packages/react-native/ReactAndroid/src/main/jni/react/fabric/CoreComponentsRegistry.cpp index 5cc5aae68d5bff..99ddee8b3b1dd1 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/fabric/CoreComponentsRegistry.cpp +++ b/packages/react-native/ReactAndroid/src/main/jni/react/fabric/CoreComponentsRegistry.cpp @@ -66,7 +66,7 @@ CoreComponentsRegistry::sharedProviderRegistry() { providerRegistry->add(concreteComponentDescriptorProvider< AndroidDrawerLayoutComponentDescriptor>()); providerRegistry->add(concreteComponentDescriptorProvider< - TraceUpdateOverlayComponentDescriptor>()); + DebuggingOverlayComponentDescriptor>()); return providerRegistry; }(); From b71bb817186a839f7881fded6be5c6f92fa2d1a6 Mon Sep 17 00:00:00 2001 From: Ruslan Lesiutin Date: Thu, 23 Nov 2023 07:53:24 -0800 Subject: [PATCH 081/162] refactor[AppContainer]: remove innerView ref from state (#41613) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41613 Changelog: [Internal] We were keeping ref in the AppContainer's state before migrating these components to functions. We actually need a real ref here, so we can use `useImperativeHandle` on it later. These refs will be passed as an argument for DebuggingRegistry subscription, whichi will call them on all necessary AppContainers to highlight required components. Reviewed By: javache Differential Revision: D51536772 fbshipit-source-id: d49035874ce3c9b1acf08d5ab666886f68e6f40e --- .../Libraries/Inspector/Inspector.js | 7 ++-- .../Inspector/ReactDevToolsOverlay.js | 42 ++++++++++--------- .../Libraries/ReactNative/AppContainer-dev.js | 17 ++++---- 3 files changed, 33 insertions(+), 33 deletions(-) diff --git a/packages/react-native/Libraries/Inspector/Inspector.js b/packages/react-native/Libraries/Inspector/Inspector.js index f22c5457756b5a..dc274521388903 100644 --- a/packages/react-native/Libraries/Inspector/Inspector.js +++ b/packages/react-native/Libraries/Inspector/Inspector.js @@ -16,7 +16,6 @@ import type { } from '../Renderer/shims/ReactNativeTypes'; import type {ViewStyleProp} from '../StyleSheet/StyleSheet'; import type {ReactDevToolsAgent} from '../Types/ReactDevToolsTypes'; -import type {HostRef} from './getInspectorDataForViewAtPoint'; const View = require('../Components/View/View'); const PressabilityDebug = require('../Pressability/PressabilityDebug'); @@ -47,13 +46,13 @@ export type InspectedElement = $ReadOnly<{ export type ElementsHierarchy = InspectorData['hierarchy']; type Props = { - inspectedView: ?HostRef, + inspectedViewRef: React.RefObject | null>, onRequestRerenderApp: () => void, reactDevToolsAgent?: ReactDevToolsAgent, }; function Inspector({ - inspectedView, + inspectedViewRef, onRequestRerenderApp, reactDevToolsAgent, }: Props): React.Node { @@ -126,7 +125,7 @@ function Inspector({ }; getInspectorDataForViewAtPoint( - inspectedView, + inspectedViewRef.current, locationX, locationY, viewData => { diff --git a/packages/react-native/Libraries/Inspector/ReactDevToolsOverlay.js b/packages/react-native/Libraries/Inspector/ReactDevToolsOverlay.js index 04959ca766e6c3..cca9e7e8b7dc88 100644 --- a/packages/react-native/Libraries/Inspector/ReactDevToolsOverlay.js +++ b/packages/react-native/Libraries/Inspector/ReactDevToolsOverlay.js @@ -14,7 +14,6 @@ import type { InstanceFromReactDevTools, ReactDevToolsAgent, } from '../Types/ReactDevToolsTypes'; -import type {HostRef} from './getInspectorDataForViewAtPoint'; import type {InspectedElement} from './Inspector'; import View from '../Components/View/View'; @@ -30,12 +29,12 @@ const getInspectorDataForViewAtPoint = require('./getInspectorDataForViewAtPoint const {useEffect, useState, useCallback} = React; type Props = { - inspectedView: ?HostRef, + inspectedViewRef: React.RefObject | null>, reactDevToolsAgent: ReactDevToolsAgent, }; export default function ReactDevToolsOverlay({ - inspectedView, + inspectedViewRef, reactDevToolsAgent, }: Props): React.Node { const [inspected, setInspected] = useState(null); @@ -125,24 +124,29 @@ export default function ReactDevToolsOverlay({ const findViewForLocation = useCallback( (x: number, y: number) => { - getInspectorDataForViewAtPoint(inspectedView, x, y, viewData => { - const {touchedViewTag, closestInstance, frame} = viewData; - if (closestInstance != null || touchedViewTag != null) { - // We call `selectNode` for both non-fabric(viewTag) and fabric(instance), - // this makes sure it works for both architectures. - reactDevToolsAgent.selectNode(findNodeHandle(touchedViewTag)); - if (closestInstance != null) { - reactDevToolsAgent.selectNode(closestInstance); + getInspectorDataForViewAtPoint( + inspectedViewRef.current, + x, + y, + viewData => { + const {touchedViewTag, closestInstance, frame} = viewData; + if (closestInstance != null || touchedViewTag != null) { + // We call `selectNode` for both non-fabric(viewTag) and fabric(instance), + // this makes sure it works for both architectures. + reactDevToolsAgent.selectNode(findNodeHandle(touchedViewTag)); + if (closestInstance != null) { + reactDevToolsAgent.selectNode(closestInstance); + } + setInspected({ + frame, + }); + return true; } - setInspected({ - frame, - }); - return true; - } - return false; - }); + return false; + }, + ); }, - [inspectedView, reactDevToolsAgent], + [inspectedViewRef, reactDevToolsAgent], ); const stopInspecting = useCallback(() => { diff --git a/packages/react-native/Libraries/ReactNative/AppContainer-dev.js b/packages/react-native/Libraries/ReactNative/AppContainer-dev.js index 4e7f2c43e6b077..3e4fe8389610e7 100644 --- a/packages/react-native/Libraries/ReactNative/AppContainer-dev.js +++ b/packages/react-native/Libraries/ReactNative/AppContainer-dev.js @@ -18,7 +18,6 @@ import type {Props} from './AppContainer'; import TraceUpdateOverlay from '../Components/TraceUpdateOverlay/TraceUpdateOverlay'; import ReactNativeStyleAttributes from '../Components/View/ReactNativeStyleAttributes'; import View from '../Components/View/View'; -import ViewNativeComponent from '../Components/View/ViewNativeComponent'; import RCTDeviceEventEmitter from '../EventEmitter/RCTDeviceEventEmitter'; import ReactDevToolsOverlay from '../Inspector/ReactDevToolsOverlay'; import LogBoxNotificationContainer from '../LogBox/LogBoxNotificationContainer'; @@ -41,13 +40,13 @@ if (reactDevToolsHook) { } type InspectorDeferredProps = { - inspectedView: React.ElementRef | null, + inspectedViewRef: React.RefObject | null>, onInspectedViewRerenderRequest: () => void, reactDevToolsAgent?: ReactDevToolsAgent, }; const InspectorDeferred = ({ - inspectedView, + inspectedViewRef, onInspectedViewRerenderRequest, reactDevToolsAgent, }: InspectorDeferredProps) => { @@ -57,7 +56,7 @@ const InspectorDeferred = ({ return ( @@ -74,9 +73,7 @@ const AppContainer = ({ showArchitectureIndicator, WrapperComponent, }: Props): React.Node => { - const [mainRef, setMainRef] = useState | null>(null); + const innerViewRef = React.useRef | null>(null); const [key, setKey] = useState(0); const [shouldRenderInspector, setShouldRenderInspector] = useState(false); @@ -118,7 +115,7 @@ const AppContainer = ({ pointerEvents="box-none" key={key} style={styles.container} - ref={setMainRef}> + ref={innerViewRef}> {children} ); @@ -149,14 +146,14 @@ const AppContainer = ({ )} {reactDevToolsAgent != null && ( )} {shouldRenderInspector && ( From 342041e9ee0f4c72b70a19f290a79040c200f859 Mon Sep 17 00:00:00 2001 From: Ruslan Shestopalyuk Date: Thu, 23 Nov 2023 10:34:32 -0800 Subject: [PATCH 082/162] Fix static view config not to filter out "onClick" events on Android (#41628) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41628 # Changelog: Even though `onClick` is used on Android (e.g. via Pressability), the fact of having the handler registered didn't get through to the C++ side on New Architecture, because of being filtered out via the corresponding static view config. As the result, there was no way to know on C++ side whether the corresponding event handler is registered for the view or not. Dynamic updates to the prop also wouldn't correctly propagate to C++, which may be a problem if a view gets e.g. the handler dynamically added. Reviewed By: javache Differential Revision: D51551255 fbshipit-source-id: 0783f5a27c7250f83fb357173bbe5be6213277e5 --- .../Libraries/NativeComponent/BaseViewConfig.android.js | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/react-native/Libraries/NativeComponent/BaseViewConfig.android.js b/packages/react-native/Libraries/NativeComponent/BaseViewConfig.android.js index 0326ec9afd621d..a077a2b1f5f3b2 100644 --- a/packages/react-native/Libraries/NativeComponent/BaseViewConfig.android.js +++ b/packages/react-native/Libraries/NativeComponent/BaseViewConfig.android.js @@ -304,6 +304,7 @@ const validAttributesForEventProps = { onTouchCancel: true, // Pointer events + onClick: true, onPointerEnter: true, onPointerEnterCapture: true, onPointerLeave: true, From f1dc061fceb627863c1f8b54e63933e93e64bcd3 Mon Sep 17 00:00:00 2001 From: Pieter De Baets Date: Thu, 23 Nov 2023 14:05:17 -0800 Subject: [PATCH 083/162] Use defaultSharedProps in ComponentView init (#41623) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41623 `static` fields require additional code to ensure the field is only ever initialized once. We already have a static "default props" field in the shadow node, so let's reuse that as much as possible. Changelog: [Internal] Reviewed By: rshest Differential Revision: D51547638 fbshipit-source-id: e4957ffb0f9352847b8cd8dc3a010dcfac8be699 --- .../RCTActivityIndicatorViewComponentView.mm | 2 +- .../DebuggingOverlay/RCTDebuggingOverlayComponentView.mm | 4 +--- .../Mounting/ComponentViews/Image/RCTImageComponentView.mm | 2 +- .../InputAccessory/RCTInputAccessoryComponentView.mm | 3 +-- .../RCTLegacyViewManagerInteropComponentView.mm | 3 +-- .../ComponentViews/Modal/RCTModalHostViewComponentView.mm | 3 +-- .../Mounting/ComponentViews/Root/RCTRootComponentView.mm | 3 +-- .../SafeAreaView/RCTSafeAreaViewComponentView.mm | 3 +-- .../ScrollView/RCTPullToRefreshViewComponentView.mm | 3 +-- .../ComponentViews/ScrollView/RCTScrollViewComponentView.mm | 3 +-- .../Mounting/ComponentViews/Switch/RCTSwitchComponentView.mm | 3 +-- .../ComponentViews/Text/RCTParagraphComponentView.mm | 3 +-- .../ComponentViews/TextInput/RCTTextInputComponentView.mm | 5 ++--- .../RCTUnimplementedNativeComponentView.mm | 3 +-- .../UnimplementedView/RCTUnimplementedViewComponentView.mm | 3 +-- .../Mounting/ComponentViews/View/RCTViewComponentView.mm | 3 +-- .../ReactCommon/react/renderer/core/ConcreteShadowNode.h | 2 +- 17 files changed, 18 insertions(+), 33 deletions(-) diff --git a/packages/react-native/React/Fabric/Mounting/ComponentViews/ActivityIndicator/RCTActivityIndicatorViewComponentView.mm b/packages/react-native/React/Fabric/Mounting/ComponentViews/ActivityIndicator/RCTActivityIndicatorViewComponentView.mm index 09b6b70700a27a..4d0c75f282ee5d 100644 --- a/packages/react-native/React/Fabric/Mounting/ComponentViews/ActivityIndicator/RCTActivityIndicatorViewComponentView.mm +++ b/packages/react-native/React/Fabric/Mounting/ComponentViews/ActivityIndicator/RCTActivityIndicatorViewComponentView.mm @@ -41,7 +41,7 @@ + (ComponentDescriptorProvider)componentDescriptorProvider - (instancetype)initWithFrame:(CGRect)frame { if (self = [super initWithFrame:frame]) { - static const auto defaultProps = std::make_shared(); + const auto &defaultProps = ActivityIndicatorViewShadowNode::defaultSharedProps(); _props = defaultProps; _activityIndicatorView = [[UIActivityIndicatorView alloc] initWithFrame:self.bounds]; diff --git a/packages/react-native/React/Fabric/Mounting/ComponentViews/DebuggingOverlay/RCTDebuggingOverlayComponentView.mm b/packages/react-native/React/Fabric/Mounting/ComponentViews/DebuggingOverlay/RCTDebuggingOverlayComponentView.mm index 31d1dcb5f77962..c9ac90286f9c4c 100644 --- a/packages/react-native/React/Fabric/Mounting/ComponentViews/DebuggingOverlay/RCTDebuggingOverlayComponentView.mm +++ b/packages/react-native/React/Fabric/Mounting/ComponentViews/DebuggingOverlay/RCTDebuggingOverlayComponentView.mm @@ -27,9 +27,7 @@ @implementation RCTDebuggingOverlayComponentView { - (instancetype)initWithFrame:(CGRect)frame { if (self = [super initWithFrame:frame]) { - static const auto defaultProps = std::make_shared(); - _props = defaultProps; - + _props = DebuggingOverlayShadowNode::defaultSharedProps(); _overlay = [[RCTDebuggingOverlay alloc] initWithFrame:self.bounds]; self.contentView = _overlay; diff --git a/packages/react-native/React/Fabric/Mounting/ComponentViews/Image/RCTImageComponentView.mm b/packages/react-native/React/Fabric/Mounting/ComponentViews/Image/RCTImageComponentView.mm index e48d5470179e4f..2de560d78f74b3 100644 --- a/packages/react-native/React/Fabric/Mounting/ComponentViews/Image/RCTImageComponentView.mm +++ b/packages/react-native/React/Fabric/Mounting/ComponentViews/Image/RCTImageComponentView.mm @@ -28,7 +28,7 @@ @implementation RCTImageComponentView { - (instancetype)initWithFrame:(CGRect)frame { if (self = [super initWithFrame:frame]) { - static const auto defaultProps = std::make_shared(); + const auto &defaultProps = ImageShadowNode::defaultSharedProps(); _props = defaultProps; _imageView = [RCTUIImageViewAnimated new]; diff --git a/packages/react-native/React/Fabric/Mounting/ComponentViews/InputAccessory/RCTInputAccessoryComponentView.mm b/packages/react-native/React/Fabric/Mounting/ComponentViews/InputAccessory/RCTInputAccessoryComponentView.mm index 454c3ff1ac279d..6ace11ce5ab012 100644 --- a/packages/react-native/React/Fabric/Mounting/ComponentViews/InputAccessory/RCTInputAccessoryComponentView.mm +++ b/packages/react-native/React/Fabric/Mounting/ComponentViews/InputAccessory/RCTInputAccessoryComponentView.mm @@ -50,8 +50,7 @@ @implementation RCTInputAccessoryComponentView { - (instancetype)initWithFrame:(CGRect)frame { if (self = [super initWithFrame:frame]) { - static const auto defaultProps = std::make_shared(); - _props = defaultProps; + _props = InputAccessoryShadowNode::defaultSharedProps(); _contentView = [RCTInputAccessoryContentView new]; _touchHandler = [RCTSurfaceTouchHandler new]; [_touchHandler attachToView:_contentView]; diff --git a/packages/react-native/React/Fabric/Mounting/ComponentViews/LegacyViewManagerInterop/RCTLegacyViewManagerInteropComponentView.mm b/packages/react-native/React/Fabric/Mounting/ComponentViews/LegacyViewManagerInterop/RCTLegacyViewManagerInteropComponentView.mm index 42fa691dfebd55..86aee3223d7659 100644 --- a/packages/react-native/React/Fabric/Mounting/ComponentViews/LegacyViewManagerInterop/RCTLegacyViewManagerInteropComponentView.mm +++ b/packages/react-native/React/Fabric/Mounting/ComponentViews/LegacyViewManagerInterop/RCTLegacyViewManagerInteropComponentView.mm @@ -31,8 +31,7 @@ @implementation RCTLegacyViewManagerInteropComponentView { - (instancetype)initWithFrame:(CGRect)frame { if (self = [super initWithFrame:frame]) { - static const auto defaultProps = std::make_shared(); - _props = defaultProps; + _props = LegacyViewManagerInteropShadowNode::defaultSharedProps(); _viewsToBeMounted = [NSMutableArray new]; _viewsToBeUnmounted = [NSMutableArray new]; _hasInvokedForwardingWarning = NO; diff --git a/packages/react-native/React/Fabric/Mounting/ComponentViews/Modal/RCTModalHostViewComponentView.mm b/packages/react-native/React/Fabric/Mounting/ComponentViews/Modal/RCTModalHostViewComponentView.mm index 445a5c79a5afaf..e20eee608a01c6 100644 --- a/packages/react-native/React/Fabric/Mounting/ComponentViews/Modal/RCTModalHostViewComponentView.mm +++ b/packages/react-native/React/Fabric/Mounting/ComponentViews/Modal/RCTModalHostViewComponentView.mm @@ -110,8 +110,7 @@ @implementation RCTModalHostViewComponentView { - (instancetype)initWithFrame:(CGRect)frame { if (self = [super initWithFrame:frame]) { - static const auto defaultProps = std::make_shared(); - _props = defaultProps; + _props = ModalHostViewShadowNode::defaultSharedProps(); _shouldAnimatePresentation = YES; _isPresented = NO; diff --git a/packages/react-native/React/Fabric/Mounting/ComponentViews/Root/RCTRootComponentView.mm b/packages/react-native/React/Fabric/Mounting/ComponentViews/Root/RCTRootComponentView.mm index 4efa8b34b4a7a0..eb81a151c3fc41 100644 --- a/packages/react-native/React/Fabric/Mounting/ComponentViews/Root/RCTRootComponentView.mm +++ b/packages/react-native/React/Fabric/Mounting/ComponentViews/Root/RCTRootComponentView.mm @@ -18,8 +18,7 @@ @implementation RCTRootComponentView - (instancetype)initWithFrame:(CGRect)frame { if (self = [super initWithFrame:frame]) { - static const auto defaultProps = std::make_shared(); - _props = defaultProps; + _props = RootShadowNode::defaultSharedProps(); } return self; diff --git a/packages/react-native/React/Fabric/Mounting/ComponentViews/SafeAreaView/RCTSafeAreaViewComponentView.mm b/packages/react-native/React/Fabric/Mounting/ComponentViews/SafeAreaView/RCTSafeAreaViewComponentView.mm index 4c9060f1a622fd..709e378ad49d83 100644 --- a/packages/react-native/React/Fabric/Mounting/ComponentViews/SafeAreaView/RCTSafeAreaViewComponentView.mm +++ b/packages/react-native/React/Fabric/Mounting/ComponentViews/SafeAreaView/RCTSafeAreaViewComponentView.mm @@ -22,8 +22,7 @@ @implementation RCTSafeAreaViewComponentView { - (instancetype)initWithFrame:(CGRect)frame { if (self = [super initWithFrame:frame]) { - static const auto defaultProps = std::make_shared(); - _props = defaultProps; + _props = SafeAreaViewShadowNode::defaultSharedProps(); } return self; diff --git a/packages/react-native/React/Fabric/Mounting/ComponentViews/ScrollView/RCTPullToRefreshViewComponentView.mm b/packages/react-native/React/Fabric/Mounting/ComponentViews/ScrollView/RCTPullToRefreshViewComponentView.mm index 231777cd48950a..64b09228a397e5 100644 --- a/packages/react-native/React/Fabric/Mounting/ComponentViews/ScrollView/RCTPullToRefreshViewComponentView.mm +++ b/packages/react-native/React/Fabric/Mounting/ComponentViews/ScrollView/RCTPullToRefreshViewComponentView.mm @@ -36,8 +36,7 @@ - (instancetype)initWithFrame:(CGRect)frame // The pull-to-refresh view is not a subview of this view. self.hidden = YES; - static const auto defaultProps = std::make_shared(); - _props = defaultProps; + _props = PullToRefreshViewShadowNode::defaultSharedProps(); _refreshControl = [UIRefreshControl new]; [_refreshControl addTarget:self diff --git a/packages/react-native/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm b/packages/react-native/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm index 504b0ef147ae0b..8272db8c85082c 100644 --- a/packages/react-native/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm +++ b/packages/react-native/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm @@ -118,8 +118,7 @@ + (RCTScrollViewComponentView *_Nullable)findScrollViewComponentViewForView:(UIV - (instancetype)initWithFrame:(CGRect)frame { if (self = [super initWithFrame:frame]) { - static const auto defaultProps = std::make_shared(); - _props = defaultProps; + _props = ScrollViewShadowNode::defaultSharedProps(); _scrollView = [[RCTEnhancedScrollView alloc] initWithFrame:self.bounds]; _scrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; diff --git a/packages/react-native/React/Fabric/Mounting/ComponentViews/Switch/RCTSwitchComponentView.mm b/packages/react-native/React/Fabric/Mounting/ComponentViews/Switch/RCTSwitchComponentView.mm index d4ed3860e474c7..941ad9b7f0978e 100644 --- a/packages/react-native/React/Fabric/Mounting/ComponentViews/Switch/RCTSwitchComponentView.mm +++ b/packages/react-native/React/Fabric/Mounting/ComponentViews/Switch/RCTSwitchComponentView.mm @@ -29,8 +29,7 @@ @implementation RCTSwitchComponentView { - (instancetype)initWithFrame:(CGRect)frame { if (self = [super initWithFrame:frame]) { - static const auto defaultProps = std::make_shared(); - _props = defaultProps; + _props = SwitchShadowNode::defaultSharedProps(); _switchView = [[UISwitch alloc] initWithFrame:self.bounds]; diff --git a/packages/react-native/React/Fabric/Mounting/ComponentViews/Text/RCTParagraphComponentView.mm b/packages/react-native/React/Fabric/Mounting/ComponentViews/Text/RCTParagraphComponentView.mm index fce427848a9c11..0787ef71cafe8e 100644 --- a/packages/react-native/React/Fabric/Mounting/ComponentViews/Text/RCTParagraphComponentView.mm +++ b/packages/react-native/React/Fabric/Mounting/ComponentViews/Text/RCTParagraphComponentView.mm @@ -40,8 +40,7 @@ @implementation RCTParagraphComponentView { - (instancetype)initWithFrame:(CGRect)frame { if (self = [super initWithFrame:frame]) { - static const auto defaultProps = std::make_shared(); - _props = defaultProps; + _props = ParagraphShadowNode::defaultSharedProps(); self.opaque = NO; self.contentMode = UIViewContentModeRedraw; diff --git a/packages/react-native/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputComponentView.mm b/packages/react-native/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputComponentView.mm index e7b69bff2f9e68..44e74da5cea06f 100644 --- a/packages/react-native/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputComponentView.mm +++ b/packages/react-native/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputComponentView.mm @@ -62,11 +62,10 @@ @implementation RCTTextInputComponentView { - (instancetype)initWithFrame:(CGRect)frame { if (self = [super initWithFrame:frame]) { - static const auto defaultProps = std::make_shared(); + const auto &defaultProps = TextInputShadowNode::defaultSharedProps(); _props = defaultProps; - auto &props = *defaultProps; - _backedTextInputView = props.traits.multiline ? [RCTUITextView new] : [RCTUITextField new]; + _backedTextInputView = defaultProps->traits.multiline ? [RCTUITextView new] : [RCTUITextField new]; _backedTextInputView.textInputDelegate = self; _ignoreNextTextInputCall = NO; _comingFromJS = NO; diff --git a/packages/react-native/React/Fabric/Mounting/ComponentViews/UnimplementedComponent/RCTUnimplementedNativeComponentView.mm b/packages/react-native/React/Fabric/Mounting/ComponentViews/UnimplementedComponent/RCTUnimplementedNativeComponentView.mm index fc39e2592de4d0..fe4c9f6a65b142 100644 --- a/packages/react-native/React/Fabric/Mounting/ComponentViews/UnimplementedComponent/RCTUnimplementedNativeComponentView.mm +++ b/packages/react-native/React/Fabric/Mounting/ComponentViews/UnimplementedComponent/RCTUnimplementedNativeComponentView.mm @@ -20,8 +20,7 @@ @implementation RCTUnimplementedNativeComponentView { - (instancetype)initWithFrame:(CGRect)frame { if (self = [super initWithFrame:frame]) { - static const auto defaultProps = std::make_shared(); - _props = defaultProps; + _props = UnimplementedNativeViewShadowNode::defaultSharedProps(); CGRect bounds = self.bounds; _label = [[UILabel alloc] initWithFrame:bounds]; diff --git a/packages/react-native/React/Fabric/Mounting/ComponentViews/UnimplementedView/RCTUnimplementedViewComponentView.mm b/packages/react-native/React/Fabric/Mounting/ComponentViews/UnimplementedView/RCTUnimplementedViewComponentView.mm index 6a9efe577fb045..b5185677875a13 100644 --- a/packages/react-native/React/Fabric/Mounting/ComponentViews/UnimplementedView/RCTUnimplementedViewComponentView.mm +++ b/packages/react-native/React/Fabric/Mounting/ComponentViews/UnimplementedView/RCTUnimplementedViewComponentView.mm @@ -27,8 +27,7 @@ @implementation RCTUnimplementedViewComponentView { - (instancetype)initWithFrame:(CGRect)frame { if (self = [super initWithFrame:frame]) { - static const auto defaultProps = std::make_shared(); - _props = defaultProps; + _props = UnimplementedViewShadowNode::defaultSharedProps(); _label = [[UILabel alloc] initWithFrame:self.bounds]; _label.backgroundColor = [UIColor colorWithRed:1.0 green:0.0 blue:0.0 alpha:0.3]; diff --git a/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm b/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm index 9fa696f7a49a72..6751018c889162 100644 --- a/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm +++ b/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm @@ -46,8 +46,7 @@ + (void)load - (instancetype)initWithFrame:(CGRect)frame { if (self = [super initWithFrame:frame]) { - static const auto defaultProps = std::make_shared(); - _props = defaultProps; + _props = ViewShadowNode::defaultSharedProps(); _reactSubviews = [NSMutableArray new]; self.multipleTouchEnabled = YES; } diff --git a/packages/react-native/ReactCommon/react/renderer/core/ConcreteShadowNode.h b/packages/react-native/ReactCommon/react/renderer/core/ConcreteShadowNode.h index e2a793b507185e..ab2ed6cf4da621 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/ConcreteShadowNode.h +++ b/packages/react-native/ReactCommon/react/renderer/core/ConcreteShadowNode.h @@ -85,7 +85,7 @@ class ConcreteShadowNode : public BaseShadowNodeT { rawProps); } - static SharedConcreteProps defaultSharedProps() { + static const SharedConcreteProps& defaultSharedProps() { static const SharedConcreteProps defaultSharedProps = std::make_shared(); return defaultSharedProps; From e441b06c68244311ddb4386a81aeb07b7201b258 Mon Sep 17 00:00:00 2001 From: Intl Scheduler <> Date: Thu, 23 Nov 2023 23:35:40 -0800 Subject: [PATCH 084/162] translation auto-update for i18n/fb4a.config.json on master Summary: Chronos Job Instance ID: 1125907943766151 Sandcastle Job Instance ID: 36028798137823401 allow-large-files ignore-conflict-markers opt-out-review Differential Revision: D51557751 fbshipit-source-id: 388d4f43881424ff389cc541602730aa32199693 --- .../src/main/res/views/uimanager/values-be/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/react-native/ReactAndroid/src/main/res/views/uimanager/values-be/strings.xml b/packages/react-native/ReactAndroid/src/main/res/views/uimanager/values-be/strings.xml index f61f41054f4697..c3859037c9b9b1 100644 --- a/packages/react-native/ReactAndroid/src/main/res/views/uimanager/values-be/strings.xml +++ b/packages/react-native/ReactAndroid/src/main/res/views/uimanager/values-be/strings.xml @@ -6,4 +6,5 @@ Спасылка Відарыс Кнопка, відарыс + Меню From 0707bbcb59658151f37040c6095883071a18cbca Mon Sep 17 00:00:00 2001 From: Ruslan Shestopalyuk Date: Fri, 24 Nov 2023 03:52:26 -0800 Subject: [PATCH 085/162] Remove dangling reference to preload.bzl file (#41634) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41634 # Changelog: [Internal]- The actual file was removed in https://github.com/facebook/react-native/pull/36900, but the reference still remains, confusing different tools. Reviewed By: sammy-SC Differential Revision: D51559281 fbshipit-source-id: 3c6fa8e1462c7e376fccb44909218328aaaabab4 --- .buckconfig | 3 --- 1 file changed, 3 deletions(-) diff --git a/.buckconfig b/.buckconfig index 3f1b5c6d11f092..272ffbbe1221a5 100644 --- a/.buckconfig +++ b/.buckconfig @@ -15,6 +15,3 @@ [alias] rntester = //packages/rn-tester/android/app:app - -[buildfile] - includes = //tools/build_defs/oss/preload.bzl From 67c852e82fe64ddd6555b0ead08bb50db9cace86 Mon Sep 17 00:00:00 2001 From: Samuel Susla Date: Fri, 24 Nov 2023 04:09:14 -0800 Subject: [PATCH 086/162] filter out yoga style props during folly::dynamic conversion (#41607) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41607 X-link: https://github.com/facebook/hermes/pull/1198 changelog: [internal] Reviewed By: javache Differential Revision: D51471665 fbshipit-source-id: 0633422d356c2f2419ea87b2a2ad6b5ea64c99f6 --- .../ReactCommon/jsi/jsi/JSIDynamic.cpp | 11 +- .../ReactCommon/jsi/jsi/JSIDynamic.h | 3 +- .../components/view/YogaStylableProps.cpp | 127 +----------------- .../core/ConcreteComponentDescriptor.h | 7 + .../react/renderer/core/RawProps.cpp | 99 +++++++++++++- .../react/renderer/core/RawProps.h | 11 ++ .../renderer/core/tests/RawPropsTest.cpp | 36 +++++ 7 files changed, 169 insertions(+), 125 deletions(-) diff --git a/packages/react-native/ReactCommon/jsi/jsi/JSIDynamic.cpp b/packages/react-native/ReactCommon/jsi/jsi/JSIDynamic.cpp index 02f112c0e0ca09..5a2d38d9dd3915 100644 --- a/packages/react-native/ReactCommon/jsi/jsi/JSIDynamic.cpp +++ b/packages/react-native/ReactCommon/jsi/jsi/JSIDynamic.cpp @@ -150,7 +150,10 @@ void dynamicFromValueShallow( } // namespace -folly::dynamic dynamicFromValue(Runtime& runtime, const Value& valueInput) { +folly::dynamic dynamicFromValue( + Runtime& runtime, + const Value& valueInput, + std::function filterObjectKeys) { std::vector stack; folly::dynamic ret; @@ -182,13 +185,17 @@ folly::dynamic dynamicFromValue(Runtime& runtime, const Value& valueInput) { if (prop.isUndefined()) { continue; } + auto nameStr = name.utf8(runtime); + if (filterObjectKeys && filterObjectKeys(nameStr)) { + continue; + } // The JSC conversion uses JSON.stringify, which substitutes // null for a function, so we do the same here. Just dropping // the pair might also work, but would require more testing. if (prop.isObject() && prop.getObject(runtime).isFunction(runtime)) { prop = Value::null(); } - props.emplace_back(name.utf8(runtime), std::move(prop)); + props.emplace_back(std::move(nameStr), std::move(prop)); top.dyn->insert(props.back().first, nullptr); } for (const auto& prop : props) { diff --git a/packages/react-native/ReactCommon/jsi/jsi/JSIDynamic.h b/packages/react-native/ReactCommon/jsi/jsi/JSIDynamic.h index 110dd13999f437..a96cc281b0d65b 100644 --- a/packages/react-native/ReactCommon/jsi/jsi/JSIDynamic.h +++ b/packages/react-native/ReactCommon/jsi/jsi/JSIDynamic.h @@ -19,7 +19,8 @@ facebook::jsi::Value valueFromDynamic( folly::dynamic dynamicFromValue( facebook::jsi::Runtime& runtime, - const facebook::jsi::Value& value); + const facebook::jsi::Value& value, + std::function filterObjectKeys = nullptr); } // namespace jsi } // namespace facebook diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/YogaStylableProps.cpp b/packages/react-native/ReactCommon/react/renderer/components/view/YogaStylableProps.cpp index f8a7f360008d27..39e32c9fa93283 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/YogaStylableProps.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/view/YogaStylableProps.cpp @@ -19,134 +19,19 @@ namespace facebook::react { -namespace { -inline RawProps filterYogaProps(const RawProps& rawProps) { - const static std::unordered_set yogaStylePropNames = { - {"direction", - "flexDirection", - "justifyContent", - "alignContent", - "alignItems", - "alignSelf", - "position", - "flexWrap", - "display", - "flex", - "flexGrow", - "flexShrink", - "flexBasis", - "margin", - "padding", - "rowGap", - "columnGap", - "gap", - // TODO: T163711275 also filter out width/height when SVG no longer read - // them from RawProps - "minWidth", - "maxWidth", - "minHeight", - "maxHeight", - "aspectRatio", - - // edges - "left", - "right", - "top", - "bottom", - "start", - "end", - - // variants of inset - "inset", - "insetStart", - "insetEnd", - "insetInline", - "insetInlineStart", - "insetInlineEnd", - "insetBlock", - "insetBlockEnd", - "insetBlockStart", - "insetVertical", - "insetHorizontal", - "insetTop", - "insetBottom", - "insetLeft", - "insetRight", - - // variants of margin - "marginStart", - "marginEnd", - "marginInline", - "marginInlineStart", - "marginInlineEnd", - "marginBlock", - "marginBlockStart", - "marginBlockEnd", - "marginVertical", - "marginHorizontal", - "marginTop", - "marginBottom", - "marginLeft", - "marginRight", - - // variants of padding - "paddingStart", - "paddingEnd", - "paddingInline", - "paddingInlineStart", - "paddingInlineEnd", - "paddingBlock", - "paddingBlockStart", - "paddingBlockEnd", - "paddingVertical", - "paddingHorizontal", - "paddingTop", - "paddingBottom", - "paddingLeft", - "paddingRight"}}; - - auto filteredRawProps = (folly::dynamic)rawProps; - - auto it = filteredRawProps.items().begin(); - while (it != filteredRawProps.items().end()) { - auto key = it->first.asString(); - if (yogaStylePropNames.find(key) != yogaStylePropNames.end()) { - it = filteredRawProps.erase(it); - } else { - ++it; - } - } - - return RawProps(std::move(filteredRawProps)); -} -} // namespace - YogaStylableProps::YogaStylableProps( const PropsParserContext& context, const YogaStylableProps& sourceProps, const RawProps& rawProps) : Props() { - if (CoreFeatures::excludeYogaFromRawProps) { - const auto filteredRawProps = filterYogaProps(rawProps); - initialize(context, sourceProps, filteredRawProps); - - yogaStyle = CoreFeatures::enablePropIteratorSetter - ? sourceProps.yogaStyle - : convertRawProp(context, filteredRawProps, sourceProps.yogaStyle); - - if (!CoreFeatures::enablePropIteratorSetter) { - convertRawPropAliases(context, sourceProps, filteredRawProps); - } - } else { - initialize(context, sourceProps, rawProps); + initialize(context, sourceProps, rawProps); - yogaStyle = CoreFeatures::enablePropIteratorSetter - ? sourceProps.yogaStyle - : convertRawProp(context, rawProps, sourceProps.yogaStyle); + yogaStyle = CoreFeatures::enablePropIteratorSetter + ? sourceProps.yogaStyle + : convertRawProp(context, rawProps, sourceProps.yogaStyle); - if (!CoreFeatures::enablePropIteratorSetter) { - convertRawPropAliases(context, sourceProps, rawProps); - } + if (!CoreFeatures::enablePropIteratorSetter) { + convertRawPropAliases(context, sourceProps, rawProps); } }; diff --git a/packages/react-native/ReactCommon/react/renderer/core/ConcreteComponentDescriptor.h b/packages/react-native/ReactCommon/react/renderer/core/ConcreteComponentDescriptor.h index a527d267eb41dd..ad8e60fb541da8 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/ConcreteComponentDescriptor.h +++ b/packages/react-native/ReactCommon/react/renderer/core/ConcreteComponentDescriptor.h @@ -105,6 +105,13 @@ class ConcreteComponentDescriptor : public ComponentDescriptor { return ShadowNodeT::defaultSharedProps(); } + if (CoreFeatures::excludeYogaFromRawProps) { + if (ShadowNodeT::IdentifierTrait() == + ShadowNodeTraits::Trait::YogaLayoutableKind) { + rawProps.filterYogaStylePropsInDynamicConversion(); + } + } + rawProps.parse(rawPropsParser_); // Call old-style constructor diff --git a/packages/react-native/ReactCommon/react/renderer/core/RawProps.cpp b/packages/react-native/ReactCommon/react/renderer/core/RawProps.cpp index 046e8c521ae33a..3e630dcd0d042a 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/RawProps.cpp +++ b/packages/react-native/ReactCommon/react/renderer/core/RawProps.cpp @@ -13,6 +13,96 @@ namespace facebook::react { +namespace { +inline bool isYogaStyleProp(const std::string& prop) { + const static std::unordered_set yogaStylePropNames = { + {"direction", + "flexDirection", + "justifyContent", + "alignContent", + "alignItems", + "alignSelf", + "position", + "flexWrap", + "display", + "flex", + "flexGrow", + "flexShrink", + "flexBasis", + "margin", + "padding", + "rowGap", + "columnGap", + "gap", + // TODO: T163711275 also filter out width/height when SVG no longer read + // them from RawProps + "minWidth", + "maxWidth", + "minHeight", + "maxHeight", + "aspectRatio", + + // edges + "left", + "right", + "top", + "bottom", + "start", + "end", + + // variants of inset + "inset", + "insetStart", + "insetEnd", + "insetInline", + "insetInlineStart", + "insetInlineEnd", + "insetBlock", + "insetBlockEnd", + "insetBlockStart", + "insetVertical", + "insetHorizontal", + "insetTop", + "insetBottom", + "insetLeft", + "insetRight", + + // variants of margin + "marginStart", + "marginEnd", + "marginInline", + "marginInlineStart", + "marginInlineEnd", + "marginBlock", + "marginBlockStart", + "marginBlockEnd", + "marginVertical", + "marginHorizontal", + "marginTop", + "marginBottom", + "marginLeft", + "marginRight", + + // variants of padding + "paddingStart", + "paddingEnd", + "paddingInline", + "paddingInlineStart", + "paddingInlineEnd", + "paddingBlock", + "paddingBlockStart", + "paddingBlockEnd", + "paddingVertical", + "paddingHorizontal", + "paddingTop", + "paddingBottom", + "paddingLeft", + "paddingRight"}}; + + return yogaStylePropNames.find(prop) != yogaStylePropNames.end(); +} +} // namespace + RawProps::RawProps() { mode_ = Mode::Empty; } @@ -55,6 +145,7 @@ RawProps::RawProps(const RawProps& other) noexcept { } else if (mode_ == Mode::Dynamic) { dynamic_ = other.dynamic_; } + ignoreYogaStyleProps_ = other.ignoreYogaStyleProps_; } RawProps& RawProps::operator=(const RawProps& other) noexcept { @@ -65,6 +156,7 @@ RawProps& RawProps::operator=(const RawProps& other) noexcept { } else if (mode_ == Mode::Dynamic) { dynamic_ = other.dynamic_; } + ignoreYogaStyleProps_ = other.ignoreYogaStyleProps_; return *this; } @@ -84,12 +176,17 @@ RawProps::operator folly::dynamic() const noexcept { case Mode::Empty: return folly::dynamic::object(); case Mode::JSI: - return jsi::dynamicFromValue(*runtime_, value_); + return jsi::dynamicFromValue( + *runtime_, value_, ignoreYogaStyleProps_ ? isYogaStyleProp : nullptr); case Mode::Dynamic: return dynamic_; } } +void RawProps::filterYogaStylePropsInDynamicConversion() noexcept { + ignoreYogaStyleProps_ = true; +} + /* * Returns `true` if the object is empty. * Empty `RawProps` does not have any stored data. diff --git a/packages/react-native/ReactCommon/react/renderer/core/RawProps.h b/packages/react-native/ReactCommon/react/renderer/core/RawProps.h index c08cf928a508bd..7edaa8a7ed30f0 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/RawProps.h +++ b/packages/react-native/ReactCommon/react/renderer/core/RawProps.h @@ -73,6 +73,15 @@ class RawProps final { */ explicit operator folly::dynamic() const noexcept; + /* + * Once called, Yoga style props will be filtered out during conversion to + * folly::dynamic. folly::dynamic conversion is only used on Android and props + * specific to Yoga do not need to be send over JNI to Android. + * This is a performance optimisation to minimise traffic between C++ and + * Java. + */ + void filterYogaStylePropsInDynamicConversion() noexcept; + /* * Returns `true` if the object is empty. * Empty `RawProps` does not have any stored data. @@ -124,6 +133,8 @@ class RawProps final { */ mutable std::vector keyIndexToValueIndex_; mutable std::vector values_; + + bool ignoreYogaStyleProps_{false}; }; } // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/renderer/core/tests/RawPropsTest.cpp b/packages/react-native/ReactCommon/react/renderer/core/tests/RawPropsTest.cpp index 9b57fe14586d62..ea9e657a428791 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/tests/RawPropsTest.cpp +++ b/packages/react-native/ReactCommon/react/renderer/core/tests/RawPropsTest.cpp @@ -467,3 +467,39 @@ TEST(RawPropsTest, copyJSIRawProps) { EXPECT_NEAR( copyProps->derivedFloatValue, originalProps->derivedFloatValue, 0.00001); } + +TEST(RawPropsTest, filterYogaRawProps) { + auto runtime = facebook::hermes::makeHermesRuntime(); + + ContextContainer contextContainer{}; + PropsParserContext parserContext{-1, contextContainer}; + + auto object = jsi::Object(*runtime); + object.setProperty(*runtime, "floatValue", 10.0); + object.setProperty(*runtime, "flex", 1); + + auto rawProps = RawProps(*runtime, jsi::Value(*runtime, object)); + + EXPECT_FALSE(rawProps.isEmpty()); + + auto dynamicProps = (folly::dynamic)rawProps; + + EXPECT_EQ(dynamicProps["floatValue"], 10.0); + EXPECT_EQ(dynamicProps["flex"], 1); + + rawProps.filterYogaStylePropsInDynamicConversion(); + + dynamicProps = (folly::dynamic)rawProps; + + EXPECT_EQ(dynamicProps["floatValue"], 10.0); + EXPECT_EQ(dynamicProps["flex"], nullptr); + + // The fact that filterYogaStylePropsInDynamicConversion should + // must apply to a copy as well. + auto copy = RawProps(rawProps); + + auto dynamicPropsFromCopy = (folly::dynamic)copy; + + EXPECT_EQ(dynamicPropsFromCopy["floatValue"], 10.0); + EXPECT_EQ(dynamicPropsFromCopy["flex"], nullptr); +} From 0363485069a0079ab7f85e2f08f77fa802ba465e Mon Sep 17 00:00:00 2001 From: Kevin Gozali Date: Fri, 24 Nov 2023 11:37:37 -0800 Subject: [PATCH 087/162] RNTester: add the ability to open a specific example from incoming URL (#41642) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41642 This allows opening an example within RNTester without tapping the module card. If the app receives an openURL request with the format `rntester://example/`, open that example (if exists) directly. Such URL request may come from various sources (e.g. custom test run, etc). Changelog: [Internal] Reviewed By: christophpurrer Differential Revision: D51543385 fbshipit-source-id: f9a01963cefb4602b629da0b01be6e334c28a912 --- packages/rn-tester/js/RNTesterAppShared.js | 47 ++++++++++++++++++- .../js/utils/RNTesterNavigationReducer.js | 9 ++++ 2 files changed, 55 insertions(+), 1 deletion(-) diff --git a/packages/rn-tester/js/RNTesterAppShared.js b/packages/rn-tester/js/RNTesterAppShared.js index 3f93d9aa4801f3..27260cc901a120 100644 --- a/packages/rn-tester/js/RNTesterAppShared.js +++ b/packages/rn-tester/js/RNTesterAppShared.js @@ -26,7 +26,13 @@ import { initialNavigationState, } from './utils/testerStateUtils'; import * as React from 'react'; -import {BackHandler, StyleSheet, View, useColorScheme} from 'react-native'; +import { + BackHandler, + Linking, + StyleSheet, + View, + useColorScheme, +} from 'react-native'; // RNTester App currently uses in memory storage for storing navigation state @@ -113,6 +119,45 @@ const RNTesterApp = ({ [dispatch], ); + // Setup Linking event subscription + const handleOpenUrlRequest = React.useCallback( + ({url}: {url: string, ...}) => { + // Supported URL pattern(s): + // * rntester://example/ + const match = /^rntester:\/\/example\/(.+)$/.exec(url); + if (!match) { + console.warn( + `handleOpenUrlRequest: Received unsupported URL: '${url}'`, + ); + return; + } + + const key = match[1]; + const exampleModule = RNTesterList.Modules[key]; + if (exampleModule == null) { + console.warn( + `handleOpenUrlRequest: Unable to find requested module with key: '${key}'`, + ); + return; + } + + console.log(`handleOpenUrlRequest: Opening example '${key}'`); + + dispatch({ + type: RNTesterNavigationActionsType.EXAMPLE_OPEN_URL_REQUEST, + data: { + key, + title: exampleModule.title || key, + }, + }); + }, + [dispatch], + ); + React.useEffect(() => { + const subscription = Linking.addEventListener('url', handleOpenUrlRequest); + return () => subscription.remove(); + }, [handleOpenUrlRequest]); + const theme = colorScheme === 'dark' ? themes.dark : themes.light; if (examplesList === null) { diff --git a/packages/rn-tester/js/utils/RNTesterNavigationReducer.js b/packages/rn-tester/js/utils/RNTesterNavigationReducer.js index 9c2097d668cadc..db59ba5a7a75de 100644 --- a/packages/rn-tester/js/utils/RNTesterNavigationReducer.js +++ b/packages/rn-tester/js/utils/RNTesterNavigationReducer.js @@ -18,6 +18,7 @@ export const RNTesterNavigationActionsType = { BACK_BUTTON_PRESS: 'BACK_BUTTON_PRESS', MODULE_CARD_PRESS: 'MODULE_CARD_PRESS', EXAMPLE_CARD_PRESS: 'EXAMPLE_CARD_PRESS', + EXAMPLE_OPEN_URL_REQUEST: 'EXAMPLE_OPEN_URL_REQUEST', }; const getUpdatedRecentlyUsed = ({ @@ -100,6 +101,14 @@ export const RNTesterNavigationReducer = ( state.activeModuleExampleKey != null ? state.activeModuleTitle : null, }; + case RNTesterNavigationActionsType.EXAMPLE_OPEN_URL_REQUEST: + return { + ...state, + activeModuleKey: key, + activeModuleTitle: title, + activeModuleExampleKey: null, + }; + default: throw new Error(`Invalid action type ${action.type}`); } From c464b215e5f07250d1fc752aec6c497715f27449 Mon Sep 17 00:00:00 2001 From: Moti Zilberman Date: Fri, 24 Nov 2023 12:04:59 -0800 Subject: [PATCH 088/162] Create JSRuntime interface (#41549) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41549 Changelog: [Internal] Introduces the `JSRuntime` interface as a straightforward wrapper around `jsi::Runtime`, and refactors `ReactInstance` to hold a `JSRuntime` instead of a `jsi::Runtime`. In an upcoming diff we'll add debugging-related methods to `JSRuntime` and specialise their implementations for Hermes. NOTE: `JSRuntime` is somewhat analogous to `JSExecutor` in the Bridge architecture. Reviewed By: huntie Differential Revision: D51447934 fbshipit-source-id: cfcab9ae0dd3d2a34c064abaac6cb676f435e216 --- .../runtime/hermes/jni/JHermesInstance.cpp | 2 +- .../runtime/hermes/jni/JHermesInstance.h | 2 +- .../main/jni/react/runtime/jsc/jni/OnLoad.cpp | 4 +-- .../react/runtime/JSRuntimeFactory.cpp | 19 ++++++++++++++ .../react/runtime/JSRuntimeFactory.h | 25 ++++++++++++++++++- .../react/runtime/React-RuntimeHermes.podspec | 1 + .../react/runtime/ReactInstance.cpp | 12 ++++----- .../ReactCommon/react/runtime/ReactInstance.h | 5 ++-- .../react/runtime/hermes/CMakeLists.txt | 1 + .../react/runtime/hermes/HermesInstance.cpp | 6 ++--- .../react/runtime/hermes/HermesInstance.h | 3 ++- .../ios/ReactCommon/RCTHermesInstance.h | 2 +- .../ios/ReactCommon/RCTHermesInstance.mm | 2 +- .../platform/ios/ReactCommon/RCTJscInstance.h | 2 +- .../ios/ReactCommon/RCTJscInstance.mm | 5 ++-- .../runtime/tests/cxx/ReactInstanceTest.cpp | 5 ++-- 16 files changed, 71 insertions(+), 25 deletions(-) create mode 100644 packages/react-native/ReactCommon/react/runtime/JSRuntimeFactory.cpp diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/runtime/hermes/jni/JHermesInstance.cpp b/packages/react-native/ReactAndroid/src/main/jni/react/runtime/hermes/jni/JHermesInstance.cpp index 3d8a9f74652443..deabc529969432 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/runtime/hermes/jni/JHermesInstance.cpp +++ b/packages/react-native/ReactAndroid/src/main/jni/react/runtime/hermes/jni/JHermesInstance.cpp @@ -28,7 +28,7 @@ void JHermesInstance::registerNatives() { }); } -std::unique_ptr JHermesInstance::createJSRuntime( +std::unique_ptr JHermesInstance::createJSRuntime( std::shared_ptr msgQueueThread) noexcept { return HermesInstance::createJSRuntime( reactNativeConfig_, nullptr, msgQueueThread); diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/runtime/hermes/jni/JHermesInstance.h b/packages/react-native/ReactAndroid/src/main/jni/react/runtime/hermes/jni/JHermesInstance.h index abc417cc065433..5ee3450442db92 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/runtime/hermes/jni/JHermesInstance.h +++ b/packages/react-native/ReactAndroid/src/main/jni/react/runtime/hermes/jni/JHermesInstance.h @@ -35,7 +35,7 @@ class JHermesInstance JHermesInstance(std::shared_ptr reactNativeConfig) : reactNativeConfig_(reactNativeConfig){}; - std::unique_ptr createJSRuntime( + std::unique_ptr createJSRuntime( std::shared_ptr msgQueueThread) noexcept; ~JHermesInstance() {} diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/runtime/jsc/jni/OnLoad.cpp b/packages/react-native/ReactAndroid/src/main/jni/react/runtime/jsc/jni/OnLoad.cpp index 068e02b41b8767..e49a55d50243c8 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/runtime/jsc/jni/OnLoad.cpp +++ b/packages/react-native/ReactAndroid/src/main/jni/react/runtime/jsc/jni/OnLoad.cpp @@ -30,9 +30,9 @@ class JSCInstance : public jni::HybridClass { }); } - std::unique_ptr createJSRuntime( + std::unique_ptr createJSRuntime( std::shared_ptr msgQueueThread) noexcept { - return jsc::makeJSCRuntime(); + return std::make_unique(jsc::makeJSCRuntime()); } private: diff --git a/packages/react-native/ReactCommon/react/runtime/JSRuntimeFactory.cpp b/packages/react-native/ReactCommon/react/runtime/JSRuntimeFactory.cpp new file mode 100644 index 00000000000000..a0b11fe6686a02 --- /dev/null +++ b/packages/react-native/ReactCommon/react/runtime/JSRuntimeFactory.cpp @@ -0,0 +1,19 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include "JSRuntimeFactory.h" + +namespace facebook::react { +jsi::Runtime& JSIRuntimeHolder::getRuntime() noexcept { + return *runtime_; +} + +JSIRuntimeHolder::JSIRuntimeHolder(std::unique_ptr runtime) + : runtime_(std::move(runtime)) { + assert(runtime_ != nullptr); +} +} // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/runtime/JSRuntimeFactory.h b/packages/react-native/ReactCommon/react/runtime/JSRuntimeFactory.h index 431a2930650444..110c1f26590967 100644 --- a/packages/react-native/ReactCommon/react/runtime/JSRuntimeFactory.h +++ b/packages/react-native/ReactCommon/react/runtime/JSRuntimeFactory.h @@ -13,15 +13,38 @@ namespace facebook::react { +/** + * An interface that represents an instance of a JS VM + */ +class JSRuntime { + public: + virtual jsi::Runtime& getRuntime() noexcept = 0; + + virtual ~JSRuntime() = default; +}; + /** * Interface for a class that creates instances of a JS VM */ class JSRuntimeFactory { public: - virtual std::unique_ptr createJSRuntime( + virtual std::unique_ptr createJSRuntime( std::shared_ptr msgQueueThread) noexcept = 0; virtual ~JSRuntimeFactory() = default; }; +/** + * Utility class for creating a JSRuntime from a uniquely owned jsi::Runtime. + */ +class JSIRuntimeHolder : public JSRuntime { + public: + jsi::Runtime& getRuntime() noexcept override; + + explicit JSIRuntimeHolder(std::unique_ptr runtime); + + private: + std::unique_ptr runtime_; +}; + } // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/runtime/React-RuntimeHermes.podspec b/packages/react-native/ReactCommon/react/runtime/React-RuntimeHermes.podspec index 54dcb839fdf598..b8bd53b8aac458 100644 --- a/packages/react-native/ReactCommon/react/runtime/React-RuntimeHermes.podspec +++ b/packages/react-native/ReactCommon/react/runtime/React-RuntimeHermes.podspec @@ -48,6 +48,7 @@ Pod::Spec.new do |s| s.dependency "React-jsitracing" s.dependency "React-utils" s.dependency "React-jsi" + s.dependency "React-RuntimeCore" if ENV["USE_HERMES"] == nil || ENV["USE_HERMES"] == "1" s.dependency "hermes-engine" diff --git a/packages/react-native/ReactCommon/react/runtime/ReactInstance.cpp b/packages/react-native/ReactCommon/react/runtime/ReactInstance.cpp index d671bace703efc..76b8029d258e46 100644 --- a/packages/react-native/ReactCommon/react/runtime/ReactInstance.cpp +++ b/packages/react-native/ReactCommon/react/runtime/ReactInstance.cpp @@ -26,7 +26,7 @@ namespace facebook::react { ReactInstance::ReactInstance( - std::unique_ptr runtime, + std::unique_ptr runtime, std::shared_ptr jsMessageQueueThread, std::shared_ptr timerManager, JsErrorHandler::JsErrorHandlingFunc jsErrorHandlingFunc, @@ -36,7 +36,7 @@ ReactInstance::ReactInstance( timerManager_(std::move(timerManager)), jsErrorHandler_(jsErrorHandlingFunc), hasFatalJsError_(std::make_shared(false)) { - auto runtimeExecutor = [weakRuntime = std::weak_ptr(runtime_), + auto runtimeExecutor = [weakRuntime = std::weak_ptr(runtime_), weakTimerManager = std::weak_ptr(timerManager_), weakJsMessageQueueThread = @@ -63,20 +63,20 @@ ReactInstance::ReactInstance( sharedJsMessageQueueThread->runOnQueue( [weakRuntime, weakTimerManager, callback = std::move(callback)]() { if (auto strongRuntime = weakRuntime.lock()) { + jsi::Runtime& jsiRuntime = strongRuntime->getRuntime(); SystraceSection s("ReactInstance::_runtimeExecutor[Callback]"); try { - callback(*strongRuntime); + callback(jsiRuntime); // If we have first-class support for microtasks, // they would've been called as part of the previous callback. if (!CoreFeatures::enableMicrotasks) { if (auto strongTimerManager = weakTimerManager.lock()) { - strongTimerManager->callReactNativeMicrotasks( - *strongRuntime); + strongTimerManager->callReactNativeMicrotasks(jsiRuntime); } } } catch (jsi::JSError& originalError) { - handleJSError(*strongRuntime, originalError, true); + handleJSError(jsiRuntime, originalError, true); } } }); diff --git a/packages/react-native/ReactCommon/react/runtime/ReactInstance.h b/packages/react-native/ReactCommon/react/runtime/ReactInstance.h index 0d1762af01c529..caad761b7f07f5 100644 --- a/packages/react-native/ReactCommon/react/runtime/ReactInstance.h +++ b/packages/react-native/ReactCommon/react/runtime/ReactInstance.h @@ -14,6 +14,7 @@ #include #include #include +#include #include namespace facebook::react { @@ -29,7 +30,7 @@ class ReactInstance final { using BindingsInstallFunc = std::function; ReactInstance( - std::unique_ptr runtime, + std::unique_ptr runtime, std::shared_ptr jsMessageQueueThread, std::shared_ptr timerManager, JsErrorHandler::JsErrorHandlingFunc JsErrorHandlingFunc, @@ -64,7 +65,7 @@ class ReactInstance final { void handleMemoryPressureJs(int pressureLevel); private: - std::shared_ptr runtime_; + std::shared_ptr runtime_; std::shared_ptr jsMessageQueueThread_; std::shared_ptr bufferedRuntimeExecutor_; std::shared_ptr timerManager_; diff --git a/packages/react-native/ReactCommon/react/runtime/hermes/CMakeLists.txt b/packages/react-native/ReactCommon/react/runtime/hermes/CMakeLists.txt index 955bb14c946a6a..e46f159bd12f96 100644 --- a/packages/react-native/ReactCommon/react/runtime/hermes/CMakeLists.txt +++ b/packages/react-native/ReactCommon/react/runtime/hermes/CMakeLists.txt @@ -22,6 +22,7 @@ target_link_libraries(bridgelesshermes hermes_inspector_modern jsi hermes_executor_common + bridgeless ) if(${CMAKE_BUILD_TYPE} MATCHES Debug) diff --git a/packages/react-native/ReactCommon/react/runtime/hermes/HermesInstance.cpp b/packages/react-native/ReactCommon/react/runtime/hermes/HermesInstance.cpp index d682224485af81..0918259c77e93c 100644 --- a/packages/react-native/ReactCommon/react/runtime/hermes/HermesInstance.cpp +++ b/packages/react-native/ReactCommon/react/runtime/hermes/HermesInstance.cpp @@ -89,7 +89,7 @@ class DecoratedRuntime : public jsi::RuntimeDecorator { #endif -std::unique_ptr HermesInstance::createJSRuntime( +std::unique_ptr HermesInstance::createJSRuntime( std::shared_ptr reactNativeConfig, std::shared_ptr<::hermes::vm::CrashManager> cm, std::shared_ptr msgQueueThread) noexcept { @@ -144,10 +144,10 @@ std::unique_ptr HermesInstance::createJSRuntime( std::unique_ptr decoratedRuntime = std::make_unique( std::move(hermesRuntime), msgQueueThread); - return decoratedRuntime; + return std::make_unique(std::move(decoratedRuntime)); #endif - return hermesRuntime; + return std::make_unique(std::move(hermesRuntime)); } } // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/runtime/hermes/HermesInstance.h b/packages/react-native/ReactCommon/react/runtime/hermes/HermesInstance.h index 63f3f73ba42f84..71b08d2fd5b07c 100644 --- a/packages/react-native/ReactCommon/react/runtime/hermes/HermesInstance.h +++ b/packages/react-native/ReactCommon/react/runtime/hermes/HermesInstance.h @@ -11,12 +11,13 @@ #include #include #include +#include namespace facebook::react { class HermesInstance { public: - static std::unique_ptr createJSRuntime( + static std::unique_ptr createJSRuntime( std::shared_ptr reactNativeConfig, std::shared_ptr<::hermes::vm::CrashManager> cm, std::shared_ptr msgQueueThread) noexcept; diff --git a/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTHermesInstance.h b/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTHermesInstance.h index d811aa6335652d..533aa82b92459e 100644 --- a/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTHermesInstance.h +++ b/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTHermesInstance.h @@ -26,7 +26,7 @@ class RCTHermesInstance : public JSRuntimeFactory { std::shared_ptr reactNativeConfig, CrashManagerProvider crashManagerProvider); - std::unique_ptr createJSRuntime( + std::unique_ptr createJSRuntime( std::shared_ptr msgQueueThread) noexcept override; ~RCTHermesInstance(){}; diff --git a/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTHermesInstance.mm b/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTHermesInstance.mm index 04335ccd9c2a13..c3e4951ded603e 100644 --- a/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTHermesInstance.mm +++ b/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTHermesInstance.mm @@ -20,7 +20,7 @@ { } -std::unique_ptr RCTHermesInstance::createJSRuntime( +std::unique_ptr RCTHermesInstance::createJSRuntime( std::shared_ptr msgQueueThread) noexcept { return _hermesInstance->createJSRuntime( diff --git a/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTJscInstance.h b/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTJscInstance.h index 8ad3220f45d309..bdd653287d0c15 100644 --- a/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTJscInstance.h +++ b/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTJscInstance.h @@ -16,7 +16,7 @@ class RCTJscInstance : public JSRuntimeFactory { public: RCTJscInstance(); - std::unique_ptr createJSRuntime( + std::unique_ptr createJSRuntime( std::shared_ptr msgQueueThread) noexcept override; ~RCTJscInstance(){}; diff --git a/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTJscInstance.mm b/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTJscInstance.mm index 168ddc3aa1228c..c56c466909de90 100644 --- a/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTJscInstance.mm +++ b/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTJscInstance.mm @@ -13,10 +13,9 @@ RCTJscInstance::RCTJscInstance() {} -std::unique_ptr RCTJscInstance::createJSRuntime( - std::shared_ptr msgQueueThread) noexcept +std::unique_ptr RCTJscInstance::createJSRuntime(std::shared_ptr msgQueueThread) noexcept { - return jsc::makeJSCRuntime(); + return std::make_unique(jsc::makeJSCRuntime()); } } // namespace react diff --git a/packages/react-native/ReactCommon/react/runtime/tests/cxx/ReactInstanceTest.cpp b/packages/react-native/ReactCommon/react/runtime/tests/cxx/ReactInstanceTest.cpp index 0d8ea7f3285006..3f8a36b39daa83 100644 --- a/packages/react-native/ReactCommon/react/runtime/tests/cxx/ReactInstanceTest.cpp +++ b/packages/react-native/ReactCommon/react/runtime/tests/cxx/ReactInstanceTest.cpp @@ -116,8 +116,9 @@ class ReactInstanceTest : public ::testing::Test { ReactInstanceTest() {} void SetUp() override { - auto runtime = hermes::makeHermesRuntime(); - runtime_ = runtime.get(); + auto runtime = + std::make_unique(hermes::makeHermesRuntime()); + runtime_ = &runtime->getRuntime(); messageQueueThread_ = std::make_shared(); auto mockRegistry = std::make_unique(); mockRegistry_ = mockRegistry.get(); From 4016bfbc377215d2929de732f682bc9d1c823f39 Mon Sep 17 00:00:00 2001 From: Nick Gerleman Date: Sat, 25 Nov 2023 11:09:53 -0800 Subject: [PATCH 089/162] Fix AndroidTextInputProps Detection of Padding (#41643) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41643 Code in `AndroidTextInputComponentDescriptor` will rewrite Yoga props for padding based on Android theme, if a value isn't supplied. It determines this by adding props in `AndroidTextInputProps` which reads Yoga RawProps to tell if they were set. RawProps are keyed using separate prefix/name/suffix, instead of the combined string name of the prop. This means that searching for the name `paddingLeft`, would be different from reading one with a name of `padding` and a suffix of `Left`. This updates the keying, based on the changes in D51510562. We should refactor this in the future (D20109605, introducing this code, admitted as much). We already have a phase, for aliased props, where we transform input props into the Yoga style (they don't need to be 1:1). This doesn't depend on RawProps, extra props, or prop mutations. Changelog: [Android][Fixed] - Fix AndroidTextInputProps Detection of Padding Reviewed By: GijsWeterings Differential Revision: D51566900 fbshipit-source-id: ca744b23d71382941903da42d86ad3eef7b65de8 --- .../AndroidTextInputProps.cpp | 40 ++++++------------- 1 file changed, 12 insertions(+), 28 deletions(-) diff --git a/packages/react-native/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputProps.cpp b/packages/react-native/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputProps.cpp index 2687d64cb3f86f..ea0fb6a1674e3d 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputProps.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputProps.cpp @@ -13,13 +13,9 @@ namespace facebook::react { -static bool hasValue( - const RawProps& rawProps, - bool defaultValue, - const char* name, - const char* prefix, - const char* suffix) { - auto rawValue = rawProps.at(name, prefix, suffix); +static bool +hasValue(const RawProps& rawProps, bool defaultValue, const char* name) { + auto rawValue = rawProps.at(name, nullptr, nullptr); // No change to prop - use default if (rawValue == nullptr) { @@ -217,47 +213,35 @@ AndroidTextInputProps::AndroidTextInputProps( convertRawProp(context, rawProps, sourceProps.paragraphAttributes, {})), // See AndroidTextInputComponentDescriptor for usage // TODO T63008435: can these, and this feature, be removed entirely? - hasPadding(CoreFeatures::enablePropIteratorSetter? sourceProps.hasPadding : hasValue(rawProps, sourceProps.hasPadding, "", "padding", "")), + hasPadding(CoreFeatures::enablePropIteratorSetter? sourceProps.hasPadding : hasValue(rawProps, sourceProps.hasPadding, "padding")), hasPaddingHorizontal(CoreFeatures::enablePropIteratorSetter? sourceProps.hasPaddingHorizontal : hasValue( rawProps, sourceProps.hasPaddingHorizontal, - "Horizontal", - "padding", - "")), + "paddingHorizontal")), hasPaddingVertical(CoreFeatures::enablePropIteratorSetter? sourceProps.hasPaddingVertical : hasValue( rawProps, sourceProps.hasPaddingVertical, - "Vertical", - "padding", - "")), + "paddingVertical")), hasPaddingLeft(CoreFeatures::enablePropIteratorSetter? sourceProps.hasPaddingLeft : hasValue( rawProps, sourceProps.hasPaddingLeft, - "Left", - "padding", - "")), + "paddingLeft")), hasPaddingTop(CoreFeatures::enablePropIteratorSetter? sourceProps.hasPaddingTop : - hasValue(rawProps, sourceProps.hasPaddingTop, "Top", "padding", "")), + hasValue(rawProps, sourceProps.hasPaddingTop, "paddingTop")), hasPaddingRight(CoreFeatures::enablePropIteratorSetter? sourceProps.hasPaddingRight : hasValue( rawProps, sourceProps.hasPaddingRight, - "Right", - "padding", - "")), + "paddingRight")), hasPaddingBottom(CoreFeatures::enablePropIteratorSetter? sourceProps.hasPaddingBottom : hasValue( rawProps, sourceProps.hasPaddingBottom, - "Bottom", - "padding", - "")), + "paddingBottom")), hasPaddingStart(CoreFeatures::enablePropIteratorSetter? sourceProps.hasPaddingStart : hasValue( rawProps, sourceProps.hasPaddingStart, - "Start", - "padding", - "")), + "paddingStart")), hasPaddingEnd(CoreFeatures::enablePropIteratorSetter? sourceProps.hasPaddingEnd : - hasValue(rawProps, sourceProps.hasPaddingEnd, "End", "padding", "")) { + hasValue(rawProps, sourceProps.hasPaddingEnd, "paddingEnd")) { } void AndroidTextInputProps::setProp( From caae388912774dfa5f8e0e73bc63ce0ff9e4ed72 Mon Sep 17 00:00:00 2001 From: Riccardo Cipolleschi Date: Sat, 25 Nov 2023 11:39:15 -0800 Subject: [PATCH 090/162] Fix React-Codegen dependencies on FabricImage (#41640) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41640 react-native-svg reported that the SVG library was not building on the latest RC of React Native because Codegen was not finding the proper files. By inspecting an example app with SVG, we realized that React-Codegen was not depending on `React-FabricImage`, while having access to their headers. We added the dependency, but them the build was failing due to a circular dependency because the `React-ImageManager` was dependeing on `React-RCTImage`. This dependency is conceptually wrong (a piece of Core should not depend on Library which depends on Core... 😑) and I verified that by removing that dependency the framework continue to build. ## Changelog: [Internal] - Fixed dependencies of Codegen on React-Image Reviewed By: cortinico Differential Revision: D51564037 fbshipit-source-id: 8e7108b83f878be1063df5562311d862d4998121 --- .../imagemanager/platform/ios/React-ImageManager.podspec | 1 - .../scripts/cocoapods/__tests__/codegen_utils-test.rb | 2 ++ packages/react-native/scripts/cocoapods/codegen_utils.rb | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/react-native/ReactCommon/react/renderer/imagemanager/platform/ios/React-ImageManager.podspec b/packages/react-native/ReactCommon/react/renderer/imagemanager/platform/ios/React-ImageManager.podspec index c85d5511f62df3..6feeafaf718f0d 100644 --- a/packages/react-native/ReactCommon/react/renderer/imagemanager/platform/ios/React-ImageManager.podspec +++ b/packages/react-native/ReactCommon/react/renderer/imagemanager/platform/ios/React-ImageManager.podspec @@ -56,7 +56,6 @@ Pod::Spec.new do |s| s.dependency "RCT-Folly/Fabric" s.dependency "React-Core/Default" - s.dependency "React-RCTImage" s.dependency "glog" add_dependency(s, "React-Fabric") diff --git a/packages/react-native/scripts/cocoapods/__tests__/codegen_utils-test.rb b/packages/react-native/scripts/cocoapods/__tests__/codegen_utils-test.rb index e635db3f708efd..57dbafd8f04405 100644 --- a/packages/react-native/scripts/cocoapods/__tests__/codegen_utils-test.rb +++ b/packages/react-native/scripts/cocoapods/__tests__/codegen_utils-test.rb @@ -559,6 +559,7 @@ def get_podspec_fabric_and_script_phases(script_phases) specs[:dependencies].merge!({ 'React-graphics': [], 'React-Fabric': [], + 'React-FabricImage': [], 'React-utils': [], 'React-debug': [], 'React-rendererdebug': [], @@ -578,6 +579,7 @@ def get_podspec_when_use_frameworks specs[:dependencies].merge!({ 'React-graphics': [], 'React-Fabric': [], + 'React-FabricImage': [], 'React-utils': [], 'React-debug': [], 'React-rendererdebug': [], diff --git a/packages/react-native/scripts/cocoapods/codegen_utils.rb b/packages/react-native/scripts/cocoapods/codegen_utils.rb index 951adaaa2572cc..9875b2646a2bf3 100644 --- a/packages/react-native/scripts/cocoapods/codegen_utils.rb +++ b/packages/react-native/scripts/cocoapods/codegen_utils.rb @@ -138,6 +138,7 @@ def get_react_codegen_spec(package_json_file, folly_version: '2023.08.07.00', he 'React-graphics': [], 'React-rendererdebug': [], 'React-Fabric': [], + 'React-FabricImage': [], 'React-debug': [], 'React-utils': [], } From 237b94cddcf5395907391c06d51abdadbf5f039c Mon Sep 17 00:00:00 2001 From: Nick Gerleman Date: Sat, 25 Nov 2023 20:41:22 -0800 Subject: [PATCH 091/162] CompactValue -> Style::Length (#41392) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41392 X-link: https://github.com/facebook/yoga/pull/1458 We're moving `CompactValue` to be an internal detail of `yoga::Style`, where users outside of the style will be dealing with a resolved/non-compact representation. This change renames usages of `CompactValue` to `Style::Length`, which will be Yoga's representation for CSS input lengths. Right now one is just a type alias of the other, but this will let us change the internals of CompactValue with the rest of the world looking the same. A few factory functions are added to `yoga::value` for creating CSS values. There are some shenanigans around how we want to represent CSS pixels (one YGUnitPoint), when we also end up adding CSS points (slightly larger than one YGUnitPoint). For now, I reused `point` until making other changes. Changelog: [Internal] Reviewed By: yungsters Differential Revision: D51000389 fbshipit-source-id: 00f55e72bfb8aa291b53308f8a62ac8797be490f --- .../Text/RCTParagraphComponentViewTests.mm | 40 ++++---- .../AndroidTextInputComponentDescriptor.h | 17 ++-- .../view/YogaLayoutableShadowNode.cpp | 56 +++++------ .../view/YogaLayoutableShadowNode.h | 2 - .../components/view/YogaStylableProps.cpp | 32 +++---- .../components/view/YogaStylableProps.h | 34 ++++--- .../renderer/components/view/conversions.h | 10 +- .../components/view/tests/LayoutTest.cpp | 40 ++++---- .../mounting/tests/StackingContextTest.cpp | 6 +- .../ReactCommon/yoga/yoga/YGNodeStyle.cpp | 96 ++++++++----------- .../yoga/yoga/algorithm/ResolveValue.h | 4 +- .../ReactCommon/yoga/yoga/node/Node.cpp | 8 +- .../ReactCommon/yoga/yoga/node/Node.h | 7 +- .../yoga/yoga/style/CompactValue.h | 18 +--- .../ReactCommon/yoga/yoga/style/Style.h | 73 ++++++++------ .../yoga/yoga/style/ValueFactories.h | 42 ++++++++ 16 files changed, 246 insertions(+), 239 deletions(-) create mode 100644 packages/react-native/ReactCommon/yoga/yoga/style/ValueFactories.h diff --git a/packages/react-native/React/Tests/Text/RCTParagraphComponentViewTests.mm b/packages/react-native/React/Tests/Text/RCTParagraphComponentViewTests.mm index 0f5dc648ded670..f6c1ba3c6ed15f 100644 --- a/packages/react-native/React/Tests/Text/RCTParagraphComponentViewTests.mm +++ b/packages/react-native/React/Tests/Text/RCTParagraphComponentViewTests.mm @@ -121,8 +121,8 @@ - (void)setUp auto &props = *sharedProps; props.layoutConstraints = LayoutConstraints{{0, 0}, {500, 500}}; auto &yogaStyle = props.yogaStyle; - yogaStyle.setDimension(yoga::Dimension::Width, yoga::CompactValue::of(200)); - yogaStyle.setDimension(yoga::Dimension::Height, yoga::CompactValue::of(200)); + yogaStyle.setDimension(yoga::Dimension::Width, yoga::value::points(200)); + yogaStyle.setDimension(yoga::Dimension::Height, yoga::value::points(200)); return sharedProps; }) .children({ @@ -134,10 +134,10 @@ - (void)setUp props.accessible = true; auto &yogaStyle = props.yogaStyle; yogaStyle.positionType() = yoga::PositionType::Absolute; - yogaStyle.setPosition(YGEdgeLeft, yoga::CompactValue::of(0)); - yogaStyle.setPosition(YGEdgeTop, yoga::CompactValue::of(0)); - yogaStyle.setDimension(yoga::Dimension::Width, yoga::CompactValue::of(200)); - yogaStyle.setDimension(yoga::Dimension::Height, yoga::CompactValue::of(200)); + yogaStyle.setPosition(YGEdgeLeft, yoga::value::points(0)); + yogaStyle.setPosition(YGEdgeTop, yoga::value::points(0)); + yogaStyle.setDimension(yoga::Dimension::Width, yoga::value::points(200)); + yogaStyle.setDimension(yoga::Dimension::Height, yoga::value::points(200)); return sharedProps; }) .children({ @@ -214,10 +214,10 @@ - (void)setUp props.accessible = true; auto &yogaStyle = props.yogaStyle; yogaStyle.positionType() = yoga::PositionType::Absolute; - yogaStyle.setPosition(YGEdgeLeft, yoga::CompactValue::of(0)); - yogaStyle.setPosition(YGEdgeTop, yoga::CompactValue::of(30)); - yogaStyle.setDimension(yoga::Dimension::Width, yoga::CompactValue::of(200)); - yogaStyle.setDimension(yoga::Dimension::Height, yoga::CompactValue::of(50)); + yogaStyle.setPosition(YGEdgeLeft, yoga::value::points(0)); + yogaStyle.setPosition(YGEdgeTop, yoga::value::points(30)); + yogaStyle.setDimension(yoga::Dimension::Width, yoga::value::points(200)); + yogaStyle.setDimension(yoga::Dimension::Height, yoga::value::points(50)); return sharedProps; }) .children({ @@ -258,10 +258,10 @@ - (void)setUp props.accessible = true; auto &yogaStyle = props.yogaStyle; yogaStyle.positionType() = yoga::PositionType::Absolute; - yogaStyle.setPosition(YGEdgeLeft, yoga::CompactValue::of(0)); - yogaStyle.setPosition(YGEdgeTop, yoga::CompactValue::of(90)); - yogaStyle.setDimension(yoga::Dimension::Width, yoga::CompactValue::of(200)); - yogaStyle.setDimension(yoga::Dimension::Height, yoga::CompactValue::of(50)); + yogaStyle.setPosition(YGEdgeLeft, yoga::value::points(0)); + yogaStyle.setPosition(YGEdgeTop, yoga::value::points(90)); + yogaStyle.setDimension(yoga::Dimension::Width, yoga::value::points(200)); + yogaStyle.setDimension(yoga::Dimension::Height, yoga::value::points(50)); return sharedProps; }) .children({ @@ -418,8 +418,8 @@ - (void)testEntireParagraphLink auto &props = *sharedProps; props.layoutConstraints = LayoutConstraints{{0, 0}, {500, 500}}; auto &yogaStyle = props.yogaStyle; - yogaStyle.setDimension(yoga::Dimension::Width, yoga::CompactValue::of(200)); - yogaStyle.setDimension(yoga::Dimension::Height, yoga::CompactValue::of(200)); + yogaStyle.setDimension(yoga::Dimension::Width, yoga::value::points(200)); + yogaStyle.setDimension(yoga::Dimension::Height, yoga::value::points(200)); return sharedProps; }) .children({ @@ -432,10 +432,10 @@ - (void)testEntireParagraphLink props.accessibilityTraits = AccessibilityTraits::Link; auto &yogaStyle = props.yogaStyle; yogaStyle.positionType() = yoga::PositionType::Absolute; - yogaStyle.setPosition(YGEdgeLeft, yoga::CompactValue::of(0)); - yogaStyle.setPosition(YGEdgeTop, yoga::CompactValue::of(0)); - yogaStyle.setDimension(yoga::Dimension::Width, yoga::CompactValue::of(200)); - yogaStyle.setDimension(yoga::Dimension::Height, yoga::CompactValue::of(20)); + yogaStyle.setPosition(YGEdgeLeft, yoga::value::points(0)); + yogaStyle.setPosition(YGEdgeTop, yoga::value::points(90)); + yogaStyle.setDimension(yoga::Dimension::Width, yoga::value::points(200)); + yogaStyle.setDimension(yoga::Dimension::Height, yoga::value::points(20)); return sharedProps; }) .children({ diff --git a/packages/react-native/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputComponentDescriptor.h b/packages/react-native/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputComponentDescriptor.h index 553ba44389a8e1..0ff0f91ea30953 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputComponentDescriptor.h +++ b/packages/react-native/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputComponentDescriptor.h @@ -13,7 +13,6 @@ #include #include -#include #include @@ -106,27 +105,23 @@ class AndroidTextInputComponentDescriptor final !textInputProps.hasPaddingLeft && !textInputProps.hasPaddingHorizontal) { changedPadding = true; - style.setPadding( - YGEdgeStart, yoga::CompactValue::of(theme.start)); + style.setPadding(YGEdgeStart, yoga::value::points(theme.start)); } if (!textInputProps.hasPadding && !textInputProps.hasPaddingEnd && !textInputProps.hasPaddingRight && !textInputProps.hasPaddingHorizontal) { changedPadding = true; - style.setPadding( - YGEdgeEnd, yoga::CompactValue::of(theme.end)); + style.setPadding(YGEdgeEnd, yoga::value::points(theme.end)); } if (!textInputProps.hasPadding && !textInputProps.hasPaddingTop && !textInputProps.hasPaddingVertical) { changedPadding = true; - style.setPadding( - YGEdgeTop, yoga::CompactValue::of(theme.top)); + style.setPadding(YGEdgeTop, yoga::value::points(theme.top)); } if (!textInputProps.hasPadding && !textInputProps.hasPaddingBottom && !textInputProps.hasPaddingVertical) { changedPadding = true; - style.setPadding( - YGEdgeBottom, yoga::CompactValue::of(theme.bottom)); + style.setPadding(YGEdgeBottom, yoga::value::points(theme.bottom)); } // If the TextInput initially does not have paddingLeft or paddingStart, a @@ -137,12 +132,12 @@ class AndroidTextInputComponentDescriptor final if ((textInputProps.hasPadding || textInputProps.hasPaddingLeft || textInputProps.hasPaddingHorizontal) && !textInputProps.hasPaddingStart) { - style.setPadding(YGEdgeStart, yoga::CompactValue::ofUndefined()); + style.setPadding(YGEdgeStart, yoga::value::undefined()); } if ((textInputProps.hasPadding || textInputProps.hasPaddingRight || textInputProps.hasPaddingHorizontal) && !textInputProps.hasPaddingEnd) { - style.setPadding(YGEdgeEnd, yoga::CompactValue::ofUndefined()); + style.setPadding(YGEdgeEnd, yoga::value::undefined()); } // Note that this is expensive: on every adopt, we need to set the Yoga diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/YogaLayoutableShadowNode.cpp b/packages/react-native/ReactCommon/react/renderer/components/view/YogaLayoutableShadowNode.cpp index ac2e89a618aaab..ed278ac98828ba 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/YogaLayoutableShadowNode.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/view/YogaLayoutableShadowNode.cpp @@ -529,12 +529,8 @@ void YogaLayoutableShadowNode::setSize(Size size) const { ensureUnsealed(); auto style = yogaNode_.getStyle(); - style.setDimension( - yoga::Dimension::Width, - yoga::CompactValue::ofMaybe(size.width)); - style.setDimension( - yoga::Dimension::Height, - yoga::CompactValue::ofMaybe(size.height)); + style.setDimension(yoga::Dimension::Width, yoga::value::points(size.width)); + style.setDimension(yoga::Dimension::Height, yoga::value::points(size.height)); yogaNode_.setStyle(style); yogaNode_.setDirty(true); } @@ -544,23 +540,19 @@ void YogaLayoutableShadowNode::setPadding(RectangleEdges padding) const { auto style = yogaNode_.getStyle(); - auto leftPadding = yoga::CompactValue::ofMaybe(padding.left); - auto topPadding = yoga::CompactValue::ofMaybe(padding.top); - auto rightPadding = yoga::CompactValue::ofMaybe(padding.right); - auto bottomPadding = yoga::CompactValue::ofMaybe(padding.bottom); + auto leftPadding = yoga::value::points(padding.left); + auto topPadding = yoga::value::points(padding.top); + auto rightPadding = yoga::value::points(padding.right); + auto bottomPadding = yoga::value::points(padding.bottom); if (leftPadding != style.padding(YGEdgeLeft) || topPadding != style.padding(YGEdgeTop) || rightPadding != style.padding(YGEdgeRight) || bottomPadding != style.padding(YGEdgeBottom)) { - style.setPadding( - YGEdgeTop, yoga::CompactValue::ofMaybe(padding.top)); - style.setPadding( - YGEdgeLeft, yoga::CompactValue::ofMaybe(padding.left)); - style.setPadding( - YGEdgeRight, yoga::CompactValue::ofMaybe(padding.right)); - style.setPadding( - YGEdgeBottom, yoga::CompactValue::ofMaybe(padding.bottom)); + style.setPadding(YGEdgeTop, yoga::value::points(padding.top)); + style.setPadding(YGEdgeLeft, yoga::value::points(padding.left)); + style.setPadding(YGEdgeRight, yoga::value::points(padding.right)); + style.setPadding(YGEdgeBottom, yoga::value::points(padding.bottom)); yogaNode_.setStyle(style); yogaNode_.setDirty(true); } @@ -630,20 +622,16 @@ void YogaLayoutableShadowNode::layoutTree( auto ownerHeight = yogaFloatFromFloat(maximumSize.height); yogaStyle.setMaxDimension( - yoga::Dimension::Width, - yoga::CompactValue::ofMaybe(maximumSize.width)); + yoga::Dimension::Width, yoga::value::points(maximumSize.width)); yogaStyle.setMaxDimension( - yoga::Dimension::Height, - yoga::CompactValue::ofMaybe(maximumSize.height)); + yoga::Dimension::Height, yoga::value::points(maximumSize.height)); yogaStyle.setMinDimension( - yoga::Dimension::Width, - yoga::CompactValue::ofMaybe(minimumSize.width)); + yoga::Dimension::Width, yoga::value::points(minimumSize.width)); yogaStyle.setMinDimension( - yoga::Dimension::Height, - yoga::CompactValue::ofMaybe(minimumSize.height)); + yoga::Dimension::Height, yoga::value::points(minimumSize.height)); auto direction = yogaDirectionFromLayoutDirection(layoutConstraints.layoutDirection); @@ -887,32 +875,32 @@ void YogaLayoutableShadowNode::swapLeftAndRightInYogaStyleProps( if (yogaStyle.position(YGEdgeLeft).isDefined()) { yogaStyle.setPosition(YGEdgeStart, yogaStyle.position(YGEdgeLeft)); - yogaStyle.setPosition(YGEdgeLeft, yoga::CompactValue::ofUndefined()); + yogaStyle.setPosition(YGEdgeLeft, yoga::value::undefined()); } if (yogaStyle.position(YGEdgeRight).isDefined()) { yogaStyle.setPosition(YGEdgeEnd, yogaStyle.position(YGEdgeRight)); - yogaStyle.setPosition(YGEdgeRight, yoga::CompactValue::ofUndefined()); + yogaStyle.setPosition(YGEdgeRight, yoga::value::undefined()); } if (yogaStyle.padding(YGEdgeLeft).isDefined()) { yogaStyle.setPadding(YGEdgeStart, yogaStyle.padding(YGEdgeLeft)); - yogaStyle.setPadding(YGEdgeLeft, yoga::CompactValue::ofUndefined()); + yogaStyle.setPadding(YGEdgeLeft, yoga::value::undefined()); } if (yogaStyle.padding(YGEdgeRight).isDefined()) { yogaStyle.setPadding(YGEdgeEnd, yogaStyle.padding(YGEdgeRight)); - yogaStyle.setPadding(YGEdgeRight, yoga::CompactValue::ofUndefined()); + yogaStyle.setPadding(YGEdgeRight, yoga::value::undefined()); } if (yogaStyle.margin(YGEdgeLeft).isDefined()) { yogaStyle.setMargin(YGEdgeStart, yogaStyle.margin(YGEdgeLeft)); - yogaStyle.setMargin(YGEdgeLeft, yoga::CompactValue::ofUndefined()); + yogaStyle.setMargin(YGEdgeLeft, yoga::value::undefined()); } if (yogaStyle.margin(YGEdgeRight).isDefined()) { yogaStyle.setMargin(YGEdgeEnd, yogaStyle.margin(YGEdgeRight)); - yogaStyle.setMargin(YGEdgeRight, yoga::CompactValue::ofUndefined()); + yogaStyle.setMargin(YGEdgeRight, yoga::value::undefined()); } shadowNode.yogaNode_.setStyle(yogaStyle); @@ -967,12 +955,12 @@ void YogaLayoutableShadowNode::swapLeftAndRightInViewProps( if (props.yogaStyle.border(YGEdgeLeft).isDefined()) { props.yogaStyle.setBorder(YGEdgeStart, props.yogaStyle.border(YGEdgeLeft)); - props.yogaStyle.setBorder(YGEdgeLeft, yoga::CompactValue::ofUndefined()); + props.yogaStyle.setBorder(YGEdgeLeft, yoga::value::undefined()); } if (props.yogaStyle.border(YGEdgeRight).isDefined()) { props.yogaStyle.setBorder(YGEdgeEnd, props.yogaStyle.border(YGEdgeRight)); - props.yogaStyle.setBorder(YGEdgeRight, yoga::CompactValue::ofUndefined()); + props.yogaStyle.setBorder(YGEdgeRight, yoga::value::undefined()); } } diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/YogaLayoutableShadowNode.h b/packages/react-native/ReactCommon/react/renderer/components/view/YogaLayoutableShadowNode.h index 0d31fb56eae31c..f4a9ba794362a8 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/YogaLayoutableShadowNode.h +++ b/packages/react-native/ReactCommon/react/renderer/components/view/YogaLayoutableShadowNode.h @@ -22,8 +22,6 @@ namespace facebook::react { class YogaLayoutableShadowNode : public LayoutableShadowNode { - using CompactValue = facebook::yoga::CompactValue; - public: using Shared = std::shared_ptr; using ListOfShared = std::vector; diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/YogaStylableProps.cpp b/packages/react-native/ReactCommon/react/renderer/components/view/YogaStylableProps.cpp index 39e32c9fa93283..ce472496bedebe 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/YogaStylableProps.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/view/YogaStylableProps.cpp @@ -417,98 +417,98 @@ void YogaStylableProps::convertRawPropAliases( rawProps, "insetBlockEnd", sourceProps.insetBlockEnd, - CompactValue::ofUndefined()); + yoga::value::undefined()); insetBlockStart = convertRawProp( context, rawProps, "insetBlockStart", sourceProps.insetBlockStart, - CompactValue::ofUndefined()); + yoga::value::undefined()); insetInlineEnd = convertRawProp( context, rawProps, "insetInlineEnd", sourceProps.insetInlineEnd, - CompactValue::ofUndefined()); + yoga::value::undefined()); insetInlineStart = convertRawProp( context, rawProps, "insetInlineStart", sourceProps.insetInlineStart, - CompactValue::ofUndefined()); + yoga::value::undefined()); marginInline = convertRawProp( context, rawProps, "marginInline", sourceProps.marginInline, - CompactValue::ofUndefined()); + yoga::value::undefined()); marginInlineStart = convertRawProp( context, rawProps, "marginInlineStart", sourceProps.marginInlineStart, - CompactValue::ofUndefined()); + yoga::value::undefined()); marginInlineEnd = convertRawProp( context, rawProps, "marginInlineEnd", sourceProps.marginInlineEnd, - CompactValue::ofUndefined()); + yoga::value::undefined()); marginBlock = convertRawProp( context, rawProps, "marginBlock", sourceProps.marginBlock, - CompactValue::ofUndefined()); + yoga::value::undefined()); marginBlockStart = convertRawProp( context, rawProps, "marginBlockStart", sourceProps.marginBlockStart, - CompactValue::ofUndefined()); + yoga::value::undefined()); marginBlockEnd = convertRawProp( context, rawProps, "marginBlockEnd", sourceProps.marginBlockEnd, - CompactValue::ofUndefined()); + yoga::value::undefined()); paddingInline = convertRawProp( context, rawProps, "paddingInline", sourceProps.paddingInline, - CompactValue::ofUndefined()); + yoga::value::undefined()); paddingInlineStart = convertRawProp( context, rawProps, "paddingInlineStart", sourceProps.paddingInlineStart, - CompactValue::ofUndefined()); + yoga::value::undefined()); paddingInlineEnd = convertRawProp( context, rawProps, "paddingInlineEnd", sourceProps.paddingInlineEnd, - CompactValue::ofUndefined()); + yoga::value::undefined()); paddingBlock = convertRawProp( context, rawProps, "paddingBlock", sourceProps.paddingBlock, - CompactValue::ofUndefined()); + yoga::value::undefined()); paddingBlockStart = convertRawProp( context, rawProps, "paddingBlockStart", sourceProps.paddingBlockStart, - CompactValue::ofUndefined()); + yoga::value::undefined()); paddingBlockEnd = convertRawProp( context, rawProps, "paddingBlockEnd", sourceProps.paddingBlockEnd, - CompactValue::ofUndefined()); + yoga::value::undefined()); } } // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/YogaStylableProps.h b/packages/react-native/ReactCommon/react/renderer/components/view/YogaStylableProps.h index 9114aa530e7ae8..165209183725ff 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/YogaStylableProps.h +++ b/packages/react-native/ReactCommon/react/renderer/components/view/YogaStylableProps.h @@ -16,8 +16,6 @@ namespace facebook::react { class YogaStylableProps : public Props { - using CompactValue = facebook::yoga::CompactValue; - public: YogaStylableProps() = default; YogaStylableProps( @@ -41,30 +39,30 @@ class YogaStylableProps : public Props { // Duplicates of existing properties with different names, taking // precedence. E.g. "marginBlock" instead of "marginVertical" - CompactValue insetInlineStart; - CompactValue insetInlineEnd; + yoga::Style::Length insetInlineStart; + yoga::Style::Length insetInlineEnd; - CompactValue marginInline; - CompactValue marginInlineStart; - CompactValue marginInlineEnd; - CompactValue marginBlock; + yoga::Style::Length marginInline; + yoga::Style::Length marginInlineStart; + yoga::Style::Length marginInlineEnd; + yoga::Style::Length marginBlock; - CompactValue paddingInline; - CompactValue paddingInlineStart; - CompactValue paddingInlineEnd; - CompactValue paddingBlock; + yoga::Style::Length paddingInline; + yoga::Style::Length paddingInlineStart; + yoga::Style::Length paddingInlineEnd; + yoga::Style::Length paddingBlock; // BlockEnd/BlockStart map to top/bottom (no writing mode), but we preserve // Yoga's precedence and prefer specific edges (e.g. top) to ones which are // flow relative (e.g. blockStart). - CompactValue insetBlockStart; - CompactValue insetBlockEnd; + yoga::Style::Length insetBlockStart; + yoga::Style::Length insetBlockEnd; - CompactValue marginBlockStart; - CompactValue marginBlockEnd; + yoga::Style::Length marginBlockStart; + yoga::Style::Length marginBlockEnd; - CompactValue paddingBlockStart; - CompactValue paddingBlockEnd; + yoga::Style::Length paddingBlockStart; + yoga::Style::Length paddingBlockEnd; #if RN_DEBUG_STRING_CONVERTIBLE diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/conversions.h b/packages/react-native/ReactCommon/react/renderer/components/view/conversions.h index 2a82a16e85a1ce..58a898fb1027d1 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/conversions.h +++ b/packages/react-native/ReactCommon/react/renderer/components/view/conversions.h @@ -395,9 +395,9 @@ inline void fromRawValue( inline void fromRawValue( const PropsParserContext& context, const RawValue& value, - yoga::CompactValue& result) { + yoga::Style::Length& result) { if (value.hasType()) { - result = yoga::CompactValue::ofMaybe((float)value); + result = yoga::value::points((float)value); return; } else if (value.hasType()) { const auto stringValue = (std::string)value; @@ -409,13 +409,13 @@ inline void fromRawValue( auto tryValue = folly::tryTo( std::string_view(stringValue).substr(0, stringValue.length() - 1)); if (tryValue.hasValue()) { - result = YGValue{tryValue.value(), YGUnitPercent}; + result = yoga::value::percent(tryValue.value()); return; } } else { auto tryValue = folly::tryTo(stringValue); if (tryValue.hasValue()) { - result = YGValue{tryValue.value(), YGUnitPoint}; + result = yoga::value::points(tryValue.value()); return; } } @@ -428,7 +428,7 @@ inline void fromRawValue( const PropsParserContext& context, const RawValue& value, YGValue& result) { - yoga::CompactValue ygValue{}; + yoga::Style::Length ygValue{}; fromRawValue(context, value, ygValue); result = ygValue; } diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/tests/LayoutTest.cpp b/packages/react-native/ReactCommon/react/renderer/components/view/tests/LayoutTest.cpp index b0be9bc7f1e32d..5e44e2d5044293 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/tests/LayoutTest.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/view/tests/LayoutTest.cpp @@ -77,8 +77,8 @@ class LayoutTest : public ::testing::Test { auto &props = *sharedProps; props.layoutConstraints = LayoutConstraints{{0,0}, {500, 500}}; auto &yogaStyle = props.yogaStyle; - yogaStyle.setDimension(yoga::Dimension::Width, yoga::CompactValue::of(200)); - yogaStyle.setDimension(yoga::Dimension::Height, yoga::CompactValue::of(200)); + yogaStyle.setDimension(yoga::Dimension::Width, yoga::value::points(200)); + yogaStyle.setDimension(yoga::Dimension::Height, yoga::value::points(200)); return sharedProps; }) .children({ @@ -90,8 +90,8 @@ class LayoutTest : public ::testing::Test { auto &props = *sharedProps; auto &yogaStyle = props.yogaStyle; yogaStyle.positionType() = yoga::PositionType::Absolute; - yogaStyle.setDimension(yoga::Dimension::Width, yoga::CompactValue::of(50)); - yogaStyle.setDimension(yoga::Dimension::Height, yoga::CompactValue::of(50)); + yogaStyle.setDimension(yoga::Dimension::Width, yoga::value::points(50)); + yogaStyle.setDimension(yoga::Dimension::Height, yoga::value::points(50)); return sharedProps; }) .children({ @@ -103,10 +103,10 @@ class LayoutTest : public ::testing::Test { auto &props = *sharedProps; auto &yogaStyle = props.yogaStyle; yogaStyle.positionType() = yoga::PositionType::Absolute; - yogaStyle.setPosition(YGEdgeLeft, yoga::CompactValue::of(10)); - yogaStyle.setPosition(YGEdgeTop, yoga::CompactValue::of(10)); - yogaStyle.setDimension(yoga::Dimension::Width, yoga::CompactValue::of(30)); - yogaStyle.setDimension(yoga::Dimension::Height, yoga::CompactValue::of(90)); + yogaStyle.setPosition(YGEdgeLeft, yoga::value::points(10)); + yogaStyle.setPosition(YGEdgeTop, yoga::value::points(10)); + yogaStyle.setDimension(yoga::Dimension::Width, yoga::value::points(30)); + yogaStyle.setDimension(yoga::Dimension::Height, yoga::value::points(90)); if (testCase == TRANSFORM_SCALE) { props.transform = props.transform * Transform::Scale(2, 2, 1); @@ -136,10 +136,10 @@ class LayoutTest : public ::testing::Test { } yogaStyle.positionType() = yoga::PositionType::Absolute; - yogaStyle.setPosition(YGEdgeLeft, yoga::CompactValue::of(10)); - yogaStyle.setPosition(YGEdgeTop, yoga::CompactValue::of(10)); - yogaStyle.setDimension(yoga::Dimension::Width, yoga::CompactValue::of(110)); - yogaStyle.setDimension(yoga::Dimension::Height, yoga::CompactValue::of(20)); + yogaStyle.setPosition(YGEdgeLeft, yoga::value::points(10)); + yogaStyle.setPosition(YGEdgeTop, yoga::value::points(10)); + yogaStyle.setDimension(yoga::Dimension::Width, yoga::value::points(110)); + yogaStyle.setDimension(yoga::Dimension::Height, yoga::value::points(20)); return sharedProps; }) .children({ @@ -151,10 +151,10 @@ class LayoutTest : public ::testing::Test { auto &props = *sharedProps; auto &yogaStyle = props.yogaStyle; yogaStyle.positionType() = yoga::PositionType::Absolute; - yogaStyle.setPosition(YGEdgeLeft, yoga::CompactValue::of(70)); - yogaStyle.setPosition(YGEdgeTop, yoga::CompactValue::of(-50)); - yogaStyle.setDimension(yoga::Dimension::Width, yoga::CompactValue::of(30)); - yogaStyle.setDimension(yoga::Dimension::Height, yoga::CompactValue::of(60)); + yogaStyle.setPosition(YGEdgeLeft, yoga::value::points(70)); + yogaStyle.setPosition(YGEdgeTop, yoga::value::points(-50)); + yogaStyle.setDimension(yoga::Dimension::Width, yoga::value::points(30)); + yogaStyle.setDimension(yoga::Dimension::Height, yoga::value::points(60)); return sharedProps; }) }), @@ -166,10 +166,10 @@ class LayoutTest : public ::testing::Test { auto &props = *sharedProps; auto &yogaStyle = props.yogaStyle; yogaStyle.positionType() = yoga::PositionType::Absolute; - yogaStyle.setPosition(YGEdgeLeft, yoga::CompactValue::of(-60)); - yogaStyle.setPosition(YGEdgeTop, yoga::CompactValue::of(50)); - yogaStyle.setDimension(yoga::Dimension::Width, yoga::CompactValue::of(70)); - yogaStyle.setDimension(yoga::Dimension::Height, yoga::CompactValue::of(20)); + yogaStyle.setPosition(YGEdgeLeft, yoga::value::points(-60)); + yogaStyle.setPosition(YGEdgeTop, yoga::value::points(50)); + yogaStyle.setDimension(yoga::Dimension::Width, yoga::value::points(70)); + yogaStyle.setDimension(yoga::Dimension::Height, yoga::value::points(20)); return sharedProps; }) }) diff --git a/packages/react-native/ReactCommon/react/renderer/mounting/tests/StackingContextTest.cpp b/packages/react-native/ReactCommon/react/renderer/mounting/tests/StackingContextTest.cpp index ab06e2f8ccce76..ae64dd3393dc34 100644 --- a/packages/react-native/ReactCommon/react/renderer/mounting/tests/StackingContextTest.cpp +++ b/packages/react-native/ReactCommon/react/renderer/mounting/tests/StackingContextTest.cpp @@ -251,8 +251,8 @@ TEST_F(StackingContextTest, mostPropsDoNotForceViewsToMaterialize) { mutateViewShadowNodeProps_(nodeAA_, [](ViewProps& props) { auto& yogaStyle = props.yogaStyle; - yogaStyle.setPadding(YGEdgeAll, yoga::CompactValue::of(42)); - yogaStyle.setMargin(YGEdgeAll, yoga::CompactValue::of(42)); + yogaStyle.setPadding(YGEdgeAll, yoga::value::points(42)); + yogaStyle.setMargin(YGEdgeAll, yoga::value::points(42)); yogaStyle.positionType() = yoga::PositionType::Absolute; props.shadowRadius = 42; props.shadowOffset = Size{42, 42}; @@ -262,7 +262,7 @@ TEST_F(StackingContextTest, mostPropsDoNotForceViewsToMaterialize) { mutateViewShadowNodeProps_(nodeBA_, [](ViewProps& props) { auto& yogaStyle = props.yogaStyle; props.zIndex = 42; - yogaStyle.setMargin(YGEdgeAll, yoga::CompactValue::of(42)); + yogaStyle.setMargin(YGEdgeAll, yoga::value::points(42)); props.shadowColor = clearColor(); props.shadowOpacity = 0.42; }); diff --git a/packages/react-native/ReactCommon/yoga/yoga/YGNodeStyle.cpp b/packages/react-native/ReactCommon/yoga/yoga/YGNodeStyle.cpp index 38a55f2c8c8a31..6767e5e8e31969 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/YGNodeStyle.cpp +++ b/packages/react-native/ReactCommon/yoga/yoga/YGNodeStyle.cpp @@ -26,22 +26,22 @@ void updateStyle( } } -template -void updateStyle(YGNodeRef node, Ref (Style::*prop)(), T value) { +template +void updateStyle(YGNodeRef node, Ref (Style::*prop)(), ValueT value) { updateStyle( resolveRef(node), value, - [prop](Style& s, T x) { return (s.*prop)() != x; }, - [prop](Style& s, T x) { (s.*prop)() = x; }); + [prop](Style& s, ValueT x) { return (s.*prop)() != x; }, + [prop](Style& s, ValueT x) { (s.*prop)() = x; }); } -template -void updateIndexedStyleProp(YGNodeRef node, IdxT idx, CompactValue value) { +template +void updateIndexedStyleProp(YGNodeRef node, IdxT idx, ValueT value) { updateStyle( resolveRef(node), value, - [idx](Style& s, CompactValue x) { return (s.*GetterT)(idx) != x; }, - [idx](Style& s, CompactValue x) { (s.*SetterT)(idx, x); }); + [idx](Style& s, ValueT x) { return (s.*GetterT)(idx) != x; }, + [idx](Style& s, ValueT x) { (s.*SetterT)(idx, x); }); } } // namespace @@ -198,20 +198,19 @@ float YGNodeStyleGetFlexShrink(const YGNodeConstRef nodeRef) { } void YGNodeStyleSetFlexBasis(const YGNodeRef node, const float flexBasis) { - auto value = CompactValue::ofMaybe(flexBasis); - updateStyle(node, &Style::flexBasis, value); + updateStyle( + node, &Style::flexBasis, value::points(flexBasis)); } void YGNodeStyleSetFlexBasisPercent( const YGNodeRef node, const float flexBasisPercent) { - auto value = CompactValue::ofMaybe(flexBasisPercent); - updateStyle(node, &Style::flexBasis, value); + updateStyle( + node, &Style::flexBasis, value::percent(flexBasisPercent)); } void YGNodeStyleSetFlexBasisAuto(const YGNodeRef node) { - updateStyle( - node, &Style::flexBasis, CompactValue::ofAuto()); + updateStyle(node, &Style::flexBasis, value::ofAuto()); } YGValue YGNodeStyleGetFlexBasis(const YGNodeConstRef node) { @@ -223,15 +222,13 @@ YGValue YGNodeStyleGetFlexBasis(const YGNodeConstRef node) { } void YGNodeStyleSetPosition(YGNodeRef node, YGEdge edge, float points) { - auto value = CompactValue::ofMaybe(points); updateIndexedStyleProp<&Style::position, &Style::setPosition>( - node, edge, value); + node, edge, value::points(points)); } void YGNodeStyleSetPositionPercent(YGNodeRef node, YGEdge edge, float percent) { - auto value = CompactValue::ofMaybe(percent); updateIndexedStyleProp<&Style::position, &Style::setPosition>( - node, edge, value); + node, edge, value::percent(percent)); } YGValue YGNodeStyleGetPosition(YGNodeConstRef node, YGEdge edge) { @@ -239,18 +236,18 @@ YGValue YGNodeStyleGetPosition(YGNodeConstRef node, YGEdge edge) { } void YGNodeStyleSetMargin(YGNodeRef node, YGEdge edge, float points) { - auto value = CompactValue::ofMaybe(points); - updateIndexedStyleProp<&Style::margin, &Style::setMargin>(node, edge, value); + updateIndexedStyleProp<&Style::margin, &Style::setMargin>( + node, edge, value::points(points)); } void YGNodeStyleSetMarginPercent(YGNodeRef node, YGEdge edge, float percent) { - auto value = CompactValue::ofMaybe(percent); - updateIndexedStyleProp<&Style::margin, &Style::setMargin>(node, edge, value); + updateIndexedStyleProp<&Style::margin, &Style::setMargin>( + node, edge, value::percent(percent)); } void YGNodeStyleSetMarginAuto(YGNodeRef node, YGEdge edge) { updateIndexedStyleProp<&Style::margin, &Style::setMargin>( - node, edge, CompactValue::ofAuto()); + node, edge, value::ofAuto()); } YGValue YGNodeStyleGetMargin(YGNodeConstRef node, YGEdge edge) { @@ -258,15 +255,13 @@ YGValue YGNodeStyleGetMargin(YGNodeConstRef node, YGEdge edge) { } void YGNodeStyleSetPadding(YGNodeRef node, YGEdge edge, float points) { - auto value = CompactValue::ofMaybe(points); updateIndexedStyleProp<&Style::padding, &Style::setPadding>( - node, edge, value); + node, edge, value::points(points)); } void YGNodeStyleSetPaddingPercent(YGNodeRef node, YGEdge edge, float percent) { - auto value = CompactValue::ofMaybe(percent); updateIndexedStyleProp<&Style::padding, &Style::setPadding>( - node, edge, value); + node, edge, value::percent(percent)); } YGValue YGNodeStyleGetPadding(YGNodeConstRef node, YGEdge edge) { @@ -277,8 +272,8 @@ void YGNodeStyleSetBorder( const YGNodeRef node, const YGEdge edge, const float border) { - auto value = CompactValue::ofMaybe(border); - updateIndexedStyleProp<&Style::border, &Style::setBorder>(node, edge, value); + updateIndexedStyleProp<&Style::border, &Style::setBorder>( + node, edge, value::points(border)); } float YGNodeStyleGetBorder(const YGNodeConstRef node, const YGEdge edge) { @@ -294,9 +289,8 @@ void YGNodeStyleSetGap( const YGNodeRef node, const YGGutter gutter, const float gapLength) { - auto length = CompactValue::ofMaybe(gapLength); updateIndexedStyleProp<&Style::gap, &Style::setGap>( - node, scopedEnum(gutter), length); + node, scopedEnum(gutter), value::points(gapLength)); } float YGNodeStyleGetGap(const YGNodeConstRef node, const YGGutter gutter) { @@ -319,20 +313,18 @@ float YGNodeStyleGetAspectRatio(const YGNodeConstRef node) { } void YGNodeStyleSetWidth(YGNodeRef node, float points) { - auto value = CompactValue::ofMaybe(points); updateIndexedStyleProp<&Style::dimension, &Style::setDimension>( - node, Dimension::Width, value); + node, Dimension::Width, value::points(points)); } void YGNodeStyleSetWidthPercent(YGNodeRef node, float percent) { - auto value = CompactValue::ofMaybe(percent); updateIndexedStyleProp<&Style::dimension, &Style::setDimension>( - node, Dimension::Width, value); + node, Dimension::Width, value::percent(percent)); } void YGNodeStyleSetWidthAuto(YGNodeRef node) { updateIndexedStyleProp<&Style::dimension, &Style::setDimension>( - node, Dimension::Width, CompactValue::ofAuto()); + node, Dimension::Width, value::ofAuto()); } YGValue YGNodeStyleGetWidth(YGNodeConstRef node) { @@ -340,20 +332,18 @@ YGValue YGNodeStyleGetWidth(YGNodeConstRef node) { } void YGNodeStyleSetHeight(YGNodeRef node, float points) { - auto value = CompactValue::ofMaybe(points); updateIndexedStyleProp<&Style::dimension, &Style::setDimension>( - node, Dimension::Height, value); + node, Dimension::Height, value::points(points)); } void YGNodeStyleSetHeightPercent(YGNodeRef node, float percent) { - auto value = CompactValue::ofMaybe(percent); updateIndexedStyleProp<&Style::dimension, &Style::setDimension>( - node, Dimension::Height, value); + node, Dimension::Height, value::percent(percent)); } void YGNodeStyleSetHeightAuto(YGNodeRef node) { updateIndexedStyleProp<&Style::dimension, &Style::setDimension>( - node, Dimension::Height, CompactValue::ofAuto()); + node, Dimension::Height, value::ofAuto()); } YGValue YGNodeStyleGetHeight(YGNodeConstRef node) { @@ -361,15 +351,13 @@ YGValue YGNodeStyleGetHeight(YGNodeConstRef node) { } void YGNodeStyleSetMinWidth(const YGNodeRef node, const float minWidth) { - auto value = CompactValue::ofMaybe(minWidth); updateIndexedStyleProp<&Style::minDimension, &Style::setMinDimension>( - node, Dimension::Width, value); + node, Dimension::Width, value::points(minWidth)); } void YGNodeStyleSetMinWidthPercent(const YGNodeRef node, const float minWidth) { - auto value = CompactValue::ofMaybe(minWidth); updateIndexedStyleProp<&Style::minDimension, &Style::setMinDimension>( - node, Dimension::Width, value); + node, Dimension::Width, value::percent(minWidth)); } YGValue YGNodeStyleGetMinWidth(const YGNodeConstRef node) { @@ -377,17 +365,15 @@ YGValue YGNodeStyleGetMinWidth(const YGNodeConstRef node) { } void YGNodeStyleSetMinHeight(const YGNodeRef node, const float minHeight) { - auto value = CompactValue::ofMaybe(minHeight); updateIndexedStyleProp<&Style::minDimension, &Style::setMinDimension>( - node, Dimension::Height, value); + node, Dimension::Height, value::points(minHeight)); } void YGNodeStyleSetMinHeightPercent( const YGNodeRef node, const float minHeight) { - auto value = CompactValue::ofMaybe(minHeight); updateIndexedStyleProp<&Style::minDimension, &Style::setMinDimension>( - node, Dimension::Height, value); + node, Dimension::Height, value::percent(minHeight)); } YGValue YGNodeStyleGetMinHeight(const YGNodeConstRef node) { @@ -395,15 +381,13 @@ YGValue YGNodeStyleGetMinHeight(const YGNodeConstRef node) { } void YGNodeStyleSetMaxWidth(const YGNodeRef node, const float maxWidth) { - auto value = CompactValue::ofMaybe(maxWidth); updateIndexedStyleProp<&Style::maxDimension, &Style::setMaxDimension>( - node, Dimension::Width, value); + node, Dimension::Width, value::points(maxWidth)); } void YGNodeStyleSetMaxWidthPercent(const YGNodeRef node, const float maxWidth) { - auto value = CompactValue::ofMaybe(maxWidth); updateIndexedStyleProp<&Style::maxDimension, &Style::setMaxDimension>( - node, Dimension::Width, value); + node, Dimension::Width, value::percent(maxWidth)); } YGValue YGNodeStyleGetMaxWidth(const YGNodeConstRef node) { @@ -411,17 +395,15 @@ YGValue YGNodeStyleGetMaxWidth(const YGNodeConstRef node) { } void YGNodeStyleSetMaxHeight(const YGNodeRef node, const float maxHeight) { - auto value = CompactValue::ofMaybe(maxHeight); updateIndexedStyleProp<&Style::maxDimension, &Style::setMaxDimension>( - node, Dimension::Height, value); + node, Dimension::Height, value::points(maxHeight)); } void YGNodeStyleSetMaxHeightPercent( const YGNodeRef node, const float maxHeight) { - auto value = CompactValue::ofMaybe(maxHeight); updateIndexedStyleProp<&Style::maxDimension, &Style::setMaxDimension>( - node, Dimension::Height, value); + node, Dimension::Height, value::percent(maxHeight)); } YGValue YGNodeStyleGetMaxHeight(const YGNodeConstRef node) { diff --git a/packages/react-native/ReactCommon/yoga/yoga/algorithm/ResolveValue.h b/packages/react-native/ReactCommon/yoga/yoga/algorithm/ResolveValue.h index 4e03d0c50d4d9a..a2d650b237a0cb 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/algorithm/ResolveValue.h +++ b/packages/react-native/ReactCommon/yoga/yoga/algorithm/ResolveValue.h @@ -10,7 +10,7 @@ #include #include -#include +#include namespace facebook::yoga { @@ -25,7 +25,7 @@ inline FloatOptional resolveValue(const YGValue value, const float ownerSize) { } } -inline FloatOptional resolveValue(CompactValue value, float ownerSize) { +inline FloatOptional resolveValue(Style::Length value, float ownerSize) { return resolveValue((YGValue)value, ownerSize); } diff --git a/packages/react-native/ReactCommon/yoga/yoga/node/Node.cpp b/packages/react-native/ReactCommon/yoga/yoga/node/Node.cpp index e5100ee2815137..0781b8e63ab44b 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/node/Node.cpp +++ b/packages/react-native/ReactCommon/yoga/yoga/node/Node.cpp @@ -58,7 +58,7 @@ void Node::print() { // TODO: Edge value resolution should be moved to `yoga::Style` template -CompactValue Node::computeEdgeValueForRow(YGEdge rowEdge, YGEdge edge) const { +Style::Length Node::computeEdgeValueForRow(YGEdge rowEdge, YGEdge edge) const { if ((style_.*Field)(rowEdge).isDefined()) { return (style_.*Field)(rowEdge); } else if ((style_.*Field)(edge).isDefined()) { @@ -72,7 +72,7 @@ CompactValue Node::computeEdgeValueForRow(YGEdge rowEdge, YGEdge edge) const { // TODO: Edge value resolution should be moved to `yoga::Style` template -CompactValue Node::computeEdgeValueForColumn(YGEdge edge) const { +Style::Length Node::computeEdgeValueForColumn(YGEdge edge) const { if ((style_.*Field)(edge).isDefined()) { return (style_.*Field)(edge); } else if ((style_.*Field)(YGEdgeVertical).isDefined()) { @@ -497,8 +497,8 @@ void Node::setLayoutHadOverflow(bool hadOverflow) { layout_.setHadOverflow(hadOverflow); } -void Node::setLayoutDimension(float dimensionValue, Dimension dimension) { - layout_.setDimension(dimension, dimensionValue); +void Node::setLayoutDimension(float LengthValue, Dimension dimension) { + layout_.setDimension(dimension, LengthValue); } // If both left and right are defined, then use left. Otherwise return +left or diff --git a/packages/react-native/ReactCommon/yoga/yoga/node/Node.h b/packages/react-native/ReactCommon/yoga/yoga/node/Node.h index 9fefcf15aa0b99..1c9acbbe86d23d 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/node/Node.h +++ b/packages/react-native/ReactCommon/yoga/yoga/node/Node.h @@ -20,7 +20,6 @@ #include #include #include -#include #include // Tag struct used to form the opaque YGNodeRef for the public C API @@ -66,10 +65,10 @@ class YG_EXPORT Node : public ::YGNode { } template - CompactValue computeEdgeValueForColumn(YGEdge edge) const; + Style::Length computeEdgeValueForColumn(YGEdge edge) const; template - CompactValue computeEdgeValueForRow(YGEdge rowEdge, YGEdge edge) const; + Style::Length computeEdgeValueForRow(YGEdge rowEdge, YGEdge edge) const; // DANGER DANGER DANGER! // If the node assigned to has children, we'd either have to deallocate @@ -327,7 +326,7 @@ class YG_EXPORT Node : public ::YGNode { uint32_t computedFlexBasisGeneration); void setLayoutMeasuredDimension(float measuredDimension, Dimension dimension); void setLayoutHadOverflow(bool hadOverflow); - void setLayoutDimension(float dimensionValue, Dimension dimension); + void setLayoutDimension(float LengthValue, Dimension dimension); void setLayoutDirection(Direction direction); void setLayoutMargin(float margin, YGEdge edge); void setLayoutBorder(float border, YGEdge edge); diff --git a/packages/react-native/ReactCommon/yoga/yoga/style/CompactValue.h b/packages/react-native/ReactCommon/yoga/yoga/style/CompactValue.h index a6ca3f1283e175..c32dd9276f1ede 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/style/CompactValue.h +++ b/packages/react-native/ReactCommon/yoga/yoga/style/CompactValue.h @@ -52,6 +52,10 @@ class YG_EXPORT CompactValue { template static CompactValue of(float value) noexcept { + if (yoga::isUndefined(value) || std::isinf(value)) { + return ofUndefined(); + } + if (value == 0.0f || (value < LOWER_BOUND && value > -LOWER_BOUND)) { constexpr auto zero = Unit == YGUnitPercent ? ZERO_BITS_PERCENT : ZERO_BITS_POINT; @@ -71,16 +75,6 @@ class YG_EXPORT CompactValue { return {data}; } - template - static CompactValue ofMaybe(float value) noexcept { - return std::isnan(value) || std::isinf(value) ? ofUndefined() - : of(value); - } - - static constexpr CompactValue ofZero() noexcept { - return CompactValue{ZERO_BITS_POINT}; - } - static constexpr CompactValue ofUndefined() noexcept { return CompactValue{}; } @@ -168,10 +162,6 @@ template <> CompactValue CompactValue::of(float) noexcept = delete; template <> CompactValue CompactValue::of(float) noexcept = delete; -template <> -CompactValue CompactValue::ofMaybe(float) noexcept = delete; -template <> -CompactValue CompactValue::ofMaybe(float) noexcept = delete; constexpr bool operator==(CompactValue a, CompactValue b) noexcept { return a.repr_ == b.repr_; diff --git a/packages/react-native/ReactCommon/yoga/yoga/style/Style.h b/packages/react-native/ReactCommon/yoga/yoga/style/Style.h index d7dbf2f1886b05..835632edd598dc 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/style/Style.h +++ b/packages/react-native/ReactCommon/yoga/yoga/style/Style.h @@ -28,18 +28,29 @@ #include #include #include +#include namespace facebook::yoga { class YG_EXPORT Style { - template - using Values = std::array()>; - - using Dimensions = Values; - using Edges = Values; - using Gutters = Values; - public: + /** + * Style::Length represents a CSS Value which may be one of: + * 1. Undefined + * 2. A keyword (e.g. auto) + * 3. A CSS value: + * a. value (e.g. 10px) + * b. value of a reference + * 4. (soon) A math function which returns a value + * + * References: + * 1. https://www.w3.org/TR/css-values-4/#lengths + * 2. https://www.w3.org/TR/css-values-4/#percentage-value + * 3. https://www.w3.org/TR/css-values-4/#mixed-percentages + * 4. https://www.w3.org/TR/css-values-4/#math + */ + using Length = CompactValue; + static constexpr float DefaultFlexGrow = 0.0f; static constexpr float DefaultFlexShrink = 0.0f; static constexpr float WebDefaultFlexShrink = 1.0f; @@ -76,6 +87,10 @@ class YG_EXPORT Style { ~Style() = default; private: + using Dimensions = std::array()>; + using Edges = std::array()>; + using Gutters = std::array()>; + static constexpr uint8_t directionOffset = 0; static constexpr uint8_t flexdirectionOffset = directionOffset + minimumBitCount(); @@ -101,13 +116,13 @@ class YG_EXPORT Style { FloatOptional flex_ = {}; FloatOptional flexGrow_ = {}; FloatOptional flexShrink_ = {}; - CompactValue flexBasis_ = CompactValue::ofAuto(); + Style::Length flexBasis_ = value::ofAuto(); Edges margin_ = {}; Edges position_ = {}; Edges padding_ = {}; Edges border_ = {}; Gutters gap_ = {}; - Dimensions dimensions_{CompactValue::ofAuto(), CompactValue::ofAuto()}; + Dimensions dimensions_{value::ofAuto(), value::ofAuto()}; Dimensions minDimensions_ = {}; Dimensions maxDimensions_ = {}; // Yoga specific properties, not compatible with flexbox specification @@ -205,66 +220,66 @@ class YG_EXPORT Style { return {*this}; } - CompactValue flexBasis() const { + Style::Length flexBasis() const { return flexBasis_; } - Ref flexBasis() { + Ref flexBasis() { return {*this}; } - CompactValue margin(YGEdge edge) const { + Style::Length margin(YGEdge edge) const { return margin_[edge]; } - void setMargin(YGEdge edge, CompactValue value) { + void setMargin(YGEdge edge, Style::Length value) { margin_[edge] = value; } - CompactValue position(YGEdge edge) const { + Style::Length position(YGEdge edge) const { return position_[edge]; } - void setPosition(YGEdge edge, CompactValue value) { + void setPosition(YGEdge edge, Style::Length value) { position_[edge] = value; } - CompactValue padding(YGEdge edge) const { + Style::Length padding(YGEdge edge) const { return padding_[edge]; } - void setPadding(YGEdge edge, CompactValue value) { + void setPadding(YGEdge edge, Style::Length value) { padding_[edge] = value; } - CompactValue border(YGEdge edge) const { + Style::Length border(YGEdge edge) const { return border_[edge]; } - void setBorder(YGEdge edge, CompactValue value) { + void setBorder(YGEdge edge, Style::Length value) { border_[edge] = value; } - CompactValue gap(Gutter gutter) const { + Style::Length gap(Gutter gutter) const { return gap_[yoga::to_underlying(gutter)]; } - void setGap(Gutter gutter, CompactValue value) { + void setGap(Gutter gutter, Style::Length value) { gap_[yoga::to_underlying(gutter)] = value; } - CompactValue dimension(Dimension axis) const { + Style::Length dimension(Dimension axis) const { return dimensions_[yoga::to_underlying(axis)]; } - void setDimension(Dimension axis, CompactValue value) { + void setDimension(Dimension axis, Style::Length value) { dimensions_[yoga::to_underlying(axis)] = value; } - CompactValue minDimension(Dimension axis) const { + Style::Length minDimension(Dimension axis) const { return minDimensions_[yoga::to_underlying(axis)]; } - void setMinDimension(Dimension axis, CompactValue value) { + void setMinDimension(Dimension axis, Style::Length value) { minDimensions_[yoga::to_underlying(axis)] = value; } - CompactValue maxDimension(Dimension axis) const { + Style::Length maxDimension(Dimension axis) const { return maxDimensions_[yoga::to_underlying(axis)]; } - void setMaxDimension(Dimension axis, CompactValue value) { + void setMaxDimension(Dimension axis, Style::Length value) { maxDimensions_[yoga::to_underlying(axis)] = value; } @@ -276,7 +291,7 @@ class YG_EXPORT Style { return {*this}; } - CompactValue resolveColumnGap() const { + Length resolveColumnGap() const { if (gap_[yoga::to_underlying(Gutter::Column)].isDefined()) { return gap_[yoga::to_underlying(Gutter::Column)]; } else { @@ -284,7 +299,7 @@ class YG_EXPORT Style { } } - CompactValue resolveRowGap() const { + Style::Length resolveRowGap() const { if (gap_[yoga::to_underlying(Gutter::Row)].isDefined()) { return gap_[yoga::to_underlying(Gutter::Row)]; } else { diff --git a/packages/react-native/ReactCommon/yoga/yoga/style/ValueFactories.h b/packages/react-native/ReactCommon/yoga/yoga/style/ValueFactories.h new file mode 100644 index 00000000000000..65486347b0a52c --- /dev/null +++ b/packages/react-native/ReactCommon/yoga/yoga/style/ValueFactories.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) Meta Platforms, Inc. and 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 + +namespace facebook::yoga::value { + +/** + * Canonical unit (one YGUnitPoint) + */ +inline CompactValue points(float value) { + return CompactValue::of(value); +} + +/** + * Percent of reference + */ +inline CompactValue percent(float value) { + return CompactValue::of(value); +} + +/** + * "auto" keyword + */ +inline CompactValue ofAuto() { + return CompactValue::ofAuto(); +} + +/** + * Undefined + */ +inline CompactValue undefined() { + return CompactValue::ofUndefined(); +} + +} // namespace facebook::yoga::value From 925525a71998a9d86cfdc2d6bd9c110d31fe1cdc Mon Sep 17 00:00:00 2001 From: Nick Gerleman Date: Sat, 25 Nov 2023 20:41:22 -0800 Subject: [PATCH 092/162] Use CSS terminology for sizing rules (#41390) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41390 X-link: https://github.com/facebook/yoga/pull/1460 Yoga passes `MeasureMode`/`YGMeasureMode` to express constraints in how a box should be measured, given definite or indefinite available space. This is modeled after Android [MeasureSpec](https://developer.android.com/reference/android/view/View.MeasureSpec), with a table above `calculateLayoutImpl()` explaining the CSS terms they map to. This can be confusing when flipping between the spec, and code. This switches internal usages to the CSS terms, but leaves around `YGMeasureMode` since it is the public API passed to measure functions. Reviewed By: joevilches Differential Revision: D51068417 fbshipit-source-id: 0a76266a4e7e0cc39996164607229c3c41de2818 --- .../ReactCommon/yoga/yoga/YGNode.cpp | 8 +- .../ReactCommon/yoga/yoga/YGNode.h | 13 + .../ReactCommon/yoga/yoga/algorithm/Cache.cpp | 70 +-- .../ReactCommon/yoga/yoga/algorithm/Cache.h | 10 +- .../yoga/yoga/algorithm/CalculateLayout.cpp | 428 +++++++++--------- .../yoga/yoga/algorithm/SizingMode.h | 73 +++ .../yoga/yoga/debug/AssertFatal.cpp | 2 + .../ReactCommon/yoga/yoga/debug/AssertFatal.h | 5 +- .../yoga/yoga/node/CachedMeasurement.h | 10 +- 9 files changed, 351 insertions(+), 268 deletions(-) create mode 100644 packages/react-native/ReactCommon/yoga/yoga/algorithm/SizingMode.h diff --git a/packages/react-native/ReactCommon/yoga/yoga/YGNode.cpp b/packages/react-native/ReactCommon/yoga/yoga/YGNode.cpp index 38d8f319161cc8..50cfd98f20af3e 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/YGNode.cpp +++ b/packages/react-native/ReactCommon/yoga/yoga/YGNode.cpp @@ -351,13 +351,13 @@ bool YGNodeCanUseCachedMeasurement( float marginColumn, YGConfigRef config) { return yoga::canUseCachedMeasurement( - scopedEnum(widthMode), + sizingMode(scopedEnum(widthMode)), availableWidth, - scopedEnum(heightMode), + sizingMode(scopedEnum(heightMode)), availableHeight, - scopedEnum(lastWidthMode), + sizingMode(scopedEnum(lastWidthMode)), lastAvailableWidth, - scopedEnum(lastHeightMode), + sizingMode(scopedEnum(lastHeightMode)), lastAvailableHeight, lastComputedWidth, lastComputedHeight, diff --git a/packages/react-native/ReactCommon/yoga/yoga/YGNode.h b/packages/react-native/ReactCommon/yoga/yoga/YGNode.h index 61a2bc4ea5f7f5..b267cde14808d7 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/YGNode.h +++ b/packages/react-native/ReactCommon/yoga/yoga/YGNode.h @@ -186,6 +186,19 @@ typedef struct YGSize { } YGSize; /** + * Returns the computed dimensions of the node, following the contraints of + * `widthMode` and `heightMode`: + * + * YGMeasureModeUndefined: The parent has not imposed any constraint on the + * child. It can be whatever size it wants. + * + * YGMeasureModeAtMost: The child can be as large as it wants up to the + * specified size. + * + * YGMeasureModeExactly: The parent has determined an exact size for the + * child. The child is going to be given those bounds regardless of how big it + * wants to be. + * * @returns the size of the leaf node, measured under the given contraints. */ typedef YGSize (*YGMeasureFunc)( diff --git a/packages/react-native/ReactCommon/yoga/yoga/algorithm/Cache.cpp b/packages/react-native/ReactCommon/yoga/yoga/algorithm/Cache.cpp index 7496e873e04ce4..9154fc6ce9cc87 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/algorithm/Cache.cpp +++ b/packages/react-native/ReactCommon/yoga/yoga/algorithm/Cache.cpp @@ -12,51 +12,52 @@ namespace facebook::yoga { static inline bool sizeIsExactAndMatchesOldMeasuredSize( - MeasureMode sizeMode, + SizingMode sizeMode, float size, float lastComputedSize) { - return sizeMode == MeasureMode::Exactly && + return sizeMode == SizingMode::StretchFit && yoga::inexactEquals(size, lastComputedSize); } -static inline bool oldSizeIsUnspecifiedAndStillFits( - MeasureMode sizeMode, +static inline bool oldSizeIsMaxContentAndStillFits( + SizingMode sizeMode, float size, - MeasureMode lastSizeMode, + SizingMode lastSizeMode, float lastComputedSize) { - return sizeMode == MeasureMode::AtMost && - lastSizeMode == MeasureMode::Undefined && + return sizeMode == SizingMode::FitContent && + lastSizeMode == SizingMode::MaxContent && (size >= lastComputedSize || yoga::inexactEquals(size, lastComputedSize)); } -static inline bool newMeasureSizeIsStricterAndStillValid( - MeasureMode sizeMode, +static inline bool newSizeIsStricterAndStillValid( + SizingMode sizeMode, float size, - MeasureMode lastSizeMode, + SizingMode lastSizeMode, float lastSize, float lastComputedSize) { - return lastSizeMode == MeasureMode::AtMost && - sizeMode == MeasureMode::AtMost && !std::isnan(lastSize) && - !std::isnan(size) && !std::isnan(lastComputedSize) && lastSize > size && + return lastSizeMode == SizingMode::FitContent && + sizeMode == SizingMode::FitContent && yoga::isDefined(lastSize) && + yoga::isDefined(size) && yoga::isDefined(lastComputedSize) && + lastSize > size && (lastComputedSize <= size || yoga::inexactEquals(size, lastComputedSize)); } bool canUseCachedMeasurement( - const MeasureMode widthMode, + const SizingMode widthMode, const float availableWidth, - const MeasureMode heightMode, + const SizingMode heightMode, const float availableHeight, - const MeasureMode lastWidthMode, + const SizingMode lastWidthMode, const float lastAvailableWidth, - const MeasureMode lastHeightMode, + const SizingMode lastHeightMode, const float lastAvailableHeight, const float lastComputedWidth, const float lastComputedHeight, const float marginRow, const float marginColumn, const yoga::Config* const config) { - if ((!std::isnan(lastComputedHeight) && lastComputedHeight < 0) || - (!std::isnan(lastComputedWidth) && lastComputedWidth < 0)) { + if ((yoga::isDefined(lastComputedHeight) && lastComputedHeight < 0) || + ((yoga::isDefined(lastComputedWidth)) && lastComputedWidth < 0)) { return false; } @@ -87,33 +88,32 @@ bool canUseCachedMeasurement( hasSameWidthSpec || sizeIsExactAndMatchesOldMeasuredSize( widthMode, availableWidth - marginRow, lastComputedWidth) || - oldSizeIsUnspecifiedAndStillFits( + oldSizeIsMaxContentAndStillFits( widthMode, availableWidth - marginRow, lastWidthMode, lastComputedWidth) || - newMeasureSizeIsStricterAndStillValid( + newSizeIsStricterAndStillValid( widthMode, availableWidth - marginRow, lastWidthMode, lastAvailableWidth, lastComputedWidth); - const bool heightIsCompatible = - hasSameHeightSpec || + const bool heightIsCompatible = hasSameHeightSpec || sizeIsExactAndMatchesOldMeasuredSize( - heightMode, availableHeight - marginColumn, lastComputedHeight) || - oldSizeIsUnspecifiedAndStillFits( - heightMode, - availableHeight - marginColumn, - lastHeightMode, - lastComputedHeight) || - newMeasureSizeIsStricterAndStillValid( - heightMode, - availableHeight - marginColumn, - lastHeightMode, - lastAvailableHeight, - lastComputedHeight); + heightMode, + availableHeight - marginColumn, + lastComputedHeight) || + oldSizeIsMaxContentAndStillFits(heightMode, + availableHeight - marginColumn, + lastHeightMode, + lastComputedHeight) || + newSizeIsStricterAndStillValid(heightMode, + availableHeight - marginColumn, + lastHeightMode, + lastAvailableHeight, + lastComputedHeight); return widthIsCompatible && heightIsCompatible; } diff --git a/packages/react-native/ReactCommon/yoga/yoga/algorithm/Cache.h b/packages/react-native/ReactCommon/yoga/yoga/algorithm/Cache.h index 31b91d5f791ead..f8857eaf35c947 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/algorithm/Cache.h +++ b/packages/react-native/ReactCommon/yoga/yoga/algorithm/Cache.h @@ -7,19 +7,19 @@ #pragma once +#include #include -#include namespace facebook::yoga { bool canUseCachedMeasurement( - MeasureMode widthMode, + SizingMode widthMode, float availableWidth, - MeasureMode heightMode, + SizingMode heightMode, float availableHeight, - MeasureMode lastWidthMode, + SizingMode lastWidthMode, float lastAvailableWidth, - MeasureMode lastHeightMode, + SizingMode lastHeightMode, float lastAvailableHeight, float lastComputedWidth, float lastComputedHeight, diff --git a/packages/react-native/ReactCommon/yoga/yoga/algorithm/CalculateLayout.cpp b/packages/react-native/ReactCommon/yoga/yoga/algorithm/CalculateLayout.cpp index c1026c9adcf823..f066dbdfc45213 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/algorithm/CalculateLayout.cpp +++ b/packages/react-native/ReactCommon/yoga/yoga/algorithm/CalculateLayout.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -39,8 +40,8 @@ bool calculateLayoutInternal( const float availableWidth, const float availableHeight, const Direction ownerDirection, - const MeasureMode widthMeasureMode, - const MeasureMode heightMeasureMode, + const SizingMode widthSizingMode, + const SizingMode heightSizingMode, const float ownerWidth, const float ownerHeight, const bool performLayout, @@ -97,22 +98,22 @@ static void constrainMaxSizeForMode( const enum FlexDirection axis, const float ownerAxisSize, const float ownerWidth, - MeasureMode* mode, + SizingMode* mode, float* size) { const FloatOptional maxSize = yoga::resolveValue( node->getStyle().maxDimension(dimension(axis)), ownerAxisSize) + FloatOptional(node->getMarginForAxis(axis, ownerWidth)); switch (*mode) { - case MeasureMode::Exactly: - case MeasureMode::AtMost: + case SizingMode::StretchFit: + case SizingMode::FitContent: *size = (maxSize.isUndefined() || *size < maxSize.unwrap()) ? *size : maxSize.unwrap(); break; - case MeasureMode::Undefined: + case SizingMode::MaxContent: if (maxSize.isDefined()) { - *mode = MeasureMode::AtMost; + *mode = SizingMode::FitContent; *size = maxSize.unwrap(); } break; @@ -123,11 +124,11 @@ static void computeFlexBasisForChild( const yoga::Node* const node, yoga::Node* const child, const float width, - const MeasureMode widthMode, + const SizingMode widthMode, const float height, const float ownerWidth, const float ownerHeight, - const MeasureMode heightMode, + const SizingMode heightMode, const Direction direction, LayoutData& layoutMarkerData, const uint32_t depth, @@ -140,8 +141,8 @@ static void computeFlexBasisForChild( float childWidth; float childHeight; - MeasureMode childWidthMeasureMode; - MeasureMode childHeightMeasureMode; + SizingMode childWidthSizingMode; + SizingMode childHeightSizingMode; const FloatOptional resolvedFlexBasis = yoga::resolveValue(child->resolveFlexBasisPtr(), mainAxisownerSize); @@ -182,8 +183,8 @@ static void computeFlexBasisForChild( // basis). childWidth = YGUndefined; childHeight = YGUndefined; - childWidthMeasureMode = MeasureMode::Undefined; - childHeightMeasureMode = MeasureMode::Undefined; + childWidthSizingMode = SizingMode::MaxContent; + childHeightSizingMode = SizingMode::MaxContent; auto marginRow = child->getMarginForAxis(FlexDirection::Row, ownerWidth); auto marginColumn = @@ -195,7 +196,7 @@ static void computeFlexBasisForChild( child->getResolvedDimension(Dimension::Width), ownerWidth) .unwrap() + marginRow; - childWidthMeasureMode = MeasureMode::Exactly; + childWidthSizingMode = SizingMode::StretchFit; } if (isColumnStyleDimDefined) { childHeight = @@ -203,7 +204,7 @@ static void computeFlexBasisForChild( child->getResolvedDimension(Dimension::Height), ownerHeight) .unwrap() + marginColumn; - childHeightMeasureMode = MeasureMode::Exactly; + childHeightSizingMode = SizingMode::StretchFit; } // The W3C spec doesn't say anything about the 'overflow' property, but all @@ -212,7 +213,7 @@ static void computeFlexBasisForChild( node->getStyle().overflow() != Overflow::Scroll) { if (yoga::isUndefined(childWidth) && yoga::isDefined(width)) { childWidth = width; - childWidthMeasureMode = MeasureMode::AtMost; + childWidthSizingMode = SizingMode::FitContent; } } @@ -220,21 +221,21 @@ static void computeFlexBasisForChild( node->getStyle().overflow() != Overflow::Scroll) { if (yoga::isUndefined(childHeight) && yoga::isDefined(height)) { childHeight = height; - childHeightMeasureMode = MeasureMode::AtMost; + childHeightSizingMode = SizingMode::FitContent; } } const auto& childStyle = child->getStyle(); if (childStyle.aspectRatio().isDefined()) { - if (!isMainAxisRow && childWidthMeasureMode == MeasureMode::Exactly) { + if (!isMainAxisRow && childWidthSizingMode == SizingMode::StretchFit) { childHeight = marginColumn + (childWidth - marginRow) / childStyle.aspectRatio().unwrap(); - childHeightMeasureMode = MeasureMode::Exactly; + childHeightSizingMode = SizingMode::StretchFit; } else if ( - isMainAxisRow && childHeightMeasureMode == MeasureMode::Exactly) { + isMainAxisRow && childHeightSizingMode == SizingMode::StretchFit) { childWidth = marginRow + (childHeight - marginColumn) * childStyle.aspectRatio().unwrap(); - childWidthMeasureMode = MeasureMode::Exactly; + childWidthSizingMode = SizingMode::StretchFit; } } @@ -242,35 +243,35 @@ static void computeFlexBasisForChild( // the cross axis to be measured exactly with the available inner width const bool hasExactWidth = - yoga::isDefined(width) && widthMode == MeasureMode::Exactly; + yoga::isDefined(width) && widthMode == SizingMode::StretchFit; const bool childWidthStretch = resolveChildAlignment(node, child) == Align::Stretch && - childWidthMeasureMode != MeasureMode::Exactly; + childWidthSizingMode != SizingMode::StretchFit; if (!isMainAxisRow && !isRowStyleDimDefined && hasExactWidth && childWidthStretch) { childWidth = width; - childWidthMeasureMode = MeasureMode::Exactly; + childWidthSizingMode = SizingMode::StretchFit; if (childStyle.aspectRatio().isDefined()) { childHeight = (childWidth - marginRow) / childStyle.aspectRatio().unwrap(); - childHeightMeasureMode = MeasureMode::Exactly; + childHeightSizingMode = SizingMode::StretchFit; } } const bool hasExactHeight = - yoga::isDefined(height) && heightMode == MeasureMode::Exactly; + yoga::isDefined(height) && heightMode == SizingMode::StretchFit; const bool childHeightStretch = resolveChildAlignment(node, child) == Align::Stretch && - childHeightMeasureMode != MeasureMode::Exactly; + childHeightSizingMode != SizingMode::StretchFit; if (isMainAxisRow && !isColumnStyleDimDefined && hasExactHeight && childHeightStretch) { childHeight = height; - childHeightMeasureMode = MeasureMode::Exactly; + childHeightSizingMode = SizingMode::StretchFit; if (childStyle.aspectRatio().isDefined()) { childWidth = (childHeight - marginColumn) * childStyle.aspectRatio().unwrap(); - childWidthMeasureMode = MeasureMode::Exactly; + childWidthSizingMode = SizingMode::StretchFit; } } @@ -279,14 +280,14 @@ static void computeFlexBasisForChild( FlexDirection::Row, ownerWidth, ownerWidth, - &childWidthMeasureMode, + &childWidthSizingMode, &childWidth); constrainMaxSizeForMode( child, FlexDirection::Column, ownerHeight, ownerWidth, - &childHeightMeasureMode, + &childHeightSizingMode, &childHeight); // Measure the child @@ -295,8 +296,8 @@ static void computeFlexBasisForChild( childWidth, childHeight, direction, - childWidthMeasureMode, - childHeightMeasureMode, + childWidthSizingMode, + childHeightSizingMode, ownerWidth, ownerHeight, false, @@ -316,7 +317,7 @@ static void layoutAbsoluteChild( const yoga::Node* const node, yoga::Node* const child, const float width, - const MeasureMode widthMode, + const SizingMode widthMode, const float height, const Direction direction, LayoutData& layoutMarkerData, @@ -329,8 +330,8 @@ static void layoutAbsoluteChild( float childWidth = YGUndefined; float childHeight = YGUndefined; - MeasureMode childWidthMeasureMode = MeasureMode::Undefined; - MeasureMode childHeightMeasureMode = MeasureMode::Undefined; + SizingMode childWidthSizingMode = SizingMode::MaxContent; + SizingMode childHeightSizingMode = SizingMode::MaxContent; auto marginRow = child->getMarginForAxis(FlexDirection::Row, width); auto marginColumn = child->getMarginForAxis(FlexDirection::Column, width); @@ -395,22 +396,22 @@ static void layoutAbsoluteChild( // If we're still missing one or the other dimension, measure the content. if (yoga::isUndefined(childWidth) || yoga::isUndefined(childHeight)) { - childWidthMeasureMode = yoga::isUndefined(childWidth) - ? MeasureMode::Undefined - : MeasureMode::Exactly; - childHeightMeasureMode = yoga::isUndefined(childHeight) - ? MeasureMode::Undefined - : MeasureMode::Exactly; + childWidthSizingMode = yoga::isUndefined(childWidth) + ? SizingMode::MaxContent + : SizingMode::StretchFit; + childHeightSizingMode = yoga::isUndefined(childHeight) + ? SizingMode::MaxContent + : SizingMode::StretchFit; // If the size of the owner is defined then try to constrain the absolute // child to that size as well. This allows text within the absolute child to // wrap to the size of its owner. This is the same behavior as many browsers // implement. if (!isMainAxisRow && yoga::isUndefined(childWidth) && - widthMode != MeasureMode::Undefined && yoga::isDefined(width) && + widthMode != SizingMode::MaxContent && yoga::isDefined(width) && width > 0) { childWidth = width; - childWidthMeasureMode = MeasureMode::AtMost; + childWidthSizingMode = SizingMode::FitContent; } calculateLayoutInternal( @@ -418,8 +419,8 @@ static void layoutAbsoluteChild( childWidth, childHeight, direction, - childWidthMeasureMode, - childHeightMeasureMode, + childWidthSizingMode, + childHeightSizingMode, childWidth, childHeight, false, @@ -438,8 +439,8 @@ static void layoutAbsoluteChild( childWidth, childHeight, direction, - MeasureMode::Exactly, - MeasureMode::Exactly, + SizingMode::StretchFit, + SizingMode::StretchFit, childWidth, childHeight, true, @@ -534,8 +535,8 @@ static void measureNodeWithMeasureFunc( yoga::Node* const node, float availableWidth, float availableHeight, - const MeasureMode widthMeasureMode, - const MeasureMode heightMeasureMode, + const SizingMode widthSizingMode, + const SizingMode heightSizingMode, const float ownerWidth, const float ownerHeight, LayoutData& layoutMarkerData, @@ -545,10 +546,10 @@ static void measureNodeWithMeasureFunc( node->hasMeasureFunc(), "Expected node to have custom measure function"); - if (widthMeasureMode == MeasureMode::Undefined) { + if (widthSizingMode == SizingMode::MaxContent) { availableWidth = YGUndefined; } - if (heightMeasureMode == MeasureMode::Undefined) { + if (heightSizingMode == SizingMode::MaxContent) { availableHeight = YGUndefined; } @@ -567,8 +568,8 @@ static void measureNodeWithMeasureFunc( ? availableHeight : yoga::maxOrDefined(0.0f, availableHeight - paddingAndBorderAxisColumn); - if (widthMeasureMode == MeasureMode::Exactly && - heightMeasureMode == MeasureMode::Exactly) { + if (widthSizingMode == SizingMode::StretchFit && + heightSizingMode == SizingMode::StretchFit) { // Don't bother sizing the text if both dimensions are already defined. node->setLayoutMeasuredDimension( boundAxis( @@ -587,7 +588,10 @@ static void measureNodeWithMeasureFunc( // Measure the text under the current constraints. const YGSize measuredSize = node->measure( - innerWidth, widthMeasureMode, innerHeight, heightMeasureMode); + innerWidth, + measureMode(widthSizingMode), + innerHeight, + measureMode(heightSizingMode)); layoutMarkerData.measureCallbacks += 1; layoutMarkerData.measureCallbackReasonsCount[static_cast(reason)] += @@ -596,9 +600,9 @@ static void measureNodeWithMeasureFunc( Event::publish( node, {innerWidth, - unscopedEnum(widthMeasureMode), + unscopedEnum(measureMode(widthSizingMode)), innerHeight, - unscopedEnum(heightMeasureMode), + unscopedEnum(measureMode(heightSizingMode)), measuredSize.width, measuredSize.height, reason}); @@ -607,8 +611,8 @@ static void measureNodeWithMeasureFunc( boundAxis( node, FlexDirection::Row, - (widthMeasureMode == MeasureMode::Undefined || - widthMeasureMode == MeasureMode::AtMost) + (widthSizingMode == SizingMode::MaxContent || + widthSizingMode == SizingMode::FitContent) ? measuredSize.width + paddingAndBorderAxisRow : availableWidth, ownerWidth, @@ -619,8 +623,8 @@ static void measureNodeWithMeasureFunc( boundAxis( node, FlexDirection::Column, - (heightMeasureMode == MeasureMode::Undefined || - heightMeasureMode == MeasureMode::AtMost) + (heightSizingMode == SizingMode::MaxContent || + heightSizingMode == SizingMode::FitContent) ? measuredSize.height + paddingAndBorderAxisColumn : availableHeight, ownerHeight, @@ -635,16 +639,16 @@ static void measureNodeWithoutChildren( yoga::Node* const node, const float availableWidth, const float availableHeight, - const MeasureMode widthMeasureMode, - const MeasureMode heightMeasureMode, + const SizingMode widthSizingMode, + const SizingMode heightSizingMode, const float ownerWidth, const float ownerHeight) { const auto& padding = node->getLayout().padding; const auto& border = node->getLayout().border; float width = availableWidth; - if (widthMeasureMode == MeasureMode::Undefined || - widthMeasureMode == MeasureMode::AtMost) { + if (widthSizingMode == SizingMode::MaxContent || + widthSizingMode == SizingMode::FitContent) { width = padding[YGEdgeLeft] + padding[YGEdgeRight] + border[YGEdgeLeft] + border[YGEdgeRight]; } @@ -653,8 +657,8 @@ static void measureNodeWithoutChildren( Dimension::Width); float height = availableHeight; - if (heightMeasureMode == MeasureMode::Undefined || - heightMeasureMode == MeasureMode::AtMost) { + if (heightSizingMode == SizingMode::MaxContent || + heightSizingMode == SizingMode::FitContent) { height = padding[YGEdgeTop] + padding[YGEdgeBottom] + border[YGEdgeTop] + border[YGEdgeBottom]; } @@ -667,22 +671,22 @@ static bool measureNodeWithFixedSize( yoga::Node* const node, const float availableWidth, const float availableHeight, - const MeasureMode widthMeasureMode, - const MeasureMode heightMeasureMode, + const SizingMode widthSizingMode, + const SizingMode heightSizingMode, const float ownerWidth, const float ownerHeight) { if ((yoga::isDefined(availableWidth) && - widthMeasureMode == MeasureMode::AtMost && availableWidth <= 0.0f) || + widthSizingMode == SizingMode::FitContent && availableWidth <= 0.0f) || (yoga::isDefined(availableHeight) && - heightMeasureMode == MeasureMode::AtMost && availableHeight <= 0.0f) || - (widthMeasureMode == MeasureMode::Exactly && - heightMeasureMode == MeasureMode::Exactly)) { + heightSizingMode == SizingMode::FitContent && availableHeight <= 0.0f) || + (widthSizingMode == SizingMode::StretchFit && + heightSizingMode == SizingMode::StretchFit)) { node->setLayoutMeasuredDimension( boundAxis( node, FlexDirection::Row, yoga::isUndefined(availableWidth) || - (widthMeasureMode == MeasureMode::AtMost && + (widthSizingMode == SizingMode::FitContent && availableWidth < 0.0f) ? 0.0f : availableWidth, @@ -695,7 +699,7 @@ static bool measureNodeWithFixedSize( node, FlexDirection::Column, yoga::isUndefined(availableHeight) || - (heightMeasureMode == MeasureMode::AtMost && + (heightSizingMode == SizingMode::FitContent && availableHeight < 0.0f) ? 0.0f : availableHeight, @@ -755,8 +759,8 @@ static float computeFlexBasisForChildren( yoga::Node* const node, const float availableInnerWidth, const float availableInnerHeight, - MeasureMode widthMeasureMode, - MeasureMode heightMeasureMode, + SizingMode widthSizingMode, + SizingMode heightSizingMode, Direction direction, FlexDirection mainAxis, bool performLayout, @@ -766,12 +770,12 @@ static float computeFlexBasisForChildren( float totalOuterFlexBasis = 0.0f; YGNodeRef singleFlexChild = nullptr; const auto& children = node->getChildren(); - MeasureMode measureModeMainDim = - isRow(mainAxis) ? widthMeasureMode : heightMeasureMode; + SizingMode sizingModeMainDim = + isRow(mainAxis) ? widthSizingMode : heightSizingMode; // If there is only one child with flexGrow + flexShrink it means we can set // the computedFlexBasis to 0 instead of measuring and shrinking / flexing the // child to exactly match the remaining space - if (measureModeMainDim == MeasureMode::Exactly) { + if (sizingModeMainDim == SizingMode::StretchFit) { for (auto child : children) { if (child->isNodeFlexible()) { if (singleFlexChild != nullptr || @@ -818,11 +822,11 @@ static float computeFlexBasisForChildren( node, child, availableInnerWidth, - widthMeasureMode, + widthSizingMode, availableInnerHeight, availableInnerWidth, availableInnerHeight, - heightMeasureMode, + heightSizingMode, direction, layoutMarkerData, depth, @@ -852,7 +856,7 @@ static float distributeFreeSpaceSecondPass( const float availableInnerWidth, const float availableInnerHeight, const bool mainAxisOverflows, - const MeasureMode measureModeCrossDim, + const SizingMode sizingModeCrossDim, const bool performLayout, LayoutData& layoutMarkerData, const uint32_t depth, @@ -925,35 +929,35 @@ static float distributeFreeSpaceSecondPass( float childCrossSize; float childMainSize = updatedMainSize + marginMain; - MeasureMode childCrossMeasureMode; - MeasureMode childMainMeasureMode = MeasureMode::Exactly; + SizingMode childCrossSizingMode; + SizingMode childMainSizingMode = SizingMode::StretchFit; const auto& childStyle = currentLineChild->getStyle(); if (childStyle.aspectRatio().isDefined()) { childCrossSize = isMainAxisRow ? (childMainSize - marginMain) / childStyle.aspectRatio().unwrap() : (childMainSize - marginMain) * childStyle.aspectRatio().unwrap(); - childCrossMeasureMode = MeasureMode::Exactly; + childCrossSizingMode = SizingMode::StretchFit; childCrossSize += marginCross; } else if ( !std::isnan(availableInnerCrossDim) && !styleDefinesDimension( currentLineChild, crossAxis, availableInnerCrossDim) && - measureModeCrossDim == MeasureMode::Exactly && + sizingModeCrossDim == SizingMode::StretchFit && !(isNodeFlexWrap && mainAxisOverflows) && resolveChildAlignment(node, currentLineChild) == Align::Stretch && currentLineChild->getFlexStartMarginValue(crossAxis).unit != YGUnitAuto && currentLineChild->marginTrailingValue(crossAxis).unit != YGUnitAuto) { childCrossSize = availableInnerCrossDim; - childCrossMeasureMode = MeasureMode::Exactly; + childCrossSizingMode = SizingMode::StretchFit; } else if (!styleDefinesDimension( currentLineChild, crossAxis, availableInnerCrossDim)) { childCrossSize = availableInnerCrossDim; - childCrossMeasureMode = yoga::isUndefined(childCrossSize) - ? MeasureMode::Undefined - : MeasureMode::AtMost; + childCrossSizingMode = yoga::isUndefined(childCrossSize) + ? SizingMode::MaxContent + : SizingMode::FitContent; } else { childCrossSize = yoga::resolveValue( @@ -964,11 +968,11 @@ static float distributeFreeSpaceSecondPass( const bool isLoosePercentageMeasurement = currentLineChild->getResolvedDimension(dimension(crossAxis)).unit == YGUnitPercent && - measureModeCrossDim != MeasureMode::Exactly; - childCrossMeasureMode = + sizingModeCrossDim != SizingMode::StretchFit; + childCrossSizingMode = yoga::isUndefined(childCrossSize) || isLoosePercentageMeasurement - ? MeasureMode::Undefined - : MeasureMode::Exactly; + ? SizingMode::MaxContent + : SizingMode::StretchFit; } constrainMaxSizeForMode( @@ -976,14 +980,14 @@ static float distributeFreeSpaceSecondPass( mainAxis, availableInnerMainDim, availableInnerWidth, - &childMainMeasureMode, + &childMainSizingMode, &childMainSize); constrainMaxSizeForMode( currentLineChild, crossAxis, availableInnerCrossDim, availableInnerWidth, - &childCrossMeasureMode, + &childCrossSizingMode, &childCrossSize); const bool requiresStretchLayout = @@ -997,10 +1001,10 @@ static float distributeFreeSpaceSecondPass( const float childWidth = isMainAxisRow ? childMainSize : childCrossSize; const float childHeight = !isMainAxisRow ? childMainSize : childCrossSize; - const MeasureMode childWidthMeasureMode = - isMainAxisRow ? childMainMeasureMode : childCrossMeasureMode; - const MeasureMode childHeightMeasureMode = - !isMainAxisRow ? childMainMeasureMode : childCrossMeasureMode; + const SizingMode childWidthSizingMode = + isMainAxisRow ? childMainSizingMode : childCrossSizingMode; + const SizingMode childHeightSizingMode = + !isMainAxisRow ? childMainSizingMode : childCrossSizingMode; const bool isLayoutPass = performLayout && !requiresStretchLayout; // Recursively call the layout algorithm for this child with the updated @@ -1010,8 +1014,8 @@ static float distributeFreeSpaceSecondPass( childWidth, childHeight, node->getLayout().direction(), - childWidthMeasureMode, - childHeightMeasureMode, + childWidthSizingMode, + childHeightSizingMode, availableInnerWidth, availableInnerHeight, isLayoutPass, @@ -1144,7 +1148,7 @@ static void resolveFlexibleLength( const float availableInnerWidth, const float availableInnerHeight, const bool mainAxisOverflows, - const MeasureMode measureModeCrossDim, + const SizingMode sizingModeCrossDim, const bool performLayout, LayoutData& layoutMarkerData, const uint32_t depth, @@ -1170,7 +1174,7 @@ static void resolveFlexibleLength( availableInnerWidth, availableInnerHeight, mainAxisOverflows, - measureModeCrossDim, + sizingModeCrossDim, performLayout, layoutMarkerData, depth, @@ -1186,8 +1190,8 @@ static void justifyMainAxis( const FlexDirection mainAxis, const FlexDirection crossAxis, const Direction direction, - const MeasureMode measureModeMainDim, - const MeasureMode measureModeCrossDim, + const SizingMode sizingModeMainDim, + const SizingMode sizingModeCrossDim, const float mainAxisownerSize, const float ownerWidth, const float availableInnerMainDim, @@ -1208,7 +1212,7 @@ static void justifyMainAxis( const float gap = node->getGapForAxis(mainAxis); // If we are using "at most" rules in the main axis, make sure that // remainingFreeSpace is 0 when min main dimension is not given - if (measureModeMainDim == MeasureMode::AtMost && + if (sizingModeMainDim == SizingMode::FitContent && flexLine.layout.remainingFreeSpace > 0) { if (style.minDimension(dimension(mainAxis)).isDefined() && yoga::resolveValue( @@ -1340,7 +1344,7 @@ static void justifyMainAxis( static_cast(numberOfAutoMarginsOnCurrentLine); } bool canSkipFlex = - !performLayout && measureModeCrossDim == MeasureMode::Exactly; + !performLayout && sizingModeCrossDim == SizingMode::StretchFit; if (canSkipFlex) { // If we skipped the flex step, then we can't rely on the measuredDims // because they weren't computed. This means we can't call @@ -1432,9 +1436,9 @@ static void justifyMainAxis( // depends on layout flags // - ownerDirection: the inline (text) direction within the owner // (left-to-right or right-to-left) -// - widthMeasureMode: indicates the sizing rules for the width (see below +// - widthSizingMode: indicates the sizing rules for the width (see below // for explanation) -// - heightMeasureMode: indicates the sizing rules for the height (see below +// - heightSizingMode: indicates the sizing rules for the height (see below // for explanation) // - performLayout: specifies whether the caller is interested in just the // dimensions of the node or it requires the entire node and its subtree to @@ -1449,26 +1453,17 @@ static void justifyMainAxis( // layout.measuredDimensions field includes any border or padding for the // node but does not include margins. // -// The spec describes four different layout modes: "fill available", "max -// content", "min content", and "fit content". Of these, we don't use "min -// content" because we don't support default minimum main sizes (see above -// for details). Each of our measure modes maps to a layout mode from the -// spec (https://www.w3.org/TR/CSS3-sizing/#terms): -// - MeasureMode::Undefined: max content -// - MeasureMode::Exactly: fill available -// - MeasureMode::AtMost: fit content -// // When calling calculateLayoutImpl and calculateLayoutInternal, if the // caller passes an available size of undefined then it must also pass a -// measure mode of MeasureMode::Undefined in that dimension. +// measure mode of SizingMode::MaxContent in that dimension. // static void calculateLayoutImpl( yoga::Node* const node, const float availableWidth, const float availableHeight, const Direction ownerDirection, - const MeasureMode widthMeasureMode, - const MeasureMode heightMeasureMode, + const SizingMode widthSizingMode, + const SizingMode heightSizingMode, const float ownerWidth, const float ownerHeight, const bool performLayout, @@ -1479,17 +1474,17 @@ static void calculateLayoutImpl( yoga::assertFatalWithNode( node, yoga::isUndefined(availableWidth) - ? widthMeasureMode == MeasureMode::Undefined + ? widthSizingMode == SizingMode::MaxContent : true, - "availableWidth is indefinite so widthMeasureMode must be " - "MeasureMode::Undefined"); + "availableWidth is indefinite so widthSizingMode must be " + "SizingMode::MaxContent"); yoga::assertFatalWithNode( node, yoga::isUndefined(availableHeight) - ? heightMeasureMode == MeasureMode::Undefined + ? heightSizingMode == SizingMode::MaxContent : true, - "availableHeight is indefinite so heightMeasureMode must be " - "MeasureMode::Undefined"); + "availableHeight is indefinite so heightSizingMode must be " + "SizingMode::MaxContent"); (performLayout ? layoutMarkerData.layouts : layoutMarkerData.measures) += 1; @@ -1549,8 +1544,8 @@ static void calculateLayoutImpl( node, availableWidth - marginAxisRow, availableHeight - marginAxisColumn, - widthMeasureMode, - heightMeasureMode, + widthSizingMode, + heightSizingMode, ownerWidth, ownerHeight, layoutMarkerData, @@ -1564,8 +1559,8 @@ static void calculateLayoutImpl( node, availableWidth - marginAxisRow, availableHeight - marginAxisColumn, - widthMeasureMode, - heightMeasureMode, + widthSizingMode, + heightSizingMode, ownerWidth, ownerHeight); return; @@ -1578,8 +1573,8 @@ static void calculateLayoutImpl( node, availableWidth - marginAxisRow, availableHeight - marginAxisColumn, - widthMeasureMode, - heightMeasureMode, + widthSizingMode, + heightSizingMode, ownerWidth, ownerHeight)) { return; @@ -1608,10 +1603,10 @@ static void calculateLayoutImpl( const float leadingPaddingAndBorderCross = node->getInlineStartPaddingAndBorder(crossAxis, direction, ownerWidth); - MeasureMode measureModeMainDim = - isMainAxisRow ? widthMeasureMode : heightMeasureMode; - MeasureMode measureModeCrossDim = - isMainAxisRow ? heightMeasureMode : widthMeasureMode; + SizingMode sizingModeMainDim = + isMainAxisRow ? widthSizingMode : heightSizingMode; + SizingMode sizingModeCrossDim = + isMainAxisRow ? heightSizingMode : widthSizingMode; const float paddingAndBorderAxisRow = isMainAxisRow ? paddingAndBorderAxisMain : paddingAndBorderAxisCross; @@ -1646,8 +1641,8 @@ static void calculateLayoutImpl( node, availableInnerWidth, availableInnerHeight, - widthMeasureMode, - heightMeasureMode, + widthSizingMode, + heightSizingMode, direction, mainAxis, performLayout, @@ -1661,12 +1656,12 @@ static void calculateLayoutImpl( } const bool mainAxisOverflows = - (measureModeMainDim != MeasureMode::Undefined) && + (sizingModeMainDim != SizingMode::MaxContent) && totalMainDim > availableInnerMainDim; if (isNodeFlexWrap && mainAxisOverflows && - measureModeMainDim == MeasureMode::AtMost) { - measureModeMainDim = MeasureMode::Exactly; + sizingModeMainDim == SizingMode::FitContent) { + sizingModeMainDim = SizingMode::StretchFit; } // STEP 4: COLLECT FLEX ITEMS INTO FLEX LINES @@ -1700,7 +1695,7 @@ static void calculateLayoutImpl( // If we don't need to measure the cross axis, we can skip the entire flex // step. const bool canSkipFlex = - !performLayout && measureModeCrossDim == MeasureMode::Exactly; + !performLayout && sizingModeCrossDim == SizingMode::StretchFit; // STEP 5: RESOLVING FLEXIBLE LENGTHS ON MAIN AXIS // Calculate the remaining available space that needs to be allocated. If @@ -1710,7 +1705,7 @@ static void calculateLayoutImpl( bool sizeBasedOnContent = false; // If we don't measure with exact main dimension we want to ensure we don't // violate min and max - if (measureModeMainDim != MeasureMode::Exactly) { + if (sizingModeMainDim != SizingMode::StretchFit) { const auto& style = node->getStyle(); const float minInnerWidth = yoga::resolveValue(style.minDimension(Dimension::Width), ownerWidth) @@ -1783,7 +1778,7 @@ static void calculateLayoutImpl( availableInnerWidth, availableInnerHeight, mainAxisOverflows, - measureModeCrossDim, + sizingModeCrossDim, performLayout, layoutMarkerData, depth, @@ -1808,8 +1803,8 @@ static void calculateLayoutImpl( mainAxis, crossAxis, direction, - measureModeMainDim, - measureModeCrossDim, + sizingModeMainDim, + sizingModeCrossDim, mainAxisownerSize, ownerWidth, availableInnerMainDim, @@ -1818,8 +1813,8 @@ static void calculateLayoutImpl( performLayout); float containerCrossAxis = availableInnerCrossDim; - if (measureModeCrossDim == MeasureMode::Undefined || - measureModeCrossDim == MeasureMode::AtMost) { + if (sizingModeCrossDim == SizingMode::MaxContent || + sizingModeCrossDim == SizingMode::FitContent) { // Compute the cross axis from the max cross dimension of the children. containerCrossAxis = boundAxis( @@ -1832,7 +1827,7 @@ static void calculateLayoutImpl( } // If there's no flex wrap, the cross dimension is defined by the container. - if (!isNodeFlexWrap && measureModeCrossDim == MeasureMode::Exactly) { + if (!isNodeFlexWrap && sizingModeCrossDim == SizingMode::StretchFit) { flexLine.layout.crossDim = availableInnerCrossDim; } @@ -1911,21 +1906,21 @@ static void calculateLayoutImpl( childMainSize += child->getMarginForAxis(mainAxis, availableInnerWidth); - MeasureMode childMainMeasureMode = MeasureMode::Exactly; - MeasureMode childCrossMeasureMode = MeasureMode::Exactly; + SizingMode childMainSizingMode = SizingMode::StretchFit; + SizingMode childCrossSizingMode = SizingMode::StretchFit; constrainMaxSizeForMode( child, mainAxis, availableInnerMainDim, availableInnerWidth, - &childMainMeasureMode, + &childMainSizingMode, &childMainSize); constrainMaxSizeForMode( child, crossAxis, availableInnerCrossDim, availableInnerWidth, - &childCrossMeasureMode, + &childCrossSizingMode, &childCrossSize); const float childWidth = @@ -1936,24 +1931,24 @@ static void calculateLayoutImpl( auto alignContent = node->getStyle().alignContent(); auto crossAxisDoesNotGrow = alignContent != Align::Stretch && isNodeFlexWrap; - const MeasureMode childWidthMeasureMode = + const SizingMode childWidthSizingMode = yoga::isUndefined(childWidth) || (!isMainAxisRow && crossAxisDoesNotGrow) - ? MeasureMode::Undefined - : MeasureMode::Exactly; - const MeasureMode childHeightMeasureMode = + ? SizingMode::MaxContent + : SizingMode::StretchFit; + const SizingMode childHeightSizingMode = yoga::isUndefined(childHeight) || (isMainAxisRow && crossAxisDoesNotGrow) - ? MeasureMode::Undefined - : MeasureMode::Exactly; + ? SizingMode::MaxContent + : SizingMode::StretchFit; calculateLayoutInternal( child, childWidth, childHeight, direction, - childWidthMeasureMode, - childHeightMeasureMode, + childWidthSizingMode, + childHeightSizingMode, availableInnerWidth, availableInnerHeight, true, @@ -2174,8 +2169,8 @@ static void calculateLayoutImpl( childWidth, childHeight, direction, - MeasureMode::Exactly, - MeasureMode::Exactly, + SizingMode::StretchFit, + SizingMode::StretchFit, availableInnerWidth, availableInnerHeight, true, @@ -2234,9 +2229,9 @@ static void calculateLayoutImpl( // If the user didn't specify a width or height for the node, set the // dimensions based on the children. - if (measureModeMainDim == MeasureMode::Undefined || + if (sizingModeMainDim == SizingMode::MaxContent || (node->getStyle().overflow() != Overflow::Scroll && - measureModeMainDim == MeasureMode::AtMost)) { + sizingModeMainDim == SizingMode::FitContent)) { // Clamp the size to the min/max size, if specified, and make sure it // doesn't go below the padding and border amount. node->setLayoutMeasuredDimension( @@ -2245,7 +2240,7 @@ static void calculateLayoutImpl( dimension(mainAxis)); } else if ( - measureModeMainDim == MeasureMode::AtMost && + sizingModeMainDim == SizingMode::FitContent && node->getStyle().overflow() == Overflow::Scroll) { node->setLayoutMeasuredDimension( yoga::maxOrDefined( @@ -2261,9 +2256,9 @@ static void calculateLayoutImpl( dimension(mainAxis)); } - if (measureModeCrossDim == MeasureMode::Undefined || + if (sizingModeCrossDim == SizingMode::MaxContent || (node->getStyle().overflow() != Overflow::Scroll && - measureModeCrossDim == MeasureMode::AtMost)) { + sizingModeCrossDim == SizingMode::FitContent)) { // Clamp the size to the min/max size, if specified, and make sure it // doesn't go below the padding and border amount. node->setLayoutMeasuredDimension( @@ -2276,7 +2271,7 @@ static void calculateLayoutImpl( dimension(crossAxis)); } else if ( - measureModeCrossDim == MeasureMode::AtMost && + sizingModeCrossDim == SizingMode::FitContent && node->getStyle().overflow() == Overflow::Scroll) { node->setLayoutMeasuredDimension( yoga::maxOrDefined( @@ -2325,7 +2320,7 @@ static void calculateLayoutImpl( absolutePercentageAgainstPaddingEdge ? node->getLayout().measuredDimension(Dimension::Width) : availableInnerWidth, - isMainAxisRow ? measureModeMainDim : measureModeCrossDim, + isMainAxisRow ? sizingModeMainDim : sizingModeCrossDim, absolutePercentageAgainstPaddingEdge ? node->getLayout().measuredDimension(Dimension::Height) : availableInnerHeight, @@ -2375,15 +2370,15 @@ static const char* spacerWithLength(const unsigned long level) { } } -static const char* measureModeName( - const MeasureMode mode, +static const char* sizingModeName( + const SizingMode mode, const bool performLayout) { switch (mode) { - case MeasureMode::Undefined: + case SizingMode::MaxContent: return performLayout ? "LAY_UNDEFINED" : "UNDEFINED"; - case MeasureMode::Exactly: + case SizingMode::StretchFit: return performLayout ? "LAY_EXACTLY" : "EXACTLY"; - case MeasureMode::AtMost: + case SizingMode::FitContent: return performLayout ? "LAY_AT_MOST" : "AT_MOST"; } return ""; @@ -2402,8 +2397,8 @@ bool calculateLayoutInternal( const float availableWidth, const float availableHeight, const Direction ownerDirection, - const MeasureMode widthMeasureMode, - const MeasureMode heightMeasureMode, + const SizingMode widthSizingMode, + const SizingMode heightSizingMode, const float ownerWidth, const float ownerHeight, const bool performLayout, @@ -2424,8 +2419,8 @@ bool calculateLayoutInternal( layout->nextCachedMeasurementsIndex = 0; layout->cachedLayout.availableWidth = -1; layout->cachedLayout.availableHeight = -1; - layout->cachedLayout.widthMeasureMode = MeasureMode::Undefined; - layout->cachedLayout.heightMeasureMode = MeasureMode::Undefined; + layout->cachedLayout.widthSizingMode = SizingMode::MaxContent; + layout->cachedLayout.heightSizingMode = SizingMode::MaxContent; layout->cachedLayout.computedWidth = -1; layout->cachedLayout.computedHeight = -1; } @@ -2448,13 +2443,13 @@ bool calculateLayoutInternal( // First, try to use the layout cache. if (canUseCachedMeasurement( - widthMeasureMode, + widthSizingMode, availableWidth, - heightMeasureMode, + heightSizingMode, availableHeight, - layout->cachedLayout.widthMeasureMode, + layout->cachedLayout.widthSizingMode, layout->cachedLayout.availableWidth, - layout->cachedLayout.heightMeasureMode, + layout->cachedLayout.heightSizingMode, layout->cachedLayout.availableHeight, layout->cachedLayout.computedWidth, layout->cachedLayout.computedHeight, @@ -2466,13 +2461,13 @@ bool calculateLayoutInternal( // Try to use the measurement cache. for (size_t i = 0; i < layout->nextCachedMeasurementsIndex; i++) { if (canUseCachedMeasurement( - widthMeasureMode, + widthSizingMode, availableWidth, - heightMeasureMode, + heightSizingMode, availableHeight, - layout->cachedMeasurements[i].widthMeasureMode, + layout->cachedMeasurements[i].widthSizingMode, layout->cachedMeasurements[i].availableWidth, - layout->cachedMeasurements[i].heightMeasureMode, + layout->cachedMeasurements[i].heightSizingMode, layout->cachedMeasurements[i].availableHeight, layout->cachedMeasurements[i].computedWidth, layout->cachedMeasurements[i].computedHeight, @@ -2489,8 +2484,8 @@ bool calculateLayoutInternal( layout->cachedLayout.availableWidth, availableWidth) && yoga::inexactEquals( layout->cachedLayout.availableHeight, availableHeight) && - layout->cachedLayout.widthMeasureMode == widthMeasureMode && - layout->cachedLayout.heightMeasureMode == heightMeasureMode) { + layout->cachedLayout.widthSizingMode == widthSizingMode && + layout->cachedLayout.heightSizingMode == heightSizingMode) { cachedResults = &layout->cachedLayout; } } else { @@ -2499,9 +2494,8 @@ bool calculateLayoutInternal( layout->cachedMeasurements[i].availableWidth, availableWidth) && yoga::inexactEquals( layout->cachedMeasurements[i].availableHeight, availableHeight) && - layout->cachedMeasurements[i].widthMeasureMode == widthMeasureMode && - layout->cachedMeasurements[i].heightMeasureMode == - heightMeasureMode) { + layout->cachedMeasurements[i].widthSizingMode == widthSizingMode && + layout->cachedMeasurements[i].heightSizingMode == heightSizingMode) { cachedResults = &layout->cachedMeasurements[i]; break; } @@ -2529,8 +2523,8 @@ bool calculateLayoutInternal( node, LogLevel::Verbose, "wm: %s, hm: %s, aw: %f ah: %f => d: (%f, %f) %s\n", - measureModeName(widthMeasureMode, performLayout), - measureModeName(heightMeasureMode, performLayout), + sizingModeName(widthSizingMode, performLayout), + sizingModeName(heightSizingMode, performLayout), availableWidth, availableHeight, cachedResults->computedWidth, @@ -2551,8 +2545,8 @@ bool calculateLayoutInternal( node, LogLevel::Verbose, "wm: %s, hm: %s, aw: %f ah: %f %s\n", - measureModeName(widthMeasureMode, performLayout), - measureModeName(heightMeasureMode, performLayout), + sizingModeName(widthSizingMode, performLayout), + sizingModeName(heightSizingMode, performLayout), availableWidth, availableHeight, LayoutPassReasonToString(reason)); @@ -2563,8 +2557,8 @@ bool calculateLayoutInternal( availableWidth, availableHeight, ownerDirection, - widthMeasureMode, - heightMeasureMode, + widthSizingMode, + heightSizingMode, ownerWidth, ownerHeight, performLayout, @@ -2586,8 +2580,8 @@ bool calculateLayoutInternal( node, LogLevel::Verbose, "wm: %s, hm: %s, d: (%f, %f) %s\n", - measureModeName(widthMeasureMode, performLayout), - measureModeName(heightMeasureMode, performLayout), + sizingModeName(widthSizingMode, performLayout), + sizingModeName(heightSizingMode, performLayout), layout->measuredDimension(Dimension::Width), layout->measuredDimension(Dimension::Height), LayoutPassReasonToString(reason)); @@ -2621,8 +2615,8 @@ bool calculateLayoutInternal( newCacheEntry->availableWidth = availableWidth; newCacheEntry->availableHeight = availableHeight; - newCacheEntry->widthMeasureMode = widthMeasureMode; - newCacheEntry->heightMeasureMode = heightMeasureMode; + newCacheEntry->widthSizingMode = widthSizingMode; + newCacheEntry->heightSizingMode = heightSizingMode; newCacheEntry->computedWidth = layout->measuredDimension(Dimension::Width); newCacheEntry->computedHeight = @@ -2672,7 +2666,7 @@ void calculateLayout( gCurrentGenerationCount.fetch_add(1, std::memory_order_relaxed); node->resolveDimension(); float width = YGUndefined; - MeasureMode widthMeasureMode = MeasureMode::Undefined; + SizingMode widthSizingMode = SizingMode::MaxContent; const auto& style = node->getStyle(); if (styleDefinesDimension(node, FlexDirection::Row, ownerWidth)) { width = @@ -2681,21 +2675,21 @@ void calculateLayout( ownerWidth) .unwrap() + node->getMarginForAxis(FlexDirection::Row, ownerWidth)); - widthMeasureMode = MeasureMode::Exactly; + widthSizingMode = SizingMode::StretchFit; } else if (yoga::resolveValue( style.maxDimension(Dimension::Width), ownerWidth) .isDefined()) { width = yoga::resolveValue(style.maxDimension(Dimension::Width), ownerWidth) .unwrap(); - widthMeasureMode = MeasureMode::AtMost; + widthSizingMode = SizingMode::FitContent; } else { width = ownerWidth; - widthMeasureMode = yoga::isUndefined(width) ? MeasureMode::Undefined - : MeasureMode::Exactly; + widthSizingMode = yoga::isUndefined(width) ? SizingMode::MaxContent + : SizingMode::StretchFit; } float height = YGUndefined; - MeasureMode heightMeasureMode = MeasureMode::Undefined; + SizingMode heightSizingMode = SizingMode::MaxContent; if (styleDefinesDimension(node, FlexDirection::Column, ownerHeight)) { height = (yoga::resolveValue( @@ -2703,26 +2697,26 @@ void calculateLayout( ownerHeight) .unwrap() + node->getMarginForAxis(FlexDirection::Column, ownerWidth)); - heightMeasureMode = MeasureMode::Exactly; + heightSizingMode = SizingMode::StretchFit; } else if (yoga::resolveValue( style.maxDimension(Dimension::Height), ownerHeight) .isDefined()) { height = yoga::resolveValue(style.maxDimension(Dimension::Height), ownerHeight) .unwrap(); - heightMeasureMode = MeasureMode::AtMost; + heightSizingMode = SizingMode::FitContent; } else { height = ownerHeight; - heightMeasureMode = yoga::isUndefined(height) ? MeasureMode::Undefined - : MeasureMode::Exactly; + heightSizingMode = yoga::isUndefined(height) ? SizingMode::MaxContent + : SizingMode::StretchFit; } if (calculateLayoutInternal( node, width, height, ownerDirection, - widthMeasureMode, - heightMeasureMode, + widthSizingMode, + heightSizingMode, ownerWidth, ownerHeight, true, diff --git a/packages/react-native/ReactCommon/yoga/yoga/algorithm/SizingMode.h b/packages/react-native/ReactCommon/yoga/yoga/algorithm/SizingMode.h new file mode 100644 index 00000000000000..bd725df13ac68b --- /dev/null +++ b/packages/react-native/ReactCommon/yoga/yoga/algorithm/SizingMode.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#pragma once + +#include +#include + +namespace facebook::yoga { + +/** + * Corresponds to a CSS auto box sizes. Missing "min-content", as Yoga does not + * current support automatic minimum sizes. + * https://www.w3.org/TR/css-sizing-3/#auto-box-sizes + * https://www.w3.org/TR/css-flexbox-1/#min-size-auto + */ +enum class SizingMode { + /** + * The size a box would take if its outer size filled the available space in + * the given axis; in other words, the stretch fit into the available space, + * if that is definite. Undefined if the available space is indefinite. + */ + StretchFit, + + /** + * A box’s “ideal” size in a given axis when given infinite available space. + * Usually this is the smallest size the box could take in that axis while + * still fitting around its contents, i.e. minimizing unfilled space while + * avoiding overflow. + */ + MaxContent, + + /** + * If the available space in a given axis is definite, equal to + * clamp(min-content size, stretch-fit size, max-content size) (i.e. + * max(min-content size, min(max-content size, stretch-fit size))). When + * sizing under a min-content constraint, equal to the min-content size. + * Otherwise, equal to the max-content size in that axis. + */ + FitContent, +}; + +inline MeasureMode measureMode(SizingMode mode) { + switch (mode) { + case SizingMode::StretchFit: + return MeasureMode::Exactly; + case SizingMode::MaxContent: + return MeasureMode::Undefined; + case SizingMode::FitContent: + return MeasureMode::AtMost; + } + + fatalWithMessage("Invalid SizingMode"); +} + +inline SizingMode sizingMode(MeasureMode mode) { + switch (mode) { + case MeasureMode::Exactly: + return SizingMode::StretchFit; + case MeasureMode::Undefined: + return SizingMode::MaxContent; + case MeasureMode::AtMost: + return SizingMode::FitContent; + } + + fatalWithMessage("Invalid MeasureMode"); +} + +} // namespace facebook::yoga diff --git a/packages/react-native/ReactCommon/yoga/yoga/debug/AssertFatal.cpp b/packages/react-native/ReactCommon/yoga/yoga/debug/AssertFatal.cpp index 2388a744539dbe..e43ce2a254ee23 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/debug/AssertFatal.cpp +++ b/packages/react-native/ReactCommon/yoga/yoga/debug/AssertFatal.cpp @@ -7,8 +7,10 @@ #include +#include #include #include +#include namespace facebook::yoga { diff --git a/packages/react-native/ReactCommon/yoga/yoga/debug/AssertFatal.h b/packages/react-native/ReactCommon/yoga/yoga/debug/AssertFatal.h index 929ff1792d0d8f..bbd8ad19eabbf0 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/debug/AssertFatal.h +++ b/packages/react-native/ReactCommon/yoga/yoga/debug/AssertFatal.h @@ -8,11 +8,12 @@ #pragma once #include -#include -#include namespace facebook::yoga { +class Node; +class Config; + [[noreturn]] void fatalWithMessage(const char* message); void assertFatal(bool condition, const char* message); diff --git a/packages/react-native/ReactCommon/yoga/yoga/node/CachedMeasurement.h b/packages/react-native/ReactCommon/yoga/yoga/node/CachedMeasurement.h index 4d2c22260075dc..9c76280acf74e1 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/node/CachedMeasurement.h +++ b/packages/react-native/ReactCommon/yoga/yoga/node/CachedMeasurement.h @@ -11,7 +11,7 @@ #include -#include +#include #include namespace facebook::yoga { @@ -19,15 +19,15 @@ namespace facebook::yoga { struct CachedMeasurement { float availableWidth{-1}; float availableHeight{-1}; - MeasureMode widthMeasureMode{MeasureMode::Undefined}; - MeasureMode heightMeasureMode{MeasureMode::Undefined}; + SizingMode widthSizingMode{SizingMode::MaxContent}; + SizingMode heightSizingMode{SizingMode::MaxContent}; float computedWidth{-1}; float computedHeight{-1}; bool operator==(CachedMeasurement measurement) const { - bool isEqual = widthMeasureMode == measurement.widthMeasureMode && - heightMeasureMode == measurement.heightMeasureMode; + bool isEqual = widthSizingMode == measurement.widthSizingMode && + heightSizingMode == measurement.heightSizingMode; if (!yoga::isUndefined(availableWidth) || !yoga::isUndefined(measurement.availableWidth)) { From b5f04d11e85afc55a948ed35e803da151069833f Mon Sep 17 00:00:00 2001 From: Nick Gerleman Date: Sat, 25 Nov 2023 20:41:22 -0800 Subject: [PATCH 093/162] YGEdge -> yoga::Edge (#41391) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41391 X-link: https://github.com/facebook/yoga/pull/1461 Converts usages of `YGEdge` within internal APIs to `yoga::Edge` scoped enum. With the exception of YGUnit which is in its own state of transition, this is the last public yoga enum to need to be moved to scoped enum form for usages internal to the Yoga public API. Changelog: [internal] Reviewed By: rshest Differential Revision: D51152779 fbshipit-source-id: 06554f67bfd7709cbc24fdd9a5474e897e9e95d8 --- .../Text/RCTParagraphComponentViewTests.mm | 16 +- .../AndroidTextInputComponentDescriptor.h | 12 +- .../components/view/BaseViewProps.cpp | 22 +- .../components/view/ViewShadowNode.cpp | 2 +- .../view/YogaLayoutableShadowNode.cpp | 113 ++++----- .../components/view/YogaStylableProps.cpp | 220 +++++++++--------- .../view/YogaStylablePropsMapBuffer.cpp | 25 +- .../components/view/propsConversions.h | 216 ++++++++--------- .../components/view/tests/LayoutTest.cpp | 16 +- .../mounting/tests/StackingContextTest.cpp | 6 +- .../ReactCommon/yoga/yoga/YGNodeLayout.cpp | 38 +-- .../ReactCommon/yoga/yoga/YGNodeStyle.cpp | 24 +- .../yoga/yoga/algorithm/Baseline.cpp | 2 +- .../yoga/yoga/algorithm/CalculateLayout.cpp | 55 +++-- .../yoga/yoga/algorithm/FlexDirection.h | 53 ++--- .../yoga/yoga/algorithm/PixelGrid.cpp | 8 +- .../yoga/yoga/debug/NodeToString.cpp | 8 +- .../yoga/yoga/node/LayoutResults.cpp | 8 +- .../yoga/yoga/node/LayoutResults.h | 71 ++++-- .../ReactCommon/yoga/yoga/node/Node.cpp | 138 +++++------ .../ReactCommon/yoga/yoga/node/Node.h | 17 +- .../ReactCommon/yoga/yoga/style/Style.h | 32 +-- 22 files changed, 575 insertions(+), 527 deletions(-) diff --git a/packages/react-native/React/Tests/Text/RCTParagraphComponentViewTests.mm b/packages/react-native/React/Tests/Text/RCTParagraphComponentViewTests.mm index f6c1ba3c6ed15f..2d8e5de1fb5c00 100644 --- a/packages/react-native/React/Tests/Text/RCTParagraphComponentViewTests.mm +++ b/packages/react-native/React/Tests/Text/RCTParagraphComponentViewTests.mm @@ -134,8 +134,8 @@ - (void)setUp props.accessible = true; auto &yogaStyle = props.yogaStyle; yogaStyle.positionType() = yoga::PositionType::Absolute; - yogaStyle.setPosition(YGEdgeLeft, yoga::value::points(0)); - yogaStyle.setPosition(YGEdgeTop, yoga::value::points(0)); + yogaStyle.setPosition(yoga::Edge::Left, yoga::value::points(0)); + yogaStyle.setPosition(yoga::Edge::Top, yoga::value::points(0)); yogaStyle.setDimension(yoga::Dimension::Width, yoga::value::points(200)); yogaStyle.setDimension(yoga::Dimension::Height, yoga::value::points(200)); return sharedProps; @@ -214,8 +214,8 @@ - (void)setUp props.accessible = true; auto &yogaStyle = props.yogaStyle; yogaStyle.positionType() = yoga::PositionType::Absolute; - yogaStyle.setPosition(YGEdgeLeft, yoga::value::points(0)); - yogaStyle.setPosition(YGEdgeTop, yoga::value::points(30)); + yogaStyle.setPosition(yoga::Edge::Left, yoga::value::points(0)); + yogaStyle.setPosition(yoga::Edge::Top, yoga::value::points(30)); yogaStyle.setDimension(yoga::Dimension::Width, yoga::value::points(200)); yogaStyle.setDimension(yoga::Dimension::Height, yoga::value::points(50)); return sharedProps; @@ -258,8 +258,8 @@ - (void)setUp props.accessible = true; auto &yogaStyle = props.yogaStyle; yogaStyle.positionType() = yoga::PositionType::Absolute; - yogaStyle.setPosition(YGEdgeLeft, yoga::value::points(0)); - yogaStyle.setPosition(YGEdgeTop, yoga::value::points(90)); + yogaStyle.setPosition(yoga::Edge::Left, yoga::value::points(0)); + yogaStyle.setPosition(yoga::Edge::Top, yoga::value::points(90)); yogaStyle.setDimension(yoga::Dimension::Width, yoga::value::points(200)); yogaStyle.setDimension(yoga::Dimension::Height, yoga::value::points(50)); return sharedProps; @@ -432,8 +432,8 @@ - (void)testEntireParagraphLink props.accessibilityTraits = AccessibilityTraits::Link; auto &yogaStyle = props.yogaStyle; yogaStyle.positionType() = yoga::PositionType::Absolute; - yogaStyle.setPosition(YGEdgeLeft, yoga::value::points(0)); - yogaStyle.setPosition(YGEdgeTop, yoga::value::points(90)); + yogaStyle.setPosition(yoga::Edge::Left, yoga::value::points(0)); + yogaStyle.setPosition(yoga::Edge::Top, yoga::value::points(90)); yogaStyle.setDimension(yoga::Dimension::Width, yoga::value::points(200)); yogaStyle.setDimension(yoga::Dimension::Height, yoga::value::points(20)); return sharedProps; diff --git a/packages/react-native/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputComponentDescriptor.h b/packages/react-native/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputComponentDescriptor.h index 0ff0f91ea30953..6ee6c1e73c192c 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputComponentDescriptor.h +++ b/packages/react-native/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputComponentDescriptor.h @@ -105,23 +105,23 @@ class AndroidTextInputComponentDescriptor final !textInputProps.hasPaddingLeft && !textInputProps.hasPaddingHorizontal) { changedPadding = true; - style.setPadding(YGEdgeStart, yoga::value::points(theme.start)); + style.setPadding(yoga::Edge::Start, yoga::value::points(theme.start)); } if (!textInputProps.hasPadding && !textInputProps.hasPaddingEnd && !textInputProps.hasPaddingRight && !textInputProps.hasPaddingHorizontal) { changedPadding = true; - style.setPadding(YGEdgeEnd, yoga::value::points(theme.end)); + style.setPadding(yoga::Edge::End, yoga::value::points(theme.end)); } if (!textInputProps.hasPadding && !textInputProps.hasPaddingTop && !textInputProps.hasPaddingVertical) { changedPadding = true; - style.setPadding(YGEdgeTop, yoga::value::points(theme.top)); + style.setPadding(yoga::Edge::Top, yoga::value::points(theme.top)); } if (!textInputProps.hasPadding && !textInputProps.hasPaddingBottom && !textInputProps.hasPaddingVertical) { changedPadding = true; - style.setPadding(YGEdgeBottom, yoga::value::points(theme.bottom)); + style.setPadding(yoga::Edge::Bottom, yoga::value::points(theme.bottom)); } // If the TextInput initially does not have paddingLeft or paddingStart, a @@ -132,12 +132,12 @@ class AndroidTextInputComponentDescriptor final if ((textInputProps.hasPadding || textInputProps.hasPaddingLeft || textInputProps.hasPaddingHorizontal) && !textInputProps.hasPaddingStart) { - style.setPadding(YGEdgeStart, yoga::value::undefined()); + style.setPadding(yoga::Edge::Start, yoga::value::undefined()); } if ((textInputProps.hasPadding || textInputProps.hasPaddingRight || textInputProps.hasPaddingHorizontal) && !textInputProps.hasPaddingEnd) { - style.setPadding(YGEdgeEnd, yoga::value::undefined()); + style.setPadding(yoga::Edge::End, yoga::value::undefined()); } // Note that this is expensive: on every adopt, we need to set the Yoga diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/BaseViewProps.cpp b/packages/react-native/ReactCommon/react/renderer/components/view/BaseViewProps.cpp index 790f14638e8622..3d55f25c38cb9c 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/BaseViewProps.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/view/BaseViewProps.cpp @@ -358,20 +358,24 @@ BorderMetrics BaseViewProps::resolveBorderMetrics( bool{layoutMetrics.layoutDirection == LayoutDirection::RightToLeft}; auto borderWidths = CascadedBorderWidths{ - /* .left = */ optionalFloatFromYogaValue(yogaStyle.border(YGEdgeLeft)), - /* .top = */ optionalFloatFromYogaValue(yogaStyle.border(YGEdgeTop)), + /* .left = */ optionalFloatFromYogaValue( + yogaStyle.border(yoga::Edge::Left)), + /* .top = */ + optionalFloatFromYogaValue(yogaStyle.border(yoga::Edge::Top)), /* .right = */ - optionalFloatFromYogaValue(yogaStyle.border(YGEdgeRight)), + optionalFloatFromYogaValue(yogaStyle.border(yoga::Edge::Right)), /* .bottom = */ - optionalFloatFromYogaValue(yogaStyle.border(YGEdgeBottom)), + optionalFloatFromYogaValue(yogaStyle.border(yoga::Edge::Bottom)), /* .start = */ - optionalFloatFromYogaValue(yogaStyle.border(YGEdgeStart)), - /* .end = */ optionalFloatFromYogaValue(yogaStyle.border(YGEdgeEnd)), + optionalFloatFromYogaValue(yogaStyle.border(yoga::Edge::Start)), + /* .end = */ + optionalFloatFromYogaValue(yogaStyle.border(yoga::Edge::End)), /* .horizontal = */ - optionalFloatFromYogaValue(yogaStyle.border(YGEdgeHorizontal)), + optionalFloatFromYogaValue(yogaStyle.border(yoga::Edge::Horizontal)), /* .vertical = */ - optionalFloatFromYogaValue(yogaStyle.border(YGEdgeVertical)), - /* .all = */ optionalFloatFromYogaValue(yogaStyle.border(YGEdgeAll)), + optionalFloatFromYogaValue(yogaStyle.border(yoga::Edge::Vertical)), + /* .all = */ + optionalFloatFromYogaValue(yogaStyle.border(yoga::Edge::All)), }; return { diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/ViewShadowNode.cpp b/packages/react-native/ReactCommon/react/renderer/components/view/ViewShadowNode.cpp index 627128b1711a87..fe11e92e1a5771 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/ViewShadowNode.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/view/ViewShadowNode.cpp @@ -41,7 +41,7 @@ void ViewShadowNode::initialize() noexcept { auto hasBorder = [&]() { for (auto edge : yoga::ordinals()) { - if (viewProps.yogaStyle.border(yoga::unscopedEnum(edge)).isDefined()) { + if (viewProps.yogaStyle.border(edge).isDefined()) { return true; } } diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/YogaLayoutableShadowNode.cpp b/packages/react-native/ReactCommon/react/renderer/components/view/YogaLayoutableShadowNode.cpp index ed278ac98828ba..7c531e3517db21 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/YogaLayoutableShadowNode.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/view/YogaLayoutableShadowNode.cpp @@ -392,54 +392,54 @@ void YogaLayoutableShadowNode::updateYogaProps() { // Aliases with precedence if (props.insetInlineEnd.isDefined()) { - result.setPosition(YGEdgeEnd, props.insetInlineEnd); + result.setPosition(yoga::Edge::End, props.insetInlineEnd); } if (props.insetInlineStart.isDefined()) { - result.setPosition(YGEdgeStart, props.insetInlineStart); + result.setPosition(yoga::Edge::Start, props.insetInlineStart); } if (props.marginInline.isDefined()) { - result.setMargin(YGEdgeHorizontal, props.marginInline); + result.setMargin(yoga::Edge::Horizontal, props.marginInline); } if (props.marginInlineStart.isDefined()) { - result.setMargin(YGEdgeStart, props.marginInlineStart); + result.setMargin(yoga::Edge::Start, props.marginInlineStart); } if (props.marginInlineEnd.isDefined()) { - result.setMargin(YGEdgeEnd, props.marginInlineEnd); + result.setMargin(yoga::Edge::End, props.marginInlineEnd); } if (props.marginBlock.isDefined()) { - result.setMargin(YGEdgeVertical, props.marginBlock); + result.setMargin(yoga::Edge::Vertical, props.marginBlock); } if (props.paddingInline.isDefined()) { - result.setPadding(YGEdgeHorizontal, props.paddingInline); + result.setPadding(yoga::Edge::Horizontal, props.paddingInline); } if (props.paddingInlineStart.isDefined()) { - result.setPadding(YGEdgeStart, props.paddingInlineStart); + result.setPadding(yoga::Edge::Start, props.paddingInlineStart); } if (props.paddingInlineEnd.isDefined()) { - result.setPadding(YGEdgeEnd, props.paddingInlineEnd); + result.setPadding(yoga::Edge::End, props.paddingInlineEnd); } if (props.paddingBlock.isDefined()) { - result.setPadding(YGEdgeVertical, props.paddingBlock); + result.setPadding(yoga::Edge::Vertical, props.paddingBlock); } // Aliases without precedence - if (result.position(YGEdgeBottom).isUndefined()) { - result.setPosition(YGEdgeBottom, props.insetBlockEnd); + if (result.position(yoga::Edge::Bottom).isUndefined()) { + result.setPosition(yoga::Edge::Bottom, props.insetBlockEnd); } - if (result.position(YGEdgeTop).isUndefined()) { - result.setPosition(YGEdgeTop, props.insetBlockStart); + if (result.position(yoga::Edge::Top).isUndefined()) { + result.setPosition(yoga::Edge::Top, props.insetBlockStart); } - if (result.margin(YGEdgeTop).isUndefined()) { - result.setMargin(YGEdgeTop, props.marginBlockStart); + if (result.margin(yoga::Edge::Top).isUndefined()) { + result.setMargin(yoga::Edge::Top, props.marginBlockStart); } - if (result.margin(YGEdgeBottom).isUndefined()) { - result.setMargin(YGEdgeBottom, props.marginBlockEnd); + if (result.margin(yoga::Edge::Bottom).isUndefined()) { + result.setMargin(yoga::Edge::Bottom, props.marginBlockEnd); } - if (result.padding(YGEdgeTop).isUndefined()) { - result.setPadding(YGEdgeTop, props.paddingBlockStart); + if (result.padding(yoga::Edge::Top).isUndefined()) { + result.setPadding(yoga::Edge::Top, props.paddingBlockStart); } - if (result.padding(YGEdgeBottom).isUndefined()) { - result.setPadding(YGEdgeBottom, props.paddingBlockEnd); + if (result.padding(yoga::Edge::Bottom).isUndefined()) { + result.setPadding(yoga::Edge::Bottom, props.paddingBlockEnd); } return result; @@ -545,14 +545,14 @@ void YogaLayoutableShadowNode::setPadding(RectangleEdges padding) const { auto rightPadding = yoga::value::points(padding.right); auto bottomPadding = yoga::value::points(padding.bottom); - if (leftPadding != style.padding(YGEdgeLeft) || - topPadding != style.padding(YGEdgeTop) || - rightPadding != style.padding(YGEdgeRight) || - bottomPadding != style.padding(YGEdgeBottom)) { - style.setPadding(YGEdgeTop, yoga::value::points(padding.top)); - style.setPadding(YGEdgeLeft, yoga::value::points(padding.left)); - style.setPadding(YGEdgeRight, yoga::value::points(padding.right)); - style.setPadding(YGEdgeBottom, yoga::value::points(padding.bottom)); + if (leftPadding != style.padding(yoga::Edge::Left) || + topPadding != style.padding(yoga::Edge::Top) || + rightPadding != style.padding(yoga::Edge::Right) || + bottomPadding != style.padding(yoga::Edge::Bottom)) { + style.setPadding(yoga::Edge::Top, yoga::value::points(padding.top)); + style.setPadding(yoga::Edge::Left, yoga::value::points(padding.left)); + style.setPadding(yoga::Edge::Right, yoga::value::points(padding.right)); + style.setPadding(yoga::Edge::Bottom, yoga::value::points(padding.bottom)); yogaNode_.setStyle(style); yogaNode_.setDirty(true); } @@ -873,34 +873,37 @@ void YogaLayoutableShadowNode::swapLeftAndRightInYogaStyleProps( // Swap Yoga node values, position, padding and margin. - if (yogaStyle.position(YGEdgeLeft).isDefined()) { - yogaStyle.setPosition(YGEdgeStart, yogaStyle.position(YGEdgeLeft)); - yogaStyle.setPosition(YGEdgeLeft, yoga::value::undefined()); + if (yogaStyle.position(yoga::Edge::Left).isDefined()) { + yogaStyle.setPosition( + yoga::Edge::Start, yogaStyle.position(yoga::Edge::Left)); + yogaStyle.setPosition(yoga::Edge::Left, yoga::value::undefined()); } - if (yogaStyle.position(YGEdgeRight).isDefined()) { - yogaStyle.setPosition(YGEdgeEnd, yogaStyle.position(YGEdgeRight)); - yogaStyle.setPosition(YGEdgeRight, yoga::value::undefined()); + if (yogaStyle.position(yoga::Edge::Right).isDefined()) { + yogaStyle.setPosition( + yoga::Edge::End, yogaStyle.position(yoga::Edge::Right)); + yogaStyle.setPosition(yoga::Edge::Right, yoga::value::undefined()); } - if (yogaStyle.padding(YGEdgeLeft).isDefined()) { - yogaStyle.setPadding(YGEdgeStart, yogaStyle.padding(YGEdgeLeft)); - yogaStyle.setPadding(YGEdgeLeft, yoga::value::undefined()); + if (yogaStyle.padding(yoga::Edge::Left).isDefined()) { + yogaStyle.setPadding( + yoga::Edge::Start, yogaStyle.padding(yoga::Edge::Left)); + yogaStyle.setPadding(yoga::Edge::Left, yoga::value::undefined()); } - if (yogaStyle.padding(YGEdgeRight).isDefined()) { - yogaStyle.setPadding(YGEdgeEnd, yogaStyle.padding(YGEdgeRight)); - yogaStyle.setPadding(YGEdgeRight, yoga::value::undefined()); + if (yogaStyle.padding(yoga::Edge::Right).isDefined()) { + yogaStyle.setPadding(yoga::Edge::End, yogaStyle.padding(yoga::Edge::Right)); + yogaStyle.setPadding(yoga::Edge::Right, yoga::value::undefined()); } - if (yogaStyle.margin(YGEdgeLeft).isDefined()) { - yogaStyle.setMargin(YGEdgeStart, yogaStyle.margin(YGEdgeLeft)); - yogaStyle.setMargin(YGEdgeLeft, yoga::value::undefined()); + if (yogaStyle.margin(yoga::Edge::Left).isDefined()) { + yogaStyle.setMargin(yoga::Edge::Start, yogaStyle.margin(yoga::Edge::Left)); + yogaStyle.setMargin(yoga::Edge::Left, yoga::value::undefined()); } - if (yogaStyle.margin(YGEdgeRight).isDefined()) { - yogaStyle.setMargin(YGEdgeEnd, yogaStyle.margin(YGEdgeRight)); - yogaStyle.setMargin(YGEdgeRight, yoga::value::undefined()); + if (yogaStyle.margin(yoga::Edge::Right).isDefined()) { + yogaStyle.setMargin(yoga::Edge::End, yogaStyle.margin(yoga::Edge::Right)); + yogaStyle.setMargin(yoga::Edge::Right, yoga::value::undefined()); } shadowNode.yogaNode_.setStyle(yogaStyle); @@ -953,14 +956,16 @@ void YogaLayoutableShadowNode::swapLeftAndRightInViewProps( props.borderStyles.right.reset(); } - if (props.yogaStyle.border(YGEdgeLeft).isDefined()) { - props.yogaStyle.setBorder(YGEdgeStart, props.yogaStyle.border(YGEdgeLeft)); - props.yogaStyle.setBorder(YGEdgeLeft, yoga::value::undefined()); + if (props.yogaStyle.border(yoga::Edge::Left).isDefined()) { + props.yogaStyle.setBorder( + yoga::Edge::Start, props.yogaStyle.border(yoga::Edge::Left)); + props.yogaStyle.setBorder(yoga::Edge::Left, yoga::value::undefined()); } - if (props.yogaStyle.border(YGEdgeRight).isDefined()) { - props.yogaStyle.setBorder(YGEdgeEnd, props.yogaStyle.border(YGEdgeRight)); - props.yogaStyle.setBorder(YGEdgeRight, yoga::value::undefined()); + if (props.yogaStyle.border(yoga::Edge::Right).isDefined()) { + props.yogaStyle.setBorder( + yoga::Edge::End, props.yogaStyle.border(yoga::Edge::Right)); + props.yogaStyle.setBorder(yoga::Edge::Right, yoga::value::undefined()); } } diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/YogaStylableProps.cpp b/packages/react-native/ReactCommon/react/renderer/components/view/YogaStylableProps.cpp index ce472496bedebe..f3bce4b95c392d 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/YogaStylableProps.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/view/YogaStylableProps.cpp @@ -81,45 +81,45 @@ static inline T const getFieldValue( REBUILD_YG_FIELD_SWITCH_CASE_INDEXED( \ field, setter, yoga::Gutter::All, gapStr); -#define REBUILD_FIELD_YG_EDGES(field, setter, prefix, suffix) \ - REBUILD_YG_FIELD_SWITCH_CASE_INDEXED( \ - field, setter, YGEdgeLeft, prefix "Left" suffix); \ - REBUILD_YG_FIELD_SWITCH_CASE_INDEXED( \ - field, setter, YGEdgeTop, prefix "Top" suffix); \ - REBUILD_YG_FIELD_SWITCH_CASE_INDEXED( \ - field, setter, YGEdgeRight, prefix "Right" suffix); \ - REBUILD_YG_FIELD_SWITCH_CASE_INDEXED( \ - field, setter, YGEdgeBottom, prefix "Bottom" suffix); \ - REBUILD_YG_FIELD_SWITCH_CASE_INDEXED( \ - field, setter, YGEdgeStart, prefix "Start" suffix); \ - REBUILD_YG_FIELD_SWITCH_CASE_INDEXED( \ - field, setter, YGEdgeEnd, prefix "End" suffix); \ - REBUILD_YG_FIELD_SWITCH_CASE_INDEXED( \ - field, setter, YGEdgeHorizontal, prefix "Horizontal" suffix); \ - REBUILD_YG_FIELD_SWITCH_CASE_INDEXED( \ - field, setter, YGEdgeVertical, prefix "Vertical" suffix); \ - REBUILD_YG_FIELD_SWITCH_CASE_INDEXED( \ - field, setter, YGEdgeAll, prefix "" suffix); +#define REBUILD_FIELD_YG_EDGES(field, setter, prefix, suffix) \ + REBUILD_YG_FIELD_SWITCH_CASE_INDEXED( \ + field, setter, yoga::Edge::Left, prefix "Left" suffix); \ + REBUILD_YG_FIELD_SWITCH_CASE_INDEXED( \ + field, setter, yoga::Edge::Top, prefix "Top" suffix); \ + REBUILD_YG_FIELD_SWITCH_CASE_INDEXED( \ + field, setter, yoga::Edge::Right, prefix "Right" suffix); \ + REBUILD_YG_FIELD_SWITCH_CASE_INDEXED( \ + field, setter, yoga::Edge::Bottom, prefix "Bottom" suffix); \ + REBUILD_YG_FIELD_SWITCH_CASE_INDEXED( \ + field, setter, yoga::Edge::Start, prefix "Start" suffix); \ + REBUILD_YG_FIELD_SWITCH_CASE_INDEXED( \ + field, setter, yoga::Edge::End, prefix "End" suffix); \ + REBUILD_YG_FIELD_SWITCH_CASE_INDEXED( \ + field, setter, yoga::Edge::Horizontal, prefix "Horizontal" suffix); \ + REBUILD_YG_FIELD_SWITCH_CASE_INDEXED( \ + field, setter, yoga::Edge::Vertical, prefix "Vertical" suffix); \ + REBUILD_YG_FIELD_SWITCH_CASE_INDEXED( \ + field, setter, yoga::Edge::All, prefix "" suffix); -#define REBUILD_FIELD_YG_EDGES_POSITION() \ - REBUILD_YG_FIELD_SWITCH_CASE_INDEXED( \ - position, setPosition, YGEdgeLeft, "left"); \ - REBUILD_YG_FIELD_SWITCH_CASE_INDEXED( \ - position, setPosition, YGEdgeTop, "top"); \ - REBUILD_YG_FIELD_SWITCH_CASE_INDEXED( \ - position, setPosition, YGEdgeRight, "right"); \ - REBUILD_YG_FIELD_SWITCH_CASE_INDEXED( \ - position, setPosition, YGEdgeBottom, "bottom"); \ - REBUILD_YG_FIELD_SWITCH_CASE_INDEXED( \ - position, setPosition, YGEdgeStart, "start"); \ - REBUILD_YG_FIELD_SWITCH_CASE_INDEXED( \ - position, setPosition, YGEdgeEnd, "end"); \ - REBUILD_YG_FIELD_SWITCH_CASE_INDEXED( \ - position, setPosition, YGEdgeHorizontal, "insetInline"); \ - REBUILD_YG_FIELD_SWITCH_CASE_INDEXED( \ - position, setPosition, YGEdgeVertical, "insetBlock"); \ - REBUILD_YG_FIELD_SWITCH_CASE_INDEXED( \ - position, setPosition, YGEdgeAll, "inset"); +#define REBUILD_FIELD_YG_EDGES_POSITION() \ + REBUILD_YG_FIELD_SWITCH_CASE_INDEXED( \ + position, setPosition, yoga::Edge::Left, "left"); \ + REBUILD_YG_FIELD_SWITCH_CASE_INDEXED( \ + position, setPosition, yoga::Edge::Top, "top"); \ + REBUILD_YG_FIELD_SWITCH_CASE_INDEXED( \ + position, setPosition, yoga::Edge::Right, "right"); \ + REBUILD_YG_FIELD_SWITCH_CASE_INDEXED( \ + position, setPosition, yoga::Edge::Bottom, "bottom"); \ + REBUILD_YG_FIELD_SWITCH_CASE_INDEXED( \ + position, setPosition, yoga::Edge::Start, "start"); \ + REBUILD_YG_FIELD_SWITCH_CASE_INDEXED( \ + position, setPosition, yoga::Edge::End, "end"); \ + REBUILD_YG_FIELD_SWITCH_CASE_INDEXED( \ + position, setPosition, yoga::Edge::Horizontal, "insetInline"); \ + REBUILD_YG_FIELD_SWITCH_CASE_INDEXED( \ + position, setPosition, yoga::Edge::Vertical, "insetBlock"); \ + REBUILD_YG_FIELD_SWITCH_CASE_INDEXED( \ + position, setPosition, yoga::Edge::All, "inset"); void YogaStylableProps::setProp( const PropsParserContext& context, @@ -234,148 +234,148 @@ SharedDebugStringConvertibleList YogaStylableProps::getDebugProps() const { "flexBasis", yogaStyle.flexBasis(), defaultYogaStyle.flexBasis()), debugStringConvertibleItem( "marginLeft", - yogaStyle.margin(YGEdgeLeft), - defaultYogaStyle.margin(YGEdgeLeft)), + yogaStyle.margin(yoga::Edge::Left), + defaultYogaStyle.margin(yoga::Edge::Left)), debugStringConvertibleItem( "marginTop", - yogaStyle.margin(YGEdgeTop), - defaultYogaStyle.margin(YGEdgeTop)), + yogaStyle.margin(yoga::Edge::Top), + defaultYogaStyle.margin(yoga::Edge::Top)), debugStringConvertibleItem( "marginRight", - yogaStyle.margin(YGEdgeRight), - defaultYogaStyle.margin(YGEdgeRight)), + yogaStyle.margin(yoga::Edge::Right), + defaultYogaStyle.margin(yoga::Edge::Right)), debugStringConvertibleItem( "marginBottom", - yogaStyle.margin(YGEdgeBottom), - defaultYogaStyle.margin(YGEdgeBottom)), + yogaStyle.margin(yoga::Edge::Bottom), + defaultYogaStyle.margin(yoga::Edge::Bottom)), debugStringConvertibleItem( "marginStart", - yogaStyle.margin(YGEdgeStart), - defaultYogaStyle.margin(YGEdgeStart)), + yogaStyle.margin(yoga::Edge::Start), + defaultYogaStyle.margin(yoga::Edge::Start)), debugStringConvertibleItem( "marginEnd", - yogaStyle.margin(YGEdgeEnd), - defaultYogaStyle.margin(YGEdgeEnd)), + yogaStyle.margin(yoga::Edge::End), + defaultYogaStyle.margin(yoga::Edge::End)), debugStringConvertibleItem( "marginHorizontal", - yogaStyle.margin(YGEdgeHorizontal), - defaultYogaStyle.margin(YGEdgeHorizontal)), + yogaStyle.margin(yoga::Edge::Horizontal), + defaultYogaStyle.margin(yoga::Edge::Horizontal)), debugStringConvertibleItem( "marginVertical", - yogaStyle.margin(YGEdgeVertical), - defaultYogaStyle.margin(YGEdgeVertical)), + yogaStyle.margin(yoga::Edge::Vertical), + defaultYogaStyle.margin(yoga::Edge::Vertical)), debugStringConvertibleItem( "margin", - yogaStyle.margin(YGEdgeAll), - defaultYogaStyle.margin(YGEdgeAll)), + yogaStyle.margin(yoga::Edge::All), + defaultYogaStyle.margin(yoga::Edge::All)), debugStringConvertibleItem( "left", - yogaStyle.position(YGEdgeLeft), - defaultYogaStyle.position(YGEdgeLeft)), + yogaStyle.position(yoga::Edge::Left), + defaultYogaStyle.position(yoga::Edge::Left)), debugStringConvertibleItem( "top", - yogaStyle.position(YGEdgeTop), - defaultYogaStyle.position(YGEdgeTop)), + yogaStyle.position(yoga::Edge::Top), + defaultYogaStyle.position(yoga::Edge::Top)), debugStringConvertibleItem( "right", - yogaStyle.position(YGEdgeRight), - defaultYogaStyle.position(YGEdgeRight)), + yogaStyle.position(yoga::Edge::Right), + defaultYogaStyle.position(yoga::Edge::Right)), debugStringConvertibleItem( "bottom", - yogaStyle.position(YGEdgeBottom), - defaultYogaStyle.position(YGEdgeBottom)), + yogaStyle.position(yoga::Edge::Bottom), + defaultYogaStyle.position(yoga::Edge::Bottom)), debugStringConvertibleItem( "start", - yogaStyle.position(YGEdgeStart), - defaultYogaStyle.position(YGEdgeStart)), + yogaStyle.position(yoga::Edge::Start), + defaultYogaStyle.position(yoga::Edge::Start)), debugStringConvertibleItem( "end", - yogaStyle.position(YGEdgeEnd), - defaultYogaStyle.position(YGEdgeEnd)), + yogaStyle.position(yoga::Edge::End), + defaultYogaStyle.position(yoga::Edge::End)), debugStringConvertibleItem( "inseInline", - yogaStyle.position(YGEdgeHorizontal), - defaultYogaStyle.position(YGEdgeHorizontal)), + yogaStyle.position(yoga::Edge::Horizontal), + defaultYogaStyle.position(yoga::Edge::Horizontal)), debugStringConvertibleItem( "insetBlock", - yogaStyle.position(YGEdgeVertical), - defaultYogaStyle.position(YGEdgeVertical)), + yogaStyle.position(yoga::Edge::Vertical), + defaultYogaStyle.position(yoga::Edge::Vertical)), debugStringConvertibleItem( "inset", - yogaStyle.position(YGEdgeAll), - defaultYogaStyle.position(YGEdgeAll)), + yogaStyle.position(yoga::Edge::All), + defaultYogaStyle.position(yoga::Edge::All)), debugStringConvertibleItem( "paddingLeft", - yogaStyle.padding(YGEdgeLeft), - defaultYogaStyle.padding(YGEdgeLeft)), + yogaStyle.padding(yoga::Edge::Left), + defaultYogaStyle.padding(yoga::Edge::Left)), debugStringConvertibleItem( "paddingTop", - yogaStyle.padding(YGEdgeTop), - defaultYogaStyle.padding(YGEdgeTop)), + yogaStyle.padding(yoga::Edge::Top), + defaultYogaStyle.padding(yoga::Edge::Top)), debugStringConvertibleItem( "paddingRight", - yogaStyle.padding(YGEdgeRight), - defaultYogaStyle.padding(YGEdgeRight)), + yogaStyle.padding(yoga::Edge::Right), + defaultYogaStyle.padding(yoga::Edge::Right)), debugStringConvertibleItem( "paddingBottom", - yogaStyle.padding(YGEdgeBottom), - defaultYogaStyle.padding(YGEdgeBottom)), + yogaStyle.padding(yoga::Edge::Bottom), + defaultYogaStyle.padding(yoga::Edge::Bottom)), debugStringConvertibleItem( "paddingStart", - yogaStyle.padding(YGEdgeStart), - defaultYogaStyle.padding(YGEdgeStart)), + yogaStyle.padding(yoga::Edge::Start), + defaultYogaStyle.padding(yoga::Edge::Start)), debugStringConvertibleItem( "paddingEnd", - yogaStyle.padding(YGEdgeEnd), - defaultYogaStyle.padding(YGEdgeEnd)), + yogaStyle.padding(yoga::Edge::End), + defaultYogaStyle.padding(yoga::Edge::End)), debugStringConvertibleItem( "paddingHorizontal", - yogaStyle.padding(YGEdgeHorizontal), - defaultYogaStyle.padding(YGEdgeHorizontal)), + yogaStyle.padding(yoga::Edge::Horizontal), + defaultYogaStyle.padding(yoga::Edge::Horizontal)), debugStringConvertibleItem( "paddingVertical", - yogaStyle.padding(YGEdgeVertical), - defaultYogaStyle.padding(YGEdgeVertical)), + yogaStyle.padding(yoga::Edge::Vertical), + defaultYogaStyle.padding(yoga::Edge::Vertical)), debugStringConvertibleItem( "padding", - yogaStyle.padding(YGEdgeAll), - defaultYogaStyle.padding(YGEdgeAll)), + yogaStyle.padding(yoga::Edge::All), + defaultYogaStyle.padding(yoga::Edge::All)), debugStringConvertibleItem( "borderLeftWidth", - yogaStyle.border(YGEdgeLeft), - defaultYogaStyle.border(YGEdgeLeft)), + yogaStyle.border(yoga::Edge::Left), + defaultYogaStyle.border(yoga::Edge::Left)), debugStringConvertibleItem( "borderTopWidth", - yogaStyle.border(YGEdgeTop), - defaultYogaStyle.border(YGEdgeTop)), + yogaStyle.border(yoga::Edge::Top), + defaultYogaStyle.border(yoga::Edge::Top)), debugStringConvertibleItem( "borderRightWidth", - yogaStyle.border(YGEdgeRight), - defaultYogaStyle.border(YGEdgeRight)), + yogaStyle.border(yoga::Edge::Right), + defaultYogaStyle.border(yoga::Edge::Right)), debugStringConvertibleItem( "borderBottomWidth", - yogaStyle.border(YGEdgeBottom), - defaultYogaStyle.border(YGEdgeBottom)), + yogaStyle.border(yoga::Edge::Bottom), + defaultYogaStyle.border(yoga::Edge::Bottom)), debugStringConvertibleItem( "borderStartWidth", - yogaStyle.border(YGEdgeStart), - defaultYogaStyle.border(YGEdgeStart)), + yogaStyle.border(yoga::Edge::Start), + defaultYogaStyle.border(yoga::Edge::Start)), debugStringConvertibleItem( "borderEndWidth", - yogaStyle.border(YGEdgeEnd), - defaultYogaStyle.border(YGEdgeEnd)), + yogaStyle.border(yoga::Edge::End), + defaultYogaStyle.border(yoga::Edge::End)), debugStringConvertibleItem( "borderHorizontalWidth", - yogaStyle.border(YGEdgeHorizontal), - defaultYogaStyle.border(YGEdgeHorizontal)), + yogaStyle.border(yoga::Edge::Horizontal), + defaultYogaStyle.border(yoga::Edge::Horizontal)), debugStringConvertibleItem( "borderVerticalWidth", - yogaStyle.border(YGEdgeVertical), - defaultYogaStyle.border(YGEdgeVertical)), + yogaStyle.border(yoga::Edge::Vertical), + defaultYogaStyle.border(yoga::Edge::Vertical)), debugStringConvertibleItem( "bordeWidth", - yogaStyle.border(YGEdgeAll), - defaultYogaStyle.border(YGEdgeAll)), + yogaStyle.border(yoga::Edge::All), + defaultYogaStyle.border(yoga::Edge::All)), debugStringConvertibleItem( "width", yogaStyle.dimension(yoga::Dimension::Width), diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/platform/android/react/renderer/components/view/YogaStylablePropsMapBuffer.cpp b/packages/react-native/ReactCommon/react/renderer/components/view/platform/android/react/renderer/components/view/YogaStylablePropsMapBuffer.cpp index f23fccf8913738..20474d7ec37a4f 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/platform/android/react/renderer/components/view/YogaStylablePropsMapBuffer.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/view/platform/android/react/renderer/components/view/YogaStylablePropsMapBuffer.cpp @@ -16,25 +16,33 @@ namespace facebook::react { MapBuffer convertBorderWidths(const yoga::Style& style) { MapBufferBuilder builder(7); putOptionalFloat( - builder, EDGE_TOP, optionalFloatFromYogaValue(style.border(YGEdgeTop))); + builder, + EDGE_TOP, + optionalFloatFromYogaValue(style.border(yoga::Edge::Top))); putOptionalFloat( builder, EDGE_RIGHT, - optionalFloatFromYogaValue(style.border(YGEdgeRight))); + optionalFloatFromYogaValue(style.border(yoga::Edge::Right))); putOptionalFloat( builder, EDGE_BOTTOM, - optionalFloatFromYogaValue(style.border(YGEdgeBottom))); + optionalFloatFromYogaValue(style.border(yoga::Edge::Bottom))); putOptionalFloat( - builder, EDGE_LEFT, optionalFloatFromYogaValue(style.border(YGEdgeLeft))); + builder, + EDGE_LEFT, + optionalFloatFromYogaValue(style.border(yoga::Edge::Left))); putOptionalFloat( builder, EDGE_START, - optionalFloatFromYogaValue(style.border(YGEdgeStart))); + optionalFloatFromYogaValue(style.border(yoga::Edge::Start))); putOptionalFloat( - builder, EDGE_END, optionalFloatFromYogaValue(style.border(YGEdgeEnd))); + builder, + EDGE_END, + optionalFloatFromYogaValue(style.border(yoga::Edge::End))); putOptionalFloat( - builder, EDGE_ALL, optionalFloatFromYogaValue(style.border(YGEdgeAll))); + builder, + EDGE_ALL, + optionalFloatFromYogaValue(style.border(yoga::Edge::All))); return builder.build(); } @@ -62,8 +70,7 @@ void YogaStylableProps::propsDiffMapBuffer( bool areBordersEqual = true; for (auto edge : yoga::ordinals()) { - if (oldStyle.border(yoga::unscopedEnum(edge)) != - newStyle.border(yoga::unscopedEnum(edge))) { + if (oldStyle.border(edge) != newStyle.border(edge)) { areBordersEqual = false; break; } diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/propsConversions.h b/packages/react-native/ReactCommon/react/renderer/components/view/propsConversions.h index 13af58193c4289..529f3236454a2f 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/propsConversions.h +++ b/packages/react-native/ReactCommon/react/renderer/components/view/propsConversions.h @@ -101,247 +101,247 @@ static inline yoga::Style convertRawProp( yogaStyle.flexBasis()); yogaStyle.setMargin( - YGEdgeLeft, + yoga::Edge::Left, convertRawProp( context, rawProps, "marginLeft", - sourceValue.margin(YGEdgeLeft), - yogaStyle.margin(YGEdgeLeft))); + sourceValue.margin(yoga::Edge::Left), + yogaStyle.margin(yoga::Edge::Left))); yogaStyle.setMargin( - YGEdgeTop, + yoga::Edge::Top, convertRawProp( context, rawProps, "marginTop", - sourceValue.margin(YGEdgeTop), - yogaStyle.margin(YGEdgeTop))); + sourceValue.margin(yoga::Edge::Top), + yogaStyle.margin(yoga::Edge::Top))); yogaStyle.setMargin( - YGEdgeRight, + yoga::Edge::Right, convertRawProp( context, rawProps, "marginRight", - sourceValue.margin(YGEdgeRight), - yogaStyle.margin(YGEdgeRight))); + sourceValue.margin(yoga::Edge::Right), + yogaStyle.margin(yoga::Edge::Right))); yogaStyle.setMargin( - YGEdgeBottom, + yoga::Edge::Bottom, convertRawProp( context, rawProps, "marginBottom", - sourceValue.margin(YGEdgeBottom), - yogaStyle.margin(YGEdgeBottom))); + sourceValue.margin(yoga::Edge::Bottom), + yogaStyle.margin(yoga::Edge::Bottom))); yogaStyle.setMargin( - YGEdgeStart, + yoga::Edge::Start, convertRawProp( context, rawProps, "marginStart", - sourceValue.margin(YGEdgeStart), - yogaStyle.margin(YGEdgeStart))); + sourceValue.margin(yoga::Edge::Start), + yogaStyle.margin(yoga::Edge::Start))); yogaStyle.setMargin( - YGEdgeEnd, + yoga::Edge::End, convertRawProp( context, rawProps, "marginEnd", - sourceValue.margin(YGEdgeEnd), - yogaStyle.margin(YGEdgeEnd))); + sourceValue.margin(yoga::Edge::End), + yogaStyle.margin(yoga::Edge::End))); yogaStyle.setMargin( - YGEdgeHorizontal, + yoga::Edge::Horizontal, convertRawProp( context, rawProps, "marginHorizontal", - sourceValue.margin(YGEdgeHorizontal), - yogaStyle.margin(YGEdgeHorizontal))); + sourceValue.margin(yoga::Edge::Horizontal), + yogaStyle.margin(yoga::Edge::Horizontal))); yogaStyle.setMargin( - YGEdgeVertical, + yoga::Edge::Vertical, convertRawProp( context, rawProps, "marginVertical", - sourceValue.margin(YGEdgeVertical), - yogaStyle.margin(YGEdgeVertical))); + sourceValue.margin(yoga::Edge::Vertical), + yogaStyle.margin(yoga::Edge::Vertical))); yogaStyle.setMargin( - YGEdgeAll, + yoga::Edge::All, convertRawProp( context, rawProps, "margin", - sourceValue.margin(YGEdgeAll), - yogaStyle.margin(YGEdgeAll))); + sourceValue.margin(yoga::Edge::All), + yogaStyle.margin(yoga::Edge::All))); yogaStyle.setPosition( - YGEdgeLeft, + yoga::Edge::Left, convertRawProp( context, rawProps, "left", - sourceValue.position(YGEdgeLeft), - yogaStyle.position(YGEdgeLeft))); + sourceValue.position(yoga::Edge::Left), + yogaStyle.position(yoga::Edge::Left))); yogaStyle.setPosition( - YGEdgeTop, + yoga::Edge::Top, convertRawProp( context, rawProps, "top", - sourceValue.position(YGEdgeTop), - yogaStyle.position(YGEdgeTop))); + sourceValue.position(yoga::Edge::Top), + yogaStyle.position(yoga::Edge::Top))); yogaStyle.setPosition( - YGEdgeRight, + yoga::Edge::Right, convertRawProp( context, rawProps, "right", - sourceValue.position(YGEdgeRight), - yogaStyle.position(YGEdgeRight))); + sourceValue.position(yoga::Edge::Right), + yogaStyle.position(yoga::Edge::Right))); yogaStyle.setPosition( - YGEdgeBottom, + yoga::Edge::Bottom, convertRawProp( context, rawProps, "bottom", - sourceValue.position(YGEdgeBottom), - yogaStyle.position(YGEdgeBottom))); + sourceValue.position(yoga::Edge::Bottom), + yogaStyle.position(yoga::Edge::Bottom))); yogaStyle.setPosition( - YGEdgeStart, + yoga::Edge::Start, convertRawProp( context, rawProps, "start", - sourceValue.position(YGEdgeStart), - yogaStyle.position(YGEdgeStart))); + sourceValue.position(yoga::Edge::Start), + yogaStyle.position(yoga::Edge::Start))); yogaStyle.setPosition( - YGEdgeEnd, + yoga::Edge::End, convertRawProp( context, rawProps, "end", - sourceValue.position(YGEdgeEnd), - yogaStyle.position(YGEdgeEnd))); + sourceValue.position(yoga::Edge::End), + yogaStyle.position(yoga::Edge::End))); yogaStyle.setPosition( - YGEdgeHorizontal, + yoga::Edge::Horizontal, convertRawProp( context, rawProps, "insetInline", - sourceValue.position(YGEdgeHorizontal), - yogaStyle.position(YGEdgeHorizontal))); + sourceValue.position(yoga::Edge::Horizontal), + yogaStyle.position(yoga::Edge::Horizontal))); yogaStyle.setPosition( - YGEdgeVertical, + yoga::Edge::Vertical, convertRawProp( context, rawProps, "insetBlock", - sourceValue.position(YGEdgeVertical), - yogaStyle.position(YGEdgeVertical))); + sourceValue.position(yoga::Edge::Vertical), + yogaStyle.position(yoga::Edge::Vertical))); yogaStyle.setPosition( - YGEdgeAll, + yoga::Edge::All, convertRawProp( context, rawProps, "inset", - sourceValue.position(YGEdgeAll), - yogaStyle.position(YGEdgeAll))); + sourceValue.position(yoga::Edge::All), + yogaStyle.position(yoga::Edge::All))); yogaStyle.setPadding( - YGEdgeLeft, + yoga::Edge::Left, convertRawProp( context, rawProps, "paddingLeft", - sourceValue.padding(YGEdgeLeft), - yogaStyle.padding(YGEdgeLeft))); + sourceValue.padding(yoga::Edge::Left), + yogaStyle.padding(yoga::Edge::Left))); yogaStyle.setPadding( - YGEdgeTop, + yoga::Edge::Top, convertRawProp( context, rawProps, "paddingTop", - sourceValue.padding(YGEdgeTop), - yogaStyle.padding(YGEdgeTop))); + sourceValue.padding(yoga::Edge::Top), + yogaStyle.padding(yoga::Edge::Top))); yogaStyle.setPadding( - YGEdgeRight, + yoga::Edge::Right, convertRawProp( context, rawProps, "paddingRight", - sourceValue.padding(YGEdgeRight), - yogaStyle.padding(YGEdgeRight))); + sourceValue.padding(yoga::Edge::Right), + yogaStyle.padding(yoga::Edge::Right))); yogaStyle.setPadding( - YGEdgeBottom, + yoga::Edge::Bottom, convertRawProp( context, rawProps, "paddingBottom", - sourceValue.padding(YGEdgeBottom), - yogaStyle.padding(YGEdgeBottom))); + sourceValue.padding(yoga::Edge::Bottom), + yogaStyle.padding(yoga::Edge::Bottom))); yogaStyle.setPadding( - YGEdgeStart, + yoga::Edge::Start, convertRawProp( context, rawProps, "paddingStart", - sourceValue.padding(YGEdgeStart), - yogaStyle.padding(YGEdgeStart))); + sourceValue.padding(yoga::Edge::Start), + yogaStyle.padding(yoga::Edge::Start))); yogaStyle.setPadding( - YGEdgeEnd, + yoga::Edge::End, convertRawProp( context, rawProps, "paddingEnd", - sourceValue.padding(YGEdgeEnd), - yogaStyle.padding(YGEdgeEnd))); + sourceValue.padding(yoga::Edge::End), + yogaStyle.padding(yoga::Edge::End))); yogaStyle.setPadding( - YGEdgeHorizontal, + yoga::Edge::Horizontal, convertRawProp( context, rawProps, "paddingHorizontal", - sourceValue.padding(YGEdgeHorizontal), - yogaStyle.padding(YGEdgeHorizontal))); + sourceValue.padding(yoga::Edge::Horizontal), + yogaStyle.padding(yoga::Edge::Horizontal))); yogaStyle.setPadding( - YGEdgeVertical, + yoga::Edge::Vertical, convertRawProp( context, rawProps, "paddingVertical", - sourceValue.padding(YGEdgeVertical), - yogaStyle.padding(YGEdgeVertical))); + sourceValue.padding(yoga::Edge::Vertical), + yogaStyle.padding(yoga::Edge::Vertical))); yogaStyle.setPadding( - YGEdgeAll, + yoga::Edge::All, convertRawProp( context, rawProps, "padding", - sourceValue.padding(YGEdgeAll), - yogaStyle.padding(YGEdgeAll))); + sourceValue.padding(yoga::Edge::All), + yogaStyle.padding(yoga::Edge::All))); yogaStyle.setGap( yoga::Gutter::Row, @@ -371,85 +371,85 @@ static inline yoga::Style convertRawProp( yogaStyle.gap(yoga::Gutter::All))); yogaStyle.setBorder( - YGEdgeLeft, + yoga::Edge::Left, convertRawProp( context, rawProps, "borderLeftWidth", - sourceValue.border(YGEdgeLeft), - yogaStyle.border(YGEdgeLeft))); + sourceValue.border(yoga::Edge::Left), + yogaStyle.border(yoga::Edge::Left))); yogaStyle.setBorder( - YGEdgeTop, + yoga::Edge::Top, convertRawProp( context, rawProps, "borderTopWidth", - sourceValue.border(YGEdgeTop), - yogaStyle.border(YGEdgeTop))); + sourceValue.border(yoga::Edge::Top), + yogaStyle.border(yoga::Edge::Top))); yogaStyle.setBorder( - YGEdgeRight, + yoga::Edge::Right, convertRawProp( context, rawProps, "borderRightWidth", - sourceValue.border(YGEdgeRight), - yogaStyle.border(YGEdgeRight))); + sourceValue.border(yoga::Edge::Right), + yogaStyle.border(yoga::Edge::Right))); yogaStyle.setBorder( - YGEdgeBottom, + yoga::Edge::Bottom, convertRawProp( context, rawProps, "borderBottomWidth", - sourceValue.border(YGEdgeBottom), - yogaStyle.border(YGEdgeBottom))); + sourceValue.border(yoga::Edge::Bottom), + yogaStyle.border(yoga::Edge::Bottom))); yogaStyle.setBorder( - YGEdgeStart, + yoga::Edge::Start, convertRawProp( context, rawProps, "borderStartWidth", - sourceValue.border(YGEdgeStart), - yogaStyle.border(YGEdgeStart))); + sourceValue.border(yoga::Edge::Start), + yogaStyle.border(yoga::Edge::Start))); yogaStyle.setBorder( - YGEdgeEnd, + yoga::Edge::End, convertRawProp( context, rawProps, "borderEndWidth", - sourceValue.border(YGEdgeEnd), - yogaStyle.border(YGEdgeEnd))); + sourceValue.border(yoga::Edge::End), + yogaStyle.border(yoga::Edge::End))); yogaStyle.setBorder( - YGEdgeHorizontal, + yoga::Edge::Horizontal, convertRawProp( context, rawProps, "borderHorizontalWidth", - sourceValue.border(YGEdgeHorizontal), - yogaStyle.border(YGEdgeHorizontal))); + sourceValue.border(yoga::Edge::Horizontal), + yogaStyle.border(yoga::Edge::Horizontal))); yogaStyle.setBorder( - YGEdgeVertical, + yoga::Edge::Vertical, convertRawProp( context, rawProps, "borderVerticalWidth", - sourceValue.border(YGEdgeVertical), - yogaStyle.border(YGEdgeVertical))); + sourceValue.border(yoga::Edge::Vertical), + yogaStyle.border(yoga::Edge::Vertical))); yogaStyle.setBorder( - YGEdgeAll, + yoga::Edge::All, convertRawProp( context, rawProps, "borderWidth", - sourceValue.border(YGEdgeAll), - yogaStyle.border(YGEdgeAll))); + sourceValue.border(yoga::Edge::All), + yogaStyle.border(yoga::Edge::All))); yogaStyle.setDimension( yoga::Dimension::Width, diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/tests/LayoutTest.cpp b/packages/react-native/ReactCommon/react/renderer/components/view/tests/LayoutTest.cpp index 5e44e2d5044293..bdb879a974598e 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/tests/LayoutTest.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/view/tests/LayoutTest.cpp @@ -103,8 +103,8 @@ class LayoutTest : public ::testing::Test { auto &props = *sharedProps; auto &yogaStyle = props.yogaStyle; yogaStyle.positionType() = yoga::PositionType::Absolute; - yogaStyle.setPosition(YGEdgeLeft, yoga::value::points(10)); - yogaStyle.setPosition(YGEdgeTop, yoga::value::points(10)); + yogaStyle.setPosition(yoga::Edge::Left, yoga::value::points(10)); + yogaStyle.setPosition(yoga::Edge::Top, yoga::value::points(10)); yogaStyle.setDimension(yoga::Dimension::Width, yoga::value::points(30)); yogaStyle.setDimension(yoga::Dimension::Height, yoga::value::points(90)); @@ -136,8 +136,8 @@ class LayoutTest : public ::testing::Test { } yogaStyle.positionType() = yoga::PositionType::Absolute; - yogaStyle.setPosition(YGEdgeLeft, yoga::value::points(10)); - yogaStyle.setPosition(YGEdgeTop, yoga::value::points(10)); + yogaStyle.setPosition(yoga::Edge::Left, yoga::value::points(10)); + yogaStyle.setPosition(yoga::Edge::Top, yoga::value::points(10)); yogaStyle.setDimension(yoga::Dimension::Width, yoga::value::points(110)); yogaStyle.setDimension(yoga::Dimension::Height, yoga::value::points(20)); return sharedProps; @@ -151,8 +151,8 @@ class LayoutTest : public ::testing::Test { auto &props = *sharedProps; auto &yogaStyle = props.yogaStyle; yogaStyle.positionType() = yoga::PositionType::Absolute; - yogaStyle.setPosition(YGEdgeLeft, yoga::value::points(70)); - yogaStyle.setPosition(YGEdgeTop, yoga::value::points(-50)); + yogaStyle.setPosition(yoga::Edge::Left, yoga::value::points(70)); + yogaStyle.setPosition(yoga::Edge::Top, yoga::value::points(-50)); yogaStyle.setDimension(yoga::Dimension::Width, yoga::value::points(30)); yogaStyle.setDimension(yoga::Dimension::Height, yoga::value::points(60)); return sharedProps; @@ -166,8 +166,8 @@ class LayoutTest : public ::testing::Test { auto &props = *sharedProps; auto &yogaStyle = props.yogaStyle; yogaStyle.positionType() = yoga::PositionType::Absolute; - yogaStyle.setPosition(YGEdgeLeft, yoga::value::points(-60)); - yogaStyle.setPosition(YGEdgeTop, yoga::value::points(50)); + yogaStyle.setPosition(yoga::Edge::Left, yoga::value::points(-60)); + yogaStyle.setPosition(yoga::Edge::Top, yoga::value::points(50)); yogaStyle.setDimension(yoga::Dimension::Width, yoga::value::points(70)); yogaStyle.setDimension(yoga::Dimension::Height, yoga::value::points(20)); return sharedProps; diff --git a/packages/react-native/ReactCommon/react/renderer/mounting/tests/StackingContextTest.cpp b/packages/react-native/ReactCommon/react/renderer/mounting/tests/StackingContextTest.cpp index ae64dd3393dc34..f09dabda6d332e 100644 --- a/packages/react-native/ReactCommon/react/renderer/mounting/tests/StackingContextTest.cpp +++ b/packages/react-native/ReactCommon/react/renderer/mounting/tests/StackingContextTest.cpp @@ -251,8 +251,8 @@ TEST_F(StackingContextTest, mostPropsDoNotForceViewsToMaterialize) { mutateViewShadowNodeProps_(nodeAA_, [](ViewProps& props) { auto& yogaStyle = props.yogaStyle; - yogaStyle.setPadding(YGEdgeAll, yoga::value::points(42)); - yogaStyle.setMargin(YGEdgeAll, yoga::value::points(42)); + yogaStyle.setPadding(yoga::Edge::All, yoga::value::points(42)); + yogaStyle.setMargin(yoga::Edge::All, yoga::value::points(42)); yogaStyle.positionType() = yoga::PositionType::Absolute; props.shadowRadius = 42; props.shadowOffset = Size{42, 42}; @@ -262,7 +262,7 @@ TEST_F(StackingContextTest, mostPropsDoNotForceViewsToMaterialize) { mutateViewShadowNodeProps_(nodeBA_, [](ViewProps& props) { auto& yogaStyle = props.yogaStyle; props.zIndex = 42; - yogaStyle.setMargin(YGEdgeAll, yoga::value::points(42)); + yogaStyle.setMargin(yoga::Edge::All, yoga::value::points(42)); props.shadowColor = clearColor(); props.shadowOpacity = 0.42; }); diff --git a/packages/react-native/ReactCommon/yoga/yoga/YGNodeLayout.cpp b/packages/react-native/ReactCommon/yoga/yoga/YGNodeLayout.cpp index 39f67f9dc9792b..d2477f72cf21f2 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/YGNodeLayout.cpp +++ b/packages/react-native/ReactCommon/yoga/yoga/YGNodeLayout.cpp @@ -7,6 +7,7 @@ #include #include +#include #include using namespace facebook; @@ -15,50 +16,48 @@ using namespace facebook::yoga; namespace { template -float getResolvedLayoutProperty( - const YGNodeConstRef nodeRef, - const YGEdge edge) { +float getResolvedLayoutProperty(const YGNodeConstRef nodeRef, const Edge edge) { const auto node = resolveRef(nodeRef); yoga::assertFatalWithNode( node, - edge <= YGEdgeEnd, + edge <= Edge::End, "Cannot get layout properties of multi-edge shorthands"); - if (edge == YGEdgeStart) { + if (edge == Edge::Start) { if (node->getLayout().direction() == Direction::RTL) { - return (node->getLayout().*LayoutMember)[YGEdgeRight]; + return (node->getLayout().*LayoutMember)(Edge::Right); } else { - return (node->getLayout().*LayoutMember)[YGEdgeLeft]; + return (node->getLayout().*LayoutMember)(Edge::Left); } } - if (edge == YGEdgeEnd) { + if (edge == Edge::End) { if (node->getLayout().direction() == Direction::RTL) { - return (node->getLayout().*LayoutMember)[YGEdgeLeft]; + return (node->getLayout().*LayoutMember)(Edge::Left); } else { - return (node->getLayout().*LayoutMember)[YGEdgeRight]; + return (node->getLayout().*LayoutMember)(Edge::Right); } } - return (node->getLayout().*LayoutMember)[edge]; + return (node->getLayout().*LayoutMember)(edge); } } // namespace float YGNodeLayoutGetLeft(const YGNodeConstRef node) { - return resolveRef(node)->getLayout().position[YGEdgeLeft]; + return resolveRef(node)->getLayout().position(Edge::Left); } float YGNodeLayoutGetTop(const YGNodeConstRef node) { - return resolveRef(node)->getLayout().position[YGEdgeTop]; + return resolveRef(node)->getLayout().position(Edge::Top); } float YGNodeLayoutGetRight(const YGNodeConstRef node) { - return resolveRef(node)->getLayout().position[YGEdgeRight]; + return resolveRef(node)->getLayout().position(Edge::Right); } float YGNodeLayoutGetBottom(const YGNodeConstRef node) { - return resolveRef(node)->getLayout().position[YGEdgeBottom]; + return resolveRef(node)->getLayout().position(Edge::Bottom); } float YGNodeLayoutGetWidth(const YGNodeConstRef node) { @@ -78,13 +77,16 @@ bool YGNodeLayoutGetHadOverflow(const YGNodeConstRef node) { } float YGNodeLayoutGetMargin(YGNodeConstRef node, YGEdge edge) { - return getResolvedLayoutProperty<&LayoutResults::margin>(node, edge); + return getResolvedLayoutProperty<&LayoutResults::margin>( + node, scopedEnum(edge)); } float YGNodeLayoutGetBorder(YGNodeConstRef node, YGEdge edge) { - return getResolvedLayoutProperty<&LayoutResults::border>(node, edge); + return getResolvedLayoutProperty<&LayoutResults::border>( + node, scopedEnum(edge)); } float YGNodeLayoutGetPadding(YGNodeConstRef node, YGEdge edge) { - return getResolvedLayoutProperty<&LayoutResults::padding>(node, edge); + return getResolvedLayoutProperty<&LayoutResults::padding>( + node, scopedEnum(edge)); } diff --git a/packages/react-native/ReactCommon/yoga/yoga/YGNodeStyle.cpp b/packages/react-native/ReactCommon/yoga/yoga/YGNodeStyle.cpp index 6767e5e8e31969..c39372a33ac10c 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/YGNodeStyle.cpp +++ b/packages/react-native/ReactCommon/yoga/yoga/YGNodeStyle.cpp @@ -223,49 +223,49 @@ YGValue YGNodeStyleGetFlexBasis(const YGNodeConstRef node) { void YGNodeStyleSetPosition(YGNodeRef node, YGEdge edge, float points) { updateIndexedStyleProp<&Style::position, &Style::setPosition>( - node, edge, value::points(points)); + node, scopedEnum(edge), value::points(points)); } void YGNodeStyleSetPositionPercent(YGNodeRef node, YGEdge edge, float percent) { updateIndexedStyleProp<&Style::position, &Style::setPosition>( - node, edge, value::percent(percent)); + node, scopedEnum(edge), value::percent(percent)); } YGValue YGNodeStyleGetPosition(YGNodeConstRef node, YGEdge edge) { - return resolveRef(node)->getStyle().position(edge); + return resolveRef(node)->getStyle().position(scopedEnum(edge)); } void YGNodeStyleSetMargin(YGNodeRef node, YGEdge edge, float points) { updateIndexedStyleProp<&Style::margin, &Style::setMargin>( - node, edge, value::points(points)); + node, scopedEnum(edge), value::points(points)); } void YGNodeStyleSetMarginPercent(YGNodeRef node, YGEdge edge, float percent) { updateIndexedStyleProp<&Style::margin, &Style::setMargin>( - node, edge, value::percent(percent)); + node, scopedEnum(edge), value::percent(percent)); } void YGNodeStyleSetMarginAuto(YGNodeRef node, YGEdge edge) { updateIndexedStyleProp<&Style::margin, &Style::setMargin>( - node, edge, value::ofAuto()); + node, scopedEnum(edge), value::ofAuto()); } YGValue YGNodeStyleGetMargin(YGNodeConstRef node, YGEdge edge) { - return resolveRef(node)->getStyle().margin(edge); + return resolveRef(node)->getStyle().margin(scopedEnum(edge)); } void YGNodeStyleSetPadding(YGNodeRef node, YGEdge edge, float points) { updateIndexedStyleProp<&Style::padding, &Style::setPadding>( - node, edge, value::points(points)); + node, scopedEnum(edge), value::points(points)); } void YGNodeStyleSetPaddingPercent(YGNodeRef node, YGEdge edge, float percent) { updateIndexedStyleProp<&Style::padding, &Style::setPadding>( - node, edge, value::percent(percent)); + node, scopedEnum(edge), value::percent(percent)); } YGValue YGNodeStyleGetPadding(YGNodeConstRef node, YGEdge edge) { - return resolveRef(node)->getStyle().padding(edge); + return resolveRef(node)->getStyle().padding(scopedEnum(edge)); } void YGNodeStyleSetBorder( @@ -273,11 +273,11 @@ void YGNodeStyleSetBorder( const YGEdge edge, const float border) { updateIndexedStyleProp<&Style::border, &Style::setBorder>( - node, edge, value::points(border)); + node, scopedEnum(edge), value::points(border)); } float YGNodeStyleGetBorder(const YGNodeConstRef node, const YGEdge edge) { - auto border = resolveRef(node)->getStyle().border(edge); + auto border = resolveRef(node)->getStyle().border(scopedEnum(edge)); if (border.isUndefined() || border.isAuto()) { return YGUndefined; } diff --git a/packages/react-native/ReactCommon/yoga/yoga/algorithm/Baseline.cpp b/packages/react-native/ReactCommon/yoga/yoga/algorithm/Baseline.cpp index aea316c03526f7..a86b9b28a48db1 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/algorithm/Baseline.cpp +++ b/packages/react-native/ReactCommon/yoga/yoga/algorithm/Baseline.cpp @@ -57,7 +57,7 @@ float calculateBaseline(const yoga::Node* node) { } const float baseline = calculateBaseline(baselineChild); - return baseline + baselineChild->getLayout().position[YGEdgeTop]; + return baseline + baselineChild->getLayout().position(Edge::Top); } bool isBaselineLayout(const yoga::Node* node) { diff --git a/packages/react-native/ReactCommon/yoga/yoga/algorithm/CalculateLayout.cpp b/packages/react-native/ReactCommon/yoga/yoga/algorithm/CalculateLayout.cpp index f066dbdfc45213..fe97b4e1166482 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/algorithm/CalculateLayout.cpp +++ b/packages/react-native/ReactCommon/yoga/yoga/algorithm/CalculateLayout.cpp @@ -89,7 +89,7 @@ static void setChildTrailingPosition( const float size = child->getLayout().measuredDimension(dimension(axis)); child->setLayoutPosition( node->getLayout().measuredDimension(dimension(axis)) - size - - child->getLayout().position[flexStartEdge(axis)], + child->getLayout().position(flexStartEdge(axis)), flexEndEdge(axis)); } @@ -553,12 +553,13 @@ static void measureNodeWithMeasureFunc( availableHeight = YGUndefined; } - const auto& padding = node->getLayout().padding; - const auto& border = node->getLayout().border; - const float paddingAndBorderAxisRow = padding[YGEdgeLeft] + - padding[YGEdgeRight] + border[YGEdgeLeft] + border[YGEdgeRight]; - const float paddingAndBorderAxisColumn = padding[YGEdgeTop] + - padding[YGEdgeBottom] + border[YGEdgeTop] + border[YGEdgeBottom]; + const auto& layout = node->getLayout(); + const float paddingAndBorderAxisRow = layout.padding(Edge::Left) + + layout.padding(Edge::Right) + layout.border(Edge::Left) + + layout.border(Edge::Right); + const float paddingAndBorderAxisColumn = layout.padding(Edge::Top) + + layout.padding(Edge::Bottom) + layout.border(Edge::Top) + + layout.border(Edge::Bottom); // We want to make sure we don't call measure with negative size const float innerWidth = yoga::isUndefined(availableWidth) @@ -643,14 +644,13 @@ static void measureNodeWithoutChildren( const SizingMode heightSizingMode, const float ownerWidth, const float ownerHeight) { - const auto& padding = node->getLayout().padding; - const auto& border = node->getLayout().border; + const auto& layout = node->getLayout(); float width = availableWidth; if (widthSizingMode == SizingMode::MaxContent || widthSizingMode == SizingMode::FitContent) { - width = padding[YGEdgeLeft] + padding[YGEdgeRight] + border[YGEdgeLeft] + - border[YGEdgeRight]; + width = layout.padding(Edge::Left) + layout.padding(Edge::Right) + + layout.border(Edge::Left) + layout.border(Edge::Right); } node->setLayoutMeasuredDimension( boundAxis(node, FlexDirection::Row, width, ownerWidth, ownerWidth), @@ -659,8 +659,8 @@ static void measureNodeWithoutChildren( float height = availableHeight; if (heightSizingMode == SizingMode::MaxContent || heightSizingMode == SizingMode::FitContent) { - height = padding[YGEdgeTop] + padding[YGEdgeBottom] + border[YGEdgeTop] + - border[YGEdgeBottom]; + height = layout.padding(Edge::Top) + layout.padding(Edge::Bottom) + + layout.border(Edge::Top) + layout.border(Edge::Bottom); } node->setLayoutMeasuredDimension( boundAxis(node, FlexDirection::Column, height, ownerHeight, ownerWidth), @@ -1330,7 +1330,7 @@ static void justifyMainAxis( if (performLayout) { child->setLayoutPosition( - childLayout.position[flexStartEdge(mainAxis)] + + childLayout.position(flexStartEdge(mainAxis)) + flexLine.layout.mainDim, flexStartEdge(mainAxis)); } @@ -1386,7 +1386,7 @@ static void justifyMainAxis( } } else if (performLayout) { child->setLayoutPosition( - childLayout.position[flexStartEdge(mainAxis)] + + childLayout.position(flexStartEdge(mainAxis)) + node->getInlineStartBorder(mainAxis, direction) + leadingMainDim, flexStartEdge(mainAxis)); @@ -1497,9 +1497,8 @@ static void calculateLayoutImpl( const FlexDirection flexColumnDirection = resolveDirection(FlexDirection::Column, direction); - const YGEdge startEdge = - direction == Direction::LTR ? YGEdgeLeft : YGEdgeRight; - const YGEdge endEdge = direction == Direction::LTR ? YGEdgeRight : YGEdgeLeft; + const Edge startEdge = direction == Direction::LTR ? Edge::Left : Edge::Right; + const Edge endEdge = direction == Direction::LTR ? Edge::Right : Edge::Left; const float marginRowLeading = node->getInlineStartMargin(flexRowDirection, direction, ownerWidth); @@ -1509,10 +1508,10 @@ static void calculateLayoutImpl( node->setLayoutMargin(marginRowTrailing, endEdge); const float marginColumnLeading = node->getInlineStartMargin(flexColumnDirection, direction, ownerWidth); - node->setLayoutMargin(marginColumnLeading, YGEdgeTop); + node->setLayoutMargin(marginColumnLeading, Edge::Top); const float marginColumnTrailing = node->getInlineEndMargin(flexColumnDirection, direction, ownerWidth); - node->setLayoutMargin(marginColumnTrailing, YGEdgeBottom); + node->setLayoutMargin(marginColumnTrailing, Edge::Bottom); const float marginAxisRow = marginRowLeading + marginRowTrailing; const float marginAxisColumn = marginColumnLeading + marginColumnTrailing; @@ -1522,9 +1521,9 @@ static void calculateLayoutImpl( node->setLayoutBorder( node->getInlineEndBorder(flexRowDirection, direction), endEdge); node->setLayoutBorder( - node->getInlineStartBorder(flexColumnDirection, direction), YGEdgeTop); + node->getInlineStartBorder(flexColumnDirection, direction), Edge::Top); node->setLayoutBorder( - node->getInlineEndBorder(flexColumnDirection, direction), YGEdgeBottom); + node->getInlineEndBorder(flexColumnDirection, direction), Edge::Bottom); node->setLayoutPadding( node->getInlineStartPadding(flexRowDirection, direction, ownerWidth), @@ -1534,10 +1533,10 @@ static void calculateLayoutImpl( endEdge); node->setLayoutPadding( node->getInlineStartPadding(flexColumnDirection, direction, ownerWidth), - YGEdgeTop); + Edge::Top); node->setLayoutPadding( node->getInlineEndPadding(flexColumnDirection, direction, ownerWidth), - YGEdgeBottom); + Edge::Bottom); if (node->hasMeasureFunc()) { measureNodeWithMeasureFunc( @@ -1868,7 +1867,7 @@ static void calculateLayoutImpl( // default to border + margin if (!isChildLeadingPosDefined || yoga::isUndefined( - child->getLayout().position[flexStartEdge(crossAxis)])) { + child->getLayout().position(flexStartEdge(crossAxis)))) { child->setLayoutPosition( node->getInlineStartBorder(crossAxis, direction) + child->getInlineStartMargin( @@ -1981,7 +1980,7 @@ static void calculateLayoutImpl( } // And we apply the position child->setLayoutPosition( - child->getLayout().position[flexStartEdge(crossAxis)] + + child->getLayout().position(flexStartEdge(crossAxis)) + totalLineCrossDim + leadingCrossDim, flexStartEdge(crossAxis)); } @@ -2190,7 +2189,7 @@ static void calculateLayoutImpl( FlexDirection::Column, direction, availableInnerCrossDim), - YGEdgeTop); + Edge::Top); break; } @@ -2296,7 +2295,7 @@ static void calculateLayoutImpl( if (child->getStyle().positionType() != PositionType::Absolute) { child->setLayoutPosition( node->getLayout().measuredDimension(dimension(crossAxis)) - - child->getLayout().position[flexStartEdge(crossAxis)] - + child->getLayout().position(flexStartEdge(crossAxis)) - child->getLayout().measuredDimension(dimension(crossAxis)), flexStartEdge(crossAxis)); } diff --git a/packages/react-native/ReactCommon/yoga/yoga/algorithm/FlexDirection.h b/packages/react-native/ReactCommon/yoga/yoga/algorithm/FlexDirection.h index a8ee7586aeb849..5bc5880a4dd886 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/algorithm/FlexDirection.h +++ b/packages/react-native/ReactCommon/yoga/yoga/algorithm/FlexDirection.h @@ -12,6 +12,7 @@ #include #include #include +#include #include namespace facebook::yoga { @@ -48,80 +49,80 @@ inline FlexDirection resolveCrossDirection( : FlexDirection::Column; } -inline YGEdge flexStartEdge(const FlexDirection flexDirection) { +inline Edge flexStartEdge(const FlexDirection flexDirection) { switch (flexDirection) { case FlexDirection::Column: - return YGEdgeTop; + return Edge::Top; case FlexDirection::ColumnReverse: - return YGEdgeBottom; + return Edge::Bottom; case FlexDirection::Row: - return YGEdgeLeft; + return Edge::Left; case FlexDirection::RowReverse: - return YGEdgeRight; + return Edge::Right; } fatalWithMessage("Invalid FlexDirection"); } -inline YGEdge flexEndEdge(const FlexDirection flexDirection) { +inline Edge flexEndEdge(const FlexDirection flexDirection) { switch (flexDirection) { case FlexDirection::Column: - return YGEdgeBottom; + return Edge::Bottom; case FlexDirection::ColumnReverse: - return YGEdgeTop; + return Edge::Top; case FlexDirection::Row: - return YGEdgeRight; + return Edge::Right; case FlexDirection::RowReverse: - return YGEdgeLeft; + return Edge::Left; } fatalWithMessage("Invalid FlexDirection"); } -inline YGEdge inlineStartEdge( +inline Edge inlineStartEdge( const FlexDirection flexDirection, const Direction direction) { if (isRow(flexDirection)) { - return direction == Direction::RTL ? YGEdgeRight : YGEdgeLeft; + return direction == Direction::RTL ? Edge::Right : Edge::Left; } - return YGEdgeTop; + return Edge::Top; } -inline YGEdge inlineEndEdge( +inline Edge inlineEndEdge( const FlexDirection flexDirection, const Direction direction) { if (isRow(flexDirection)) { - return direction == Direction::RTL ? YGEdgeLeft : YGEdgeRight; + return direction == Direction::RTL ? Edge::Left : Edge::Right; } - return YGEdgeBottom; + return Edge::Bottom; } /** - * The physical edges that YGEdgeStart and YGEdgeEnd correspond to (e.g. + * The physical edges that Edge::Start and Edge::End correspond to (e.g. * left/right) are soley dependent on the direction. However, there are cases * where we want the flex start/end edge (i.e. which edge is the start/end * for laying out flex items), which can be distinct from the corresponding * inline edge. In these cases we need to know which "relative edge" - * (YGEdgeStart/YGEdgeEnd) corresponds to the said flex start/end edge as these + * (Edge::Start/Edge::End) corresponds to the said flex start/end edge as these * relative edges can be used instead of physical ones when defining certain * attributes like border or padding. */ -inline YGEdge flexStartRelativeEdge( +inline Edge flexStartRelativeEdge( FlexDirection flexDirection, Direction direction) { - const YGEdge leadLayoutEdge = inlineStartEdge(flexDirection, direction); - const YGEdge leadFlexItemEdge = flexStartEdge(flexDirection); - return leadLayoutEdge == leadFlexItemEdge ? YGEdgeStart : YGEdgeEnd; + const Edge leadLayoutEdge = inlineStartEdge(flexDirection, direction); + const Edge leadFlexItemEdge = flexStartEdge(flexDirection); + return leadLayoutEdge == leadFlexItemEdge ? Edge::Start : Edge::End; } -inline YGEdge flexEndRelativeEdge( +inline Edge flexEndRelativeEdge( FlexDirection flexDirection, Direction direction) { - const YGEdge trailLayoutEdge = inlineEndEdge(flexDirection, direction); - const YGEdge trailFlexItemEdge = flexEndEdge(flexDirection); - return trailLayoutEdge == trailFlexItemEdge ? YGEdgeEnd : YGEdgeStart; + const Edge trailLayoutEdge = inlineEndEdge(flexDirection, direction); + const Edge trailFlexItemEdge = flexEndEdge(flexDirection); + return trailLayoutEdge == trailFlexItemEdge ? Edge::End : Edge::Start; } inline Dimension dimension(const FlexDirection flexDirection) { diff --git a/packages/react-native/ReactCommon/yoga/yoga/algorithm/PixelGrid.cpp b/packages/react-native/ReactCommon/yoga/yoga/algorithm/PixelGrid.cpp index 5e44c2cc8d40c6..b84cd7db090671 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/algorithm/PixelGrid.cpp +++ b/packages/react-native/ReactCommon/yoga/yoga/algorithm/PixelGrid.cpp @@ -68,8 +68,8 @@ void roundLayoutResultsToPixelGrid( const double absoluteTop) { const auto pointScaleFactor = node->getConfig()->getPointScaleFactor(); - const double nodeLeft = node->getLayout().position[YGEdgeLeft]; - const double nodeTop = node->getLayout().position[YGEdgeTop]; + const double nodeLeft = node->getLayout().position(Edge::Left); + const double nodeTop = node->getLayout().position(Edge::Top); const double nodeWidth = node->getLayout().dimension(Dimension::Width); const double nodeHeight = node->getLayout().dimension(Dimension::Height); @@ -87,11 +87,11 @@ void roundLayoutResultsToPixelGrid( node->setLayoutPosition( roundValueToPixelGrid(nodeLeft, pointScaleFactor, false, textRounding), - YGEdgeLeft); + Edge::Left); node->setLayoutPosition( roundValueToPixelGrid(nodeTop, pointScaleFactor, false, textRounding), - YGEdgeTop); + Edge::Top); // We multiply dimension by scale factor and if the result is close to the // whole number, we don't have any fraction To verify if the result is close diff --git a/packages/react-native/ReactCommon/yoga/yoga/debug/NodeToString.cpp b/packages/react-native/ReactCommon/yoga/yoga/debug/NodeToString.cpp index ef55ea1d215e9d..18e8aeec659b50 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/debug/NodeToString.cpp +++ b/packages/react-native/ReactCommon/yoga/yoga/debug/NodeToString.cpp @@ -9,8 +9,6 @@ #include -#include - #include #include #include @@ -85,7 +83,7 @@ static void appendEdges(std::string& base, const std::string& key, const Style& style) { for (auto edge : ordinals()) { std::string str = key + "-" + toString(edge); - appendNumberIfNotZero(base, str, (style.*Field)(unscopedEnum(edge))); + appendNumberIfNotZero(base, str, (style.*Field)(edge)); } } @@ -104,9 +102,9 @@ void nodeToString( appendFormattedString( str, "height: %g; ", node->getLayout().dimension(Dimension::Height)); appendFormattedString( - str, "top: %g; ", node->getLayout().position[YGEdgeTop]); + str, "top: %g; ", node->getLayout().position(Edge::Top)); appendFormattedString( - str, "left: %g;", node->getLayout().position[YGEdgeLeft]); + str, "left: %g;", node->getLayout().position(Edge::Left)); appendFormattedString(str, "\" "); } diff --git a/packages/react-native/ReactCommon/yoga/yoga/node/LayoutResults.cpp b/packages/react-native/ReactCommon/yoga/yoga/node/LayoutResults.cpp index d050bfdc73fec6..fd70870e65b3a7 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/node/LayoutResults.cpp +++ b/packages/react-native/ReactCommon/yoga/yoga/node/LayoutResults.cpp @@ -13,11 +13,11 @@ namespace facebook::yoga { bool LayoutResults::operator==(LayoutResults layout) const { - bool isEqual = yoga::inexactEquals(position, layout.position) && + bool isEqual = yoga::inexactEquals(position_, layout.position_) && yoga::inexactEquals(dimensions_, layout.dimensions_) && - yoga::inexactEquals(margin, layout.margin) && - yoga::inexactEquals(border, layout.border) && - yoga::inexactEquals(padding, layout.padding) && + yoga::inexactEquals(margin_, layout.margin_) && + yoga::inexactEquals(border_, layout.border_) && + yoga::inexactEquals(padding_, layout.padding_) && direction() == layout.direction() && hadOverflow() == layout.hadOverflow() && lastOwnerDirection == layout.lastOwnerDirection && diff --git a/packages/react-native/ReactCommon/yoga/yoga/node/LayoutResults.h b/packages/react-native/ReactCommon/yoga/yoga/node/LayoutResults.h index 8b324e6454bf38..f7cf8b8cf47858 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/node/LayoutResults.h +++ b/packages/react-native/ReactCommon/yoga/yoga/node/LayoutResults.h @@ -10,8 +10,10 @@ #include #include +#include #include #include +#include #include #include @@ -22,19 +24,6 @@ struct LayoutResults { // 98% of analyzed layouts require less than 8 entries. static constexpr int32_t MaxCachedMeasurements = 8; - std::array position = {}; - std::array margin = {}; - std::array border = {}; - std::array padding = {}; - - private: - Direction direction_ : bitCount() = Direction::Inherit; - bool hadOverflow_ : 1 = false; - - std::array dimensions_ = {{YGUndefined, YGUndefined}}; - std::array measuredDimensions_ = {{YGUndefined, YGUndefined}}; - - public: uint32_t computedFlexBasisGeneration = 0; FloatOptional computedFlexBasis = {}; @@ -80,10 +69,66 @@ struct LayoutResults { measuredDimensions_[yoga::to_underlying(axis)] = dimension; } + float position(Edge cardinalEdge) const { + assertCardinalEdge(cardinalEdge); + return position_[yoga::to_underlying(cardinalEdge)]; + } + + void setPosition(Edge cardinalEdge, float dimension) { + assertCardinalEdge(cardinalEdge); + position_[yoga::to_underlying(cardinalEdge)] = dimension; + } + + float margin(Edge cardinalEdge) const { + assertCardinalEdge(cardinalEdge); + return margin_[yoga::to_underlying(cardinalEdge)]; + } + + void setMargin(Edge cardinalEdge, float dimension) { + assertCardinalEdge(cardinalEdge); + margin_[yoga::to_underlying(cardinalEdge)] = dimension; + } + + float border(Edge cardinalEdge) const { + assertCardinalEdge(cardinalEdge); + return border_[yoga::to_underlying(cardinalEdge)]; + } + + void setBorder(Edge cardinalEdge, float dimension) { + assertCardinalEdge(cardinalEdge); + border_[yoga::to_underlying(cardinalEdge)] = dimension; + } + + float padding(Edge cardinalEdge) const { + assertCardinalEdge(cardinalEdge); + return padding_[yoga::to_underlying(cardinalEdge)]; + } + + void setPadding(Edge cardinalEdge, float dimension) { + assertCardinalEdge(cardinalEdge); + padding_[yoga::to_underlying(cardinalEdge)] = dimension; + } + bool operator==(LayoutResults layout) const; bool operator!=(LayoutResults layout) const { return !(*this == layout); } + + private: + static inline void assertCardinalEdge(Edge edge) { + assertFatal( + static_cast(edge) <= 3, "Edge must be top/left/bottom/right"); + } + + Direction direction_ : bitCount() = Direction::Inherit; + bool hadOverflow_ : 1 = false; + + std::array dimensions_ = {{YGUndefined, YGUndefined}}; + std::array measuredDimensions_ = {{YGUndefined, YGUndefined}}; + std::array position_ = {}; + std::array margin_ = {}; + std::array border_ = {}; + std::array padding_ = {}; }; } // namespace facebook::yoga diff --git a/packages/react-native/ReactCommon/yoga/yoga/node/Node.cpp b/packages/react-native/ReactCommon/yoga/yoga/node/Node.cpp index 0781b8e63ab44b..faf812e8cf1949 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/node/Node.cpp +++ b/packages/react-native/ReactCommon/yoga/yoga/node/Node.cpp @@ -58,31 +58,31 @@ void Node::print() { // TODO: Edge value resolution should be moved to `yoga::Style` template -Style::Length Node::computeEdgeValueForRow(YGEdge rowEdge, YGEdge edge) const { +Style::Length Node::computeEdgeValueForRow(Edge rowEdge, Edge edge) const { if ((style_.*Field)(rowEdge).isDefined()) { return (style_.*Field)(rowEdge); } else if ((style_.*Field)(edge).isDefined()) { return (style_.*Field)(edge); - } else if ((style_.*Field)(YGEdgeHorizontal).isDefined()) { - return (style_.*Field)(YGEdgeHorizontal); + } else if ((style_.*Field)(Edge::Horizontal).isDefined()) { + return (style_.*Field)(Edge::Horizontal); } else { - return (style_.*Field)(YGEdgeAll); + return (style_.*Field)(Edge::All); } } // TODO: Edge value resolution should be moved to `yoga::Style` template -Style::Length Node::computeEdgeValueForColumn(YGEdge edge) const { +Style::Length Node::computeEdgeValueForColumn(Edge edge) const { if ((style_.*Field)(edge).isDefined()) { return (style_.*Field)(edge); - } else if ((style_.*Field)(YGEdgeVertical).isDefined()) { - return (style_.*Field)(YGEdgeVertical); + } else if ((style_.*Field)(Edge::Vertical).isDefined()) { + return (style_.*Field)(Edge::Vertical); } else { - return (style_.*Field)(YGEdgeAll); + return (style_.*Field)(Edge::All); } } -YGEdge Node::getInlineStartEdgeUsingErrata( +Edge Node::getInlineStartEdgeUsingErrata( FlexDirection flexDirection, Direction direction) const { return hasErrata(Errata::StartingEndingEdgeFromFlexDirection) @@ -90,7 +90,7 @@ YGEdge Node::getInlineStartEdgeUsingErrata( : inlineStartEdge(flexDirection, direction); } -YGEdge Node::getInlineEndEdgeUsingErrata( +Edge Node::getInlineEndEdgeUsingErrata( FlexDirection flexDirection, Direction direction) const { return hasErrata(Errata::StartingEndingEdgeFromFlexDirection) @@ -99,9 +99,9 @@ YGEdge Node::getInlineEndEdgeUsingErrata( } bool Node::isFlexStartPositionDefined(FlexDirection axis) const { - const YGEdge startEdge = flexStartEdge(axis); + const Edge startEdge = flexStartEdge(axis); auto leadingPosition = isRow(axis) - ? computeEdgeValueForRow<&Style::position>(YGEdgeStart, startEdge) + ? computeEdgeValueForRow<&Style::position>(Edge::Start, startEdge) : computeEdgeValueForColumn<&Style::position>(startEdge); return leadingPosition.isDefined(); @@ -109,18 +109,18 @@ bool Node::isFlexStartPositionDefined(FlexDirection axis) const { bool Node::isInlineStartPositionDefined(FlexDirection axis, Direction direction) const { - const YGEdge startEdge = getInlineStartEdgeUsingErrata(axis, direction); + const Edge startEdge = getInlineStartEdgeUsingErrata(axis, direction); auto leadingPosition = isRow(axis) - ? computeEdgeValueForRow<&Style::position>(YGEdgeStart, startEdge) + ? computeEdgeValueForRow<&Style::position>(Edge::Start, startEdge) : computeEdgeValueForColumn<&Style::position>(startEdge); return leadingPosition.isDefined(); } bool Node::isFlexEndPositionDefined(FlexDirection axis) const { - const YGEdge endEdge = flexEndEdge(axis); + const Edge endEdge = flexEndEdge(axis); auto trailingPosition = isRow(axis) - ? computeEdgeValueForRow<&Style::position>(YGEdgeEnd, endEdge) + ? computeEdgeValueForRow<&Style::position>(Edge::End, endEdge) : computeEdgeValueForColumn<&Style::position>(endEdge); return !trailingPosition.isUndefined(); @@ -128,18 +128,18 @@ bool Node::isFlexEndPositionDefined(FlexDirection axis) const { bool Node::isInlineEndPositionDefined(FlexDirection axis, Direction direction) const { - const YGEdge endEdge = getInlineEndEdgeUsingErrata(axis, direction); + const Edge endEdge = getInlineEndEdgeUsingErrata(axis, direction); auto trailingPosition = isRow(axis) - ? computeEdgeValueForRow<&Style::position>(YGEdgeEnd, endEdge) + ? computeEdgeValueForRow<&Style::position>(Edge::End, endEdge) : computeEdgeValueForColumn<&Style::position>(endEdge); return trailingPosition.isDefined(); } float Node::getFlexStartPosition(FlexDirection axis, float axisSize) const { - const YGEdge startEdge = flexStartEdge(axis); + const Edge startEdge = flexStartEdge(axis); auto leadingPosition = isRow(axis) - ? computeEdgeValueForRow<&Style::position>(YGEdgeStart, startEdge) + ? computeEdgeValueForRow<&Style::position>(Edge::Start, startEdge) : computeEdgeValueForColumn<&Style::position>(startEdge); return resolveValue(leadingPosition, axisSize).unwrapOrDefault(0.0f); @@ -149,18 +149,18 @@ float Node::getInlineStartPosition( FlexDirection axis, Direction direction, float axisSize) const { - const YGEdge startEdge = getInlineStartEdgeUsingErrata(axis, direction); + const Edge startEdge = getInlineStartEdgeUsingErrata(axis, direction); auto leadingPosition = isRow(axis) - ? computeEdgeValueForRow<&Style::position>(YGEdgeStart, startEdge) + ? computeEdgeValueForRow<&Style::position>(Edge::Start, startEdge) : computeEdgeValueForColumn<&Style::position>(startEdge); return resolveValue(leadingPosition, axisSize).unwrapOrDefault(0.0f); } float Node::getFlexEndPosition(FlexDirection axis, float axisSize) const { - const YGEdge endEdge = flexEndEdge(axis); + const Edge endEdge = flexEndEdge(axis); auto trailingPosition = isRow(axis) - ? computeEdgeValueForRow<&Style::position>(YGEdgeEnd, endEdge) + ? computeEdgeValueForRow<&Style::position>(Edge::End, endEdge) : computeEdgeValueForColumn<&Style::position>(endEdge); return resolveValue(trailingPosition, axisSize).unwrapOrDefault(0.0f); @@ -170,18 +170,18 @@ float Node::getInlineEndPosition( FlexDirection axis, Direction direction, float axisSize) const { - const YGEdge endEdge = getInlineEndEdgeUsingErrata(axis, direction); + const Edge endEdge = getInlineEndEdgeUsingErrata(axis, direction); auto trailingPosition = isRow(axis) - ? computeEdgeValueForRow<&Style::position>(YGEdgeEnd, endEdge) + ? computeEdgeValueForRow<&Style::position>(Edge::End, endEdge) : computeEdgeValueForColumn<&Style::position>(endEdge); return resolveValue(trailingPosition, axisSize).unwrapOrDefault(0.0f); } float Node::getFlexStartMargin(FlexDirection axis, float widthSize) const { - const YGEdge startEdge = flexStartEdge(axis); + const Edge startEdge = flexStartEdge(axis); auto leadingMargin = isRow(axis) - ? computeEdgeValueForRow<&Style::margin>(YGEdgeStart, startEdge) + ? computeEdgeValueForRow<&Style::margin>(Edge::Start, startEdge) : computeEdgeValueForColumn<&Style::margin>(startEdge); return resolveValue(leadingMargin, widthSize).unwrapOrDefault(0.0f); @@ -191,18 +191,18 @@ float Node::getInlineStartMargin( FlexDirection axis, Direction direction, float widthSize) const { - const YGEdge startEdge = getInlineStartEdgeUsingErrata(axis, direction); + const Edge startEdge = getInlineStartEdgeUsingErrata(axis, direction); auto leadingMargin = isRow(axis) - ? computeEdgeValueForRow<&Style::margin>(YGEdgeStart, startEdge) + ? computeEdgeValueForRow<&Style::margin>(Edge::Start, startEdge) : computeEdgeValueForColumn<&Style::margin>(startEdge); return resolveValue(leadingMargin, widthSize).unwrapOrDefault(0.0f); } float Node::getFlexEndMargin(FlexDirection axis, float widthSize) const { - const YGEdge endEdge = flexEndEdge(axis); + const Edge endEdge = flexEndEdge(axis); auto trailingMargin = isRow(axis) - ? computeEdgeValueForRow<&Style::margin>(YGEdgeEnd, endEdge) + ? computeEdgeValueForRow<&Style::margin>(Edge::End, endEdge) : computeEdgeValueForColumn<&Style::margin>(endEdge); return resolveValue(trailingMargin, widthSize).unwrapOrDefault(0.0f); @@ -212,9 +212,9 @@ float Node::getInlineEndMargin( FlexDirection axis, Direction direction, float widthSize) const { - const YGEdge endEdge = getInlineEndEdgeUsingErrata(axis, direction); + const Edge endEdge = getInlineEndEdgeUsingErrata(axis, direction); auto trailingMargin = isRow(axis) - ? computeEdgeValueForRow<&Style::margin>(YGEdgeEnd, endEdge) + ? computeEdgeValueForRow<&Style::margin>(Edge::End, endEdge) : computeEdgeValueForColumn<&Style::margin>(endEdge); return resolveValue(trailingMargin, widthSize).unwrapOrDefault(0.0f); @@ -222,17 +222,16 @@ float Node::getInlineEndMargin( float Node::getInlineStartBorder(FlexDirection axis, Direction direction) const { - const YGEdge startEdge = getInlineStartEdgeUsingErrata(axis, direction); + const Edge startEdge = getInlineStartEdgeUsingErrata(axis, direction); YGValue leadingBorder = isRow(axis) - ? computeEdgeValueForRow<&Style::border>(YGEdgeStart, startEdge) + ? computeEdgeValueForRow<&Style::border>(Edge::Start, startEdge) : computeEdgeValueForColumn<&Style::border>(startEdge); return maxOrDefined(leadingBorder.value, 0.0f); } float Node::getFlexStartBorder(FlexDirection axis, Direction direction) const { - const YGEdge leadRelativeFlexItemEdge = - flexStartRelativeEdge(axis, direction); + const Edge leadRelativeFlexItemEdge = flexStartRelativeEdge(axis, direction); YGValue leadingBorder = isRow(axis) ? computeEdgeValueForRow<&Style::border>( leadRelativeFlexItemEdge, flexStartEdge(axis)) @@ -242,16 +241,16 @@ float Node::getFlexStartBorder(FlexDirection axis, Direction direction) const { } float Node::getInlineEndBorder(FlexDirection axis, Direction direction) const { - const YGEdge endEdge = getInlineEndEdgeUsingErrata(axis, direction); + const Edge endEdge = getInlineEndEdgeUsingErrata(axis, direction); YGValue trailingBorder = isRow(axis) - ? computeEdgeValueForRow<&Style::border>(YGEdgeEnd, endEdge) + ? computeEdgeValueForRow<&Style::border>(Edge::End, endEdge) : computeEdgeValueForColumn<&Style::border>(endEdge); return maxOrDefined(trailingBorder.value, 0.0f); } float Node::getFlexEndBorder(FlexDirection axis, Direction direction) const { - const YGEdge trailRelativeFlexItemEdge = flexEndRelativeEdge(axis, direction); + const Edge trailRelativeFlexItemEdge = flexEndRelativeEdge(axis, direction); YGValue trailingBorder = isRow(axis) ? computeEdgeValueForRow<&Style::border>( trailRelativeFlexItemEdge, flexEndEdge(axis)) @@ -264,9 +263,9 @@ float Node::getInlineStartPadding( FlexDirection axis, Direction direction, float widthSize) const { - const YGEdge startEdge = getInlineStartEdgeUsingErrata(axis, direction); + const Edge startEdge = getInlineStartEdgeUsingErrata(axis, direction); auto leadingPadding = isRow(axis) - ? computeEdgeValueForRow<&Style::padding>(YGEdgeStart, startEdge) + ? computeEdgeValueForRow<&Style::padding>(Edge::Start, startEdge) : computeEdgeValueForColumn<&Style::padding>(startEdge); return maxOrDefined(resolveValue(leadingPadding, widthSize).unwrap(), 0.0f); @@ -276,8 +275,7 @@ float Node::getFlexStartPadding( FlexDirection axis, Direction direction, float widthSize) const { - const YGEdge leadRelativeFlexItemEdge = - flexStartRelativeEdge(axis, direction); + const Edge leadRelativeFlexItemEdge = flexStartRelativeEdge(axis, direction); auto leadingPadding = isRow(axis) ? computeEdgeValueForRow<&Style::padding>( leadRelativeFlexItemEdge, flexStartEdge(axis)) @@ -290,9 +288,9 @@ float Node::getInlineEndPadding( FlexDirection axis, Direction direction, float widthSize) const { - const YGEdge endEdge = getInlineEndEdgeUsingErrata(axis, direction); + const Edge endEdge = getInlineEndEdgeUsingErrata(axis, direction); auto trailingPadding = isRow(axis) - ? computeEdgeValueForRow<&Style::padding>(YGEdgeEnd, endEdge) + ? computeEdgeValueForRow<&Style::padding>(Edge::End, endEdge) : computeEdgeValueForColumn<&Style::padding>(endEdge); return maxOrDefined(resolveValue(trailingPadding, widthSize).unwrap(), 0.0f); @@ -302,7 +300,7 @@ float Node::getFlexEndPadding( FlexDirection axis, Direction direction, float widthSize) const { - const YGEdge trailRelativeFlexItemEdge = flexEndRelativeEdge(axis, direction); + const Edge trailRelativeFlexItemEdge = flexEndRelativeEdge(axis, direction); auto trailingPadding = isRow(axis) ? computeEdgeValueForRow<&Style::padding>( trailRelativeFlexItemEdge, flexEndEdge(axis)) @@ -446,25 +444,16 @@ void Node::setLayoutDirection(Direction direction) { layout_.setDirection(direction); } -void Node::setLayoutMargin(float margin, YGEdge edge) { - assertFatal( - edge < static_cast(layout_.margin.size()), - "Edge must be top/left/bottom/right"); - layout_.margin[edge] = margin; +void Node::setLayoutMargin(float margin, Edge edge) { + layout_.setMargin(edge, margin); } -void Node::setLayoutBorder(float border, YGEdge edge) { - assertFatal( - edge < static_cast(layout_.border.size()), - "Edge must be top/left/bottom/right"); - layout_.border[edge] = border; +void Node::setLayoutBorder(float border, Edge edge) { + layout_.setBorder(edge, border); } -void Node::setLayoutPadding(float padding, YGEdge edge) { - assertFatal( - edge < static_cast(layout_.padding.size()), - "Edge must be top/left/bottom/right"); - layout_.padding[edge] = padding; +void Node::setLayoutPadding(float padding, Edge edge) { + layout_.setPadding(edge, padding); } void Node::setLayoutLastOwnerDirection(Direction direction) { @@ -475,11 +464,8 @@ void Node::setLayoutComputedFlexBasis(const FloatOptional computedFlexBasis) { layout_.computedFlexBasis = computedFlexBasis; } -void Node::setLayoutPosition(float position, YGEdge edge) { - assertFatal( - edge < static_cast(layout_.position.size()), - "Edge must be top/left/bottom/right"); - layout_.position[edge] = position; +void Node::setLayoutPosition(float position, Edge edge) { + layout_.setPosition(edge, position); } void Node::setLayoutComputedFlexBasisGeneration( @@ -536,13 +522,13 @@ void Node::setPosition( const float relativePositionCross = relativePosition(crossAxis, directionRespectingRoot, crossSize); - const YGEdge mainAxisLeadingEdge = + const Edge mainAxisLeadingEdge = getInlineStartEdgeUsingErrata(mainAxis, direction); - const YGEdge mainAxisTrailingEdge = + const Edge mainAxisTrailingEdge = getInlineEndEdgeUsingErrata(mainAxis, direction); - const YGEdge crossAxisLeadingEdge = + const Edge crossAxisLeadingEdge = getInlineStartEdgeUsingErrata(crossAxis, direction); - const YGEdge crossAxisTrailingEdge = + const Edge crossAxisTrailingEdge = getInlineEndEdgeUsingErrata(crossAxis, direction); setLayoutPosition( @@ -564,16 +550,16 @@ void Node::setPosition( } YGValue Node::getFlexStartMarginValue(FlexDirection axis) const { - if (isRow(axis) && style_.margin(YGEdgeStart).isDefined()) { - return style_.margin(YGEdgeStart); + if (isRow(axis) && style_.margin(Edge::Start).isDefined()) { + return style_.margin(Edge::Start); } else { return style_.margin(flexStartEdge(axis)); } } YGValue Node::marginTrailingValue(FlexDirection axis) const { - if (isRow(axis) && style_.margin(YGEdgeEnd).isDefined()) { - return style_.margin(YGEdgeEnd); + if (isRow(axis) && style_.margin(Edge::End).isDefined()) { + return style_.margin(Edge::End); } else { return style_.margin(flexEndEdge(axis)); } diff --git a/packages/react-native/ReactCommon/yoga/yoga/node/Node.h b/packages/react-native/ReactCommon/yoga/yoga/node/Node.h index 1c9acbbe86d23d..d01a1ed4ca6da2 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/node/Node.h +++ b/packages/react-native/ReactCommon/yoga/yoga/node/Node.h @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -52,10 +53,10 @@ class YG_EXPORT Node : public ::YGNode { Direction direction, const float axisSize) const; - YGEdge getInlineStartEdgeUsingErrata( + Edge getInlineStartEdgeUsingErrata( FlexDirection flexDirection, Direction direction) const; - YGEdge getInlineEndEdgeUsingErrata( + Edge getInlineEndEdgeUsingErrata( FlexDirection flexDirection, Direction direction) const; @@ -65,10 +66,10 @@ class YG_EXPORT Node : public ::YGNode { } template - Style::Length computeEdgeValueForColumn(YGEdge edge) const; + Style::Length computeEdgeValueForColumn(Edge edge) const; template - Style::Length computeEdgeValueForRow(YGEdge rowEdge, YGEdge edge) const; + Style::Length computeEdgeValueForRow(Edge rowEdge, Edge edge) const; // DANGER DANGER DANGER! // If the node assigned to has children, we'd either have to deallocate @@ -328,10 +329,10 @@ class YG_EXPORT Node : public ::YGNode { void setLayoutHadOverflow(bool hadOverflow); void setLayoutDimension(float LengthValue, Dimension dimension); void setLayoutDirection(Direction direction); - void setLayoutMargin(float margin, YGEdge edge); - void setLayoutBorder(float border, YGEdge edge); - void setLayoutPadding(float padding, YGEdge edge); - void setLayoutPosition(float position, YGEdge edge); + void setLayoutMargin(float margin, Edge edge); + void setLayoutBorder(float border, Edge edge); + void setLayoutPadding(float padding, Edge edge); + void setLayoutPosition(float position, Edge edge); void setPosition( const Direction direction, const float mainSize, diff --git a/packages/react-native/ReactCommon/yoga/yoga/style/Style.h b/packages/react-native/ReactCommon/yoga/yoga/style/Style.h index 835632edd598dc..e40f1c4fb644f7 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/style/Style.h +++ b/packages/react-native/ReactCommon/yoga/yoga/style/Style.h @@ -227,32 +227,32 @@ class YG_EXPORT Style { return {*this}; } - Style::Length margin(YGEdge edge) const { - return margin_[edge]; + Style::Length margin(Edge edge) const { + return margin_[yoga::to_underlying(edge)]; } - void setMargin(YGEdge edge, Style::Length value) { - margin_[edge] = value; + void setMargin(Edge edge, Style::Length value) { + margin_[yoga::to_underlying(edge)] = value; } - Style::Length position(YGEdge edge) const { - return position_[edge]; + Style::Length position(Edge edge) const { + return position_[yoga::to_underlying(edge)]; } - void setPosition(YGEdge edge, Style::Length value) { - position_[edge] = value; + void setPosition(Edge edge, Style::Length value) { + position_[yoga::to_underlying(edge)] = value; } - Style::Length padding(YGEdge edge) const { - return padding_[edge]; + Style::Length padding(Edge edge) const { + return padding_[yoga::to_underlying(edge)]; } - void setPadding(YGEdge edge, Style::Length value) { - padding_[edge] = value; + void setPadding(Edge edge, Style::Length value) { + padding_[yoga::to_underlying(edge)] = value; } - Style::Length border(YGEdge edge) const { - return border_[edge]; + Style::Length border(Edge edge) const { + return border_[yoga::to_underlying(edge)]; } - void setBorder(YGEdge edge, Style::Length value) { - border_[edge] = value; + void setBorder(Edge edge, Style::Length value) { + border_[yoga::to_underlying(edge)] = value; } Style::Length gap(Gutter gutter) const { From b50a7093bc3bb8a352fd052e7fae81051d978551 Mon Sep 17 00:00:00 2001 From: Intl Scheduler <> Date: Sun, 26 Nov 2023 08:33:33 -0800 Subject: [PATCH 094/162] translation auto-update for i18n/fb4a.config.json on master Summary: Chronos Job Instance ID: 1125907943844335 Sandcastle Job Instance ID: 1121001921 allow-large-files ignore-conflict-markers opt-out-review Differential Revision: D51576545 fbshipit-source-id: 726fda7e125295492881cb43bfbd7249cdf0b022 --- .../src/main/res/views/uimanager/values-tg/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/react-native/ReactAndroid/src/main/res/views/uimanager/values-tg/strings.xml b/packages/react-native/ReactAndroid/src/main/res/views/uimanager/values-tg/strings.xml index 01bc8a89457279..6922f562e1ec4c 100644 --- a/packages/react-native/ReactAndroid/src/main/res/views/uimanager/values-tg/strings.xml +++ b/packages/react-native/ReactAndroid/src/main/res/views/uimanager/values-tg/strings.xml @@ -7,6 +7,7 @@ Тасвир Тугма, тасвир Рӯйхати таркибӣ + Меню фаъол хомӯш From ef9c164f5fd66ffed894df1cf3fd2f03ce20cbb4 Mon Sep 17 00:00:00 2001 From: Christoph Purrer Date: Mon, 27 Nov 2023 03:43:28 -0800 Subject: [PATCH 095/162] Simplify C++ TM struct generation (#41645) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41645 Right now, when defining concrete structs and Bridging headers for Cxx TMs we need to define their member types twice: ``` using ConstantsStruct = NativeCxxModuleExampleCxxBaseConstantsStruct; template <> struct Bridging : NativeCxxModuleExampleCxxBaseConstantsStructBridging< bool, int32_t, std::string> {}; ``` Now we only need to define those once ``` using ConstantsStruct = NativeCxxModuleExampleCxxConstantsStruct; template <> struct Bridging : NativeCxxModuleExampleCxxConstantsStructBridging {}; ``` This change keeps the existing base types untouched - but they will be removed in the next RN version. Changelog: [Internal] Reviewed By: rshest Differential Revision: D51571453 fbshipit-source-id: 2783bd48bf786ffa80d322d06456b5d6f2d7ba8a --- .../GenerateModuleH-test.js.snap | 858 ++++++++++++++++-- .../src/generators/modules/GenerateModuleH.js | 132 ++- .../GenerateModuleH-test.js.snap | 573 +++++++++++- .../NativeIntersectionObserver.h | 30 +- .../MutationObserver/NativeMutationObserver.h | 26 +- .../NativePerformanceObserver.h | 19 +- .../NativeCxxModuleExample.h | 22 +- 7 files changed, 1481 insertions(+), 179 deletions(-) diff --git a/packages/react-native-codegen/e2e/__tests__/modules/__snapshots__/GenerateModuleH-test.js.snap b/packages/react-native-codegen/e2e/__tests__/modules/__snapshots__/GenerateModuleH-test.js.snap index 344b22b8866d77..ca285481d2374c 100644 --- a/packages/react-native-codegen/e2e/__tests__/modules/__snapshots__/GenerateModuleH-test.js.snap +++ b/packages/react-native-codegen/e2e/__tests__/modules/__snapshots__/GenerateModuleH-test.js.snap @@ -324,7 +324,7 @@ struct Bridging { #pragma mark - NativeEnumTurboModuleBaseStateType template -struct NativeEnumTurboModuleBaseStateType { +struct [[deprecated(\\"Use NativeEnumTurboModuleStateType instead.\\")]] NativeEnumTurboModuleBaseStateType { P0 state; bool operator==(const NativeEnumTurboModuleBaseStateType &other) const { return state == other.state; @@ -332,7 +332,7 @@ struct NativeEnumTurboModuleBaseStateType { }; template -struct NativeEnumTurboModuleBaseStateTypeBridging { +struct [[deprecated(\\"Use NativeEnumTurboModuleStateTypeBridging instead.\\")]] NativeEnumTurboModuleBaseStateTypeBridging { static NativeEnumTurboModuleBaseStateType fromJs( jsi::Runtime &rt, const jsi::Object &value, @@ -363,7 +363,7 @@ struct NativeEnumTurboModuleBaseStateTypeBridging { #pragma mark - NativeEnumTurboModuleBaseStateTypeWithEnums template -struct NativeEnumTurboModuleBaseStateTypeWithEnums { +struct [[deprecated(\\"Use NativeEnumTurboModuleStateTypeWithEnums instead.\\")]] NativeEnumTurboModuleBaseStateTypeWithEnums { P0 state; P1 regular; P2 str; @@ -375,7 +375,7 @@ struct NativeEnumTurboModuleBaseStateTypeWithEnums { }; template -struct NativeEnumTurboModuleBaseStateTypeWithEnumsBridging { +struct [[deprecated(\\"Use NativeEnumTurboModuleStateTypeWithEnumsBridging instead.\\")]] NativeEnumTurboModuleBaseStateTypeWithEnumsBridging { static NativeEnumTurboModuleBaseStateTypeWithEnums fromJs( jsi::Runtime &rt, const jsi::Object &value, @@ -425,6 +425,115 @@ struct NativeEnumTurboModuleBaseStateTypeWithEnumsBridging { } }; + +#pragma mark - NativeEnumTurboModuleStateType + +template +struct NativeEnumTurboModuleStateType { + P0 state; + bool operator==(const NativeEnumTurboModuleStateType &other) const { + return state == other.state; + } +}; + +template +struct NativeEnumTurboModuleStateTypeBridging { + static T types; + + static T fromJs( + jsi::Runtime &rt, + const jsi::Object &value, + const std::shared_ptr &jsInvoker) { + T result{ + bridging::fromJs(rt, value.getProperty(rt, \\"state\\"), jsInvoker)}; + return result; + } + +#ifdef DEBUG + static jsi::String stateToJs(jsi::Runtime &rt, decltype(types.state) value) { + return bridging::toJs(rt, value); + } +#endif + + static jsi::Object toJs( + jsi::Runtime &rt, + const T &value, + const std::shared_ptr &jsInvoker) { + auto result = facebook::jsi::Object(rt); + result.setProperty(rt, \\"state\\", bridging::toJs(rt, value.state, jsInvoker)); + return result; + } +}; + + + +#pragma mark - NativeEnumTurboModuleStateTypeWithEnums + +template +struct NativeEnumTurboModuleStateTypeWithEnums { + P0 state; + P1 regular; + P2 str; + P3 num; + P4 fraction; + bool operator==(const NativeEnumTurboModuleStateTypeWithEnums &other) const { + return state == other.state && regular == other.regular && str == other.str && num == other.num && fraction == other.fraction; + } +}; + +template +struct NativeEnumTurboModuleStateTypeWithEnumsBridging { + static T types; + + static T fromJs( + jsi::Runtime &rt, + const jsi::Object &value, + const std::shared_ptr &jsInvoker) { + T result{ + bridging::fromJs(rt, value.getProperty(rt, \\"state\\"), jsInvoker), + bridging::fromJs(rt, value.getProperty(rt, \\"regular\\"), jsInvoker), + bridging::fromJs(rt, value.getProperty(rt, \\"str\\"), jsInvoker), + bridging::fromJs(rt, value.getProperty(rt, \\"num\\"), jsInvoker), + bridging::fromJs(rt, value.getProperty(rt, \\"fraction\\"), jsInvoker)}; + return result; + } + +#ifdef DEBUG + static jsi::String stateToJs(jsi::Runtime &rt, decltype(types.state) value) { + return bridging::toJs(rt, value); + } + + static jsi::String regularToJs(jsi::Runtime &rt, decltype(types.regular) value) { + return bridging::toJs(rt, value); + } + + static jsi::String strToJs(jsi::Runtime &rt, decltype(types.str) value) { + return bridging::toJs(rt, value); + } + + static int numToJs(jsi::Runtime &rt, decltype(types.num) value) { + return bridging::toJs(rt, value); + } + + static double fractionToJs(jsi::Runtime &rt, decltype(types.fraction) value) { + return bridging::toJs(rt, value); + } +#endif + + static jsi::Object toJs( + jsi::Runtime &rt, + const T &value, + const std::shared_ptr &jsInvoker) { + auto result = facebook::jsi::Object(rt); + result.setProperty(rt, \\"state\\", bridging::toJs(rt, value.state, jsInvoker)); + result.setProperty(rt, \\"regular\\", bridging::toJs(rt, value.regular, jsInvoker)); + result.setProperty(rt, \\"str\\", bridging::toJs(rt, value.str, jsInvoker)); + result.setProperty(rt, \\"num\\", bridging::toJs(rt, value.num, jsInvoker)); + result.setProperty(rt, \\"fraction\\", bridging::toJs(rt, value.fraction, jsInvoker)); + return result; + } +}; + class JSI_EXPORT NativeEnumTurboModuleCxxSpecJSI : public TurboModule { protected: NativeEnumTurboModuleCxxSpecJSI(std::shared_ptr jsInvoker); @@ -794,7 +903,7 @@ private: #pragma mark - NativePartialAnnotationTurboModuleBaseSomeObj template -struct NativePartialAnnotationTurboModuleBaseSomeObj { +struct [[deprecated(\\"Use NativePartialAnnotationTurboModuleSomeObj instead.\\")]] NativePartialAnnotationTurboModuleBaseSomeObj { P0 a; P1 b; bool operator==(const NativePartialAnnotationTurboModuleBaseSomeObj &other) const { @@ -803,7 +912,7 @@ struct NativePartialAnnotationTurboModuleBaseSomeObj { }; template -struct NativePartialAnnotationTurboModuleBaseSomeObjBridging { +struct [[deprecated(\\"Use NativePartialAnnotationTurboModuleSomeObjBridging instead.\\")]] NativePartialAnnotationTurboModuleBaseSomeObjBridging { static NativePartialAnnotationTurboModuleBaseSomeObj fromJs( jsi::Runtime &rt, const jsi::Object &value, @@ -837,6 +946,55 @@ struct NativePartialAnnotationTurboModuleBaseSomeObjBridging { } }; + +#pragma mark - NativePartialAnnotationTurboModuleSomeObj + +template +struct NativePartialAnnotationTurboModuleSomeObj { + P0 a; + P1 b; + bool operator==(const NativePartialAnnotationTurboModuleSomeObj &other) const { + return a == other.a && b == other.b; + } +}; + +template +struct NativePartialAnnotationTurboModuleSomeObjBridging { + static T types; + + static T fromJs( + jsi::Runtime &rt, + const jsi::Object &value, + const std::shared_ptr &jsInvoker) { + T result{ + bridging::fromJs(rt, value.getProperty(rt, \\"a\\"), jsInvoker), + bridging::fromJs(rt, value.getProperty(rt, \\"b\\"), jsInvoker)}; + return result; + } + +#ifdef DEBUG + static jsi::String aToJs(jsi::Runtime &rt, decltype(types.a) value) { + return bridging::toJs(rt, value); + } + + static bool bToJs(jsi::Runtime &rt, decltype(types.b) value) { + return bridging::toJs(rt, value); + } +#endif + + static jsi::Object toJs( + jsi::Runtime &rt, + const T &value, + const std::shared_ptr &jsInvoker) { + auto result = facebook::jsi::Object(rt); + result.setProperty(rt, \\"a\\", bridging::toJs(rt, value.a, jsInvoker)); + if (value.b) { + result.setProperty(rt, \\"b\\", bridging::toJs(rt, value.b.value(), jsInvoker)); + } + return result; + } +}; + class JSI_EXPORT NativePartialAnnotationTurboModuleCxxSpecJSI : public TurboModule { protected: NativePartialAnnotationTurboModuleCxxSpecJSI(std::shared_ptr jsInvoker); @@ -969,7 +1127,7 @@ private: #pragma mark - SampleTurboModuleBaseAnimal template -struct SampleTurboModuleBaseAnimal { +struct [[deprecated(\\"Use SampleTurboModuleAnimal instead.\\")]] SampleTurboModuleBaseAnimal { P0 name; bool operator==(const SampleTurboModuleBaseAnimal &other) const { return name == other.name; @@ -977,7 +1135,7 @@ struct SampleTurboModuleBaseAnimal { }; template -struct SampleTurboModuleBaseAnimalBridging { +struct [[deprecated(\\"Use SampleTurboModuleAnimalBridging instead.\\")]] SampleTurboModuleBaseAnimalBridging { static SampleTurboModuleBaseAnimal fromJs( jsi::Runtime &rt, const jsi::Object &value, @@ -1003,6 +1161,46 @@ struct SampleTurboModuleBaseAnimalBridging { } }; + +#pragma mark - SampleTurboModuleAnimal + +template +struct SampleTurboModuleAnimal { + P0 name; + bool operator==(const SampleTurboModuleAnimal &other) const { + return name == other.name; + } +}; + +template +struct SampleTurboModuleAnimalBridging { + static T types; + + static T fromJs( + jsi::Runtime &rt, + const jsi::Object &value, + const std::shared_ptr &jsInvoker) { + T result{ + bridging::fromJs(rt, value.getProperty(rt, \\"name\\"), jsInvoker)}; + return result; + } + +#ifdef DEBUG + static jsi::String nameToJs(jsi::Runtime &rt, decltype(types.name) value) { + return bridging::toJs(rt, value); + } +#endif + + static jsi::Object toJs( + jsi::Runtime &rt, + const T &value, + const std::shared_ptr &jsInvoker) { + auto result = facebook::jsi::Object(rt); + result.setProperty(rt, \\"name\\", bridging::toJs(rt, value.name, jsInvoker)); + return result; + } +}; + class JSI_EXPORT NativeSampleTurboModuleCxxSpecJSI : public TurboModule { protected: NativeSampleTurboModuleCxxSpecJSI(std::shared_ptr jsInvoker); @@ -1161,7 +1359,7 @@ private: #pragma mark - SampleTurboModuleArraysBaseAnimal template -struct SampleTurboModuleArraysBaseAnimal { +struct [[deprecated(\\"Use SampleTurboModuleArraysAnimal instead.\\")]] SampleTurboModuleArraysBaseAnimal { P0 name; bool operator==(const SampleTurboModuleArraysBaseAnimal &other) const { return name == other.name; @@ -1169,7 +1367,7 @@ struct SampleTurboModuleArraysBaseAnimal { }; template -struct SampleTurboModuleArraysBaseAnimalBridging { +struct [[deprecated(\\"Use SampleTurboModuleArraysAnimalBridging instead.\\")]] SampleTurboModuleArraysBaseAnimalBridging { static SampleTurboModuleArraysBaseAnimal fromJs( jsi::Runtime &rt, const jsi::Object &value, @@ -1195,6 +1393,46 @@ struct SampleTurboModuleArraysBaseAnimalBridging { } }; + +#pragma mark - SampleTurboModuleArraysAnimal + +template +struct SampleTurboModuleArraysAnimal { + P0 name; + bool operator==(const SampleTurboModuleArraysAnimal &other) const { + return name == other.name; + } +}; + +template +struct SampleTurboModuleArraysAnimalBridging { + static T types; + + static T fromJs( + jsi::Runtime &rt, + const jsi::Object &value, + const std::shared_ptr &jsInvoker) { + T result{ + bridging::fromJs(rt, value.getProperty(rt, \\"name\\"), jsInvoker)}; + return result; + } + +#ifdef DEBUG + static jsi::String nameToJs(jsi::Runtime &rt, decltype(types.name) value) { + return bridging::toJs(rt, value); + } +#endif + + static jsi::Object toJs( + jsi::Runtime &rt, + const T &value, + const std::shared_ptr &jsInvoker) { + auto result = facebook::jsi::Object(rt); + result.setProperty(rt, \\"name\\", bridging::toJs(rt, value.name, jsInvoker)); + return result; + } +}; + class JSI_EXPORT NativeSampleTurboModuleArraysCxxSpecJSI : public TurboModule { protected: NativeSampleTurboModuleArraysCxxSpecJSI(std::shared_ptr jsInvoker); @@ -1353,7 +1591,7 @@ private: #pragma mark - SampleTurboModuleNullableBaseAnimal template -struct SampleTurboModuleNullableBaseAnimal { +struct [[deprecated(\\"Use SampleTurboModuleNullableAnimal instead.\\")]] SampleTurboModuleNullableBaseAnimal { P0 name; bool operator==(const SampleTurboModuleNullableBaseAnimal &other) const { return name == other.name; @@ -1361,7 +1599,7 @@ struct SampleTurboModuleNullableBaseAnimal { }; template -struct SampleTurboModuleNullableBaseAnimalBridging { +struct [[deprecated(\\"Use SampleTurboModuleNullableAnimalBridging instead.\\")]] SampleTurboModuleNullableBaseAnimalBridging { static SampleTurboModuleNullableBaseAnimal fromJs( jsi::Runtime &rt, const jsi::Object &value, @@ -1387,6 +1625,46 @@ struct SampleTurboModuleNullableBaseAnimalBridging { } }; + +#pragma mark - SampleTurboModuleNullableAnimal + +template +struct SampleTurboModuleNullableAnimal { + P0 name; + bool operator==(const SampleTurboModuleNullableAnimal &other) const { + return name == other.name; + } +}; + +template +struct SampleTurboModuleNullableAnimalBridging { + static T types; + + static T fromJs( + jsi::Runtime &rt, + const jsi::Object &value, + const std::shared_ptr &jsInvoker) { + T result{ + bridging::fromJs(rt, value.getProperty(rt, \\"name\\"), jsInvoker)}; + return result; + } + +#ifdef DEBUG + static std::optional nameToJs(jsi::Runtime &rt, decltype(types.name) value) { + return bridging::toJs(rt, value); + } +#endif + + static jsi::Object toJs( + jsi::Runtime &rt, + const T &value, + const std::shared_ptr &jsInvoker) { + auto result = facebook::jsi::Object(rt); + result.setProperty(rt, \\"name\\", bridging::toJs(rt, value.name, jsInvoker)); + return result; + } +}; + class JSI_EXPORT NativeSampleTurboModuleNullableCxxSpecJSI : public TurboModule { protected: NativeSampleTurboModuleNullableCxxSpecJSI(std::shared_ptr jsInvoker); @@ -1545,7 +1823,7 @@ private: #pragma mark - SampleTurboModuleNullableAndOptionalBaseAnimal template -struct SampleTurboModuleNullableAndOptionalBaseAnimal { +struct [[deprecated(\\"Use SampleTurboModuleNullableAndOptionalAnimal instead.\\")]] SampleTurboModuleNullableAndOptionalBaseAnimal { P0 name; bool operator==(const SampleTurboModuleNullableAndOptionalBaseAnimal &other) const { return name == other.name; @@ -1553,7 +1831,7 @@ struct SampleTurboModuleNullableAndOptionalBaseAnimal { }; template -struct SampleTurboModuleNullableAndOptionalBaseAnimalBridging { +struct [[deprecated(\\"Use SampleTurboModuleNullableAndOptionalAnimalBridging instead.\\")]] SampleTurboModuleNullableAndOptionalBaseAnimalBridging { static SampleTurboModuleNullableAndOptionalBaseAnimal fromJs( jsi::Runtime &rt, const jsi::Object &value, @@ -1581,6 +1859,48 @@ struct SampleTurboModuleNullableAndOptionalBaseAnimalBridging { } }; + +#pragma mark - SampleTurboModuleNullableAndOptionalAnimal + +template +struct SampleTurboModuleNullableAndOptionalAnimal { + P0 name; + bool operator==(const SampleTurboModuleNullableAndOptionalAnimal &other) const { + return name == other.name; + } +}; + +template +struct SampleTurboModuleNullableAndOptionalAnimalBridging { + static T types; + + static T fromJs( + jsi::Runtime &rt, + const jsi::Object &value, + const std::shared_ptr &jsInvoker) { + T result{ + bridging::fromJs(rt, value.getProperty(rt, \\"name\\"), jsInvoker)}; + return result; + } + +#ifdef DEBUG + static std::optional nameToJs(jsi::Runtime &rt, decltype(types.name) value) { + return bridging::toJs(rt, value); + } +#endif + + static jsi::Object toJs( + jsi::Runtime &rt, + const T &value, + const std::shared_ptr &jsInvoker) { + auto result = facebook::jsi::Object(rt); + if (value.name) { + result.setProperty(rt, \\"name\\", bridging::toJs(rt, value.name.value(), jsInvoker)); + } + return result; + } +}; + class JSI_EXPORT NativeSampleTurboModuleNullableAndOptionalCxxSpecJSI : public TurboModule { protected: NativeSampleTurboModuleNullableAndOptionalCxxSpecJSI(std::shared_ptr jsInvoker); @@ -1739,7 +2059,7 @@ private: #pragma mark - SampleTurboModuleOptionalBaseAnimal template -struct SampleTurboModuleOptionalBaseAnimal { +struct [[deprecated(\\"Use SampleTurboModuleOptionalAnimal instead.\\")]] SampleTurboModuleOptionalBaseAnimal { P0 name; bool operator==(const SampleTurboModuleOptionalBaseAnimal &other) const { return name == other.name; @@ -1747,7 +2067,7 @@ struct SampleTurboModuleOptionalBaseAnimal { }; template -struct SampleTurboModuleOptionalBaseAnimalBridging { +struct [[deprecated(\\"Use SampleTurboModuleOptionalAnimalBridging instead.\\")]] SampleTurboModuleOptionalBaseAnimalBridging { static SampleTurboModuleOptionalBaseAnimal fromJs( jsi::Runtime &rt, const jsi::Object &value, @@ -1775,6 +2095,48 @@ struct SampleTurboModuleOptionalBaseAnimalBridging { } }; + +#pragma mark - SampleTurboModuleOptionalAnimal + +template +struct SampleTurboModuleOptionalAnimal { + P0 name; + bool operator==(const SampleTurboModuleOptionalAnimal &other) const { + return name == other.name; + } +}; + +template +struct SampleTurboModuleOptionalAnimalBridging { + static T types; + + static T fromJs( + jsi::Runtime &rt, + const jsi::Object &value, + const std::shared_ptr &jsInvoker) { + T result{ + bridging::fromJs(rt, value.getProperty(rt, \\"name\\"), jsInvoker)}; + return result; + } + +#ifdef DEBUG + static jsi::String nameToJs(jsi::Runtime &rt, decltype(types.name) value) { + return bridging::toJs(rt, value); + } +#endif + + static jsi::Object toJs( + jsi::Runtime &rt, + const T &value, + const std::shared_ptr &jsInvoker) { + auto result = facebook::jsi::Object(rt); + if (value.name) { + result.setProperty(rt, \\"name\\", bridging::toJs(rt, value.name.value(), jsInvoker)); + } + return result; + } +}; + class JSI_EXPORT NativeSampleTurboModuleOptionalCxxSpecJSI : public TurboModule { protected: NativeSampleTurboModuleOptionalCxxSpecJSI(std::shared_ptr jsInvoker); @@ -2296,49 +2658,156 @@ struct Bridging { } } - static jsi::Value toJs(jsi::Runtime &rt, NativeEnumTurboModuleStatusFractionEnum value) { - if (value == NativeEnumTurboModuleStatusFractionEnum::Active) { - return bridging::toJs(rt, 0.2f); - } else if (value == NativeEnumTurboModuleStatusFractionEnum::Paused) { - return bridging::toJs(rt, 0.1f); - } else if (value == NativeEnumTurboModuleStatusFractionEnum::Off) { - return bridging::toJs(rt, 0f); - } else { - throw jsi::JSError(rt, \\"No appropriate enum member found for enum value\\"); - } + static jsi::Value toJs(jsi::Runtime &rt, NativeEnumTurboModuleStatusFractionEnum value) { + if (value == NativeEnumTurboModuleStatusFractionEnum::Active) { + return bridging::toJs(rt, 0.2f); + } else if (value == NativeEnumTurboModuleStatusFractionEnum::Paused) { + return bridging::toJs(rt, 0.1f); + } else if (value == NativeEnumTurboModuleStatusFractionEnum::Off) { + return bridging::toJs(rt, 0f); + } else { + throw jsi::JSError(rt, \\"No appropriate enum member found for enum value\\"); + } + } +}; + +#pragma mark - NativeEnumTurboModuleBaseStateType + +template +struct [[deprecated(\\"Use NativeEnumTurboModuleStateType instead.\\")]] NativeEnumTurboModuleBaseStateType { + P0 state; + bool operator==(const NativeEnumTurboModuleBaseStateType &other) const { + return state == other.state; + } +}; + +template +struct [[deprecated(\\"Use NativeEnumTurboModuleStateTypeBridging instead.\\")]] NativeEnumTurboModuleBaseStateTypeBridging { + static NativeEnumTurboModuleBaseStateType fromJs( + jsi::Runtime &rt, + const jsi::Object &value, + const std::shared_ptr &jsInvoker) { + NativeEnumTurboModuleBaseStateType result{ + bridging::fromJs(rt, value.getProperty(rt, \\"state\\"), jsInvoker)}; + return result; + } + +#ifdef DEBUG + static jsi::String stateToJs(jsi::Runtime &rt, P0 value) { + return bridging::toJs(rt, value); + } +#endif + + static jsi::Object toJs( + jsi::Runtime &rt, + const NativeEnumTurboModuleBaseStateType &value, + const std::shared_ptr &jsInvoker) { + auto result = facebook::jsi::Object(rt); + result.setProperty(rt, \\"state\\", bridging::toJs(rt, value.state, jsInvoker)); + return result; + } +}; + + + +#pragma mark - NativeEnumTurboModuleBaseStateTypeWithEnums + +template +struct [[deprecated(\\"Use NativeEnumTurboModuleStateTypeWithEnums instead.\\")]] NativeEnumTurboModuleBaseStateTypeWithEnums { + P0 state; + P1 regular; + P2 str; + P3 num; + P4 fraction; + bool operator==(const NativeEnumTurboModuleBaseStateTypeWithEnums &other) const { + return state == other.state && regular == other.regular && str == other.str && num == other.num && fraction == other.fraction; + } +}; + +template +struct [[deprecated(\\"Use NativeEnumTurboModuleStateTypeWithEnumsBridging instead.\\")]] NativeEnumTurboModuleBaseStateTypeWithEnumsBridging { + static NativeEnumTurboModuleBaseStateTypeWithEnums fromJs( + jsi::Runtime &rt, + const jsi::Object &value, + const std::shared_ptr &jsInvoker) { + NativeEnumTurboModuleBaseStateTypeWithEnums result{ + bridging::fromJs(rt, value.getProperty(rt, \\"state\\"), jsInvoker), + bridging::fromJs(rt, value.getProperty(rt, \\"regular\\"), jsInvoker), + bridging::fromJs(rt, value.getProperty(rt, \\"str\\"), jsInvoker), + bridging::fromJs(rt, value.getProperty(rt, \\"num\\"), jsInvoker), + bridging::fromJs(rt, value.getProperty(rt, \\"fraction\\"), jsInvoker)}; + return result; + } + +#ifdef DEBUG + static jsi::String stateToJs(jsi::Runtime &rt, P0 value) { + return bridging::toJs(rt, value); + } + + static jsi::String regularToJs(jsi::Runtime &rt, P1 value) { + return bridging::toJs(rt, value); + } + + static jsi::String strToJs(jsi::Runtime &rt, P2 value) { + return bridging::toJs(rt, value); + } + + static int numToJs(jsi::Runtime &rt, P3 value) { + return bridging::toJs(rt, value); + } + + static double fractionToJs(jsi::Runtime &rt, P4 value) { + return bridging::toJs(rt, value); + } +#endif + + static jsi::Object toJs( + jsi::Runtime &rt, + const NativeEnumTurboModuleBaseStateTypeWithEnums &value, + const std::shared_ptr &jsInvoker) { + auto result = facebook::jsi::Object(rt); + result.setProperty(rt, \\"state\\", bridging::toJs(rt, value.state, jsInvoker)); + result.setProperty(rt, \\"regular\\", bridging::toJs(rt, value.regular, jsInvoker)); + result.setProperty(rt, \\"str\\", bridging::toJs(rt, value.str, jsInvoker)); + result.setProperty(rt, \\"num\\", bridging::toJs(rt, value.num, jsInvoker)); + result.setProperty(rt, \\"fraction\\", bridging::toJs(rt, value.fraction, jsInvoker)); + return result; } }; - -#pragma mark - NativeEnumTurboModuleBaseStateType + + +#pragma mark - NativeEnumTurboModuleStateType template -struct NativeEnumTurboModuleBaseStateType { +struct NativeEnumTurboModuleStateType { P0 state; - bool operator==(const NativeEnumTurboModuleBaseStateType &other) const { + bool operator==(const NativeEnumTurboModuleStateType &other) const { return state == other.state; } }; -template -struct NativeEnumTurboModuleBaseStateTypeBridging { - static NativeEnumTurboModuleBaseStateType fromJs( +template +struct NativeEnumTurboModuleStateTypeBridging { + static T types; + + static T fromJs( jsi::Runtime &rt, const jsi::Object &value, const std::shared_ptr &jsInvoker) { - NativeEnumTurboModuleBaseStateType result{ - bridging::fromJs(rt, value.getProperty(rt, \\"state\\"), jsInvoker)}; + T result{ + bridging::fromJs(rt, value.getProperty(rt, \\"state\\"), jsInvoker)}; return result; } #ifdef DEBUG - static jsi::String stateToJs(jsi::Runtime &rt, P0 value) { + static jsi::String stateToJs(jsi::Runtime &rt, decltype(types.state) value) { return bridging::toJs(rt, value); } #endif static jsi::Object toJs( jsi::Runtime &rt, - const NativeEnumTurboModuleBaseStateType &value, + const T &value, const std::shared_ptr &jsInvoker) { auto result = facebook::jsi::Object(rt); result.setProperty(rt, \\"state\\", bridging::toJs(rt, value.state, jsInvoker)); @@ -2348,60 +2817,62 @@ struct NativeEnumTurboModuleBaseStateTypeBridging { -#pragma mark - NativeEnumTurboModuleBaseStateTypeWithEnums +#pragma mark - NativeEnumTurboModuleStateTypeWithEnums template -struct NativeEnumTurboModuleBaseStateTypeWithEnums { +struct NativeEnumTurboModuleStateTypeWithEnums { P0 state; P1 regular; P2 str; P3 num; P4 fraction; - bool operator==(const NativeEnumTurboModuleBaseStateTypeWithEnums &other) const { + bool operator==(const NativeEnumTurboModuleStateTypeWithEnums &other) const { return state == other.state && regular == other.regular && str == other.str && num == other.num && fraction == other.fraction; } }; -template -struct NativeEnumTurboModuleBaseStateTypeWithEnumsBridging { - static NativeEnumTurboModuleBaseStateTypeWithEnums fromJs( +template +struct NativeEnumTurboModuleStateTypeWithEnumsBridging { + static T types; + + static T fromJs( jsi::Runtime &rt, const jsi::Object &value, const std::shared_ptr &jsInvoker) { - NativeEnumTurboModuleBaseStateTypeWithEnums result{ - bridging::fromJs(rt, value.getProperty(rt, \\"state\\"), jsInvoker), - bridging::fromJs(rt, value.getProperty(rt, \\"regular\\"), jsInvoker), - bridging::fromJs(rt, value.getProperty(rt, \\"str\\"), jsInvoker), - bridging::fromJs(rt, value.getProperty(rt, \\"num\\"), jsInvoker), - bridging::fromJs(rt, value.getProperty(rt, \\"fraction\\"), jsInvoker)}; + T result{ + bridging::fromJs(rt, value.getProperty(rt, \\"state\\"), jsInvoker), + bridging::fromJs(rt, value.getProperty(rt, \\"regular\\"), jsInvoker), + bridging::fromJs(rt, value.getProperty(rt, \\"str\\"), jsInvoker), + bridging::fromJs(rt, value.getProperty(rt, \\"num\\"), jsInvoker), + bridging::fromJs(rt, value.getProperty(rt, \\"fraction\\"), jsInvoker)}; return result; } #ifdef DEBUG - static jsi::String stateToJs(jsi::Runtime &rt, P0 value) { + static jsi::String stateToJs(jsi::Runtime &rt, decltype(types.state) value) { return bridging::toJs(rt, value); } - static jsi::String regularToJs(jsi::Runtime &rt, P1 value) { + static jsi::String regularToJs(jsi::Runtime &rt, decltype(types.regular) value) { return bridging::toJs(rt, value); } - static jsi::String strToJs(jsi::Runtime &rt, P2 value) { + static jsi::String strToJs(jsi::Runtime &rt, decltype(types.str) value) { return bridging::toJs(rt, value); } - static int numToJs(jsi::Runtime &rt, P3 value) { + static int numToJs(jsi::Runtime &rt, decltype(types.num) value) { return bridging::toJs(rt, value); } - static double fractionToJs(jsi::Runtime &rt, P4 value) { + static double fractionToJs(jsi::Runtime &rt, decltype(types.fraction) value) { return bridging::toJs(rt, value); } #endif static jsi::Object toJs( jsi::Runtime &rt, - const NativeEnumTurboModuleBaseStateTypeWithEnums &value, + const T &value, const std::shared_ptr &jsInvoker) { auto result = facebook::jsi::Object(rt); result.setProperty(rt, \\"state\\", bridging::toJs(rt, value.state, jsInvoker)); @@ -2782,7 +3253,7 @@ private: #pragma mark - NativePartialAnnotationTurboModuleBaseSomeObj template -struct NativePartialAnnotationTurboModuleBaseSomeObj { +struct [[deprecated(\\"Use NativePartialAnnotationTurboModuleSomeObj instead.\\")]] NativePartialAnnotationTurboModuleBaseSomeObj { P0 a; P1 b; bool operator==(const NativePartialAnnotationTurboModuleBaseSomeObj &other) const { @@ -2791,7 +3262,7 @@ struct NativePartialAnnotationTurboModuleBaseSomeObj { }; template -struct NativePartialAnnotationTurboModuleBaseSomeObjBridging { +struct [[deprecated(\\"Use NativePartialAnnotationTurboModuleSomeObjBridging instead.\\")]] NativePartialAnnotationTurboModuleBaseSomeObjBridging { static NativePartialAnnotationTurboModuleBaseSomeObj fromJs( jsi::Runtime &rt, const jsi::Object &value, @@ -2825,6 +3296,55 @@ struct NativePartialAnnotationTurboModuleBaseSomeObjBridging { } }; + +#pragma mark - NativePartialAnnotationTurboModuleSomeObj + +template +struct NativePartialAnnotationTurboModuleSomeObj { + P0 a; + P1 b; + bool operator==(const NativePartialAnnotationTurboModuleSomeObj &other) const { + return a == other.a && b == other.b; + } +}; + +template +struct NativePartialAnnotationTurboModuleSomeObjBridging { + static T types; + + static T fromJs( + jsi::Runtime &rt, + const jsi::Object &value, + const std::shared_ptr &jsInvoker) { + T result{ + bridging::fromJs(rt, value.getProperty(rt, \\"a\\"), jsInvoker), + bridging::fromJs(rt, value.getProperty(rt, \\"b\\"), jsInvoker)}; + return result; + } + +#ifdef DEBUG + static jsi::String aToJs(jsi::Runtime &rt, decltype(types.a) value) { + return bridging::toJs(rt, value); + } + + static bool bToJs(jsi::Runtime &rt, decltype(types.b) value) { + return bridging::toJs(rt, value); + } +#endif + + static jsi::Object toJs( + jsi::Runtime &rt, + const T &value, + const std::shared_ptr &jsInvoker) { + auto result = facebook::jsi::Object(rt); + result.setProperty(rt, \\"a\\", bridging::toJs(rt, value.a, jsInvoker)); + if (value.b) { + result.setProperty(rt, \\"b\\", bridging::toJs(rt, value.b.value(), jsInvoker)); + } + return result; + } +}; + class JSI_EXPORT NativePartialAnnotationTurboModuleCxxSpecJSI : public TurboModule { protected: NativePartialAnnotationTurboModuleCxxSpecJSI(std::shared_ptr jsInvoker); @@ -2957,7 +3477,7 @@ private: #pragma mark - SampleTurboModuleBaseAnimal template -struct SampleTurboModuleBaseAnimal { +struct [[deprecated(\\"Use SampleTurboModuleAnimal instead.\\")]] SampleTurboModuleBaseAnimal { P0 name; bool operator==(const SampleTurboModuleBaseAnimal &other) const { return name == other.name; @@ -2965,7 +3485,7 @@ struct SampleTurboModuleBaseAnimal { }; template -struct SampleTurboModuleBaseAnimalBridging { +struct [[deprecated(\\"Use SampleTurboModuleAnimalBridging instead.\\")]] SampleTurboModuleBaseAnimalBridging { static SampleTurboModuleBaseAnimal fromJs( jsi::Runtime &rt, const jsi::Object &value, @@ -2991,6 +3511,46 @@ struct SampleTurboModuleBaseAnimalBridging { } }; + +#pragma mark - SampleTurboModuleAnimal + +template +struct SampleTurboModuleAnimal { + P0 name; + bool operator==(const SampleTurboModuleAnimal &other) const { + return name == other.name; + } +}; + +template +struct SampleTurboModuleAnimalBridging { + static T types; + + static T fromJs( + jsi::Runtime &rt, + const jsi::Object &value, + const std::shared_ptr &jsInvoker) { + T result{ + bridging::fromJs(rt, value.getProperty(rt, \\"name\\"), jsInvoker)}; + return result; + } + +#ifdef DEBUG + static jsi::String nameToJs(jsi::Runtime &rt, decltype(types.name) value) { + return bridging::toJs(rt, value); + } +#endif + + static jsi::Object toJs( + jsi::Runtime &rt, + const T &value, + const std::shared_ptr &jsInvoker) { + auto result = facebook::jsi::Object(rt); + result.setProperty(rt, \\"name\\", bridging::toJs(rt, value.name, jsInvoker)); + return result; + } +}; + class JSI_EXPORT NativeSampleTurboModuleCxxSpecJSI : public TurboModule { protected: NativeSampleTurboModuleCxxSpecJSI(std::shared_ptr jsInvoker); @@ -3149,7 +3709,7 @@ private: #pragma mark - SampleTurboModuleArraysBaseAnimal template -struct SampleTurboModuleArraysBaseAnimal { +struct [[deprecated(\\"Use SampleTurboModuleArraysAnimal instead.\\")]] SampleTurboModuleArraysBaseAnimal { P0 name; bool operator==(const SampleTurboModuleArraysBaseAnimal &other) const { return name == other.name; @@ -3157,7 +3717,7 @@ struct SampleTurboModuleArraysBaseAnimal { }; template -struct SampleTurboModuleArraysBaseAnimalBridging { +struct [[deprecated(\\"Use SampleTurboModuleArraysAnimalBridging instead.\\")]] SampleTurboModuleArraysBaseAnimalBridging { static SampleTurboModuleArraysBaseAnimal fromJs( jsi::Runtime &rt, const jsi::Object &value, @@ -3183,6 +3743,46 @@ struct SampleTurboModuleArraysBaseAnimalBridging { } }; + +#pragma mark - SampleTurboModuleArraysAnimal + +template +struct SampleTurboModuleArraysAnimal { + P0 name; + bool operator==(const SampleTurboModuleArraysAnimal &other) const { + return name == other.name; + } +}; + +template +struct SampleTurboModuleArraysAnimalBridging { + static T types; + + static T fromJs( + jsi::Runtime &rt, + const jsi::Object &value, + const std::shared_ptr &jsInvoker) { + T result{ + bridging::fromJs(rt, value.getProperty(rt, \\"name\\"), jsInvoker)}; + return result; + } + +#ifdef DEBUG + static jsi::String nameToJs(jsi::Runtime &rt, decltype(types.name) value) { + return bridging::toJs(rt, value); + } +#endif + + static jsi::Object toJs( + jsi::Runtime &rt, + const T &value, + const std::shared_ptr &jsInvoker) { + auto result = facebook::jsi::Object(rt); + result.setProperty(rt, \\"name\\", bridging::toJs(rt, value.name, jsInvoker)); + return result; + } +}; + class JSI_EXPORT NativeSampleTurboModuleArraysCxxSpecJSI : public TurboModule { protected: NativeSampleTurboModuleArraysCxxSpecJSI(std::shared_ptr jsInvoker); @@ -3341,7 +3941,7 @@ private: #pragma mark - SampleTurboModuleNullableBaseAnimal template -struct SampleTurboModuleNullableBaseAnimal { +struct [[deprecated(\\"Use SampleTurboModuleNullableAnimal instead.\\")]] SampleTurboModuleNullableBaseAnimal { P0 name; bool operator==(const SampleTurboModuleNullableBaseAnimal &other) const { return name == other.name; @@ -3349,7 +3949,7 @@ struct SampleTurboModuleNullableBaseAnimal { }; template -struct SampleTurboModuleNullableBaseAnimalBridging { +struct [[deprecated(\\"Use SampleTurboModuleNullableAnimalBridging instead.\\")]] SampleTurboModuleNullableBaseAnimalBridging { static SampleTurboModuleNullableBaseAnimal fromJs( jsi::Runtime &rt, const jsi::Object &value, @@ -3375,6 +3975,46 @@ struct SampleTurboModuleNullableBaseAnimalBridging { } }; + +#pragma mark - SampleTurboModuleNullableAnimal + +template +struct SampleTurboModuleNullableAnimal { + P0 name; + bool operator==(const SampleTurboModuleNullableAnimal &other) const { + return name == other.name; + } +}; + +template +struct SampleTurboModuleNullableAnimalBridging { + static T types; + + static T fromJs( + jsi::Runtime &rt, + const jsi::Object &value, + const std::shared_ptr &jsInvoker) { + T result{ + bridging::fromJs(rt, value.getProperty(rt, \\"name\\"), jsInvoker)}; + return result; + } + +#ifdef DEBUG + static std::optional nameToJs(jsi::Runtime &rt, decltype(types.name) value) { + return bridging::toJs(rt, value); + } +#endif + + static jsi::Object toJs( + jsi::Runtime &rt, + const T &value, + const std::shared_ptr &jsInvoker) { + auto result = facebook::jsi::Object(rt); + result.setProperty(rt, \\"name\\", bridging::toJs(rt, value.name, jsInvoker)); + return result; + } +}; + class JSI_EXPORT NativeSampleTurboModuleNullableCxxSpecJSI : public TurboModule { protected: NativeSampleTurboModuleNullableCxxSpecJSI(std::shared_ptr jsInvoker); @@ -3533,7 +4173,7 @@ private: #pragma mark - SampleTurboModuleNullableAndOptionalBaseAnimal template -struct SampleTurboModuleNullableAndOptionalBaseAnimal { +struct [[deprecated(\\"Use SampleTurboModuleNullableAndOptionalAnimal instead.\\")]] SampleTurboModuleNullableAndOptionalBaseAnimal { P0 name; bool operator==(const SampleTurboModuleNullableAndOptionalBaseAnimal &other) const { return name == other.name; @@ -3541,7 +4181,7 @@ struct SampleTurboModuleNullableAndOptionalBaseAnimal { }; template -struct SampleTurboModuleNullableAndOptionalBaseAnimalBridging { +struct [[deprecated(\\"Use SampleTurboModuleNullableAndOptionalAnimalBridging instead.\\")]] SampleTurboModuleNullableAndOptionalBaseAnimalBridging { static SampleTurboModuleNullableAndOptionalBaseAnimal fromJs( jsi::Runtime &rt, const jsi::Object &value, @@ -3569,6 +4209,48 @@ struct SampleTurboModuleNullableAndOptionalBaseAnimalBridging { } }; + +#pragma mark - SampleTurboModuleNullableAndOptionalAnimal + +template +struct SampleTurboModuleNullableAndOptionalAnimal { + P0 name; + bool operator==(const SampleTurboModuleNullableAndOptionalAnimal &other) const { + return name == other.name; + } +}; + +template +struct SampleTurboModuleNullableAndOptionalAnimalBridging { + static T types; + + static T fromJs( + jsi::Runtime &rt, + const jsi::Object &value, + const std::shared_ptr &jsInvoker) { + T result{ + bridging::fromJs(rt, value.getProperty(rt, \\"name\\"), jsInvoker)}; + return result; + } + +#ifdef DEBUG + static std::optional nameToJs(jsi::Runtime &rt, decltype(types.name) value) { + return bridging::toJs(rt, value); + } +#endif + + static jsi::Object toJs( + jsi::Runtime &rt, + const T &value, + const std::shared_ptr &jsInvoker) { + auto result = facebook::jsi::Object(rt); + if (value.name) { + result.setProperty(rt, \\"name\\", bridging::toJs(rt, value.name.value(), jsInvoker)); + } + return result; + } +}; + class JSI_EXPORT NativeSampleTurboModuleNullableAndOptionalCxxSpecJSI : public TurboModule { protected: NativeSampleTurboModuleNullableAndOptionalCxxSpecJSI(std::shared_ptr jsInvoker); @@ -3727,7 +4409,7 @@ private: #pragma mark - SampleTurboModuleOptionalBaseAnimal template -struct SampleTurboModuleOptionalBaseAnimal { +struct [[deprecated(\\"Use SampleTurboModuleOptionalAnimal instead.\\")]] SampleTurboModuleOptionalBaseAnimal { P0 name; bool operator==(const SampleTurboModuleOptionalBaseAnimal &other) const { return name == other.name; @@ -3735,7 +4417,7 @@ struct SampleTurboModuleOptionalBaseAnimal { }; template -struct SampleTurboModuleOptionalBaseAnimalBridging { +struct [[deprecated(\\"Use SampleTurboModuleOptionalAnimalBridging instead.\\")]] SampleTurboModuleOptionalBaseAnimalBridging { static SampleTurboModuleOptionalBaseAnimal fromJs( jsi::Runtime &rt, const jsi::Object &value, @@ -3763,6 +4445,48 @@ struct SampleTurboModuleOptionalBaseAnimalBridging { } }; + +#pragma mark - SampleTurboModuleOptionalAnimal + +template +struct SampleTurboModuleOptionalAnimal { + P0 name; + bool operator==(const SampleTurboModuleOptionalAnimal &other) const { + return name == other.name; + } +}; + +template +struct SampleTurboModuleOptionalAnimalBridging { + static T types; + + static T fromJs( + jsi::Runtime &rt, + const jsi::Object &value, + const std::shared_ptr &jsInvoker) { + T result{ + bridging::fromJs(rt, value.getProperty(rt, \\"name\\"), jsInvoker)}; + return result; + } + +#ifdef DEBUG + static jsi::String nameToJs(jsi::Runtime &rt, decltype(types.name) value) { + return bridging::toJs(rt, value); + } +#endif + + static jsi::Object toJs( + jsi::Runtime &rt, + const T &value, + const std::shared_ptr &jsInvoker) { + auto result = facebook::jsi::Object(rt); + if (value.name) { + result.setProperty(rt, \\"name\\", bridging::toJs(rt, value.name.value(), jsInvoker)); + } + return result; + } +}; + class JSI_EXPORT NativeSampleTurboModuleOptionalCxxSpecJSI : public TurboModule { protected: NativeSampleTurboModuleOptionalCxxSpecJSI(std::shared_ptr jsInvoker); diff --git a/packages/react-native-codegen/src/generators/modules/GenerateModuleH.js b/packages/react-native-codegen/src/generators/modules/GenerateModuleH.js index 6dd3289216aadc..31b29998105089 100644 --- a/packages/react-native-codegen/src/generators/modules/GenerateModuleH.js +++ b/packages/react-native-codegen/src/generators/modules/GenerateModuleH.js @@ -232,33 +232,36 @@ function createStructsString( enumMap, ); - return Object.keys(aliasMap) - .map(alias => { - const value = aliasMap[alias]; - if (value.properties.length === 0) { - return ''; - } - const structName = `${moduleName}Base${alias}`; - const templateParameterWithTypename = value.properties - .map((v, i) => `typename P${i}`) - .join(', '); - const templateParameter = value.properties - .map((v, i) => 'P' + i) - .join(', '); - const debugParameterConversion = value.properties - .map( - (v, i) => ` static ${getCppType(v)} ${ - v.name - }ToJs(jsi::Runtime &rt, P${i} value) { + // TODO: T171006733 [Begin] Remove deprecated Cxx TMs structs after a new release. + return ( + Object.keys(aliasMap) + .map(alias => { + const value = aliasMap[alias]; + if (value.properties.length === 0) { + return ''; + } + const structName = `${moduleName}Base${alias}`; + const structNameNew = `${moduleName}${alias}`; + const templateParameterWithTypename = value.properties + .map((v, i) => `typename P${i}`) + .join(', '); + const templateParameter = value.properties + .map((v, i) => 'P' + i) + .join(', '); + const debugParameterConversion = value.properties + .map( + (v, i) => ` static ${getCppType(v)} ${ + v.name + }ToJs(jsi::Runtime &rt, P${i} value) { return bridging::toJs(rt, value); }`, - ) - .join('\n\n'); - return ` + ) + .join('\n\n'); + return ` #pragma mark - ${structName} template <${templateParameterWithTypename}> -struct ${structName} { +struct [[deprecated("Use ${structNameNew} instead.")]] ${structName} { ${value.properties.map((v, i) => ' P' + i + ' ' + v.name).join(';\n')}; bool operator==(const ${structName} &other) const { return ${value.properties @@ -268,7 +271,7 @@ ${value.properties.map((v, i) => ' P' + i + ' ' + v.name).join(';\n')}; }; template <${templateParameterWithTypename}> -struct ${structName}Bridging { +struct [[deprecated("Use ${structNameNew}Bridging instead.")]] ${structName}Bridging { static ${structName}<${templateParameter}> fromJs( jsi::Runtime &rt, const jsi::Object &value, @@ -308,8 +311,87 @@ ${value.properties }; `; - }) - .join('\n'); + }) + .join('\n') + + // TODO: T171006733 [End] Remove deprecated Cxx TMs structs after a new release. + Object.keys(aliasMap) + .map(alias => { + const value = aliasMap[alias]; + if (value.properties.length === 0) { + return ''; + } + const structName = `${moduleName}${alias}`; + const templateParameterWithTypename = value.properties + .map((v, i) => `typename P${i}`) + .join(', '); + const debugParameterConversion = value.properties + .map( + (v, i) => ` static ${getCppType(v)} ${ + v.name + }ToJs(jsi::Runtime &rt, decltype(types.${v.name}) value) { + return bridging::toJs(rt, value); + }`, + ) + .join('\n\n'); + return ` +#pragma mark - ${structName} + +template <${templateParameterWithTypename}> +struct ${structName} { +${value.properties.map((v, i) => ' P' + i + ' ' + v.name).join(';\n')}; + bool operator==(const ${structName} &other) const { + return ${value.properties + .map(v => `${v.name} == other.${v.name}`) + .join(' && ')}; + } +}; + +template +struct ${structName}Bridging { + static T types; + + static T fromJs( + jsi::Runtime &rt, + const jsi::Object &value, + const std::shared_ptr &jsInvoker) { + T result{ +${value.properties + .map( + (v, i) => + ` bridging::fromJs(rt, value.getProperty(rt, "${v.name}"), jsInvoker)`, + ) + .join(',\n')}}; + return result; + } + +#ifdef DEBUG +${debugParameterConversion} +#endif + + static jsi::Object toJs( + jsi::Runtime &rt, + const T &value, + const std::shared_ptr &jsInvoker) { + auto result = facebook::jsi::Object(rt); +${value.properties + .map((v, i) => { + if (v.optional) { + return ` if (value.${v.name}) { + result.setProperty(rt, "${v.name}", bridging::toJs(rt, value.${v.name}.value(), jsInvoker)); + }`; + } else { + return ` result.setProperty(rt, "${v.name}", bridging::toJs(rt, value.${v.name}, jsInvoker));`; + } + }) + .join('\n')} + return result; + } +}; + +`; + }) + .join('\n') + ); } type NativeEnumMemberValueType = 'std::string' | 'int32_t' | 'float'; diff --git a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleH-test.js.snap b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleH-test.js.snap index 75e2dd9187d176..aa012fe2c151e3 100644 --- a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleH-test.js.snap +++ b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleH-test.js.snap @@ -300,7 +300,7 @@ struct Bridging { #pragma mark - SampleTurboModuleCxxBaseObjectAlias template -struct SampleTurboModuleCxxBaseObjectAlias { +struct [[deprecated(\\"Use SampleTurboModuleCxxObjectAlias instead.\\")]] SampleTurboModuleCxxBaseObjectAlias { P0 x; bool operator==(const SampleTurboModuleCxxBaseObjectAlias &other) const { return x == other.x; @@ -308,7 +308,7 @@ struct SampleTurboModuleCxxBaseObjectAlias { }; template -struct SampleTurboModuleCxxBaseObjectAliasBridging { +struct [[deprecated(\\"Use SampleTurboModuleCxxObjectAliasBridging instead.\\")]] SampleTurboModuleCxxBaseObjectAliasBridging { static SampleTurboModuleCxxBaseObjectAlias fromJs( jsi::Runtime &rt, const jsi::Object &value, @@ -334,6 +334,46 @@ struct SampleTurboModuleCxxBaseObjectAliasBridging { } }; + +#pragma mark - SampleTurboModuleCxxObjectAlias + +template +struct SampleTurboModuleCxxObjectAlias { + P0 x; + bool operator==(const SampleTurboModuleCxxObjectAlias &other) const { + return x == other.x; + } +}; + +template +struct SampleTurboModuleCxxObjectAliasBridging { + static T types; + + static T fromJs( + jsi::Runtime &rt, + const jsi::Object &value, + const std::shared_ptr &jsInvoker) { + T result{ + bridging::fromJs(rt, value.getProperty(rt, \\"x\\"), jsInvoker)}; + return result; + } + +#ifdef DEBUG + static double xToJs(jsi::Runtime &rt, decltype(types.x) value) { + return bridging::toJs(rt, value); + } +#endif + + static jsi::Object toJs( + jsi::Runtime &rt, + const T &value, + const std::shared_ptr &jsInvoker) { + auto result = facebook::jsi::Object(rt); + result.setProperty(rt, \\"x\\", bridging::toJs(rt, value.x, jsInvoker)); + return result; + } +}; + class JSI_EXPORT NativeSampleTurboModuleCxxSpecJSI : public TurboModule { protected: NativeSampleTurboModuleCxxSpecJSI(std::shared_ptr jsInvoker); @@ -509,7 +549,7 @@ namespace react { #pragma mark - AliasTurboModuleBaseOptions template -struct AliasTurboModuleBaseOptions { +struct [[deprecated(\\"Use AliasTurboModuleOptions instead.\\")]] AliasTurboModuleBaseOptions { P0 offset; P1 size; P2 displaySize; @@ -521,7 +561,7 @@ struct AliasTurboModuleBaseOptions { }; template -struct AliasTurboModuleBaseOptionsBridging { +struct [[deprecated(\\"Use AliasTurboModuleOptionsBridging instead.\\")]] AliasTurboModuleBaseOptionsBridging { static AliasTurboModuleBaseOptions fromJs( jsi::Runtime &rt, const jsi::Object &value, @@ -577,6 +617,80 @@ struct AliasTurboModuleBaseOptionsBridging { } }; + +#pragma mark - AliasTurboModuleOptions + +template +struct AliasTurboModuleOptions { + P0 offset; + P1 size; + P2 displaySize; + P3 resizeMode; + P4 allowExternalStorage; + bool operator==(const AliasTurboModuleOptions &other) const { + return offset == other.offset && size == other.size && displaySize == other.displaySize && resizeMode == other.resizeMode && allowExternalStorage == other.allowExternalStorage; + } +}; + +template +struct AliasTurboModuleOptionsBridging { + static T types; + + static T fromJs( + jsi::Runtime &rt, + const jsi::Object &value, + const std::shared_ptr &jsInvoker) { + T result{ + bridging::fromJs(rt, value.getProperty(rt, \\"offset\\"), jsInvoker), + bridging::fromJs(rt, value.getProperty(rt, \\"size\\"), jsInvoker), + bridging::fromJs(rt, value.getProperty(rt, \\"displaySize\\"), jsInvoker), + bridging::fromJs(rt, value.getProperty(rt, \\"resizeMode\\"), jsInvoker), + bridging::fromJs(rt, value.getProperty(rt, \\"allowExternalStorage\\"), jsInvoker)}; + return result; + } + +#ifdef DEBUG + static jsi::Object offsetToJs(jsi::Runtime &rt, decltype(types.offset) value) { + return bridging::toJs(rt, value); + } + + static jsi::Object sizeToJs(jsi::Runtime &rt, decltype(types.size) value) { + return bridging::toJs(rt, value); + } + + static jsi::Object displaySizeToJs(jsi::Runtime &rt, decltype(types.displaySize) value) { + return bridging::toJs(rt, value); + } + + static jsi::String resizeModeToJs(jsi::Runtime &rt, decltype(types.resizeMode) value) { + return bridging::toJs(rt, value); + } + + static bool allowExternalStorageToJs(jsi::Runtime &rt, decltype(types.allowExternalStorage) value) { + return bridging::toJs(rt, value); + } +#endif + + static jsi::Object toJs( + jsi::Runtime &rt, + const T &value, + const std::shared_ptr &jsInvoker) { + auto result = facebook::jsi::Object(rt); + result.setProperty(rt, \\"offset\\", bridging::toJs(rt, value.offset, jsInvoker)); + result.setProperty(rt, \\"size\\", bridging::toJs(rt, value.size, jsInvoker)); + if (value.displaySize) { + result.setProperty(rt, \\"displaySize\\", bridging::toJs(rt, value.displaySize.value(), jsInvoker)); + } + if (value.resizeMode) { + result.setProperty(rt, \\"resizeMode\\", bridging::toJs(rt, value.resizeMode.value(), jsInvoker)); + } + if (value.allowExternalStorage) { + result.setProperty(rt, \\"allowExternalStorage\\", bridging::toJs(rt, value.allowExternalStorage.value(), jsInvoker)); + } + return result; + } +}; + class JSI_EXPORT AliasTurboModuleCxxSpecJSI : public TurboModule { protected: AliasTurboModuleCxxSpecJSI(std::shared_ptr jsInvoker); @@ -661,7 +775,7 @@ namespace react { #pragma mark - CameraRollManagerBasePhotoIdentifierImage template -struct CameraRollManagerBasePhotoIdentifierImage { +struct [[deprecated(\\"Use CameraRollManagerPhotoIdentifierImage instead.\\")]] CameraRollManagerBasePhotoIdentifierImage { P0 uri; P1 playableDuration; P2 width; @@ -674,7 +788,7 @@ struct CameraRollManagerBasePhotoIdentifierImage { }; template -struct CameraRollManagerBasePhotoIdentifierImageBridging { +struct [[deprecated(\\"Use CameraRollManagerPhotoIdentifierImageBridging instead.\\")]] CameraRollManagerBasePhotoIdentifierImageBridging { static CameraRollManagerBasePhotoIdentifierImage fromJs( jsi::Runtime &rt, const jsi::Object &value, @@ -737,7 +851,7 @@ struct CameraRollManagerBasePhotoIdentifierImageBridging { #pragma mark - CameraRollManagerBasePhotoIdentifier template -struct CameraRollManagerBasePhotoIdentifier { +struct [[deprecated(\\"Use CameraRollManagerPhotoIdentifier instead.\\")]] CameraRollManagerBasePhotoIdentifier { P0 node; bool operator==(const CameraRollManagerBasePhotoIdentifier &other) const { return node == other.node; @@ -745,7 +859,7 @@ struct CameraRollManagerBasePhotoIdentifier { }; template -struct CameraRollManagerBasePhotoIdentifierBridging { +struct [[deprecated(\\"Use CameraRollManagerPhotoIdentifierBridging instead.\\")]] CameraRollManagerBasePhotoIdentifierBridging { static CameraRollManagerBasePhotoIdentifier fromJs( jsi::Runtime &rt, const jsi::Object &value, @@ -776,7 +890,7 @@ struct CameraRollManagerBasePhotoIdentifierBridging { #pragma mark - CameraRollManagerBasePhotoIdentifiersPage template -struct CameraRollManagerBasePhotoIdentifiersPage { +struct [[deprecated(\\"Use CameraRollManagerPhotoIdentifiersPage instead.\\")]] CameraRollManagerBasePhotoIdentifiersPage { P0 edges; P1 page_info; bool operator==(const CameraRollManagerBasePhotoIdentifiersPage &other) const { @@ -785,7 +899,7 @@ struct CameraRollManagerBasePhotoIdentifiersPage { }; template -struct CameraRollManagerBasePhotoIdentifiersPageBridging { +struct [[deprecated(\\"Use CameraRollManagerPhotoIdentifiersPageBridging instead.\\")]] CameraRollManagerBasePhotoIdentifiersPageBridging { static CameraRollManagerBasePhotoIdentifiersPage fromJs( jsi::Runtime &rt, const jsi::Object &value, @@ -822,7 +936,7 @@ struct CameraRollManagerBasePhotoIdentifiersPageBridging { #pragma mark - CameraRollManagerBaseGetPhotosParams template -struct CameraRollManagerBaseGetPhotosParams { +struct [[deprecated(\\"Use CameraRollManagerGetPhotosParams instead.\\")]] CameraRollManagerBaseGetPhotosParams { P0 first; P1 after; P2 groupName; @@ -836,7 +950,7 @@ struct CameraRollManagerBaseGetPhotosParams { }; template -struct CameraRollManagerBaseGetPhotosParamsBridging { +struct [[deprecated(\\"Use CameraRollManagerGetPhotosParamsBridging instead.\\")]] CameraRollManagerBaseGetPhotosParamsBridging { static CameraRollManagerBaseGetPhotosParams fromJs( jsi::Runtime &rt, const jsi::Object &value, @@ -910,6 +1024,267 @@ struct CameraRollManagerBaseGetPhotosParamsBridging { } }; + +#pragma mark - CameraRollManagerPhotoIdentifierImage + +template +struct CameraRollManagerPhotoIdentifierImage { + P0 uri; + P1 playableDuration; + P2 width; + P3 height; + P4 isStored; + P5 filename; + bool operator==(const CameraRollManagerPhotoIdentifierImage &other) const { + return uri == other.uri && playableDuration == other.playableDuration && width == other.width && height == other.height && isStored == other.isStored && filename == other.filename; + } +}; + +template +struct CameraRollManagerPhotoIdentifierImageBridging { + static T types; + + static T fromJs( + jsi::Runtime &rt, + const jsi::Object &value, + const std::shared_ptr &jsInvoker) { + T result{ + bridging::fromJs(rt, value.getProperty(rt, \\"uri\\"), jsInvoker), + bridging::fromJs(rt, value.getProperty(rt, \\"playableDuration\\"), jsInvoker), + bridging::fromJs(rt, value.getProperty(rt, \\"width\\"), jsInvoker), + bridging::fromJs(rt, value.getProperty(rt, \\"height\\"), jsInvoker), + bridging::fromJs(rt, value.getProperty(rt, \\"isStored\\"), jsInvoker), + bridging::fromJs(rt, value.getProperty(rt, \\"filename\\"), jsInvoker)}; + return result; + } + +#ifdef DEBUG + static jsi::String uriToJs(jsi::Runtime &rt, decltype(types.uri) value) { + return bridging::toJs(rt, value); + } + + static double playableDurationToJs(jsi::Runtime &rt, decltype(types.playableDuration) value) { + return bridging::toJs(rt, value); + } + + static double widthToJs(jsi::Runtime &rt, decltype(types.width) value) { + return bridging::toJs(rt, value); + } + + static double heightToJs(jsi::Runtime &rt, decltype(types.height) value) { + return bridging::toJs(rt, value); + } + + static bool isStoredToJs(jsi::Runtime &rt, decltype(types.isStored) value) { + return bridging::toJs(rt, value); + } + + static jsi::String filenameToJs(jsi::Runtime &rt, decltype(types.filename) value) { + return bridging::toJs(rt, value); + } +#endif + + static jsi::Object toJs( + jsi::Runtime &rt, + const T &value, + const std::shared_ptr &jsInvoker) { + auto result = facebook::jsi::Object(rt); + result.setProperty(rt, \\"uri\\", bridging::toJs(rt, value.uri, jsInvoker)); + result.setProperty(rt, \\"playableDuration\\", bridging::toJs(rt, value.playableDuration, jsInvoker)); + result.setProperty(rt, \\"width\\", bridging::toJs(rt, value.width, jsInvoker)); + result.setProperty(rt, \\"height\\", bridging::toJs(rt, value.height, jsInvoker)); + if (value.isStored) { + result.setProperty(rt, \\"isStored\\", bridging::toJs(rt, value.isStored.value(), jsInvoker)); + } + result.setProperty(rt, \\"filename\\", bridging::toJs(rt, value.filename, jsInvoker)); + return result; + } +}; + + + +#pragma mark - CameraRollManagerPhotoIdentifier + +template +struct CameraRollManagerPhotoIdentifier { + P0 node; + bool operator==(const CameraRollManagerPhotoIdentifier &other) const { + return node == other.node; + } +}; + +template +struct CameraRollManagerPhotoIdentifierBridging { + static T types; + + static T fromJs( + jsi::Runtime &rt, + const jsi::Object &value, + const std::shared_ptr &jsInvoker) { + T result{ + bridging::fromJs(rt, value.getProperty(rt, \\"node\\"), jsInvoker)}; + return result; + } + +#ifdef DEBUG + static jsi::Object nodeToJs(jsi::Runtime &rt, decltype(types.node) value) { + return bridging::toJs(rt, value); + } +#endif + + static jsi::Object toJs( + jsi::Runtime &rt, + const T &value, + const std::shared_ptr &jsInvoker) { + auto result = facebook::jsi::Object(rt); + result.setProperty(rt, \\"node\\", bridging::toJs(rt, value.node, jsInvoker)); + return result; + } +}; + + + +#pragma mark - CameraRollManagerPhotoIdentifiersPage + +template +struct CameraRollManagerPhotoIdentifiersPage { + P0 edges; + P1 page_info; + bool operator==(const CameraRollManagerPhotoIdentifiersPage &other) const { + return edges == other.edges && page_info == other.page_info; + } +}; + +template +struct CameraRollManagerPhotoIdentifiersPageBridging { + static T types; + + static T fromJs( + jsi::Runtime &rt, + const jsi::Object &value, + const std::shared_ptr &jsInvoker) { + T result{ + bridging::fromJs(rt, value.getProperty(rt, \\"edges\\"), jsInvoker), + bridging::fromJs(rt, value.getProperty(rt, \\"page_info\\"), jsInvoker)}; + return result; + } + +#ifdef DEBUG + static jsi::Array edgesToJs(jsi::Runtime &rt, decltype(types.edges) value) { + return bridging::toJs(rt, value); + } + + static jsi::Object page_infoToJs(jsi::Runtime &rt, decltype(types.page_info) value) { + return bridging::toJs(rt, value); + } +#endif + + static jsi::Object toJs( + jsi::Runtime &rt, + const T &value, + const std::shared_ptr &jsInvoker) { + auto result = facebook::jsi::Object(rt); + result.setProperty(rt, \\"edges\\", bridging::toJs(rt, value.edges, jsInvoker)); + result.setProperty(rt, \\"page_info\\", bridging::toJs(rt, value.page_info, jsInvoker)); + return result; + } +}; + + + +#pragma mark - CameraRollManagerGetPhotosParams + +template +struct CameraRollManagerGetPhotosParams { + P0 first; + P1 after; + P2 groupName; + P3 groupTypes; + P4 assetType; + P5 maxSize; + P6 mimeTypes; + bool operator==(const CameraRollManagerGetPhotosParams &other) const { + return first == other.first && after == other.after && groupName == other.groupName && groupTypes == other.groupTypes && assetType == other.assetType && maxSize == other.maxSize && mimeTypes == other.mimeTypes; + } +}; + +template +struct CameraRollManagerGetPhotosParamsBridging { + static T types; + + static T fromJs( + jsi::Runtime &rt, + const jsi::Object &value, + const std::shared_ptr &jsInvoker) { + T result{ + bridging::fromJs(rt, value.getProperty(rt, \\"first\\"), jsInvoker), + bridging::fromJs(rt, value.getProperty(rt, \\"after\\"), jsInvoker), + bridging::fromJs(rt, value.getProperty(rt, \\"groupName\\"), jsInvoker), + bridging::fromJs(rt, value.getProperty(rt, \\"groupTypes\\"), jsInvoker), + bridging::fromJs(rt, value.getProperty(rt, \\"assetType\\"), jsInvoker), + bridging::fromJs(rt, value.getProperty(rt, \\"maxSize\\"), jsInvoker), + bridging::fromJs(rt, value.getProperty(rt, \\"mimeTypes\\"), jsInvoker)}; + return result; + } + +#ifdef DEBUG + static double firstToJs(jsi::Runtime &rt, decltype(types.first) value) { + return bridging::toJs(rt, value); + } + + static jsi::String afterToJs(jsi::Runtime &rt, decltype(types.after) value) { + return bridging::toJs(rt, value); + } + + static jsi::String groupNameToJs(jsi::Runtime &rt, decltype(types.groupName) value) { + return bridging::toJs(rt, value); + } + + static jsi::String groupTypesToJs(jsi::Runtime &rt, decltype(types.groupTypes) value) { + return bridging::toJs(rt, value); + } + + static jsi::String assetTypeToJs(jsi::Runtime &rt, decltype(types.assetType) value) { + return bridging::toJs(rt, value); + } + + static double maxSizeToJs(jsi::Runtime &rt, decltype(types.maxSize) value) { + return bridging::toJs(rt, value); + } + + static jsi::Array mimeTypesToJs(jsi::Runtime &rt, decltype(types.mimeTypes) value) { + return bridging::toJs(rt, value); + } +#endif + + static jsi::Object toJs( + jsi::Runtime &rt, + const T &value, + const std::shared_ptr &jsInvoker) { + auto result = facebook::jsi::Object(rt); + result.setProperty(rt, \\"first\\", bridging::toJs(rt, value.first, jsInvoker)); + if (value.after) { + result.setProperty(rt, \\"after\\", bridging::toJs(rt, value.after.value(), jsInvoker)); + } + if (value.groupName) { + result.setProperty(rt, \\"groupName\\", bridging::toJs(rt, value.groupName.value(), jsInvoker)); + } + if (value.groupTypes) { + result.setProperty(rt, \\"groupTypes\\", bridging::toJs(rt, value.groupTypes.value(), jsInvoker)); + } + if (value.assetType) { + result.setProperty(rt, \\"assetType\\", bridging::toJs(rt, value.assetType.value(), jsInvoker)); + } + if (value.maxSize) { + result.setProperty(rt, \\"maxSize\\", bridging::toJs(rt, value.maxSize.value(), jsInvoker)); + } + if (value.mimeTypes) { + result.setProperty(rt, \\"mimeTypes\\", bridging::toJs(rt, value.mimeTypes.value(), jsInvoker)); + } + return result; + } +}; + class JSI_EXPORT NativeCameraRollManagerCxxSpecJSI : public TurboModule { protected: NativeCameraRollManagerCxxSpecJSI(std::shared_ptr jsInvoker); @@ -987,7 +1362,7 @@ private: #pragma mark - ExceptionsManagerBaseStackFrame template -struct ExceptionsManagerBaseStackFrame { +struct [[deprecated(\\"Use ExceptionsManagerStackFrame instead.\\")]] ExceptionsManagerBaseStackFrame { P0 column; P1 file; P2 lineNumber; @@ -999,7 +1374,7 @@ struct ExceptionsManagerBaseStackFrame { }; template -struct ExceptionsManagerBaseStackFrameBridging { +struct [[deprecated(\\"Use ExceptionsManagerStackFrameBridging instead.\\")]] ExceptionsManagerBaseStackFrameBridging { static ExceptionsManagerBaseStackFrame fromJs( jsi::Runtime &rt, const jsi::Object &value, @@ -1060,7 +1435,7 @@ struct ExceptionsManagerBaseStackFrameBridging { #pragma mark - ExceptionsManagerBaseExceptionData template -struct ExceptionsManagerBaseExceptionData { +struct [[deprecated(\\"Use ExceptionsManagerExceptionData instead.\\")]] ExceptionsManagerBaseExceptionData { P0 message; P1 originalMessage; P2 name; @@ -1075,7 +1450,7 @@ struct ExceptionsManagerBaseExceptionData { }; template -struct ExceptionsManagerBaseExceptionDataBridging { +struct [[deprecated(\\"Use ExceptionsManagerExceptionDataBridging instead.\\")]] ExceptionsManagerBaseExceptionDataBridging { static ExceptionsManagerBaseExceptionData fromJs( jsi::Runtime &rt, const jsi::Object &value, @@ -1145,6 +1520,172 @@ struct ExceptionsManagerBaseExceptionDataBridging { } }; + +#pragma mark - ExceptionsManagerStackFrame + +template +struct ExceptionsManagerStackFrame { + P0 column; + P1 file; + P2 lineNumber; + P3 methodName; + P4 collapse; + bool operator==(const ExceptionsManagerStackFrame &other) const { + return column == other.column && file == other.file && lineNumber == other.lineNumber && methodName == other.methodName && collapse == other.collapse; + } +}; + +template +struct ExceptionsManagerStackFrameBridging { + static T types; + + static T fromJs( + jsi::Runtime &rt, + const jsi::Object &value, + const std::shared_ptr &jsInvoker) { + T result{ + bridging::fromJs(rt, value.getProperty(rt, \\"column\\"), jsInvoker), + bridging::fromJs(rt, value.getProperty(rt, \\"file\\"), jsInvoker), + bridging::fromJs(rt, value.getProperty(rt, \\"lineNumber\\"), jsInvoker), + bridging::fromJs(rt, value.getProperty(rt, \\"methodName\\"), jsInvoker), + bridging::fromJs(rt, value.getProperty(rt, \\"collapse\\"), jsInvoker)}; + return result; + } + +#ifdef DEBUG + static double columnToJs(jsi::Runtime &rt, decltype(types.column) value) { + return bridging::toJs(rt, value); + } + + static jsi::String fileToJs(jsi::Runtime &rt, decltype(types.file) value) { + return bridging::toJs(rt, value); + } + + static double lineNumberToJs(jsi::Runtime &rt, decltype(types.lineNumber) value) { + return bridging::toJs(rt, value); + } + + static jsi::String methodNameToJs(jsi::Runtime &rt, decltype(types.methodName) value) { + return bridging::toJs(rt, value); + } + + static bool collapseToJs(jsi::Runtime &rt, decltype(types.collapse) value) { + return bridging::toJs(rt, value); + } +#endif + + static jsi::Object toJs( + jsi::Runtime &rt, + const T &value, + const std::shared_ptr &jsInvoker) { + auto result = facebook::jsi::Object(rt); + if (value.column) { + result.setProperty(rt, \\"column\\", bridging::toJs(rt, value.column.value(), jsInvoker)); + } + result.setProperty(rt, \\"file\\", bridging::toJs(rt, value.file, jsInvoker)); + if (value.lineNumber) { + result.setProperty(rt, \\"lineNumber\\", bridging::toJs(rt, value.lineNumber.value(), jsInvoker)); + } + result.setProperty(rt, \\"methodName\\", bridging::toJs(rt, value.methodName, jsInvoker)); + if (value.collapse) { + result.setProperty(rt, \\"collapse\\", bridging::toJs(rt, value.collapse.value(), jsInvoker)); + } + return result; + } +}; + + + +#pragma mark - ExceptionsManagerExceptionData + +template +struct ExceptionsManagerExceptionData { + P0 message; + P1 originalMessage; + P2 name; + P3 componentStack; + P4 stack; + P5 id; + P6 isFatal; + P7 extraData; + bool operator==(const ExceptionsManagerExceptionData &other) const { + return message == other.message && originalMessage == other.originalMessage && name == other.name && componentStack == other.componentStack && stack == other.stack && id == other.id && isFatal == other.isFatal && extraData == other.extraData; + } +}; + +template +struct ExceptionsManagerExceptionDataBridging { + static T types; + + static T fromJs( + jsi::Runtime &rt, + const jsi::Object &value, + const std::shared_ptr &jsInvoker) { + T result{ + bridging::fromJs(rt, value.getProperty(rt, \\"message\\"), jsInvoker), + bridging::fromJs(rt, value.getProperty(rt, \\"originalMessage\\"), jsInvoker), + bridging::fromJs(rt, value.getProperty(rt, \\"name\\"), jsInvoker), + bridging::fromJs(rt, value.getProperty(rt, \\"componentStack\\"), jsInvoker), + bridging::fromJs(rt, value.getProperty(rt, \\"stack\\"), jsInvoker), + bridging::fromJs(rt, value.getProperty(rt, \\"id\\"), jsInvoker), + bridging::fromJs(rt, value.getProperty(rt, \\"isFatal\\"), jsInvoker), + bridging::fromJs(rt, value.getProperty(rt, \\"extraData\\"), jsInvoker)}; + return result; + } + +#ifdef DEBUG + static jsi::String messageToJs(jsi::Runtime &rt, decltype(types.message) value) { + return bridging::toJs(rt, value); + } + + static jsi::String originalMessageToJs(jsi::Runtime &rt, decltype(types.originalMessage) value) { + return bridging::toJs(rt, value); + } + + static jsi::String nameToJs(jsi::Runtime &rt, decltype(types.name) value) { + return bridging::toJs(rt, value); + } + + static jsi::String componentStackToJs(jsi::Runtime &rt, decltype(types.componentStack) value) { + return bridging::toJs(rt, value); + } + + static jsi::Array stackToJs(jsi::Runtime &rt, decltype(types.stack) value) { + return bridging::toJs(rt, value); + } + + static double idToJs(jsi::Runtime &rt, decltype(types.id) value) { + return bridging::toJs(rt, value); + } + + static bool isFatalToJs(jsi::Runtime &rt, decltype(types.isFatal) value) { + return bridging::toJs(rt, value); + } + + static jsi::Object extraDataToJs(jsi::Runtime &rt, decltype(types.extraData) value) { + return bridging::toJs(rt, value); + } +#endif + + static jsi::Object toJs( + jsi::Runtime &rt, + const T &value, + const std::shared_ptr &jsInvoker) { + auto result = facebook::jsi::Object(rt); + result.setProperty(rt, \\"message\\", bridging::toJs(rt, value.message, jsInvoker)); + result.setProperty(rt, \\"originalMessage\\", bridging::toJs(rt, value.originalMessage, jsInvoker)); + result.setProperty(rt, \\"name\\", bridging::toJs(rt, value.name, jsInvoker)); + result.setProperty(rt, \\"componentStack\\", bridging::toJs(rt, value.componentStack, jsInvoker)); + result.setProperty(rt, \\"stack\\", bridging::toJs(rt, value.stack, jsInvoker)); + result.setProperty(rt, \\"id\\", bridging::toJs(rt, value.id, jsInvoker)); + result.setProperty(rt, \\"isFatal\\", bridging::toJs(rt, value.isFatal, jsInvoker)); + if (value.extraData) { + result.setProperty(rt, \\"extraData\\", bridging::toJs(rt, value.extraData.value(), jsInvoker)); + } + return result; + } +}; + class JSI_EXPORT NativeExceptionsManagerCxxSpecJSI : public TurboModule { protected: NativeExceptionsManagerCxxSpecJSI(std::shared_ptr jsInvoker); diff --git a/packages/react-native/Libraries/IntersectionObserver/NativeIntersectionObserver.h b/packages/react-native/Libraries/IntersectionObserver/NativeIntersectionObserver.h index 20cd6e63db3fa9..1281f60db29fe1 100644 --- a/packages/react-native/Libraries/IntersectionObserver/NativeIntersectionObserver.h +++ b/packages/react-native/Libraries/IntersectionObserver/NativeIntersectionObserver.h @@ -20,7 +20,7 @@ using NativeIntersectionObserverIntersectionObserverId = int32_t; using RectAsTuple = std::tuple; using NativeIntersectionObserverObserveOptions = - NativeIntersectionObserverCxxBaseNativeIntersectionObserverObserveOptions< + NativeIntersectionObserverCxxNativeIntersectionObserverObserveOptions< // intersectionObserverId NativeIntersectionObserverIntersectionObserverId, // targetShadowNode @@ -30,16 +30,11 @@ using NativeIntersectionObserverObserveOptions = template <> struct Bridging - : NativeIntersectionObserverCxxBaseNativeIntersectionObserverObserveOptionsBridging< - // intersectionObserverId - NativeIntersectionObserverIntersectionObserverId, - // targetShadowNode - jsi::Object, - // thresholds - std::vector> {}; + : NativeIntersectionObserverCxxNativeIntersectionObserverObserveOptionsBridging< + NativeIntersectionObserverObserveOptions> {}; using NativeIntersectionObserverEntry = - NativeIntersectionObserverCxxBaseNativeIntersectionObserverEntry< + NativeIntersectionObserverCxxNativeIntersectionObserverEntry< // intersectionObserverId NativeIntersectionObserverIntersectionObserverId, // targetInstanceHandle @@ -57,21 +52,8 @@ using NativeIntersectionObserverEntry = template <> struct Bridging - : NativeIntersectionObserverCxxBaseNativeIntersectionObserverEntryBridging< - // intersectionObserverId - NativeIntersectionObserverIntersectionObserverId, - // targetInstanceHandle - jsi::Value, - // targetRect - RectAsTuple, - // rootRect - RectAsTuple, - // intersectionRect - std::optional, - // isIntersectingAboveThresholds - bool, - // time - double> {}; + : NativeIntersectionObserverCxxNativeIntersectionObserverEntryBridging< + NativeIntersectionObserverEntry> {}; class NativeIntersectionObserver : public NativeIntersectionObserverCxxSpec, diff --git a/packages/react-native/Libraries/MutationObserver/NativeMutationObserver.h b/packages/react-native/Libraries/MutationObserver/NativeMutationObserver.h index cbf7120a49d56a..b7c2eab986d930 100644 --- a/packages/react-native/Libraries/MutationObserver/NativeMutationObserver.h +++ b/packages/react-native/Libraries/MutationObserver/NativeMutationObserver.h @@ -17,7 +17,7 @@ namespace facebook::react { using NativeMutationObserverObserveOptions = - NativeMutationObserverCxxBaseNativeMutationObserverObserveOptions< + NativeMutationObserverCxxNativeMutationObserverObserveOptions< // mutationObserverId MutationObserverId, // targetShadowNode @@ -27,15 +27,10 @@ using NativeMutationObserverObserveOptions = template <> struct Bridging - : NativeMutationObserverCxxBaseNativeMutationObserverObserveOptionsBridging< - // mutationObserverId - MutationObserverId, - // targetShadowNode - jsi::Object, - // subtree - bool> {}; - -using NativeMutationRecord = NativeMutationObserverCxxBaseNativeMutationRecord< + : NativeMutationObserverCxxNativeMutationObserverObserveOptionsBridging< + NativeMutationObserverObserveOptions> {}; + +using NativeMutationRecord = NativeMutationObserverCxxNativeMutationRecord< // mutationObserverId MutationObserverId, // target @@ -47,15 +42,8 @@ using NativeMutationRecord = NativeMutationObserverCxxBaseNativeMutationRecord< template <> struct Bridging - : NativeMutationObserverCxxBaseNativeMutationRecordBridging< - // mutationObserverId - MutationObserverId, - // target - jsi::Value, - // addedNodes - std::vector, - // removedNodes - std::vector> {}; + : NativeMutationObserverCxxNativeMutationRecordBridging< + NativeMutationRecord> {}; class NativeMutationObserver : public NativeMutationObserverCxxSpec, diff --git a/packages/react-native/Libraries/WebPerformance/NativePerformanceObserver.h b/packages/react-native/Libraries/WebPerformance/NativePerformanceObserver.h index bc55f2476d2132..c5e7c3cc4b8ec4 100644 --- a/packages/react-native/Libraries/WebPerformance/NativePerformanceObserver.h +++ b/packages/react-native/Libraries/WebPerformance/NativePerformanceObserver.h @@ -20,7 +20,7 @@ class PerformanceEntryReporter; using RawPerformanceEntryType = int32_t; -using RawPerformanceEntry = NativePerformanceObserverCxxBaseRawPerformanceEntry< +using RawPerformanceEntry = NativePerformanceObserverCxxRawPerformanceEntry< std::string, RawPerformanceEntryType, double, @@ -32,25 +32,18 @@ using RawPerformanceEntry = NativePerformanceObserverCxxBaseRawPerformanceEntry< template <> struct Bridging - : NativePerformanceObserverCxxBaseRawPerformanceEntryBridging< - std::string, - RawPerformanceEntryType, - double, - double, - std::optional, - std::optional, - std::optional> {}; + : NativePerformanceObserverCxxRawPerformanceEntryBridging< + RawPerformanceEntry> {}; using GetPendingEntriesResult = - NativePerformanceObserverCxxBaseGetPendingEntriesResult< + NativePerformanceObserverCxxGetPendingEntriesResult< std::vector, uint32_t>; template <> struct Bridging - : NativePerformanceObserverCxxBaseGetPendingEntriesResultBridging< - std::vector, - uint32_t> {}; + : NativePerformanceObserverCxxGetPendingEntriesResultBridging< + GetPendingEntriesResult> {}; #pragma mark - implementation diff --git a/packages/rn-tester/NativeCxxModuleExample/NativeCxxModuleExample.h b/packages/rn-tester/NativeCxxModuleExample/NativeCxxModuleExample.h index a13f8336b5fa9a..ed2e3aaaf91c69 100644 --- a/packages/rn-tester/NativeCxxModuleExample/NativeCxxModuleExample.h +++ b/packages/rn-tester/NativeCxxModuleExample/NativeCxxModuleExample.h @@ -24,35 +24,27 @@ namespace facebook::react { #pragma mark - Structs using ConstantsStruct = - NativeCxxModuleExampleCxxBaseConstantsStruct; + NativeCxxModuleExampleCxxConstantsStruct; template <> struct Bridging - : NativeCxxModuleExampleCxxBaseConstantsStructBridging< - bool, - int32_t, - std::string> {}; + : NativeCxxModuleExampleCxxConstantsStructBridging {}; -using ObjectStruct = NativeCxxModuleExampleCxxBaseObjectStruct< +using ObjectStruct = NativeCxxModuleExampleCxxObjectStruct< int32_t, std::string, std::optional>; template <> struct Bridging - : NativeCxxModuleExampleCxxBaseObjectStructBridging< - int32_t, - std::string, - std::optional> {}; + : NativeCxxModuleExampleCxxObjectStructBridging {}; using ValueStruct = - NativeCxxModuleExampleCxxBaseValueStruct; + NativeCxxModuleExampleCxxValueStruct; template <> -struct Bridging : NativeCxxModuleExampleCxxBaseValueStructBridging< - double, - std::string, - ObjectStruct> {}; +struct Bridging + : NativeCxxModuleExampleCxxValueStructBridging {}; #pragma mark - enums enum CustomEnumInt { A = 23, B = 42 }; From ca39a11b27bf9f90c3a792974910bb9060b2990f Mon Sep 17 00:00:00 2001 From: Dmitry Rykun Date: Mon, 27 Nov 2023 06:57:53 -0800 Subject: [PATCH 096/162] Refactor generate-artifacts-executor.js: delete handleLibrariesFromReactNativeConfig (#41654) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41654 This diff removes support for defining external codegen targets in `react-native.config.js` for iOS. Now you can simply add your external dependency to the project's `package.json` and it will be resolved as a normal Node packages. ## Motivation The need for defining external codegen targets in `react-native.config.js` historically appeared due to limitations of how codegen searched for external dependencies. Basically we performed search only in the project directory. External dependency paths had to be listed in `react-native.config.js`. After D51303793 has landed we don't need this any longer. We can simply rely on Node resolution to find those external dependencies. Changelog: [iOS][Breaking] - Defining external codegen targets in `react-native.config.js` is not supported anymore. Define them as normal dependencies in `package.json`. Reviewed By: cipolleschi Differential Revision: D51308595 fbshipit-source-id: 97841a3a8c295aa717c577bb188d48373b04ba38 --- .../generate-artifacts-executor-test.js | 70 ------------------- .../codegen/generate-artifacts-executor.js | 45 ------------ 2 files changed, 115 deletions(-) diff --git a/packages/react-native/scripts/codegen/__tests__/generate-artifacts-executor-test.js b/packages/react-native/scripts/codegen/__tests__/generate-artifacts-executor-test.js index f195b66f8210f3..7a85ef8e3bd1ad 100644 --- a/packages/react-native/scripts/codegen/__tests__/generate-artifacts-executor-test.js +++ b/packages/react-native/scripts/codegen/__tests__/generate-artifacts-executor-test.js @@ -118,76 +118,6 @@ describe('extractLibrariesFromJSON', () => { }); }); -describe('findCodegenEnabledLibraries', () => { - const mock = require('mock-fs'); - const { - _findCodegenEnabledLibraries: findCodegenEnabledLibraries, - } = require('../generate-artifacts-executor'); - - afterEach(() => { - mock.restore(); - }); - - it('returns libraries defined in react-native.config.js', () => { - const projectDir = path.join(__dirname, '../../../../test-project'); - const baseCodegenConfigFileDir = path.join(__dirname, '../../..'); - const baseCodegenConfigFilePath = path.join( - baseCodegenConfigFileDir, - 'package.json', - ); - - mock({ - [baseCodegenConfigFilePath]: ` - { - "codegenConfig": {} - } - `, - [projectDir]: { - app: { - 'package.json': `{ - "name": "my-app" - }`, - 'react-native.config.js': '', - }, - 'library-foo': { - 'package.json': `{ - "name": "react-native-foo", - "codegenConfig": { - "name": "RNFooSpec", - "type": "modules", - "jsSrcsDir": "src" - } - }`, - }, - }, - }); - - jest.mock(path.join(projectDir, 'app', 'react-native.config.js'), () => ({ - dependencies: { - 'react-native-foo': { - root: path.join(projectDir, 'library-foo'), - }, - 'react-native-bar': { - root: path.join(projectDir, 'library-bar'), - }, - }, - })); - - const libraries = findCodegenEnabledLibraries(`${projectDir}/app`); - - expect(libraries).toEqual([ - { - config: {}, - libraryPath: baseCodegenConfigFileDir, - }, - { - config: {name: 'RNFooSpec', type: 'modules', jsSrcsDir: 'src'}, - libraryPath: path.join(projectDir, 'library-foo'), - }, - ]); - }); -}); - describe('delete empty files and folders', () => { beforeEach(() => { jest.resetModules(); diff --git a/packages/react-native/scripts/codegen/generate-artifacts-executor.js b/packages/react-native/scripts/codegen/generate-artifacts-executor.js index d72d427c89b66a..afcad1ae7a4cc1 100644 --- a/packages/react-native/scripts/codegen/generate-artifacts-executor.js +++ b/packages/react-native/scripts/codegen/generate-artifacts-executor.js @@ -180,48 +180,6 @@ function handleThirdPartyLibraries(pkgJson) { }); } -function handleLibrariesFromReactNativeConfig(appRootDir) { - const rnConfigFileName = 'react-native.config.js'; - - console.log( - `\n\n[Codegen] >>>>> Searching for codegen-enabled libraries in ${rnConfigFileName}`, - ); - - const rnConfigFilePath = path.resolve(appRootDir, rnConfigFileName); - - if (!fs.existsSync(rnConfigFilePath)) { - return []; - } - const rnConfig = require(rnConfigFilePath); - - if (rnConfig.dependencies == null) { - return []; - } - return Object.keys(rnConfig.dependencies).flatMap(name => { - const dependencyConfig = rnConfig.dependencies[name]; - - if (!dependencyConfig.root) { - return []; - } - const codegenConfigFileDir = path.resolve( - appRootDir, - dependencyConfig.root, - ); - let configFile; - try { - configFile = readPkgJsonInDirectory(codegenConfigFileDir); - } catch { - return []; - } - - return extractLibrariesFromJSON( - configFile, - configFile.name, - codegenConfigFileDir, - ); - }); -} - function handleInAppLibraries(pkgJson, appRootDir) { console.log( '\n\n[Codegen] >>>>> Searching for codegen-enabled libraries in the app', @@ -343,7 +301,6 @@ function findCodegenEnabledLibraries(appRootDir) { return [ ...handleReactNativeCoreLibraries(), ...handleThirdPartyLibraries(pkgJson), - ...handleLibrariesFromReactNativeConfig(appRootDir), ...handleInAppLibraries(pkgJson, appRootDir), ]; } @@ -434,7 +391,5 @@ module.exports = { execute: execute, // exported for testing purposes only: _extractLibrariesFromJSON: extractLibrariesFromJSON, - _findCodegenEnabledLibraries: findCodegenEnabledLibraries, - _generateCode: generateCode, _cleanupEmptyFilesAndFolders: cleanupEmptyFilesAndFolders, }; From 03a840e0a9ff6c0591557e1bac8e44dcdc72d3a9 Mon Sep 17 00:00:00 2001 From: zhongwuzw Date: Mon, 27 Nov 2023 07:09:34 -0800 Subject: [PATCH 097/162] Update AcitvityIndicator spec default value (#41638) Summary: Update AcitvityIndicator spec default value. https://reactnative.dev/docs/activityindicator ## Changelog: [GENERAL] [FIXED] - Update AcitvityIndicator spec default value Pull Request resolved: https://github.com/facebook/react-native/pull/41638 Test Plan: Codegen generates native code correctly. ![image](https://github.com/facebook/react-native/assets/5061845/ae087e06-d996-4aa1-bd41-da84bc50bdd7) Reviewed By: christophpurrer Differential Revision: D51584438 Pulled By: javache fbshipit-source-id: ee0df8314597457fd35f86008a96264be3f761ba --- .../ActivityIndicatorViewNativeComponent.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/react-native/Libraries/Components/ActivityIndicator/ActivityIndicatorViewNativeComponent.js b/packages/react-native/Libraries/Components/ActivityIndicator/ActivityIndicatorViewNativeComponent.js index 7394582902dcf0..0d79257ae1c382 100644 --- a/packages/react-native/Libraries/Components/ActivityIndicator/ActivityIndicatorViewNativeComponent.js +++ b/packages/react-native/Libraries/Components/ActivityIndicator/ActivityIndicatorViewNativeComponent.js @@ -21,16 +21,16 @@ type NativeProps = $ReadOnly<{| /** * Whether the indicator should hide when not animating (true by default). * - * See https://reactnative.dev/docs/activityindicator#hideswhenstopped + * See https://reactnative.dev/docs/activityindicator#hideswhenstopped-ios */ - hidesWhenStopped?: WithDefault, + hidesWhenStopped?: WithDefault, /** * Whether to show the indicator (true, the default) or hide it (false). * * See https://reactnative.dev/docs/activityindicator#animating */ - animating?: WithDefault, + animating?: WithDefault, /** * The foreground color of the spinner (default is gray). From 834447424ff2dca1c0a7387f0976a65ffa243c1e Mon Sep 17 00:00:00 2001 From: Dmitry Rykun Date: Mon, 27 Nov 2023 07:37:56 -0800 Subject: [PATCH 098/162] Refactor generate-artifacts-executor.js: process react-native as a normal dependency (#41558) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41558 Now that the previous diff in the stack (D51303793) provides proper dependency path resolution, we can process `react-native` as a normal dependency, and remove a special code path for it. Changelog: [Internal] Reviewed By: cipolleschi Differential Revision: D51256764 fbshipit-source-id: 2a11641e9362d7bfad1ff9995b4f3bb4c92d9c0f --- .../generate-artifacts-executor-test.js | 41 ++-------------- .../codegen/generate-artifacts-executor.js | 47 ++++--------------- 2 files changed, 15 insertions(+), 73 deletions(-) diff --git a/packages/react-native/scripts/codegen/__tests__/generate-artifacts-executor-test.js b/packages/react-native/scripts/codegen/__tests__/generate-artifacts-executor-test.js index 7a85ef8e3bd1ad..79fa376c6ade0b 100644 --- a/packages/react-native/scripts/codegen/__tests__/generate-artifacts-executor-test.js +++ b/packages/react-native/scripts/codegen/__tests__/generate-artifacts-executor-test.js @@ -14,34 +14,12 @@ const fixtures = require('../__test_fixtures__/fixtures'); const underTest = require('../generate-artifacts-executor'); const path = require('path'); -const reactNativeDependencyName = 'react-native'; const rootPath = path.join(__dirname, '../../..'); describe('extractLibrariesFromJSON', () => { - it('throws if in react-native and no dependencies found', () => { - let configFile = {}; - expect(() => { - underTest._extractLibrariesFromJSON(configFile); - }).toThrow(); - }); - - it('it skips if not into react-native and no dependencies found', () => { - let configFile = {}; - let libraries = underTest._extractLibrariesFromJSON( - configFile, - 'some-node-module', - 'node_modules/some', - ); - expect(libraries.length).toBe(0); - }); - it('extracts a single dependency when config has no libraries', () => { let configFile = fixtures.noLibrariesConfigFile; - let libraries = underTest._extractLibrariesFromJSON( - configFile, - 'my-app', - '.', - ); + let libraries = underTest._extractLibrariesFromJSON(configFile, '.'); expect(libraries.length).toBe(1); expect(libraries[0]).toEqual({ config: { @@ -53,23 +31,15 @@ describe('extractLibrariesFromJSON', () => { }); }); - it("extract codegenConfig when it's empty", () => { + it("doesn't extract libraries when they are present but empty", () => { const configFile = {codegenConfig: {libraries: []}}; - let libraries = underTest._extractLibrariesFromJSON( - configFile, - reactNativeDependencyName, - rootPath, - ); + let libraries = underTest._extractLibrariesFromJSON(configFile, rootPath); expect(libraries.length).toBe(0); }); - it('extract codegenConfig when dependency is one', () => { + it('extracts libraries when they are present and not empty', () => { const configFile = fixtures.singleLibraryCodegenConfig; - let libraries = underTest._extractLibrariesFromJSON( - configFile, - reactNativeDependencyName, - rootPath, - ); + let libraries = underTest._extractLibrariesFromJSON(configFile, rootPath); expect(libraries.length).toBe(1); expect(libraries[0]).toEqual({ config: { @@ -87,7 +57,6 @@ describe('extractLibrariesFromJSON', () => { const myDependencyPath = path.join(__dirname, myDependency); let libraries = underTest._extractLibrariesFromJSON( configFile, - myDependency, myDependencyPath, ); expect(libraries.length).toBe(3); diff --git a/packages/react-native/scripts/codegen/generate-artifacts-executor.js b/packages/react-native/scripts/codegen/generate-artifacts-executor.js index afcad1ae7a4cc1..17db4e48c4f627 100644 --- a/packages/react-native/scripts/codegen/generate-artifacts-executor.js +++ b/packages/react-native/scripts/codegen/generate-artifacts-executor.js @@ -110,24 +110,11 @@ function extractLibrariesFromConfigurationArray(configFile, dependencyPath) { }); } -function extractLibrariesFromJSON(configFile, dependency, dependencyPath) { - var isBlocking = false; - if (dependency == null) { - dependency = REACT_NATIVE; - dependencyPath = REACT_NATIVE_PACKAGE_ROOT_FOLDER; - // If we are exploring the ReactNative libraries, we want to raise an error - // if the codegen is not properly configured. - isBlocking = true; - } - +function extractLibrariesFromJSON(configFile, dependencyPath) { if (configFile.codegenConfig == null) { - if (isBlocking) { - throw `[Codegen] Error: Could not find codegen config for ${dependency} .`; - } return []; } - - console.log(`[Codegen] Found ${dependency}`); + console.log(`[Codegen] Found ${configFile.name}`); if (configFile.codegenConfig.libraries == null) { const config = configFile.codegenConfig; return [ @@ -137,43 +124,30 @@ function extractLibrariesFromJSON(configFile, dependency, dependencyPath) { }, ]; } else { - printDeprecationWarningIfNeeded(dependency); + printDeprecationWarningIfNeeded(configFile.name); return extractLibrariesFromConfigurationArray(configFile, dependencyPath); } } -function handleReactNativeCoreLibraries() { - // Handle react-native core libraries. - // This is required when react-native is outside of node_modules. - console.log('[Codegen] Processing react-native core libraries'); - return extractLibrariesFromJSON( - readPkgJsonInDirectory(REACT_NATIVE_PACKAGE_ROOT_FOLDER), - ); -} - function handleThirdPartyLibraries(pkgJson) { - const dependencies = {...pkgJson.dependencies, ...pkgJson.devDependencies}; + const dependencies = { + ...pkgJson.dependencies, + ...pkgJson.devDependencies, + ...pkgJson.peerDependencies, + }; // Determine which of these are codegen-enabled libraries console.log( '\n\n[Codegen] >>>>> Searching for codegen-enabled libraries in the project dependencies.', ); // Handle third-party libraries return Object.keys(dependencies).flatMap(dependency => { - if (dependency === REACT_NATIVE) { - // react-native should already be added. - return []; - } try { const configFilePath = require.resolve( path.join(dependency, 'package.json'), ); const configFile = JSON.parse(fs.readFileSync(configFilePath)); const codegenConfigFileDir = path.dirname(configFilePath); - return extractLibrariesFromJSON( - configFile, - dependency, - codegenConfigFileDir, - ); + return extractLibrariesFromJSON(configFile, codegenConfigFileDir); } catch (e) { return []; } @@ -185,7 +159,7 @@ function handleInAppLibraries(pkgJson, appRootDir) { '\n\n[Codegen] >>>>> Searching for codegen-enabled libraries in the app', ); - return extractLibrariesFromJSON(pkgJson, pkgJson.name, appRootDir); + return extractLibrariesFromJSON(pkgJson, appRootDir); } // CodeGen @@ -299,7 +273,6 @@ function createComponentProvider(schemas) { function findCodegenEnabledLibraries(appRootDir) { const pkgJson = readPkgJsonInDirectory(appRootDir); return [ - ...handleReactNativeCoreLibraries(), ...handleThirdPartyLibraries(pkgJson), ...handleInAppLibraries(pkgJson, appRootDir), ]; From eb7e10bc0e78d57726e2971c9dc566e9323deb69 Mon Sep 17 00:00:00 2001 From: Dmitry Rykun Date: Mon, 27 Nov 2023 09:45:55 -0800 Subject: [PATCH 099/162] Refactor generate-artifacts-executor.js: give library lookup functions more accurate names (#41560) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41560 This diff gives some functions and variables more accurate names: 1. `appRoot` -> `projectRoot` 2. `handleThirdPartyLibraries` -> `findExternalLibraries` 3. `handleLibrariesFromReactNativeConfig` -> `findLibrariesFromReactNativeConfig` 4. `handleInAppLibraries` -> `findProjectRootLibraries` It also removes `isAppRootValid` check that checks that `appRoot != null`, it is redundant since `appRoot`(now `projectRoot`) is required by the CLI. Changelog: [Internal] Reviewed By: cipolleschi Differential Revision: D51309027 fbshipit-source-id: c5e34c2aa788a7795c68697a0fa9ddf0163cec0e --- .../codegen/generate-artifacts-executor.js | 42 +++++++------------ .../scripts/generate-codegen-artifacts.js | 4 +- 2 files changed, 18 insertions(+), 28 deletions(-) diff --git a/packages/react-native/scripts/codegen/generate-artifacts-executor.js b/packages/react-native/scripts/codegen/generate-artifacts-executor.js index 17db4e48c4f627..e0b7c0dd56bb33 100644 --- a/packages/react-native/scripts/codegen/generate-artifacts-executor.js +++ b/packages/react-native/scripts/codegen/generate-artifacts-executor.js @@ -45,15 +45,6 @@ function isReactNativeCoreLibrary(libraryName) { return libraryName in CORE_LIBRARIES_WITH_OUTPUT_FOLDER; } -function isAppRootValid(appRootDir) { - if (appRootDir == null) { - console.error('Missing path to React Native application'); - process.exitCode = 1; - return false; - } - return true; -} - function readPkgJsonInDirectory(dir) { const pkgJsonPath = path.join(dir, 'package.json'); if (!fs.existsSync(pkgJsonPath)) { @@ -129,7 +120,7 @@ function extractLibrariesFromJSON(configFile, dependencyPath) { } } -function handleThirdPartyLibraries(pkgJson) { +function findExternalLibraries(pkgJson) { const dependencies = { ...pkgJson.dependencies, ...pkgJson.devDependencies, @@ -154,12 +145,12 @@ function handleThirdPartyLibraries(pkgJson) { }); } -function handleInAppLibraries(pkgJson, appRootDir) { +function findProjectRootLibraries(pkgJson, projectRoot) { console.log( '\n\n[Codegen] >>>>> Searching for codegen-enabled libraries in the app', ); - return extractLibrariesFromJSON(pkgJson, appRootDir); + return extractLibrariesFromJSON(pkgJson, projectRoot); } // CodeGen @@ -184,8 +175,11 @@ function buildCodegenIfNeeded() { }); } -function computeIOSOutputDir(outputPath, appRootDir) { - return path.join(outputPath ? outputPath : appRootDir, 'build/generated/ios'); +function computeIOSOutputDir(outputPath, projectRoot) { + return path.join( + outputPath ? outputPath : projectRoot, + 'build/generated/ios', + ); } function generateSchemaInfo(library) { @@ -270,11 +264,11 @@ function createComponentProvider(schemas) { console.log(`Generated provider in: ${outputDir}`); } -function findCodegenEnabledLibraries(appRootDir) { - const pkgJson = readPkgJsonInDirectory(appRootDir); +function findCodegenEnabledLibraries(projectRoot) { + const pkgJson = readPkgJsonInDirectory(projectRoot); return [ - ...handleThirdPartyLibraries(pkgJson), - ...handleInAppLibraries(pkgJson, appRootDir), + ...findExternalLibraries(pkgJson), + ...findProjectRootLibraries(pkgJson, projectRoot), ]; } @@ -320,28 +314,24 @@ function cleanupEmptyFilesAndFolders(filepath) { * - setups the CLI to generate the code * - generate the code * - * @parameter appRootDir: the directory with the app source code, where the package.json lives. + * @parameter projectRoot: the directory with the app source code, where the package.json lives. * @parameter outputPath: the base output path for the CodeGen. * @throws If it can't find a config file for react-native. * @throws If it can't find a CodeGen configuration in the file. * @throws If it can't find a cli for the CodeGen. */ -function execute(appRootDir, outputPath) { - if (!isAppRootValid(appRootDir)) { - return; - } - +function execute(projectRoot, outputPath) { buildCodegenIfNeeded(); try { - const libraries = findCodegenEnabledLibraries(appRootDir); + const libraries = findCodegenEnabledLibraries(projectRoot); if (libraries.length === 0) { console.log('[Codegen] No codegen-enabled libraries found.'); return; } - const iosOutputDir = computeIOSOutputDir(outputPath, appRootDir); + const iosOutputDir = computeIOSOutputDir(outputPath, projectRoot); const schemaInfos = generateSchemaInfos(libraries); generateNativeCode(iosOutputDir, schemaInfos); diff --git a/packages/react-native/scripts/generate-codegen-artifacts.js b/packages/react-native/scripts/generate-codegen-artifacts.js index 186c1f39c32dbc..00849c8091b8b8 100644 --- a/packages/react-native/scripts/generate-codegen-artifacts.js +++ b/packages/react-native/scripts/generate-codegen-artifacts.js @@ -15,11 +15,11 @@ const yargs = require('yargs'); const argv = yargs .option('p', { alias: 'path', - description: 'Path to React Native application', + description: 'Path to the React Native project root.', }) .option('o', { alias: 'outputPath', - description: 'Path where generated artifacts will be output to', + description: 'Path where generated artifacts will be output to.', }) .usage('Usage: $0 -p [path to app]') .demandOption(['p']).argv; From f9315c6ee13709d3dd1788090237d92fd92ef456 Mon Sep 17 00:00:00 2001 From: Bill Alves Date: Mon, 27 Nov 2023 10:41:10 -0800 Subject: [PATCH 100/162] Schedule a Choreographer callback only if there is ongoing animation Summary: changelog: [internal] From sammy-SC, we would like to minimize the number of times that React Native schedules Choreographer calls. For animations, we do not need choreographer running on every frame, it only needs to run on frames that have an animation active. This diff modifies the frame callbacks such that Choreographer calls are only enqueued if there is an ongoing animation. Reviewed By: sammy-SC Differential Revision: D50647971 fbshipit-source-id: d77b246beafc5c658c738e574b0e02dd68fadce9 --- .../react/animated/NativeAnimatedModule.java | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/animated/NativeAnimatedModule.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/animated/NativeAnimatedModule.java index 76749aaff7f948..cff0a92988adfe 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/animated/NativeAnimatedModule.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/animated/NativeAnimatedModule.java @@ -25,6 +25,7 @@ import com.facebook.react.bridge.UIManagerListener; import com.facebook.react.bridge.WritableMap; import com.facebook.react.common.annotations.VisibleForTesting; +import com.facebook.react.config.ReactFeatureFlags; import com.facebook.react.module.annotations.ReactModule; import com.facebook.react.modules.core.ReactChoreographer; import com.facebook.react.uimanager.GuardedFrameCallback; @@ -247,14 +248,13 @@ protected void doFrameGuarded(final long frameTimeNanos) { return; } - // TODO: Would be great to avoid adding this callback in case there are no active - // animations and no outstanding tasks on the operations queue. Apparently frame - // callbacks can only be posted from the UI thread and therefore we cannot schedule - // them directly from other threads. - Assertions.assertNotNull(mReactChoreographer) - .postFrameCallback( - ReactChoreographer.CallbackType.NATIVE_ANIMATED_MODULE, - mAnimatedFrameCallback); + if (!ReactFeatureFlags.enableOnDemandReactChoreographer + || nodesManager != null && nodesManager.hasActiveAnimations()) { + Assertions.assertNotNull(mReactChoreographer) + .postFrameCallback( + ReactChoreographer.CallbackType.NATIVE_ANIMATED_MODULE, + mAnimatedFrameCallback); + } } catch (Exception ex) { throw new RuntimeException(ex); } @@ -1116,6 +1116,7 @@ public void onValueUpdate(double value) { opsAndArgs.getInt(i++), opsAndArgs.getInt(i++)); break; case OP_CODE_START_ANIMATING_NODE: + enqueueFrameCallback(); animatedNodesManager.startAnimatingNode( opsAndArgs.getInt(i++), opsAndArgs.getInt(i++), opsAndArgs.getMap(i++), null); break; From 6d9d6def980378b8b14f8f76ea5541a860e678fb Mon Sep 17 00:00:00 2001 From: Riccardo Cipolleschi Date: Mon, 27 Nov 2023 10:46:13 -0800 Subject: [PATCH 101/162] Back out "RNTester-ios / RCTAppDelegate > correctly check for USE_HERMES Flag" (#41626) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41626 In the codebase, we never set the RCT_USE_HERMES flag. When we install the pods, we use the USE_HERMES flag and we set USE_HERMES as a build setting. So, the RCT_USE_HERMES flag will always be not set for the OSS. https://pxl.cl/3RRxr ## Changelog: [iOS][Fixed] - use the right USE_HERMES flag ## Facebook: This change was incorrect as in OSS we never set the RCT_USE_HERMES flag, while we actually set the USE_HERMES one. I will align the BUCK RNTester setup in the next diff of the stackog: Reviewed By: dmytrorykun Differential Revision: D51547810 fbshipit-source-id: 1da5b3a48a83a8ba49cf65382927bed2f9fc893d --- packages/react-native/Libraries/AppDelegate/RCTAppDelegate.mm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/react-native/Libraries/AppDelegate/RCTAppDelegate.mm b/packages/react-native/Libraries/AppDelegate/RCTAppDelegate.mm index 414534f9fb4dbe..924664e6cd6a40 100644 --- a/packages/react-native/Libraries/AppDelegate/RCTAppDelegate.mm +++ b/packages/react-native/Libraries/AppDelegate/RCTAppDelegate.mm @@ -26,7 +26,7 @@ #import #import #import -#if RCT_USE_HERMES +#if USE_HERMES #import #else #import @@ -292,7 +292,7 @@ - (void)createReactHost - (std::shared_ptr)createJSRuntimeFactory { -#if RCT_USE_HERMES +#if USE_HERMES return std::make_shared(_reactNativeConfig, nullptr); #else return std::make_shared(); From 3a045b602616d61b6df9df3803ac150f09d6f66f Mon Sep 17 00:00:00 2001 From: Riccardo Cipolleschi Date: Mon, 27 Nov 2023 10:46:13 -0800 Subject: [PATCH 102/162] Unify usage of USE_HERMES flag (#41625) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41625 To tell React Native whether we are building with hermes or not on iOS, we were using 2 different build time flags: - USE_HERMES - RCT_USE_HERMES The first was widely used by the OSS use case, while the latter was set internally. Worse than that, their default values were the opposite and we were never setting the RCT_USE_HERMES explicitly with Cocoapods, while there was some piece of code that was trying to "smartly" detect whether Hermes was included or not. This change unifies the behavior, removing the "smartness" in favor od a declarative approach. ## Changelog: [Internal] - Unify the USE_HERMES flags Reviewed By: christophpurrer Differential Revision: D51549284 fbshipit-source-id: 829ad361e185d5b4fa227605523af3a8e590e95c --- packages/react-native/React-Core.podspec | 3 ++- .../react-native/React/CxxBridge/RCTCxxBridge.mm | 12 ++---------- 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/packages/react-native/React-Core.podspec b/packages/react-native/React-Core.podspec index 101b5e9cc10056..e2b1ed82b7622b 100644 --- a/packages/react-native/React-Core.podspec +++ b/packages/react-native/React-Core.podspec @@ -22,6 +22,7 @@ socket_rocket_version = '0.7.0' boost_compiler_flags = '-Wno-documentation' use_hermes = ENV['USE_HERMES'] == nil || ENV['USE_HERMES'] == '1' +use_hermes_flag = use_hermes ? "-DUSE_HERMES=1" : "" header_subspecs = { 'CoreModulesHeaders' => 'React/CoreModules/**/*.h', @@ -63,7 +64,7 @@ Pod::Spec.new do |s| s.platforms = min_supported_versions s.source = source s.resource_bundle = { "RCTI18nStrings" => ["React/I18n/strings/*.lproj"]} - s.compiler_flags = folly_compiler_flags + ' ' + boost_compiler_flags + s.compiler_flags = folly_compiler_flags + ' ' + boost_compiler_flags + ' ' + use_hermes_flag s.header_dir = "React" s.framework = "JavaScriptCore" s.pod_target_xcconfig = { diff --git a/packages/react-native/React/CxxBridge/RCTCxxBridge.mm b/packages/react-native/React/CxxBridge/RCTCxxBridge.mm index af931fd45ca10f..03aa3d0654c2a8 100644 --- a/packages/react-native/React/CxxBridge/RCTCxxBridge.mm +++ b/packages/react-native/React/CxxBridge/RCTCxxBridge.mm @@ -41,15 +41,7 @@ #import #import -#ifndef RCT_USE_HERMES -#if __has_include() -#define RCT_USE_HERMES 1 -#else -#define RCT_USE_HERMES 0 -#endif -#endif - -#if RCT_USE_HERMES +#if USE_HERMES #import #else #import "JSCExecutorFactory.h" @@ -423,7 +415,7 @@ - (void)start } if (!executorFactory) { auto installBindings = RCTJSIExecutorRuntimeInstaller(nullptr); -#if RCT_USE_HERMES +#if USE_HERMES executorFactory = std::make_shared(installBindings); #else executorFactory = std::make_shared(installBindings); From 86c5abac2a2402ba6eb4b8e32c262d5ee563177a Mon Sep 17 00:00:00 2001 From: Bill Alves Date: Mon, 27 Nov 2023 11:49:47 -0800 Subject: [PATCH 103/162] avoid scheduling frame callback if there are no events (#41658) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41658 changelog: [internal] FabricEventDispatcher does not need to run on every frame. Whenever a new event is added to Fabric's event queue, it will call `FabricUIManager.onRequestEventBeat` in Java. This in turn calls `FabricEventDispatcher.maybePostFrameCallbackFromNonUI` and adds a frame callback on the Choreographer. This makes code simpler, as we do not need to manage the frame callback subscription. Reviewed By: sammy-SC Differential Revision: D50604303 fbshipit-source-id: ce2c7b77678bfc14aa7ecac71e40f78263c7036a --- .../events/FabricEventDispatcher.java | 27 ++++++++++++------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/FabricEventDispatcher.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/FabricEventDispatcher.java index 953649288c239a..a1515559cd1642 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/FabricEventDispatcher.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/FabricEventDispatcher.java @@ -11,6 +11,7 @@ import com.facebook.react.bridge.LifecycleEventListener; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.UiThreadUtil; +import com.facebook.react.config.ReactFeatureFlags; import com.facebook.react.modules.core.ReactChoreographer; import com.facebook.react.uimanager.common.UIManagerType; import com.facebook.systrace.Systrace; @@ -84,7 +85,9 @@ public void removeBatchEventDispatchedListener(BatchEventDispatchedListener list @Override public void onHostResume() { - maybePostFrameCallbackFromNonUI(); + if (!ReactFeatureFlags.enableOnDemandReactChoreographer) { + maybePostFrameCallbackFromNonUI(); + } } @Override @@ -94,17 +97,21 @@ public void onHostPause() { @Override public void onHostDestroy() { - stopFrameCallback(); + if (!ReactFeatureFlags.enableOnDemandReactChoreographer) { + stopFrameCallback(); + } } public void onCatalystInstanceDestroyed() { - UiThreadUtil.runOnUiThread( - new Runnable() { - @Override - public void run() { - stopFrameCallback(); - } - }); + if (!ReactFeatureFlags.enableOnDemandReactChoreographer) { + UiThreadUtil.runOnUiThread( + new Runnable() { + @Override + public void run() { + stopFrameCallback(); + } + }); + } } private void stopFrameCallback() { @@ -133,7 +140,7 @@ private class ScheduleDispatchFrameCallback implements Choreographer.FrameCallba public void doFrame(long frameTimeNanos) { UiThreadUtil.assertOnUiThread(); - if (mShouldStop) { + if (ReactFeatureFlags.enableOnDemandReactChoreographer || mShouldStop) { mIsPosted = false; } else { post(); From e979a456eb5c0228ab1ae12ef6cabd813ca177e1 Mon Sep 17 00:00:00 2001 From: Nicola Corti Date: Mon, 27 Nov 2023 14:52:15 -0800 Subject: [PATCH 104/162] AGP to 8.1.4 (#41662) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41662 This bumps AGP to the latest bugfix version Changelog: [Internal] [Changed] - AGP to 8.1.4 Reviewed By: NickGerleman Differential Revision: D51589071 fbshipit-source-id: cd62c94a75b1718572acd1f45f817b16b7d5ed11 --- packages/react-native-gradle-plugin/gradle/libs.versions.toml | 2 +- packages/react-native/gradle/libs.versions.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/react-native-gradle-plugin/gradle/libs.versions.toml b/packages/react-native-gradle-plugin/gradle/libs.versions.toml index f2a1d2edab765a..21f0dca4d214b3 100644 --- a/packages/react-native-gradle-plugin/gradle/libs.versions.toml +++ b/packages/react-native-gradle-plugin/gradle/libs.versions.toml @@ -1,5 +1,5 @@ [versions] -agp = "8.1.1" +agp = "8.1.4" gson = "2.8.9" guava = "31.0.1-jre" javapoet = "1.13.0" diff --git a/packages/react-native/gradle/libs.versions.toml b/packages/react-native/gradle/libs.versions.toml index 48ea84cc9acabd..6af863b45b8c05 100644 --- a/packages/react-native/gradle/libs.versions.toml +++ b/packages/react-native/gradle/libs.versions.toml @@ -5,7 +5,7 @@ targetSdk = "34" compileSdk = "34" buildTools = "34.0.0" # Dependencies versions -agp = "8.1.2" +agp = "8.1.4" androidx-annotation = "1.6.0" androidx-appcompat = "1.6.1" androidx-autofill = "1.1.0" From 09a289542c1a01d4aab346da558cba90dff5871e Mon Sep 17 00:00:00 2001 From: Phillip Pan Date: Mon, 27 Nov 2023 15:04:20 -0800 Subject: [PATCH 105/162] dispatch RCTNativeAnimatedTurboModule methods onto UIManager queue (#41472) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41472 Changelog: [Internal] this module doesn't work correctly with synchronous void methods, fixing it here Reviewed By: cipolleschi Differential Revision: D51293023 fbshipit-source-id: 86b19eceac8f28142351961e061f07f57ed98bca --- .../RCTNativeAnimatedTurboModule.mm | 201 ++++++++++-------- 1 file changed, 116 insertions(+), 85 deletions(-) diff --git a/packages/react-native/Libraries/NativeAnimation/RCTNativeAnimatedTurboModule.mm b/packages/react-native/Libraries/NativeAnimation/RCTNativeAnimatedTurboModule.mm index b1b884a097fa37..cdf38d90dcd297 100644 --- a/packages/react-native/Libraries/NativeAnimation/RCTNativeAnimatedTurboModule.mm +++ b/packages/react-native/Libraries/NativeAnimation/RCTNativeAnimatedTurboModule.mm @@ -59,14 +59,6 @@ - (void)invalidate [_surfacePresenter removeObserver:self]; } -- (dispatch_queue_t)methodQueue -{ - // This module needs to be on the same queue as the UIManager to avoid - // having to lock `_operations` and `_preOperations` since `uiManagerWillPerformMounting` - // will be called from that queue. - return RCTGetUIManagerQueue(); -} - /* * In bridgeless mode, `setBridge` is never called during initializtion. Instead this selector is invoked via * BridgelessTurboModuleSetup. @@ -90,32 +82,40 @@ - (void)setSurfacePresenter:(id)surfacePresenter RCT_EXPORT_METHOD(createAnimatedNode : (double)tag config : (NSDictionary *)config) { - [self addOperationBlock:^(RCTNativeAnimatedNodesManager *nodesManager) { - [nodesManager createAnimatedNode:[NSNumber numberWithDouble:tag] config:config]; - }]; + dispatch_async(RCTGetUIManagerQueue(), ^{ + [self addOperationBlock:^(RCTNativeAnimatedNodesManager *nodesManager) { + [nodesManager createAnimatedNode:[NSNumber numberWithDouble:tag] config:config]; + }]; + }); } RCT_EXPORT_METHOD(updateAnimatedNodeConfig : (double)tag config : (NSDictionary *)config) { - [self addOperationBlock:^(RCTNativeAnimatedNodesManager *nodesManager) { - [nodesManager updateAnimatedNodeConfig:[NSNumber numberWithDouble:tag] config:config]; - }]; + dispatch_async(RCTGetUIManagerQueue(), ^{ + [self addOperationBlock:^(RCTNativeAnimatedNodesManager *nodesManager) { + [nodesManager updateAnimatedNodeConfig:[NSNumber numberWithDouble:tag] config:config]; + }]; + }); } RCT_EXPORT_METHOD(connectAnimatedNodes : (double)parentTag childTag : (double)childTag) { - [self addOperationBlock:^(RCTNativeAnimatedNodesManager *nodesManager) { - [nodesManager connectAnimatedNodes:[NSNumber numberWithDouble:parentTag] - childTag:[NSNumber numberWithDouble:childTag]]; - }]; + dispatch_async(RCTGetUIManagerQueue(), ^{ + [self addOperationBlock:^(RCTNativeAnimatedNodesManager *nodesManager) { + [nodesManager connectAnimatedNodes:[NSNumber numberWithDouble:parentTag] + childTag:[NSNumber numberWithDouble:childTag]]; + }]; + }); } RCT_EXPORT_METHOD(disconnectAnimatedNodes : (double)parentTag childTag : (double)childTag) { - [self addOperationBlock:^(RCTNativeAnimatedNodesManager *nodesManager) { - [nodesManager disconnectAnimatedNodes:[NSNumber numberWithDouble:parentTag] - childTag:[NSNumber numberWithDouble:childTag]]; - }]; + dispatch_async(RCTGetUIManagerQueue(), ^{ + [self addOperationBlock:^(RCTNativeAnimatedNodesManager *nodesManager) { + [nodesManager disconnectAnimatedNodes:[NSNumber numberWithDouble:parentTag] + childTag:[NSNumber numberWithDouble:childTag]]; + }]; + }); } RCT_EXPORT_METHOD(startAnimatingNode @@ -124,101 +124,126 @@ - (void)setSurfacePresenter:(id)surfacePresenter : (NSDictionary *)config endCallback : (RCTResponseSenderBlock)callBack) { - [self addOperationBlock:^(RCTNativeAnimatedNodesManager *nodesManager) { - [nodesManager startAnimatingNode:[NSNumber numberWithDouble:animationId] - nodeTag:[NSNumber numberWithDouble:nodeTag] - config:config - endCallback:callBack]; - }]; + dispatch_async(RCTGetUIManagerQueue(), ^{ + [self addOperationBlock:^(RCTNativeAnimatedNodesManager *nodesManager) { + [nodesManager startAnimatingNode:[NSNumber numberWithDouble:animationId] + nodeTag:[NSNumber numberWithDouble:nodeTag] + config:config + endCallback:callBack]; + }]; - [self flushOperationQueues]; + [self flushOperationQueues]; + }); } RCT_EXPORT_METHOD(stopAnimation : (double)animationId) { - [self addOperationBlock:^(RCTNativeAnimatedNodesManager *nodesManager) { - [nodesManager stopAnimation:[NSNumber numberWithDouble:animationId]]; - }]; - [self flushOperationQueues]; + dispatch_async(RCTGetUIManagerQueue(), ^{ + [self addOperationBlock:^(RCTNativeAnimatedNodesManager *nodesManager) { + [nodesManager stopAnimation:[NSNumber numberWithDouble:animationId]]; + }]; + [self flushOperationQueues]; + }); } RCT_EXPORT_METHOD(setAnimatedNodeValue : (double)nodeTag value : (double)value) { - [self addOperationBlock:^(RCTNativeAnimatedNodesManager *nodesManager) { - [nodesManager setAnimatedNodeValue:[NSNumber numberWithDouble:nodeTag] value:[NSNumber numberWithDouble:value]]; - }]; - // In Bridge, flushing of native animations is done from RCTCxxBridge batchDidComplete(). - // Since RCTCxxBridge doesn't exist in Bridgeless, and components are not remounted in Fabric for native animations, - // flush here for changes in Animated.Value for Animated.event. - [self flushOperationQueues]; + dispatch_async(RCTGetUIManagerQueue(), ^{ + [self addOperationBlock:^(RCTNativeAnimatedNodesManager *nodesManager) { + [nodesManager setAnimatedNodeValue:[NSNumber numberWithDouble:nodeTag] value:[NSNumber numberWithDouble:value]]; + }]; + // In Bridge, flushing of native animations is done from RCTCxxBridge batchDidComplete(). + // Since RCTCxxBridge doesn't exist in Bridgeless, and components are not remounted in Fabric for native animations, + // flush here for changes in Animated.Value for Animated.event. + [self flushOperationQueues]; + }); } RCT_EXPORT_METHOD(setAnimatedNodeOffset : (double)nodeTag offset : (double)offset) { - [self addOperationBlock:^(RCTNativeAnimatedNodesManager *nodesManager) { - [nodesManager setAnimatedNodeOffset:[NSNumber numberWithDouble:nodeTag] offset:[NSNumber numberWithDouble:offset]]; - }]; + dispatch_async(RCTGetUIManagerQueue(), ^{ + [self addOperationBlock:^(RCTNativeAnimatedNodesManager *nodesManager) { + [nodesManager setAnimatedNodeOffset:[NSNumber numberWithDouble:nodeTag] + offset:[NSNumber numberWithDouble:offset]]; + }]; + }); } RCT_EXPORT_METHOD(flattenAnimatedNodeOffset : (double)nodeTag) { - [self addOperationBlock:^(RCTNativeAnimatedNodesManager *nodesManager) { - [nodesManager flattenAnimatedNodeOffset:[NSNumber numberWithDouble:nodeTag]]; - }]; + dispatch_async(RCTGetUIManagerQueue(), ^{ + [self addOperationBlock:^(RCTNativeAnimatedNodesManager *nodesManager) { + [nodesManager flattenAnimatedNodeOffset:[NSNumber numberWithDouble:nodeTag]]; + }]; + }); } RCT_EXPORT_METHOD(extractAnimatedNodeOffset : (double)nodeTag) { - [self addOperationBlock:^(RCTNativeAnimatedNodesManager *nodesManager) { - [nodesManager extractAnimatedNodeOffset:[NSNumber numberWithDouble:nodeTag]]; - }]; + dispatch_async(RCTGetUIManagerQueue(), ^{ + [self addOperationBlock:^(RCTNativeAnimatedNodesManager *nodesManager) { + [nodesManager extractAnimatedNodeOffset:[NSNumber numberWithDouble:nodeTag]]; + }]; + }); } RCT_EXPORT_METHOD(connectAnimatedNodeToView : (double)nodeTag viewTag : (double)viewTag) { - [self addOperationBlock:^(RCTNativeAnimatedNodesManager *nodesManager) { - // viewName is not used when node is managed by Fabric, and nodes are always managed by Fabric in Bridgeless. - [nodesManager connectAnimatedNodeToView:[NSNumber numberWithDouble:nodeTag] - viewTag:[NSNumber numberWithDouble:viewTag] - viewName:nil]; - }]; + dispatch_async(RCTGetUIManagerQueue(), ^{ + [self addOperationBlock:^(RCTNativeAnimatedNodesManager *nodesManager) { + // viewName is not used when node is managed by Fabric, and nodes are always managed by Fabric in Bridgeless. + [nodesManager connectAnimatedNodeToView:[NSNumber numberWithDouble:nodeTag] + viewTag:[NSNumber numberWithDouble:viewTag] + viewName:nil]; + }]; + }); } RCT_EXPORT_METHOD(disconnectAnimatedNodeFromView : (double)nodeTag viewTag : (double)viewTag) { - [self addOperationBlock:^(RCTNativeAnimatedNodesManager *nodesManager) { - [nodesManager disconnectAnimatedNodeFromView:[NSNumber numberWithDouble:nodeTag] - viewTag:[NSNumber numberWithDouble:viewTag]]; - }]; + dispatch_async(RCTGetUIManagerQueue(), ^{ + [self addOperationBlock:^(RCTNativeAnimatedNodesManager *nodesManager) { + [nodesManager disconnectAnimatedNodeFromView:[NSNumber numberWithDouble:nodeTag] + viewTag:[NSNumber numberWithDouble:viewTag]]; + }]; + }); } RCT_EXPORT_METHOD(restoreDefaultValues : (double)nodeTag) { - [self addPreOperationBlock:^(RCTNativeAnimatedNodesManager *nodesManager) { - [nodesManager restoreDefaultValues:[NSNumber numberWithDouble:nodeTag]]; - }]; + dispatch_async(RCTGetUIManagerQueue(), ^{ + [self addPreOperationBlock:^(RCTNativeAnimatedNodesManager *nodesManager) { + [nodesManager restoreDefaultValues:[NSNumber numberWithDouble:nodeTag]]; + }]; + }); } RCT_EXPORT_METHOD(dropAnimatedNode : (double)tag) { - [self addOperationBlock:^(RCTNativeAnimatedNodesManager *nodesManager) { - [nodesManager dropAnimatedNode:[NSNumber numberWithDouble:tag]]; - }]; + dispatch_async(RCTGetUIManagerQueue(), ^{ + [self addOperationBlock:^(RCTNativeAnimatedNodesManager *nodesManager) { + [nodesManager dropAnimatedNode:[NSNumber numberWithDouble:tag]]; + }]; + }); } RCT_EXPORT_METHOD(startListeningToAnimatedNodeValue : (double)tag) { - __weak id valueObserver = self; - [self addOperationBlock:^(RCTNativeAnimatedNodesManager *nodesManager) { - [nodesManager startListeningToAnimatedNodeValue:[NSNumber numberWithDouble:tag] valueObserver:valueObserver]; - }]; + dispatch_async(RCTGetUIManagerQueue(), ^{ + __weak id valueObserver = self; + [self addOperationBlock:^(RCTNativeAnimatedNodesManager *nodesManager) { + [nodesManager startListeningToAnimatedNodeValue:[NSNumber numberWithDouble:tag] valueObserver:valueObserver]; + }]; + }); } RCT_EXPORT_METHOD(stopListeningToAnimatedNodeValue : (double)tag) { - [self addOperationBlock:^(RCTNativeAnimatedNodesManager *nodesManager) { - [nodesManager stopListeningToAnimatedNodeValue:[NSNumber numberWithDouble:tag]]; - }]; + dispatch_async(RCTGetUIManagerQueue(), ^{ + [self addOperationBlock:^(RCTNativeAnimatedNodesManager *nodesManager) { + [nodesManager stopListeningToAnimatedNodeValue:[NSNumber numberWithDouble:tag]]; + }]; + }); } RCT_EXPORT_METHOD(addAnimatedEventToView @@ -233,11 +258,13 @@ - (void)setSurfacePresenter:(id)surfacePresenter eventMappingDict[@"animatedValueTag"] = @(*eventMapping.animatedValueTag()); } - [self addOperationBlock:^(RCTNativeAnimatedNodesManager *nodesManager) { - [nodesManager addAnimatedEventToView:[NSNumber numberWithDouble:viewTag] - eventName:eventName - eventMapping:eventMappingDict]; - }]; + dispatch_async(RCTGetUIManagerQueue(), ^{ + [self addOperationBlock:^(RCTNativeAnimatedNodesManager *nodesManager) { + [nodesManager addAnimatedEventToView:[NSNumber numberWithDouble:viewTag] + eventName:eventName + eventMapping:eventMappingDict]; + }]; + }); } RCT_EXPORT_METHOD(removeAnimatedEventFromView @@ -245,18 +272,22 @@ - (void)setSurfacePresenter:(id)surfacePresenter : (nonnull NSString *)eventName animatedNodeTag : (double)animatedNodeTag) { - [self addOperationBlock:^(RCTNativeAnimatedNodesManager *nodesManager) { - [nodesManager removeAnimatedEventFromView:[NSNumber numberWithDouble:viewTag] - eventName:eventName - animatedNodeTag:[NSNumber numberWithDouble:animatedNodeTag]]; - }]; + dispatch_async(RCTGetUIManagerQueue(), ^{ + [self addOperationBlock:^(RCTNativeAnimatedNodesManager *nodesManager) { + [nodesManager removeAnimatedEventFromView:[NSNumber numberWithDouble:viewTag] + eventName:eventName + animatedNodeTag:[NSNumber numberWithDouble:animatedNodeTag]]; + }]; + }); } RCT_EXPORT_METHOD(getValue : (double)nodeTag saveValueCallback : (RCTResponseSenderBlock)saveValueCallback) { - [self addOperationBlock:^(RCTNativeAnimatedNodesManager *nodesManager) { - [nodesManager getValue:[NSNumber numberWithDouble:nodeTag] saveCallback:saveValueCallback]; - }]; + dispatch_async(RCTGetUIManagerQueue(), ^{ + [self addOperationBlock:^(RCTNativeAnimatedNodesManager *nodesManager) { + [nodesManager getValue:[NSNumber numberWithDouble:nodeTag] saveCallback:saveValueCallback]; + }]; + }); } RCT_EXPORT_METHOD(queueAndExecuteBatchedOperations : (NSArray *)operationsAndArgs) From dc36be335fd034fa83e5ce0b6a44eb1685761cc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oskar=20Kwas=CC=81niewski?= Date: Mon, 27 Nov 2023 16:53:31 -0800 Subject: [PATCH 106/162] chore: remove duplicated pod 'Yoga' in RNTester (#41627) Summary: This PR removes duplicated `pod 'Yoga'` as it is already declared in `use_react_native`. ## Changelog: [INTERNAL] [REMOVED] - duplicated pod 'Yoga' in RNTester Pull Request resolved: https://github.com/facebook/react-native/pull/41627 Test Plan: CI Green Reviewed By: christophpurrer Differential Revision: D51603340 Pulled By: NickGerleman fbshipit-source-id: 89e77e5a544cb54d77b969462130725853b36d5d --- packages/rn-tester/Podfile | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/rn-tester/Podfile b/packages/rn-tester/Podfile index 1aff97a42fc655..7a9bda7f3f9ffa 100644 --- a/packages/rn-tester/Podfile +++ b/packages/rn-tester/Podfile @@ -55,7 +55,6 @@ def pods(target_name, options = {}) # Additional Pods which aren't included in the default Podfile pod 'React-RCTPushNotification', :path => "#{@prefix_path}/Libraries/PushNotificationIOS" - pod 'Yoga', :path => "#{@prefix_path}/ReactCommon/yoga", :modular_headers => true # Additional Pods which are classed as unstable # RNTester native modules and components From 3294bc737cdfd227ed808aa4e19f4a887915b698 Mon Sep 17 00:00:00 2001 From: Nick Gerleman Date: Mon, 27 Nov 2023 21:20:20 -0800 Subject: [PATCH 107/162] Remove yoga::Style::Ref (#41389) Summary: X-link: https://github.com/facebook/yoga/pull/1462 Pull Request resolved: https://github.com/facebook/react-native/pull/41389 Moves the last usages of `yoga::Style::Ref` to setters. Changelog: [Internal] Reviewed By: joevilches Differential Revision: D51154501 fbshipit-source-id: 52dbca7a76de500a8841387eb59fded463864de7 --- .../components/view/YogaStylableProps.cpp | 16 ++++++--- .../components/view/propsConversions.h | 24 ++++++++------ .../ReactCommon/yoga/yoga/YGNodeStyle.cpp | 33 ++++++++++++------- .../ReactCommon/yoga/yoga/style/Style.h | 33 ++++++------------- 4 files changed, 56 insertions(+), 50 deletions(-) diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/YogaStylableProps.cpp b/packages/react-native/ReactCommon/react/renderer/components/view/YogaStylableProps.cpp index f3bce4b95c392d..064d9ecf93f444 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/YogaStylableProps.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/view/YogaStylableProps.cpp @@ -59,6 +59,12 @@ static inline T const getFieldValue( #define REBUILD_FIELD_SWITCH_CASE_YSP(field) \ REBUILD_FIELD_SWITCH_CASE2(field, #field) +#define REBUILD_FIELD_SWITCH_CASE_YSP_SETTER(field, setter) \ + case CONSTEXPR_RAW_PROPS_KEY_HASH(#field): { \ + yogaStyle.setter(getFieldValue(context, value, ygDefaults.field())); \ + return; \ + } + #define REBUILD_YG_FIELD_SWITCH_CASE_INDEXED(field, setter, index, fieldName) \ case CONSTEXPR_RAW_PROPS_KEY_HASH(fieldName): { \ yogaStyle.setter( \ @@ -141,13 +147,13 @@ void YogaStylableProps::setProp( REBUILD_FIELD_SWITCH_CASE_YSP(flexWrap); REBUILD_FIELD_SWITCH_CASE_YSP(overflow); REBUILD_FIELD_SWITCH_CASE_YSP(display); - REBUILD_FIELD_SWITCH_CASE_YSP(flex); - REBUILD_FIELD_SWITCH_CASE_YSP(flexGrow); - REBUILD_FIELD_SWITCH_CASE_YSP(flexShrink); - REBUILD_FIELD_SWITCH_CASE_YSP(flexBasis); + REBUILD_FIELD_SWITCH_CASE_YSP_SETTER(flex, setFlex); + REBUILD_FIELD_SWITCH_CASE_YSP_SETTER(flexGrow, setFlexGrow); + REBUILD_FIELD_SWITCH_CASE_YSP_SETTER(flexShrink, setFlexShrink); + REBUILD_FIELD_SWITCH_CASE_YSP_SETTER(flexBasis, setFlexBasis); REBUILD_FIELD_SWITCH_CASE2(positionType, "position"); REBUILD_FIELD_YG_GUTTER(gap, setGap, "rowGap", "columnGap", "gap"); - REBUILD_FIELD_SWITCH_CASE_YSP(aspectRatio); + REBUILD_FIELD_SWITCH_CASE_YSP_SETTER(aspectRatio, setAspectRatio); REBUILD_FIELD_YG_DIMENSION(dimension, setDimension, "width", "height"); REBUILD_FIELD_YG_DIMENSION( minDimension, setMinDimension, "minWidth", "minHeight"); diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/propsConversions.h b/packages/react-native/ReactCommon/react/renderer/components/view/propsConversions.h index 529f3236454a2f..fc236455fa8f8e 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/propsConversions.h +++ b/packages/react-native/ReactCommon/react/renderer/components/view/propsConversions.h @@ -79,26 +79,30 @@ static inline yoga::Style convertRawProp( yogaStyle.overflow()); yogaStyle.display() = convertRawProp( context, rawProps, "display", sourceValue.display(), yogaStyle.display()); - yogaStyle.flex() = convertRawProp( - context, rawProps, "flex", sourceValue.flex(), yogaStyle.flex()); - yogaStyle.flexGrow() = convertRawProp( + + yogaStyle.setFlex(convertRawProp( + context, rawProps, "flex", sourceValue.flex(), yogaStyle.flex())); + + yogaStyle.setFlexGrow(convertRawProp( context, rawProps, "flexGrow", sourceValue.flexGrow(), - yogaStyle.flexGrow()); - yogaStyle.flexShrink() = convertRawProp( + yogaStyle.flexGrow())); + + yogaStyle.setFlexShrink(convertRawProp( context, rawProps, "flexShrink", sourceValue.flexShrink(), - yogaStyle.flexShrink()); - yogaStyle.flexBasis() = convertRawProp( + yogaStyle.flexShrink())); + + yogaStyle.setFlexBasis(convertRawProp( context, rawProps, "flexBasis", sourceValue.flexBasis(), - yogaStyle.flexBasis()); + yogaStyle.flexBasis())); yogaStyle.setMargin( yoga::Edge::Left, @@ -502,12 +506,12 @@ static inline yoga::Style convertRawProp( sourceValue.maxDimension(yoga::Dimension::Height), {})); - yogaStyle.aspectRatio() = convertRawProp( + yogaStyle.setAspectRatio(convertRawProp( context, rawProps, "aspectRatio", sourceValue.aspectRatio(), - yogaStyle.aspectRatio()); + yogaStyle.aspectRatio())); return yogaStyle; } diff --git a/packages/react-native/ReactCommon/yoga/yoga/YGNodeStyle.cpp b/packages/react-native/ReactCommon/yoga/yoga/YGNodeStyle.cpp index c39372a33ac10c..441b7797f776fb 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/YGNodeStyle.cpp +++ b/packages/react-native/ReactCommon/yoga/yoga/YGNodeStyle.cpp @@ -35,6 +35,15 @@ void updateStyle(YGNodeRef node, Ref (Style::*prop)(), ValueT value) { [prop](Style& s, ValueT x) { (s.*prop)() = x; }); } +template +void updateStyle(YGNodeRef node, ValueT value) { + updateStyle( + resolveRef(node), + value, + [](Style& s, ValueT x) { return (s.*GetterT)() != x; }, + [](Style& s, ValueT x) { (s.*SetterT)(x); }); +} + template void updateIndexedStyleProp(YGNodeRef node, IdxT idx, ValueT value) { updateStyle( @@ -162,7 +171,7 @@ YGDisplay YGNodeStyleGetDisplay(const YGNodeConstRef node) { } void YGNodeStyleSetFlex(const YGNodeRef node, const float flex) { - updateStyle(node, &Style::flex, FloatOptional{flex}); + updateStyle<&Style::flex, &Style::setFlex>(node, FloatOptional{flex}); } float YGNodeStyleGetFlex(const YGNodeConstRef nodeRef) { @@ -173,8 +182,8 @@ float YGNodeStyleGetFlex(const YGNodeConstRef nodeRef) { } void YGNodeStyleSetFlexGrow(const YGNodeRef node, const float flexGrow) { - updateStyle( - node, &Style::flexGrow, FloatOptional{flexGrow}); + updateStyle<&Style::flexGrow, &Style::setFlexGrow>( + node, FloatOptional{flexGrow}); } float YGNodeStyleGetFlexGrow(const YGNodeConstRef nodeRef) { @@ -185,8 +194,8 @@ float YGNodeStyleGetFlexGrow(const YGNodeConstRef nodeRef) { } void YGNodeStyleSetFlexShrink(const YGNodeRef node, const float flexShrink) { - updateStyle( - node, &Style::flexShrink, FloatOptional{flexShrink}); + updateStyle<&Style::flexShrink, &Style::setFlexShrink>( + node, FloatOptional{flexShrink}); } float YGNodeStyleGetFlexShrink(const YGNodeConstRef nodeRef) { @@ -198,19 +207,19 @@ float YGNodeStyleGetFlexShrink(const YGNodeConstRef nodeRef) { } void YGNodeStyleSetFlexBasis(const YGNodeRef node, const float flexBasis) { - updateStyle( - node, &Style::flexBasis, value::points(flexBasis)); + updateStyle<&Style::flexBasis, &Style::setFlexBasis>( + node, value::points(flexBasis)); } void YGNodeStyleSetFlexBasisPercent( const YGNodeRef node, const float flexBasisPercent) { - updateStyle( - node, &Style::flexBasis, value::percent(flexBasisPercent)); + updateStyle<&Style::flexBasis, &Style::setFlexBasis>( + node, value::percent(flexBasisPercent)); } void YGNodeStyleSetFlexBasisAuto(const YGNodeRef node) { - updateStyle(node, &Style::flexBasis, value::ofAuto()); + updateStyle<&Style::flexBasis, &Style::setFlexBasis>(node, value::ofAuto()); } YGValue YGNodeStyleGetFlexBasis(const YGNodeConstRef node) { @@ -303,8 +312,8 @@ float YGNodeStyleGetGap(const YGNodeConstRef node, const YGGutter gutter) { } void YGNodeStyleSetAspectRatio(const YGNodeRef node, const float aspectRatio) { - updateStyle( - node, &Style::aspectRatio, FloatOptional{aspectRatio}); + updateStyle<&Style::aspectRatio, &Style::setAspectRatio>( + node, FloatOptional{aspectRatio}); } float YGNodeStyleGetAspectRatio(const YGNodeConstRef node) { diff --git a/packages/react-native/ReactCommon/yoga/yoga/style/Style.h b/packages/react-native/ReactCommon/yoga/yoga/style/Style.h index e40f1c4fb644f7..09f5c3c1fb88ca 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/style/Style.h +++ b/packages/react-native/ReactCommon/yoga/yoga/style/Style.h @@ -68,18 +68,6 @@ class YG_EXPORT Style { } }; - template - struct Ref { - Style& style; - operator T() const { - return style.*Prop; - } - Ref& operator=(T value) { - style.*Prop = value; - return *this; - } - }; - Style() { alignContent() = Align::FlexStart; alignItems() = Align::Stretch; @@ -202,29 +190,29 @@ class YG_EXPORT Style { FloatOptional flex() const { return flex_; } - Ref flex() { - return {*this}; + void setFlex(FloatOptional value) { + flex_ = value; } FloatOptional flexGrow() const { return flexGrow_; } - Ref flexGrow() { - return {*this}; + void setFlexGrow(FloatOptional value) { + flexGrow_ = value; } FloatOptional flexShrink() const { return flexShrink_; } - Ref flexShrink() { - return {*this}; + void setFlexShrink(FloatOptional value) { + flexShrink_ = value; } Style::Length flexBasis() const { return flexBasis_; } - Ref flexBasis() { - return {*this}; + void setFlexBasis(Style::Length value) { + flexBasis_ = value; } Style::Length margin(Edge edge) const { @@ -283,12 +271,11 @@ class YG_EXPORT Style { maxDimensions_[yoga::to_underlying(axis)] = value; } - // Yoga specific properties, not compatible with flexbox specification FloatOptional aspectRatio() const { return aspectRatio_; } - Ref aspectRatio() { - return {*this}; + void setAspectRatio(FloatOptional value) { + aspectRatio_ = value; } Length resolveColumnGap() const { From 495fee4ff2c1998b1e8383fa0aeadd3963ff9b39 Mon Sep 17 00:00:00 2001 From: Nick Gerleman Date: Mon, 27 Nov 2023 21:20:20 -0800 Subject: [PATCH 108/162] Remove yoga::Style::BitfieldRef (#41393) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41393 X-link: https://github.com/facebook/yoga/pull/1459 Removes the last of the non setter-style style setters. Changelog: [Internal] Reviewed By: javache Differential Revision: D51155925 fbshipit-source-id: 2921c87d95ad36495b7013e592d5169015321545 --- .../Text/RCTParagraphComponentViewTests.mm | 8 +- .../view/YogaLayoutableShadowNode.cpp | 2 +- .../components/view/YogaStylableProps.cpp | 47 +++---- .../components/view/propsConversions.h | 57 +++++--- .../components/view/tests/LayoutTest.cpp | 12 +- .../components/view/tests/ViewTest.cpp | 8 +- .../core/tests/FindNodeAtPointTest.cpp | 2 +- .../mounting/tests/StackingContextTest.cpp | 24 ++-- .../ReactCommon/yoga/yoga/YGNodeStyle.cpp | 132 +++++++----------- .../ReactCommon/yoga/yoga/node/Node.h | 4 +- .../ReactCommon/yoga/yoga/style/Style.h | 81 +++++------ 11 files changed, 173 insertions(+), 204 deletions(-) diff --git a/packages/react-native/React/Tests/Text/RCTParagraphComponentViewTests.mm b/packages/react-native/React/Tests/Text/RCTParagraphComponentViewTests.mm index 2d8e5de1fb5c00..f23f353e121288 100644 --- a/packages/react-native/React/Tests/Text/RCTParagraphComponentViewTests.mm +++ b/packages/react-native/React/Tests/Text/RCTParagraphComponentViewTests.mm @@ -133,7 +133,7 @@ - (void)setUp auto &props = *sharedProps; props.accessible = true; auto &yogaStyle = props.yogaStyle; - yogaStyle.positionType() = yoga::PositionType::Absolute; + yogaStyle.setPositionType(yoga::PositionType::Absolute); yogaStyle.setPosition(yoga::Edge::Left, yoga::value::points(0)); yogaStyle.setPosition(yoga::Edge::Top, yoga::value::points(0)); yogaStyle.setDimension(yoga::Dimension::Width, yoga::value::points(200)); @@ -213,7 +213,7 @@ - (void)setUp auto &props = *sharedProps; props.accessible = true; auto &yogaStyle = props.yogaStyle; - yogaStyle.positionType() = yoga::PositionType::Absolute; + yogaStyle.setPositionType(yoga::PositionType::Absolute); yogaStyle.setPosition(yoga::Edge::Left, yoga::value::points(0)); yogaStyle.setPosition(yoga::Edge::Top, yoga::value::points(30)); yogaStyle.setDimension(yoga::Dimension::Width, yoga::value::points(200)); @@ -257,7 +257,7 @@ - (void)setUp auto &props = *sharedProps; props.accessible = true; auto &yogaStyle = props.yogaStyle; - yogaStyle.positionType() = yoga::PositionType::Absolute; + yogaStyle.setPositionType(yoga::PositionType::Absolute); yogaStyle.setPosition(yoga::Edge::Left, yoga::value::points(0)); yogaStyle.setPosition(yoga::Edge::Top, yoga::value::points(90)); yogaStyle.setDimension(yoga::Dimension::Width, yoga::value::points(200)); @@ -431,7 +431,7 @@ - (void)testEntireParagraphLink props.accessible = true; props.accessibilityTraits = AccessibilityTraits::Link; auto &yogaStyle = props.yogaStyle; - yogaStyle.positionType() = yoga::PositionType::Absolute; + yogaStyle.setPositionType(yoga::PositionType::Absolute); yogaStyle.setPosition(yoga::Edge::Left, yoga::value::points(0)); yogaStyle.setPosition(yoga::Edge::Top, yoga::value::points(90)); yogaStyle.setDimension(yoga::Dimension::Width, yoga::value::points(200)); diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/YogaLayoutableShadowNode.cpp b/packages/react-native/ReactCommon/react/renderer/components/view/YogaLayoutableShadowNode.cpp index 7c531e3517db21..96e3cb75a7e7af 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/YogaLayoutableShadowNode.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/view/YogaLayoutableShadowNode.cpp @@ -563,7 +563,7 @@ void YogaLayoutableShadowNode::setPositionType( ensureUnsealed(); auto style = yogaNode_.getStyle(); - style.positionType() = yoga::scopedEnum(positionType); + style.setPositionType(yoga::scopedEnum(positionType)); yogaNode_.setStyle(style); yogaNode_.setDirty(true); } diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/YogaStylableProps.cpp b/packages/react-native/ReactCommon/react/renderer/components/view/YogaStylableProps.cpp index 064d9ecf93f444..67c2a530b3bb08 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/YogaStylableProps.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/view/YogaStylableProps.cpp @@ -49,22 +49,15 @@ static inline T const getFieldValue( return defaultValue; } -#define REBUILD_FIELD_SWITCH_CASE2(field, fieldName) \ - case CONSTEXPR_RAW_PROPS_KEY_HASH(fieldName): { \ - yogaStyle.field() = getFieldValue(context, value, ygDefaults.field()); \ - return; \ - } - -// @lint-ignore CLANGTIDY cppcoreguidelines-macro-usage -#define REBUILD_FIELD_SWITCH_CASE_YSP(field) \ - REBUILD_FIELD_SWITCH_CASE2(field, #field) - -#define REBUILD_FIELD_SWITCH_CASE_YSP_SETTER(field, setter) \ - case CONSTEXPR_RAW_PROPS_KEY_HASH(#field): { \ +#define REBUILD_FIELD_SWITCH_CASE2(field, setter, fieldName) \ + case CONSTEXPR_RAW_PROPS_KEY_HASH(fieldName): { \ yogaStyle.setter(getFieldValue(context, value, ygDefaults.field())); \ return; \ } +#define REBUILD_FIELD_SWITCH_CASE_YSP(field, setter) \ + REBUILD_FIELD_SWITCH_CASE2(field, setter, #field) + #define REBUILD_YG_FIELD_SWITCH_CASE_INDEXED(field, setter, index, fieldName) \ case CONSTEXPR_RAW_PROPS_KEY_HASH(fieldName): { \ yogaStyle.setter( \ @@ -138,22 +131,22 @@ void YogaStylableProps::setProp( Props::setProp(context, hash, propName, value); switch (hash) { - REBUILD_FIELD_SWITCH_CASE_YSP(direction); - REBUILD_FIELD_SWITCH_CASE_YSP(flexDirection); - REBUILD_FIELD_SWITCH_CASE_YSP(justifyContent); - REBUILD_FIELD_SWITCH_CASE_YSP(alignContent); - REBUILD_FIELD_SWITCH_CASE_YSP(alignItems); - REBUILD_FIELD_SWITCH_CASE_YSP(alignSelf); - REBUILD_FIELD_SWITCH_CASE_YSP(flexWrap); - REBUILD_FIELD_SWITCH_CASE_YSP(overflow); - REBUILD_FIELD_SWITCH_CASE_YSP(display); - REBUILD_FIELD_SWITCH_CASE_YSP_SETTER(flex, setFlex); - REBUILD_FIELD_SWITCH_CASE_YSP_SETTER(flexGrow, setFlexGrow); - REBUILD_FIELD_SWITCH_CASE_YSP_SETTER(flexShrink, setFlexShrink); - REBUILD_FIELD_SWITCH_CASE_YSP_SETTER(flexBasis, setFlexBasis); - REBUILD_FIELD_SWITCH_CASE2(positionType, "position"); + REBUILD_FIELD_SWITCH_CASE_YSP(direction, setDirection); + REBUILD_FIELD_SWITCH_CASE_YSP(flexDirection, setFlexDirection); + REBUILD_FIELD_SWITCH_CASE_YSP(justifyContent, setJustifyContent); + REBUILD_FIELD_SWITCH_CASE_YSP(alignContent, setAlignContent); + REBUILD_FIELD_SWITCH_CASE_YSP(alignItems, setAlignItems); + REBUILD_FIELD_SWITCH_CASE_YSP(alignSelf, setAlignSelf); + REBUILD_FIELD_SWITCH_CASE_YSP(flexWrap, setFlexWrap); + REBUILD_FIELD_SWITCH_CASE_YSP(overflow, setOverflow); + REBUILD_FIELD_SWITCH_CASE_YSP(display, setDisplay); + REBUILD_FIELD_SWITCH_CASE_YSP(flex, setFlex); + REBUILD_FIELD_SWITCH_CASE_YSP(flexGrow, setFlexGrow); + REBUILD_FIELD_SWITCH_CASE_YSP(flexShrink, setFlexShrink); + REBUILD_FIELD_SWITCH_CASE_YSP(flexBasis, setFlexBasis); + REBUILD_FIELD_SWITCH_CASE2(positionType, setPositionType, "position"); REBUILD_FIELD_YG_GUTTER(gap, setGap, "rowGap", "columnGap", "gap"); - REBUILD_FIELD_SWITCH_CASE_YSP_SETTER(aspectRatio, setAspectRatio); + REBUILD_FIELD_SWITCH_CASE_YSP(aspectRatio, setAspectRatio); REBUILD_FIELD_YG_DIMENSION(dimension, setDimension, "width", "height"); REBUILD_FIELD_YG_DIMENSION( minDimension, setMinDimension, "minWidth", "minHeight"); diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/propsConversions.h b/packages/react-native/ReactCommon/react/renderer/components/view/propsConversions.h index fc236455fa8f8e..e68f15740c2fa2 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/propsConversions.h +++ b/packages/react-native/ReactCommon/react/renderer/components/view/propsConversions.h @@ -23,62 +23,76 @@ static inline yoga::Style convertRawProp( const RawProps& rawProps, const yoga::Style& sourceValue) { yoga::Style yogaStyle{}; - yogaStyle.direction() = convertRawProp( + + yogaStyle.setDirection(convertRawProp( context, rawProps, "direction", sourceValue.direction(), - yogaStyle.direction()); - yogaStyle.flexDirection() = convertRawProp( + yogaStyle.direction())); + + yogaStyle.setFlexDirection(convertRawProp( context, rawProps, "flexDirection", sourceValue.flexDirection(), - yogaStyle.flexDirection()); - yogaStyle.justifyContent() = convertRawProp( + yogaStyle.flexDirection())); + + yogaStyle.setJustifyContent(convertRawProp( context, rawProps, "justifyContent", sourceValue.justifyContent(), - yogaStyle.justifyContent()); - yogaStyle.alignContent() = convertRawProp( + yogaStyle.justifyContent())); + + yogaStyle.setAlignContent(convertRawProp( context, rawProps, "alignContent", sourceValue.alignContent(), - yogaStyle.alignContent()); - yogaStyle.alignItems() = convertRawProp( + yogaStyle.alignContent())); + + yogaStyle.setAlignItems(convertRawProp( context, rawProps, "alignItems", sourceValue.alignItems(), - yogaStyle.alignItems()); - yogaStyle.alignSelf() = convertRawProp( + yogaStyle.alignItems())); + + yogaStyle.setAlignSelf(convertRawProp( context, rawProps, "alignSelf", sourceValue.alignSelf(), - yogaStyle.alignSelf()); - yogaStyle.positionType() = convertRawProp( + yogaStyle.alignSelf())); + + yogaStyle.setPositionType(convertRawProp( context, rawProps, "position", sourceValue.positionType(), - yogaStyle.positionType()); - yogaStyle.flexWrap() = convertRawProp( + yogaStyle.positionType())); + + yogaStyle.setFlexWrap(convertRawProp( context, rawProps, "flexWrap", sourceValue.flexWrap(), - yogaStyle.flexWrap()); - yogaStyle.overflow() = convertRawProp( + yogaStyle.flexWrap())); + + yogaStyle.setOverflow(convertRawProp( context, rawProps, "overflow", sourceValue.overflow(), - yogaStyle.overflow()); - yogaStyle.display() = convertRawProp( - context, rawProps, "display", sourceValue.display(), yogaStyle.display()); + yogaStyle.overflow())); + + yogaStyle.setDisplay(convertRawProp( + context, + rawProps, + "display", + sourceValue.display(), + yogaStyle.display())); yogaStyle.setFlex(convertRawProp( context, rawProps, "flex", sourceValue.flex(), yogaStyle.flex())); @@ -463,6 +477,7 @@ static inline yoga::Style convertRawProp( "width", sourceValue.dimension(yoga::Dimension::Width), {})); + yogaStyle.setDimension( yoga::Dimension::Height, convertRawProp( @@ -480,6 +495,7 @@ static inline yoga::Style convertRawProp( "minWidth", sourceValue.minDimension(yoga::Dimension::Width), {})); + yogaStyle.setMinDimension( yoga::Dimension::Height, convertRawProp( @@ -497,6 +513,7 @@ static inline yoga::Style convertRawProp( "maxWidth", sourceValue.maxDimension(yoga::Dimension::Width), {})); + yogaStyle.setMaxDimension( yoga::Dimension::Height, convertRawProp( diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/tests/LayoutTest.cpp b/packages/react-native/ReactCommon/react/renderer/components/view/tests/LayoutTest.cpp index bdb879a974598e..9933cce9f47ed7 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/tests/LayoutTest.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/view/tests/LayoutTest.cpp @@ -89,7 +89,7 @@ class LayoutTest : public ::testing::Test { auto sharedProps = std::make_shared(); auto &props = *sharedProps; auto &yogaStyle = props.yogaStyle; - yogaStyle.positionType() = yoga::PositionType::Absolute; + yogaStyle.setPositionType(yoga::PositionType::Absolute); yogaStyle.setDimension(yoga::Dimension::Width, yoga::value::points(50)); yogaStyle.setDimension(yoga::Dimension::Height, yoga::value::points(50)); return sharedProps; @@ -102,7 +102,7 @@ class LayoutTest : public ::testing::Test { auto sharedProps = std::make_shared(); auto &props = *sharedProps; auto &yogaStyle = props.yogaStyle; - yogaStyle.positionType() = yoga::PositionType::Absolute; + yogaStyle.setPositionType(yoga::PositionType::Absolute); yogaStyle.setPosition(yoga::Edge::Left, yoga::value::points(10)); yogaStyle.setPosition(yoga::Edge::Top, yoga::value::points(10)); yogaStyle.setDimension(yoga::Dimension::Width, yoga::value::points(30)); @@ -132,10 +132,10 @@ class LayoutTest : public ::testing::Test { auto &yogaStyle = props.yogaStyle; if (testCase == CLIPPING) { - yogaStyle.overflow() = yoga::Overflow::Hidden; + yogaStyle.setOverflow(yoga::Overflow::Hidden); } - yogaStyle.positionType() = yoga::PositionType::Absolute; + yogaStyle.setPositionType(yoga::PositionType::Absolute); yogaStyle.setPosition(yoga::Edge::Left, yoga::value::points(10)); yogaStyle.setPosition(yoga::Edge::Top, yoga::value::points(10)); yogaStyle.setDimension(yoga::Dimension::Width, yoga::value::points(110)); @@ -150,7 +150,7 @@ class LayoutTest : public ::testing::Test { auto sharedProps = std::make_shared(); auto &props = *sharedProps; auto &yogaStyle = props.yogaStyle; - yogaStyle.positionType() = yoga::PositionType::Absolute; + yogaStyle.setPositionType(yoga::PositionType::Absolute); yogaStyle.setPosition(yoga::Edge::Left, yoga::value::points(70)); yogaStyle.setPosition(yoga::Edge::Top, yoga::value::points(-50)); yogaStyle.setDimension(yoga::Dimension::Width, yoga::value::points(30)); @@ -165,7 +165,7 @@ class LayoutTest : public ::testing::Test { auto sharedProps = std::make_shared(); auto &props = *sharedProps; auto &yogaStyle = props.yogaStyle; - yogaStyle.positionType() = yoga::PositionType::Absolute; + yogaStyle.setPositionType(yoga::PositionType::Absolute); yogaStyle.setPosition(yoga::Edge::Left, yoga::value::points(-60)); yogaStyle.setPosition(yoga::Edge::Top, yoga::value::points(50)); yogaStyle.setDimension(yoga::Dimension::Width, yoga::value::points(70)); diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/tests/ViewTest.cpp b/packages/react-native/ReactCommon/react/renderer/components/view/tests/ViewTest.cpp index f948248c680eef..f0302ffc06f9bd 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/tests/ViewTest.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/view/tests/ViewTest.cpp @@ -52,8 +52,8 @@ class YogaDirtyFlagTest : public ::testing::Test { auto &props = *mutableViewProps; props.nativeId = "native Id"; props.opacity = 0.5; - props.yogaStyle.alignContent() = yoga::Align::Baseline; - props.yogaStyle.flexDirection() = yoga::FlexDirection::RowReverse; + props.yogaStyle.setAlignContent(yoga::Align::Baseline); + props.yogaStyle.setFlexDirection(yoga::FlexDirection::RowReverse); return mutableViewProps; }), Element() @@ -136,8 +136,8 @@ TEST_F(YogaDirtyFlagTest, changingLayoutSubPropsMustDirtyYogaNode) { auto viewProps = std::make_shared(); auto& props = *viewProps; - props.yogaStyle.alignContent() = yoga::Align::Baseline; - props.yogaStyle.display() = yoga::Display::None; + props.yogaStyle.setAlignContent(yoga::Align::Baseline); + props.yogaStyle.setDisplay(yoga::Display::None); return oldShadowNode.clone(ShadowNodeFragment{viewProps}); }); diff --git a/packages/react-native/ReactCommon/react/renderer/core/tests/FindNodeAtPointTest.cpp b/packages/react-native/ReactCommon/react/renderer/core/tests/FindNodeAtPointTest.cpp index 25bc0e35d4768a..c5f74fd84fb94c 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/tests/FindNodeAtPointTest.cpp +++ b/packages/react-native/ReactCommon/react/renderer/core/tests/FindNodeAtPointTest.cpp @@ -202,7 +202,7 @@ TEST(FindNodeAtPointTest, overlappingViewsWithZIndex) { auto sharedProps = std::make_shared(); sharedProps->zIndex = 1; auto &yogaStyle = sharedProps->yogaStyle; - yogaStyle.positionType() = yoga::PositionType::Absolute; + yogaStyle.setPositionType(yoga::PositionType::Absolute); return sharedProps; }) .finalize([](ViewShadowNode &shadowNode){ diff --git a/packages/react-native/ReactCommon/react/renderer/mounting/tests/StackingContextTest.cpp b/packages/react-native/ReactCommon/react/renderer/mounting/tests/StackingContextTest.cpp index f09dabda6d332e..e1eabecd057ad2 100644 --- a/packages/react-native/ReactCommon/react/renderer/mounting/tests/StackingContextTest.cpp +++ b/packages/react-native/ReactCommon/react/renderer/mounting/tests/StackingContextTest.cpp @@ -253,7 +253,7 @@ TEST_F(StackingContextTest, mostPropsDoNotForceViewsToMaterialize) { auto& yogaStyle = props.yogaStyle; yogaStyle.setPadding(yoga::Edge::All, yoga::value::points(42)); yogaStyle.setMargin(yoga::Edge::All, yoga::value::points(42)); - yogaStyle.positionType() = yoga::PositionType::Absolute; + yogaStyle.setPositionType(yoga::PositionType::Absolute); props.shadowRadius = 42; props.shadowOffset = Size{42, 42}; props.backgroundColor = clearColor(); @@ -269,7 +269,7 @@ TEST_F(StackingContextTest, mostPropsDoNotForceViewsToMaterialize) { mutateViewShadowNodeProps_(nodeBBA_, [](ViewProps& props) { auto& yogaStyle = props.yogaStyle; - yogaStyle.positionType() = yoga::PositionType::Relative; + yogaStyle.setPositionType(yoga::PositionType::Relative); props.borderRadii.all = 42; props.borderColors.all = blackColor(); @@ -456,7 +456,7 @@ TEST_F(StackingContextTest, somePropsForceViewsToMaterialize2) { mutateViewShadowNodeProps_(nodeBBB_, [](ViewProps& props) { auto& yogaStyle = props.yogaStyle; - yogaStyle.positionType() = yoga::PositionType::Relative; + yogaStyle.setPositionType(yoga::PositionType::Relative); props.zIndex = 42; }); @@ -538,37 +538,37 @@ TEST_F(StackingContextTest, zIndexAndFlattenedNodes) { mutateViewShadowNodeProps_(nodeAA_, [](ViewProps& props) { auto& yogaStyle = props.yogaStyle; - yogaStyle.positionType() = yoga::PositionType::Relative; + yogaStyle.setPositionType(yoga::PositionType::Relative); props.zIndex = 9001; }); mutateViewShadowNodeProps_(nodeBA_, [](ViewProps& props) { auto& yogaStyle = props.yogaStyle; - yogaStyle.positionType() = yoga::PositionType::Relative; + yogaStyle.setPositionType(yoga::PositionType::Relative); props.zIndex = 9000; }); mutateViewShadowNodeProps_(nodeBBA_, [](ViewProps& props) { auto& yogaStyle = props.yogaStyle; - yogaStyle.positionType() = yoga::PositionType::Relative; + yogaStyle.setPositionType(yoga::PositionType::Relative); props.zIndex = 8999; }); mutateViewShadowNodeProps_(nodeBBB_, [](ViewProps& props) { auto& yogaStyle = props.yogaStyle; - yogaStyle.positionType() = yoga::PositionType::Relative; + yogaStyle.setPositionType(yoga::PositionType::Relative); props.zIndex = 8998; }); mutateViewShadowNodeProps_(nodeBC_, [](ViewProps& props) { auto& yogaStyle = props.yogaStyle; - yogaStyle.positionType() = yoga::PositionType::Relative; + yogaStyle.setPositionType(yoga::PositionType::Relative); props.zIndex = 8997; }); mutateViewShadowNodeProps_(nodeBD_, [](ViewProps& props) { auto& yogaStyle = props.yogaStyle; - yogaStyle.positionType() = yoga::PositionType::Relative; + yogaStyle.setPositionType(yoga::PositionType::Relative); props.zIndex = 8996; }); @@ -652,7 +652,7 @@ TEST_F(StackingContextTest, zIndexAndFlattenedNodes) { mutateViewShadowNodeProps_(nodeBB_, [](ViewProps& props) { auto& yogaStyle = props.yogaStyle; - yogaStyle.positionType() = yoga::PositionType::Relative; + yogaStyle.setPositionType(yoga::PositionType::Relative); props.zIndex = 42; }); @@ -680,7 +680,7 @@ TEST_F(StackingContextTest, zIndexAndFlattenedNodes) { mutateViewShadowNodeProps_(nodeBB_, [](ViewProps& props) { auto& yogaStyle = props.yogaStyle; - yogaStyle.positionType() = yoga::PositionType::Static; + yogaStyle.setPositionType(yoga::PositionType::Static); props.zIndex = {}; }); @@ -764,7 +764,7 @@ TEST_F(StackingContextTest, zIndexAndFlattenedNodes) { mutateViewShadowNodeProps_(nodeBB_, [](ViewProps& props) { auto& yogaStyle = props.yogaStyle; - yogaStyle.display() = yoga::Display::None; + yogaStyle.setDisplay(yoga::Display::None); }); testViewTree_([](const StubViewTree& viewTree) { diff --git a/packages/react-native/ReactCommon/yoga/yoga/YGNodeStyle.cpp b/packages/react-native/ReactCommon/yoga/yoga/YGNodeStyle.cpp index 441b7797f776fb..14f2dc3062270e 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/YGNodeStyle.cpp +++ b/packages/react-native/ReactCommon/yoga/yoga/YGNodeStyle.cpp @@ -14,54 +14,26 @@ using namespace facebook::yoga; namespace { -template -void updateStyle( - yoga::Node* node, - T value, - NeedsUpdate&& needsUpdate, - Update&& update) { - if (needsUpdate(node->getStyle(), value)) { - update(node->getStyle(), value); - node->markDirtyAndPropagate(); - } -} - -template -void updateStyle(YGNodeRef node, Ref (Style::*prop)(), ValueT value) { - updateStyle( - resolveRef(node), - value, - [prop](Style& s, ValueT x) { return (s.*prop)() != x; }, - [prop](Style& s, ValueT x) { (s.*prop)() = x; }); -} - template void updateStyle(YGNodeRef node, ValueT value) { - updateStyle( - resolveRef(node), - value, - [](Style& s, ValueT x) { return (s.*GetterT)() != x; }, - [](Style& s, ValueT x) { (s.*SetterT)(x); }); + auto& style = resolveRef(node)->getStyle(); + if ((style.*GetterT)() != value) { + (style.*SetterT)(value); + resolveRef(node)->markDirtyAndPropagate(); + } } template -void updateIndexedStyleProp(YGNodeRef node, IdxT idx, ValueT value) { - updateStyle( - resolveRef(node), - value, - [idx](Style& s, ValueT x) { return (s.*GetterT)(idx) != x; }, - [idx](Style& s, ValueT x) { (s.*SetterT)(idx, x); }); +void updateStyle(YGNodeRef node, IdxT idx, ValueT value) { + auto& style = resolveRef(node)->getStyle(); + if ((style.*GetterT)(idx) != value) { + (style.*SetterT)(idx, value); + resolveRef(node)->markDirtyAndPropagate(); + } } } // namespace -// MSVC has trouble inferring the return type of pointer to member functions -// with const and non-const overloads, instead of preferring the non-const -// overload like clang and GCC. For the purposes of updateStyle(), we can help -// MSVC by specifying that return type explicitly. In combination with -// decltype, MSVC will prefer the non-const version. -#define MSVC_HINT(PROP) decltype(Style{}.PROP()) - void YGNodeCopyStyle( const YGNodeRef dstNodeRef, const YGNodeConstRef srcNodeRef) { @@ -75,7 +47,7 @@ void YGNodeCopyStyle( } void YGNodeStyleSetDirection(const YGNodeRef node, const YGDirection value) { - updateStyle(node, &Style::direction, scopedEnum(value)); + updateStyle<&Style::direction, &Style::setDirection>(node, scopedEnum(value)); } YGDirection YGNodeStyleGetDirection(const YGNodeConstRef node) { @@ -85,8 +57,8 @@ YGDirection YGNodeStyleGetDirection(const YGNodeConstRef node) { void YGNodeStyleSetFlexDirection( const YGNodeRef node, const YGFlexDirection flexDirection) { - updateStyle( - node, &Style::flexDirection, scopedEnum(flexDirection)); + updateStyle<&Style::flexDirection, &Style::setFlexDirection>( + node, scopedEnum(flexDirection)); } YGFlexDirection YGNodeStyleGetFlexDirection(const YGNodeConstRef node) { @@ -96,8 +68,8 @@ YGFlexDirection YGNodeStyleGetFlexDirection(const YGNodeConstRef node) { void YGNodeStyleSetJustifyContent( const YGNodeRef node, const YGJustify justifyContent) { - updateStyle( - node, &Style::justifyContent, scopedEnum(justifyContent)); + updateStyle<&Style::justifyContent, &Style::setJustifyContent>( + node, scopedEnum(justifyContent)); } YGJustify YGNodeStyleGetJustifyContent(const YGNodeConstRef node) { @@ -107,8 +79,8 @@ YGJustify YGNodeStyleGetJustifyContent(const YGNodeConstRef node) { void YGNodeStyleSetAlignContent( const YGNodeRef node, const YGAlign alignContent) { - updateStyle( - node, &Style::alignContent, scopedEnum(alignContent)); + updateStyle<&Style::alignContent, &Style::setAlignContent>( + node, scopedEnum(alignContent)); } YGAlign YGNodeStyleGetAlignContent(const YGNodeConstRef node) { @@ -116,8 +88,8 @@ YGAlign YGNodeStyleGetAlignContent(const YGNodeConstRef node) { } void YGNodeStyleSetAlignItems(const YGNodeRef node, const YGAlign alignItems) { - updateStyle( - node, &Style::alignItems, scopedEnum(alignItems)); + updateStyle<&Style::alignItems, &Style::setAlignItems>( + node, scopedEnum(alignItems)); } YGAlign YGNodeStyleGetAlignItems(const YGNodeConstRef node) { @@ -125,8 +97,8 @@ YGAlign YGNodeStyleGetAlignItems(const YGNodeConstRef node) { } void YGNodeStyleSetAlignSelf(const YGNodeRef node, const YGAlign alignSelf) { - updateStyle( - node, &Style::alignSelf, scopedEnum(alignSelf)); + updateStyle<&Style::alignSelf, &Style::setAlignSelf>( + node, scopedEnum(alignSelf)); } YGAlign YGNodeStyleGetAlignSelf(const YGNodeConstRef node) { @@ -136,8 +108,8 @@ YGAlign YGNodeStyleGetAlignSelf(const YGNodeConstRef node) { void YGNodeStyleSetPositionType( const YGNodeRef node, const YGPositionType positionType) { - updateStyle( - node, &Style::positionType, scopedEnum(positionType)); + updateStyle<&Style::positionType, &Style::setPositionType>( + node, scopedEnum(positionType)); } YGPositionType YGNodeStyleGetPositionType(const YGNodeConstRef node) { @@ -145,8 +117,8 @@ YGPositionType YGNodeStyleGetPositionType(const YGNodeConstRef node) { } void YGNodeStyleSetFlexWrap(const YGNodeRef node, const YGWrap flexWrap) { - updateStyle( - node, &Style::flexWrap, scopedEnum(flexWrap)); + updateStyle<&Style::flexWrap, &Style::setFlexWrap>( + node, scopedEnum(flexWrap)); } YGWrap YGNodeStyleGetFlexWrap(const YGNodeConstRef node) { @@ -154,8 +126,8 @@ YGWrap YGNodeStyleGetFlexWrap(const YGNodeConstRef node) { } void YGNodeStyleSetOverflow(const YGNodeRef node, const YGOverflow overflow) { - updateStyle( - node, &Style::overflow, scopedEnum(overflow)); + updateStyle<&Style::overflow, &Style::setOverflow>( + node, scopedEnum(overflow)); } YGOverflow YGNodeStyleGetOverflow(const YGNodeConstRef node) { @@ -163,7 +135,7 @@ YGOverflow YGNodeStyleGetOverflow(const YGNodeConstRef node) { } void YGNodeStyleSetDisplay(const YGNodeRef node, const YGDisplay display) { - updateStyle(node, &Style::display, scopedEnum(display)); + updateStyle<&Style::display, &Style::setDisplay>(node, scopedEnum(display)); } YGDisplay YGNodeStyleGetDisplay(const YGNodeConstRef node) { @@ -231,12 +203,12 @@ YGValue YGNodeStyleGetFlexBasis(const YGNodeConstRef node) { } void YGNodeStyleSetPosition(YGNodeRef node, YGEdge edge, float points) { - updateIndexedStyleProp<&Style::position, &Style::setPosition>( + updateStyle<&Style::position, &Style::setPosition>( node, scopedEnum(edge), value::points(points)); } void YGNodeStyleSetPositionPercent(YGNodeRef node, YGEdge edge, float percent) { - updateIndexedStyleProp<&Style::position, &Style::setPosition>( + updateStyle<&Style::position, &Style::setPosition>( node, scopedEnum(edge), value::percent(percent)); } @@ -245,17 +217,17 @@ YGValue YGNodeStyleGetPosition(YGNodeConstRef node, YGEdge edge) { } void YGNodeStyleSetMargin(YGNodeRef node, YGEdge edge, float points) { - updateIndexedStyleProp<&Style::margin, &Style::setMargin>( + updateStyle<&Style::margin, &Style::setMargin>( node, scopedEnum(edge), value::points(points)); } void YGNodeStyleSetMarginPercent(YGNodeRef node, YGEdge edge, float percent) { - updateIndexedStyleProp<&Style::margin, &Style::setMargin>( + updateStyle<&Style::margin, &Style::setMargin>( node, scopedEnum(edge), value::percent(percent)); } void YGNodeStyleSetMarginAuto(YGNodeRef node, YGEdge edge) { - updateIndexedStyleProp<&Style::margin, &Style::setMargin>( + updateStyle<&Style::margin, &Style::setMargin>( node, scopedEnum(edge), value::ofAuto()); } @@ -264,12 +236,12 @@ YGValue YGNodeStyleGetMargin(YGNodeConstRef node, YGEdge edge) { } void YGNodeStyleSetPadding(YGNodeRef node, YGEdge edge, float points) { - updateIndexedStyleProp<&Style::padding, &Style::setPadding>( + updateStyle<&Style::padding, &Style::setPadding>( node, scopedEnum(edge), value::points(points)); } void YGNodeStyleSetPaddingPercent(YGNodeRef node, YGEdge edge, float percent) { - updateIndexedStyleProp<&Style::padding, &Style::setPadding>( + updateStyle<&Style::padding, &Style::setPadding>( node, scopedEnum(edge), value::percent(percent)); } @@ -281,7 +253,7 @@ void YGNodeStyleSetBorder( const YGNodeRef node, const YGEdge edge, const float border) { - updateIndexedStyleProp<&Style::border, &Style::setBorder>( + updateStyle<&Style::border, &Style::setBorder>( node, scopedEnum(edge), value::points(border)); } @@ -298,7 +270,7 @@ void YGNodeStyleSetGap( const YGNodeRef node, const YGGutter gutter, const float gapLength) { - updateIndexedStyleProp<&Style::gap, &Style::setGap>( + updateStyle<&Style::gap, &Style::setGap>( node, scopedEnum(gutter), value::points(gapLength)); } @@ -322,17 +294,17 @@ float YGNodeStyleGetAspectRatio(const YGNodeConstRef node) { } void YGNodeStyleSetWidth(YGNodeRef node, float points) { - updateIndexedStyleProp<&Style::dimension, &Style::setDimension>( + updateStyle<&Style::dimension, &Style::setDimension>( node, Dimension::Width, value::points(points)); } void YGNodeStyleSetWidthPercent(YGNodeRef node, float percent) { - updateIndexedStyleProp<&Style::dimension, &Style::setDimension>( + updateStyle<&Style::dimension, &Style::setDimension>( node, Dimension::Width, value::percent(percent)); } void YGNodeStyleSetWidthAuto(YGNodeRef node) { - updateIndexedStyleProp<&Style::dimension, &Style::setDimension>( + updateStyle<&Style::dimension, &Style::setDimension>( node, Dimension::Width, value::ofAuto()); } @@ -341,17 +313,17 @@ YGValue YGNodeStyleGetWidth(YGNodeConstRef node) { } void YGNodeStyleSetHeight(YGNodeRef node, float points) { - updateIndexedStyleProp<&Style::dimension, &Style::setDimension>( + updateStyle<&Style::dimension, &Style::setDimension>( node, Dimension::Height, value::points(points)); } void YGNodeStyleSetHeightPercent(YGNodeRef node, float percent) { - updateIndexedStyleProp<&Style::dimension, &Style::setDimension>( + updateStyle<&Style::dimension, &Style::setDimension>( node, Dimension::Height, value::percent(percent)); } void YGNodeStyleSetHeightAuto(YGNodeRef node) { - updateIndexedStyleProp<&Style::dimension, &Style::setDimension>( + updateStyle<&Style::dimension, &Style::setDimension>( node, Dimension::Height, value::ofAuto()); } @@ -360,12 +332,12 @@ YGValue YGNodeStyleGetHeight(YGNodeConstRef node) { } void YGNodeStyleSetMinWidth(const YGNodeRef node, const float minWidth) { - updateIndexedStyleProp<&Style::minDimension, &Style::setMinDimension>( + updateStyle<&Style::minDimension, &Style::setMinDimension>( node, Dimension::Width, value::points(minWidth)); } void YGNodeStyleSetMinWidthPercent(const YGNodeRef node, const float minWidth) { - updateIndexedStyleProp<&Style::minDimension, &Style::setMinDimension>( + updateStyle<&Style::minDimension, &Style::setMinDimension>( node, Dimension::Width, value::percent(minWidth)); } @@ -374,14 +346,14 @@ YGValue YGNodeStyleGetMinWidth(const YGNodeConstRef node) { } void YGNodeStyleSetMinHeight(const YGNodeRef node, const float minHeight) { - updateIndexedStyleProp<&Style::minDimension, &Style::setMinDimension>( + updateStyle<&Style::minDimension, &Style::setMinDimension>( node, Dimension::Height, value::points(minHeight)); } void YGNodeStyleSetMinHeightPercent( const YGNodeRef node, const float minHeight) { - updateIndexedStyleProp<&Style::minDimension, &Style::setMinDimension>( + updateStyle<&Style::minDimension, &Style::setMinDimension>( node, Dimension::Height, value::percent(minHeight)); } @@ -390,12 +362,12 @@ YGValue YGNodeStyleGetMinHeight(const YGNodeConstRef node) { } void YGNodeStyleSetMaxWidth(const YGNodeRef node, const float maxWidth) { - updateIndexedStyleProp<&Style::maxDimension, &Style::setMaxDimension>( + updateStyle<&Style::maxDimension, &Style::setMaxDimension>( node, Dimension::Width, value::points(maxWidth)); } void YGNodeStyleSetMaxWidthPercent(const YGNodeRef node, const float maxWidth) { - updateIndexedStyleProp<&Style::maxDimension, &Style::setMaxDimension>( + updateStyle<&Style::maxDimension, &Style::setMaxDimension>( node, Dimension::Width, value::percent(maxWidth)); } @@ -404,14 +376,14 @@ YGValue YGNodeStyleGetMaxWidth(const YGNodeConstRef node) { } void YGNodeStyleSetMaxHeight(const YGNodeRef node, const float maxHeight) { - updateIndexedStyleProp<&Style::maxDimension, &Style::setMaxDimension>( + updateStyle<&Style::maxDimension, &Style::setMaxDimension>( node, Dimension::Height, value::points(maxHeight)); } void YGNodeStyleSetMaxHeightPercent( const YGNodeRef node, const float maxHeight) { - updateIndexedStyleProp<&Style::maxDimension, &Style::setMaxDimension>( + updateStyle<&Style::maxDimension, &Style::setMaxDimension>( node, Dimension::Height, value::percent(maxHeight)); } diff --git a/packages/react-native/ReactCommon/yoga/yoga/node/Node.h b/packages/react-native/ReactCommon/yoga/yoga/node/Node.h index d01a1ed4ca6da2..0cb9fabc8ea8af 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/node/Node.h +++ b/packages/react-native/ReactCommon/yoga/yoga/node/Node.h @@ -61,8 +61,8 @@ class YG_EXPORT Node : public ::YGNode { Direction direction) const; void useWebDefaults() { - style_.flexDirection() = FlexDirection::Row; - style_.alignContent() = Align::Stretch; + style_.setFlexDirection(FlexDirection::Row); + style_.setAlignContent(Align::Stretch); } template diff --git a/packages/react-native/ReactCommon/yoga/yoga/style/Style.h b/packages/react-native/ReactCommon/yoga/yoga/style/Style.h index 09f5c3c1fb88ca..74736d27b9bec4 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/style/Style.h +++ b/packages/react-native/ReactCommon/yoga/yoga/style/Style.h @@ -55,22 +55,9 @@ class YG_EXPORT Style { static constexpr float DefaultFlexShrink = 0.0f; static constexpr float WebDefaultFlexShrink = 1.0f; - template - struct BitfieldRef { - Style& style; - uint8_t offset; - operator T() const { - return getEnumData(style.flags, offset); - } - BitfieldRef& operator=(T x) { - setEnumData(style.flags, offset, x); - return *this; - } - }; - Style() { - alignContent() = Align::FlexStart; - alignItems() = Align::Stretch; + setAlignContent(Align::FlexStart); + setAlignItems(Align::Stretch); } ~Style() = default; @@ -99,7 +86,7 @@ class YG_EXPORT Style { static constexpr uint8_t displayOffset = overflowOffset + minimumBitCount(); - uint32_t flags = 0; + uint32_t flags_ = 0; FloatOptional flex_ = {}; FloatOptional flexGrow_ = {}; @@ -118,73 +105,73 @@ class YG_EXPORT Style { public: Direction direction() const { - return getEnumData(flags, directionOffset); + return getEnumData(flags_, directionOffset); } - BitfieldRef direction() { - return {*this, directionOffset}; + void setDirection(Direction value) { + setEnumData(flags_, directionOffset, value); } FlexDirection flexDirection() const { - return getEnumData(flags, flexdirectionOffset); + return getEnumData(flags_, flexdirectionOffset); } - BitfieldRef flexDirection() { - return {*this, flexdirectionOffset}; + void setFlexDirection(FlexDirection value) { + setEnumData(flags_, flexdirectionOffset, value); } Justify justifyContent() const { - return getEnumData(flags, justifyContentOffset); + return getEnumData(flags_, justifyContentOffset); } - BitfieldRef justifyContent() { - return {*this, justifyContentOffset}; + void setJustifyContent(Justify value) { + setEnumData(flags_, justifyContentOffset, value); } Align alignContent() const { - return getEnumData(flags, alignContentOffset); + return getEnumData(flags_, alignContentOffset); } - BitfieldRef alignContent() { - return {*this, alignContentOffset}; + void setAlignContent(Align value) { + setEnumData(flags_, alignContentOffset, value); } Align alignItems() const { - return getEnumData(flags, alignItemsOffset); + return getEnumData(flags_, alignItemsOffset); } - BitfieldRef alignItems() { - return {*this, alignItemsOffset}; + void setAlignItems(Align value) { + setEnumData(flags_, alignItemsOffset, value); } Align alignSelf() const { - return getEnumData(flags, alignSelfOffset); + return getEnumData(flags_, alignSelfOffset); } - BitfieldRef alignSelf() { - return {*this, alignSelfOffset}; + void setAlignSelf(Align value) { + setEnumData(flags_, alignSelfOffset, value); } PositionType positionType() const { - return getEnumData(flags, positionTypeOffset); + return getEnumData(flags_, positionTypeOffset); } - BitfieldRef positionType() { - return {*this, positionTypeOffset}; + void setPositionType(PositionType value) { + setEnumData(flags_, positionTypeOffset, value); } Wrap flexWrap() const { - return getEnumData(flags, flexWrapOffset); + return getEnumData(flags_, flexWrapOffset); } - BitfieldRef flexWrap() { - return {*this, flexWrapOffset}; + void setFlexWrap(Wrap value) { + setEnumData(flags_, flexWrapOffset, value); } Overflow overflow() const { - return getEnumData(flags, overflowOffset); + return getEnumData(flags_, overflowOffset); } - BitfieldRef overflow() { - return {*this, overflowOffset}; + void setOverflow(Overflow value) { + setEnumData(flags_, overflowOffset, value); } Display display() const { - return getEnumData(flags, displayOffset); + return getEnumData(flags_, displayOffset); } - BitfieldRef display() { - return {*this, displayOffset}; + void setDisplay(Display value) { + setEnumData(flags_, displayOffset, value); } FloatOptional flex() const { @@ -295,7 +282,7 @@ class YG_EXPORT Style { } bool operator==(const Style& other) const { - return flags == other.flags && inexactEquals(flex_, other.flex_) && + return flags_ == other.flags_ && inexactEquals(flex_, other.flex_) && inexactEquals(flexGrow_, other.flexGrow_) && inexactEquals(flexShrink_, other.flexShrink_) && inexactEquals(flexBasis_, other.flexBasis_) && From 9078db77a900aa417c3cdf6e8e5b4217061cc442 Mon Sep 17 00:00:00 2001 From: Nick Gerleman Date: Mon, 27 Nov 2023 21:20:20 -0800 Subject: [PATCH 109/162] Remove NumericBitfield (#41394) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41394 X-link: https://github.com/facebook/yoga/pull/1463 Now that are enums are unsigned, and we don't have BitfieldRef, we can convert the last remaining user of NumericBitfield to a plain old bitfield, for better readability (e.g. the default values), debugability, and less complexity. We also break a cycle which lets us properly group public vs private members. Reviewed By: joevilches Differential Revision: D51159415 fbshipit-source-id: 7842a8330eed6061b863de3f175c761dcf4aa2be --- .../ReactCommon/yoga/yoga/YGEnums.h | 32 ++--- .../ReactCommon/yoga/yoga/YGMacros.h | 34 ----- .../yoga/yoga/bits/NumericBitfield.h | 67 --------- .../yoga/yoga/node/LayoutResults.h | 1 - .../ReactCommon/yoga/yoga/style/Style.h | 130 ++++++++---------- 5 files changed, 75 insertions(+), 189 deletions(-) delete mode 100644 packages/react-native/ReactCommon/yoga/yoga/bits/NumericBitfield.h diff --git a/packages/react-native/ReactCommon/yoga/yoga/YGEnums.h b/packages/react-native/ReactCommon/yoga/yoga/YGEnums.h index e1197444db8274..e0454394dae4d8 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/YGEnums.h +++ b/packages/react-native/ReactCommon/yoga/yoga/YGEnums.h @@ -12,7 +12,7 @@ YG_EXTERN_C_BEGIN -YG_ENUM_SEQ_DECL( +YG_ENUM_DECL( YGAlign, YGAlignAuto, YGAlignFlexStart, @@ -24,23 +24,23 @@ YG_ENUM_SEQ_DECL( YGAlignSpaceAround, YGAlignSpaceEvenly) -YG_ENUM_SEQ_DECL( +YG_ENUM_DECL( YGDimension, YGDimensionWidth, YGDimensionHeight) -YG_ENUM_SEQ_DECL( +YG_ENUM_DECL( YGDirection, YGDirectionInherit, YGDirectionLTR, YGDirectionRTL) -YG_ENUM_SEQ_DECL( +YG_ENUM_DECL( YGDisplay, YGDisplayFlex, YGDisplayNone) -YG_ENUM_SEQ_DECL( +YG_ENUM_DECL( YGEdge, YGEdgeLeft, YGEdgeTop, @@ -62,25 +62,25 @@ YG_ENUM_DECL( YGErrataClassic = 2147483646) YG_DEFINE_ENUM_FLAG_OPERATORS(YGErrata) -YG_ENUM_SEQ_DECL( +YG_ENUM_DECL( YGExperimentalFeature, YGExperimentalFeatureWebFlexBasis, YGExperimentalFeatureAbsolutePercentageAgainstPaddingEdge) -YG_ENUM_SEQ_DECL( +YG_ENUM_DECL( YGFlexDirection, YGFlexDirectionColumn, YGFlexDirectionColumnReverse, YGFlexDirectionRow, YGFlexDirectionRowReverse) -YG_ENUM_SEQ_DECL( +YG_ENUM_DECL( YGGutter, YGGutterColumn, YGGutterRow, YGGutterAll) -YG_ENUM_SEQ_DECL( +YG_ENUM_DECL( YGJustify, YGJustifyFlexStart, YGJustifyCenter, @@ -89,7 +89,7 @@ YG_ENUM_SEQ_DECL( YGJustifySpaceAround, YGJustifySpaceEvenly) -YG_ENUM_SEQ_DECL( +YG_ENUM_DECL( YGLogLevel, YGLogLevelError, YGLogLevelWarn, @@ -98,24 +98,24 @@ YG_ENUM_SEQ_DECL( YGLogLevelVerbose, YGLogLevelFatal) -YG_ENUM_SEQ_DECL( +YG_ENUM_DECL( YGMeasureMode, YGMeasureModeUndefined, YGMeasureModeExactly, YGMeasureModeAtMost) -YG_ENUM_SEQ_DECL( +YG_ENUM_DECL( YGNodeType, YGNodeTypeDefault, YGNodeTypeText) -YG_ENUM_SEQ_DECL( +YG_ENUM_DECL( YGOverflow, YGOverflowVisible, YGOverflowHidden, YGOverflowScroll) -YG_ENUM_SEQ_DECL( +YG_ENUM_DECL( YGPositionType, YGPositionTypeStatic, YGPositionTypeRelative, @@ -128,14 +128,14 @@ YG_ENUM_DECL( YGPrintOptionsChildren = 4) YG_DEFINE_ENUM_FLAG_OPERATORS(YGPrintOptions) -YG_ENUM_SEQ_DECL( +YG_ENUM_DECL( YGUnit, YGUnitUndefined, YGUnitPoint, YGUnitPercent, YGUnitAuto) -YG_ENUM_SEQ_DECL( +YG_ENUM_DECL( YGWrap, YGWrapNoWrap, YGWrapWrap, diff --git a/packages/react-native/ReactCommon/yoga/yoga/YGMacros.h b/packages/react-native/ReactCommon/yoga/yoga/YGMacros.h index 07ddb1903b99a8..6460297a3d1684 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/YGMacros.h +++ b/packages/react-native/ReactCommon/yoga/yoga/YGMacros.h @@ -88,40 +88,6 @@ #define YG_DEFINE_ENUM_FLAG_OPERATORS(name) #endif -#ifdef __cplusplus - -namespace facebook::yoga { - -template -constexpr int -ordinalCount(); // can't use `= delete` due to a defect in clang < 3.9 - -namespace detail { -template -constexpr int n() { - return sizeof...(xs); -} -} // namespace detail - -} // namespace facebook::yoga -#endif - #define YG_ENUM_DECL(NAME, ...) \ typedef YG_ENUM_BEGIN(NAME){__VA_ARGS__} YG_ENUM_END(NAME); \ YG_EXPORT const char* NAME##ToString(NAME); - -#ifdef __cplusplus -#define YG_ENUM_SEQ_DECL(NAME, ...) \ - YG_ENUM_DECL(NAME, __VA_ARGS__) \ - YG_EXTERN_C_END \ - \ - namespace facebook::yoga { \ - template <> \ - constexpr int ordinalCount() { \ - return detail::n<__VA_ARGS__>(); \ - } \ - } \ - YG_EXTERN_C_BEGIN -#else -#define YG_ENUM_SEQ_DECL YG_ENUM_DECL -#endif diff --git a/packages/react-native/ReactCommon/yoga/yoga/bits/NumericBitfield.h b/packages/react-native/ReactCommon/yoga/yoga/bits/NumericBitfield.h deleted file mode 100644 index d6102409b2b787..00000000000000 --- a/packages/react-native/ReactCommon/yoga/yoga/bits/NumericBitfield.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and 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 - -#include -#include - -namespace facebook::yoga::details { - -constexpr uint8_t log2ceilFn(uint8_t n) { - return n < 1 ? 0 : (1 + log2ceilFn(n / 2)); -} - -constexpr uint32_t mask(uint8_t bitWidth, uint8_t index) { - return ((1u << bitWidth) - 1u) << index; -} - -} // namespace facebook::yoga::details - -namespace facebook::yoga { - -// The number of bits necessary to represent enums defined with YG_ENUM_SEQ_DECL -template < - typename Enum, - std::enable_if_t<(ordinalCount() > 0), bool> = true> -constexpr uint8_t minimumBitCount() { - return details::log2ceilFn(static_cast(ordinalCount() - 1)); -} - -template -constexpr Enum getEnumData(uint32_t flags, uint8_t index) { - return static_cast( - (flags & details::mask(minimumBitCount(), index)) >> index); -} - -template -void setEnumData(uint32_t& flags, uint8_t index, Value newValue) { - flags = - (flags & - ~static_cast(details::mask(minimumBitCount(), index))) | - ((static_cast(newValue) << index) & - (details::mask(minimumBitCount(), index))); -} - -constexpr bool getBooleanData(uint32_t flags, uint8_t index) { - return (flags >> index) & 1; -} - -inline void setBooleanData(uint32_t& flags, uint8_t index, bool value) { - if (value) { - flags |= 1 << index; - } else { - flags &= ~(1 << index); - } -} - -} // namespace facebook::yoga diff --git a/packages/react-native/ReactCommon/yoga/yoga/node/LayoutResults.h b/packages/react-native/ReactCommon/yoga/yoga/node/LayoutResults.h index f7cf8b8cf47858..819ec1e487d989 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/node/LayoutResults.h +++ b/packages/react-native/ReactCommon/yoga/yoga/node/LayoutResults.h @@ -9,7 +9,6 @@ #include -#include #include #include #include diff --git a/packages/react-native/ReactCommon/yoga/yoga/style/Style.h b/packages/react-native/ReactCommon/yoga/yoga/style/Style.h index 74736d27b9bec4..30f631f279b602 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/style/Style.h +++ b/packages/react-native/ReactCommon/yoga/yoga/style/Style.h @@ -14,7 +14,6 @@ #include -#include #include #include #include @@ -55,123 +54,74 @@ class YG_EXPORT Style { static constexpr float DefaultFlexShrink = 0.0f; static constexpr float WebDefaultFlexShrink = 1.0f; - Style() { - setAlignContent(Align::FlexStart); - setAlignItems(Align::Stretch); - } - ~Style() = default; - - private: - using Dimensions = std::array()>; - using Edges = std::array()>; - using Gutters = std::array()>; - - static constexpr uint8_t directionOffset = 0; - static constexpr uint8_t flexdirectionOffset = - directionOffset + minimumBitCount(); - static constexpr uint8_t justifyContentOffset = - flexdirectionOffset + minimumBitCount(); - static constexpr uint8_t alignContentOffset = - justifyContentOffset + minimumBitCount(); - static constexpr uint8_t alignItemsOffset = - alignContentOffset + minimumBitCount(); - static constexpr uint8_t alignSelfOffset = - alignItemsOffset + minimumBitCount(); - static constexpr uint8_t positionTypeOffset = - alignSelfOffset + minimumBitCount(); - static constexpr uint8_t flexWrapOffset = - positionTypeOffset + minimumBitCount(); - static constexpr uint8_t overflowOffset = - flexWrapOffset + minimumBitCount(); - static constexpr uint8_t displayOffset = - overflowOffset + minimumBitCount(); - - uint32_t flags_ = 0; - - FloatOptional flex_ = {}; - FloatOptional flexGrow_ = {}; - FloatOptional flexShrink_ = {}; - Style::Length flexBasis_ = value::ofAuto(); - Edges margin_ = {}; - Edges position_ = {}; - Edges padding_ = {}; - Edges border_ = {}; - Gutters gap_ = {}; - Dimensions dimensions_{value::ofAuto(), value::ofAuto()}; - Dimensions minDimensions_ = {}; - Dimensions maxDimensions_ = {}; - // Yoga specific properties, not compatible with flexbox specification - FloatOptional aspectRatio_ = {}; - - public: Direction direction() const { - return getEnumData(flags_, directionOffset); + return direction_; } void setDirection(Direction value) { - setEnumData(flags_, directionOffset, value); + direction_ = value; } FlexDirection flexDirection() const { - return getEnumData(flags_, flexdirectionOffset); + return flexDirection_; } void setFlexDirection(FlexDirection value) { - setEnumData(flags_, flexdirectionOffset, value); + flexDirection_ = value; } Justify justifyContent() const { - return getEnumData(flags_, justifyContentOffset); + return justifyContent_; } void setJustifyContent(Justify value) { - setEnumData(flags_, justifyContentOffset, value); + justifyContent_ = value; } Align alignContent() const { - return getEnumData(flags_, alignContentOffset); + return alignContent_; } void setAlignContent(Align value) { - setEnumData(flags_, alignContentOffset, value); + alignContent_ = value; } Align alignItems() const { - return getEnumData(flags_, alignItemsOffset); + return alignItems_; } void setAlignItems(Align value) { - setEnumData(flags_, alignItemsOffset, value); + alignItems_ = value; } Align alignSelf() const { - return getEnumData(flags_, alignSelfOffset); + return alignSelf_; } void setAlignSelf(Align value) { - setEnumData(flags_, alignSelfOffset, value); + alignSelf_ = value; } PositionType positionType() const { - return getEnumData(flags_, positionTypeOffset); + return positionType_; } void setPositionType(PositionType value) { - setEnumData(flags_, positionTypeOffset, value); + positionType_ = value; } Wrap flexWrap() const { - return getEnumData(flags_, flexWrapOffset); + return flexWrap_; } void setFlexWrap(Wrap value) { - setEnumData(flags_, flexWrapOffset, value); + flexWrap_ = value; } Overflow overflow() const { - return getEnumData(flags_, overflowOffset); + return overflow_; } void setOverflow(Overflow value) { - setEnumData(flags_, overflowOffset, value); + overflow_ = value; } Display display() const { - return getEnumData(flags_, displayOffset); + return display_; } void setDisplay(Display value) { - setEnumData(flags_, displayOffset, value); + display_ = value; } FloatOptional flex() const { @@ -282,7 +232,14 @@ class YG_EXPORT Style { } bool operator==(const Style& other) const { - return flags_ == other.flags_ && inexactEquals(flex_, other.flex_) && + return direction_ == other.direction_ && + flexDirection_ == other.flexDirection_ && + justifyContent_ == other.justifyContent_ && + alignContent_ == other.alignContent_ && + alignItems_ == other.alignItems_ && alignSelf_ == other.alignSelf_ && + positionType_ == other.positionType_ && flexWrap_ == other.flexWrap_ && + overflow_ == other.overflow_ && display_ == other.display_ && + inexactEquals(flex_, other.flex_) && inexactEquals(flexGrow_, other.flexGrow_) && inexactEquals(flexShrink_, other.flexShrink_) && inexactEquals(flexBasis_, other.flexBasis_) && @@ -300,6 +257,37 @@ class YG_EXPORT Style { bool operator!=(const Style& other) const { return !(*this == other); } + + private: + using Dimensions = std::array()>; + using Edges = std::array()>; + using Gutters = std::array()>; + + Direction direction_ : bitCount() = Direction::Inherit; + FlexDirection flexDirection_ + : bitCount() = FlexDirection::Column; + Justify justifyContent_ : bitCount() = Justify::FlexStart; + Align alignContent_ : bitCount() = Align::FlexStart; + Align alignItems_ : bitCount() = Align::Stretch; + Align alignSelf_ : bitCount() = Align::Auto; + PositionType positionType_ : bitCount() = PositionType::Static; + Wrap flexWrap_ : bitCount() = Wrap::NoWrap; + Overflow overflow_ : bitCount() = Overflow::Visible; + Display display_ : bitCount() = Display::Flex; + + FloatOptional flex_{}; + FloatOptional flexGrow_{}; + FloatOptional flexShrink_{}; + Style::Length flexBasis_{value::ofAuto()}; + Edges margin_{}; + Edges position_{}; + Edges padding_{}; + Edges border_{}; + Gutters gap_{}; + Dimensions dimensions_{value::ofAuto(), value::ofAuto()}; + Dimensions minDimensions_{}; + Dimensions maxDimensions_{}; + FloatOptional aspectRatio_{}; }; } // namespace facebook::yoga From 94c76612062c548782cb9b033398467cb8a079e4 Mon Sep 17 00:00:00 2001 From: Gabriel Donadel Date: Tue, 28 Nov 2023 03:24:25 -0800 Subject: [PATCH 110/162] Update 'cannot calculate shadow efficiently' log message (#39700) Summary: While working in an app I kept getting these `View X of type Y has a shadow set but cannot calculate shadow efficiently. Consider setting a background color to fix this` warnings even though I had added a background color to that view. Upon inspecting RCTView.m I notice that what is actually required to fix this is a solid background To make this a bit clearer to developers I believe we should update this log message to explicitly say "solid background" instead of "background" ## Changelog: [IOS] [CHANGED] - Update 'cannot calculate shadow efficiently' log message to explicitly say solid background Pull Request resolved: https://github.com/facebook/react-native/pull/39700 Test Plan: N / A Reviewed By: christophpurrer Differential Revision: D51584574 Pulled By: javache fbshipit-source-id: b1741f7002ebb876e4a50959bef7f39df76a5c3c --- packages/react-native/React/Views/RCTView.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react-native/React/Views/RCTView.m b/packages/react-native/React/Views/RCTView.m index bb8336615a0208..6e6f9cd2761035 100644 --- a/packages/react-native/React/Views/RCTView.m +++ b/packages/react-native/React/Views/RCTView.m @@ -883,7 +883,7 @@ static void RCTUpdateShadowPathForView(RCTView *view) RCTLogAdvice( @"View #%@ of type %@ has a shadow set but cannot calculate " - "shadow efficiently. Consider setting a background color to " + "shadow efficiently. Consider setting a solid background color to " "fix this, or apply the shadow to a more specific component.", view.reactTag, [view class]); From 4f3094aba440985afa5a88f6e2fd38ffb94f995f Mon Sep 17 00:00:00 2001 From: Nicola Corti Date: Tue, 28 Nov 2023 03:53:47 -0800 Subject: [PATCH 111/162] Kotlin to 1.8.22 (#41661) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41661 This aligns the Kotlin version used inside fbsource to the one used for React Native GitHub Changelog: [Internal] [Changed] - Kotlin to 1.8.22 Reviewed By: NickGerleman Differential Revision: D51587726 fbshipit-source-id: 5f985bd50c7688e4d369184b79dbf1bdc799876e --- packages/react-native-gradle-plugin/gradle/libs.versions.toml | 2 +- packages/react-native/gradle/libs.versions.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/react-native-gradle-plugin/gradle/libs.versions.toml b/packages/react-native-gradle-plugin/gradle/libs.versions.toml index 21f0dca4d214b3..38856f8132ecb2 100644 --- a/packages/react-native-gradle-plugin/gradle/libs.versions.toml +++ b/packages/react-native-gradle-plugin/gradle/libs.versions.toml @@ -4,7 +4,7 @@ gson = "2.8.9" guava = "31.0.1-jre" javapoet = "1.13.0" junit = "4.13.2" -kotlin = "1.8.0" +kotlin = "1.8.22" [libraries] kotlin-gradle-plugin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" } diff --git a/packages/react-native/gradle/libs.versions.toml b/packages/react-native/gradle/libs.versions.toml index 6af863b45b8c05..35f899193977b7 100644 --- a/packages/react-native/gradle/libs.versions.toml +++ b/packages/react-native/gradle/libs.versions.toml @@ -21,7 +21,7 @@ javax-annotation-api = "1.3.2" javax-inject = "1" jsr305 = "3.0.2" junit = "4.13.2" -kotlin = "1.8.0" +kotlin = "1.8.22" mockito = "3.12.4" nexus-publish = "1.3.0" okhttp = "4.9.2" From 25196ba24fe98d387f9320dbc628e154e95c895d Mon Sep 17 00:00:00 2001 From: Nicola Corti Date: Tue, 28 Nov 2023 07:08:54 -0800 Subject: [PATCH 112/162] Fix several build warnings on RN Tester Android (#41660) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41660 While working on other things, I noticed those warnings firing on console which I'm fixing here. Changelog: [Internal] [Changed] - Fix several build warnings on RN Tester Android Reviewed By: cipolleschi Differential Revision: D51589072 fbshipit-source-id: 1ddb29afd0d150f1ccbc7a8def9f27ecedb69724 --- .../java/com/facebook/react/uiapp/RNTesterActivity.kt | 5 ++--- .../react/uiapp/component/MyLegacyViewManager.kt | 10 ++++------ .../com/facebook/react/uiapp/component/MyNativeView.kt | 1 + 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/packages/rn-tester/android/app/src/main/java/com/facebook/react/uiapp/RNTesterActivity.kt b/packages/rn-tester/android/app/src/main/java/com/facebook/react/uiapp/RNTesterActivity.kt index e2e13d7dc96f0f..ad9bff582193b4 100644 --- a/packages/rn-tester/android/app/src/main/java/com/facebook/react/uiapp/RNTesterActivity.kt +++ b/packages/rn-tester/android/app/src/main/java/com/facebook/react/uiapp/RNTesterActivity.kt @@ -20,12 +20,11 @@ class RNTesterActivity : ReactActivity() { override fun onCreate(savedInstanceState: Bundle?) { // Get remote param before calling super which uses it - val bundle = activity.getIntent()?.getExtras() + val bundle = activity.intent?.extras if (bundle != null && bundle.containsKey(PARAM_ROUTE)) { val routeUri = "rntester://example/${bundle.getString(PARAM_ROUTE)}Example" - initialProps = Bundle() - initialProps?.putString("exampleFromAppetizeParams", routeUri) + initialProps = Bundle().apply { putString("exampleFromAppetizeParams", routeUri) } } super.onCreate(savedInstanceState) diff --git a/packages/rn-tester/android/app/src/main/java/com/facebook/react/uiapp/component/MyLegacyViewManager.kt b/packages/rn-tester/android/app/src/main/java/com/facebook/react/uiapp/component/MyLegacyViewManager.kt index d7e101b7d3c5dc..68504be6b060b7 100644 --- a/packages/rn-tester/android/app/src/main/java/com/facebook/react/uiapp/component/MyLegacyViewManager.kt +++ b/packages/rn-tester/android/app/src/main/java/com/facebook/react/uiapp/component/MyLegacyViewManager.kt @@ -35,15 +35,13 @@ internal class MyLegacyViewManager(reactContext: ReactApplicationContext) : } @ReactProp(name = ViewProps.COLOR) - fun setColor(view: MyNativeView, color: String) { - view.setBackgroundColor(Color.parseColor(color)) + fun setColor(view: MyNativeView, color: String?) { + color?.let { view.setBackgroundColor(Color.parseColor(it)) } } @ReactProp(name = "cornerRadius") - fun setCornerRadius(view: MyNativeView, cornerRadius: Float) { - if (cornerRadius !== null) { - view.setCornerRadius(cornerRadius) - } + fun setCornerRadius(view: MyNativeView, cornerRadius: Float?) { + cornerRadius?.let { view.setCornerRadius(it) } } override fun getExportedViewConstants(): Map = mapOf("PI" to 3.14) diff --git a/packages/rn-tester/android/app/src/main/java/com/facebook/react/uiapp/component/MyNativeView.kt b/packages/rn-tester/android/app/src/main/java/com/facebook/react/uiapp/component/MyNativeView.kt index c9365d728025c7..50e7708a422650 100644 --- a/packages/rn-tester/android/app/src/main/java/com/facebook/react/uiapp/component/MyNativeView.kt +++ b/packages/rn-tester/android/app/src/main/java/com/facebook/react/uiapp/component/MyNativeView.kt @@ -5,6 +5,7 @@ * LICENSE file in the root directory of this source tree. */ +@file:Suppress("DEPRECATION") // As we want to test RCTEventEmitter here package com.facebook.react.uiapp.component import android.graphics.Color From a8fc20616fbe673cdc854d33450a772fb7f11cf1 Mon Sep 17 00:00:00 2001 From: Samuel Susla Date: Tue, 28 Nov 2023 08:10:17 -0800 Subject: [PATCH 113/162] do not use ShadowNode::defaultSharedProps in UIManager::clone (#41667) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41667 changelog: [internal] I made a mistake during refactor in D51471667 where I removed the check if rawProps is nullptr. We must check if props are empty during `UIManager::clone`, leaving the check for `ConcreteComponentDescriptor::cloneProps` does not lead to the same result. There is a deeper problem here that needs to be analysed but this should resolve the lunch blocker. Reviewed By: javache Differential Revision: D51614396 fbshipit-source-id: 055694c4a71a914d8732a3632c50026cc24cbe7d --- .../react/renderer/uimanager/UIManager.cpp | 34 ++++++++++--------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/packages/react-native/ReactCommon/react/renderer/uimanager/UIManager.cpp b/packages/react-native/ReactCommon/react/renderer/uimanager/UIManager.cpp index b83cc710b69ef0..a0f667430a912f 100644 --- a/packages/react-native/ReactCommon/react/renderer/uimanager/UIManager.cpp +++ b/packages/react-native/ReactCommon/react/renderer/uimanager/UIManager.cpp @@ -122,22 +122,24 @@ std::shared_ptr UIManager::cloneNode( auto& family = shadowNode.getFamily(); auto props = ShadowNodeFragment::propsPlaceholder(); - if (family.nativeProps_DEPRECATED != nullptr) { - // Values in `rawProps` patch (take precedence over) - // `nativeProps_DEPRECATED`. For example, if both `nativeProps_DEPRECATED` - // and `rawProps` contain key 'A'. Value from `rawProps` overrides what - // was previously in `nativeProps_DEPRECATED`. - family.nativeProps_DEPRECATED = - std::make_unique(mergeDynamicProps( - *family.nativeProps_DEPRECATED, (folly::dynamic)rawProps)); - - props = componentDescriptor.cloneProps( - propsParserContext, - shadowNode.getProps(), - RawProps(*family.nativeProps_DEPRECATED)); - } else { - props = componentDescriptor.cloneProps( - propsParserContext, shadowNode.getProps(), std::move(rawProps)); + if (!rawProps.isEmpty()) { + if (family.nativeProps_DEPRECATED != nullptr) { + // Values in `rawProps` patch (take precedence over) + // `nativeProps_DEPRECATED`. For example, if both `nativeProps_DEPRECATED` + // and `rawProps` contain key 'A'. Value from `rawProps` overrides what + // was previously in `nativeProps_DEPRECATED`. + family.nativeProps_DEPRECATED = + std::make_unique(mergeDynamicProps( + *family.nativeProps_DEPRECATED, (folly::dynamic)rawProps)); + + props = componentDescriptor.cloneProps( + propsParserContext, + shadowNode.getProps(), + RawProps(*family.nativeProps_DEPRECATED)); + } else { + props = componentDescriptor.cloneProps( + propsParserContext, shadowNode.getProps(), std::move(rawProps)); + } } auto clonedShadowNode = componentDescriptor.cloneShadowNode( From 528f97152b7e0a7465c5b5c02e96c2c4306c78fe Mon Sep 17 00:00:00 2001 From: Nicholas Block Date: Tue, 28 Nov 2023 08:57:23 -0800 Subject: [PATCH 114/162] Backout - Schedule a Choreographer callback only if there is ongoing animation Summary: caused performace problems with react app Reviewed By: gpalves Differential Revision: D51617862 fbshipit-source-id: 38c0c06dacdd7aa862fd523a7ce136e54ed55fa2 --- .../react/animated/NativeAnimatedModule.java | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/animated/NativeAnimatedModule.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/animated/NativeAnimatedModule.java index cff0a92988adfe..76749aaff7f948 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/animated/NativeAnimatedModule.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/animated/NativeAnimatedModule.java @@ -25,7 +25,6 @@ import com.facebook.react.bridge.UIManagerListener; import com.facebook.react.bridge.WritableMap; import com.facebook.react.common.annotations.VisibleForTesting; -import com.facebook.react.config.ReactFeatureFlags; import com.facebook.react.module.annotations.ReactModule; import com.facebook.react.modules.core.ReactChoreographer; import com.facebook.react.uimanager.GuardedFrameCallback; @@ -248,13 +247,14 @@ protected void doFrameGuarded(final long frameTimeNanos) { return; } - if (!ReactFeatureFlags.enableOnDemandReactChoreographer - || nodesManager != null && nodesManager.hasActiveAnimations()) { - Assertions.assertNotNull(mReactChoreographer) - .postFrameCallback( - ReactChoreographer.CallbackType.NATIVE_ANIMATED_MODULE, - mAnimatedFrameCallback); - } + // TODO: Would be great to avoid adding this callback in case there are no active + // animations and no outstanding tasks on the operations queue. Apparently frame + // callbacks can only be posted from the UI thread and therefore we cannot schedule + // them directly from other threads. + Assertions.assertNotNull(mReactChoreographer) + .postFrameCallback( + ReactChoreographer.CallbackType.NATIVE_ANIMATED_MODULE, + mAnimatedFrameCallback); } catch (Exception ex) { throw new RuntimeException(ex); } @@ -1116,7 +1116,6 @@ public void onValueUpdate(double value) { opsAndArgs.getInt(i++), opsAndArgs.getInt(i++)); break; case OP_CODE_START_ANIMATING_NODE: - enqueueFrameCallback(); animatedNodesManager.startAnimatingNode( opsAndArgs.getInt(i++), opsAndArgs.getInt(i++), opsAndArgs.getMap(i++), null); break; From 00e70354cadd2d33b985bc9c57c2e376eb4241a1 Mon Sep 17 00:00:00 2001 From: Ramanpreet Nara Date: Tue, 28 Nov 2023 13:17:22 -0800 Subject: [PATCH 115/162] CxxReactPackage: Use hungarian notation for hybridData (#41675) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41675 FBJni expects the HybridData object to exist on the mHybridData property of the java object. So, we have to call this propery mHybridData. Otherwise, this fbjni class just won't work. Changelog: [Internal] Reviewed By: javache Differential Revision: D51550621 fbshipit-source-id: d169266474717f0a38799ede7c07af57461012b7 --- .../facebook/react/runtime/cxxreactpackage/CxxReactPackage.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/cxxreactpackage/CxxReactPackage.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/cxxreactpackage/CxxReactPackage.kt index 278d3d723c3ec7..34a77fa21542c0 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/cxxreactpackage/CxxReactPackage.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/cxxreactpackage/CxxReactPackage.kt @@ -17,13 +17,13 @@ import com.facebook.soloader.SoLoader @UnstableReactNativeAPI() abstract class CxxReactPackage { - @DoNotStrip @SuppressWarnings("unused") private val hybridData: HybridData + @DoNotStrip @Suppress("NoHungarianNotation") private var mHybridData: HybridData? = initHybrid() protected abstract fun initHybrid(): HybridData protected constructor() { maybeLoadOtherSoLibraries() - hybridData = initHybrid() + mHybridData = initHybrid() } @Synchronized protected open fun maybeLoadOtherSoLibraries(): Unit {} From 4c1bdea81db6963bc8d932ec0e472e9b21796a8f Mon Sep 17 00:00:00 2001 From: Ramanpreet Nara Date: Tue, 28 Nov 2023 13:17:22 -0800 Subject: [PATCH 116/162] CxxReactPackage: Load So's during class loads (#41674) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41674 The problem: The Java runtime couldn't find CatalystCxxReactPackage.initHybrid. Why: I think is because CxxReactPackage loads CatalystCxxReactPackage's so in its constructor. This might be too late to load the derived class's so. So, I just switched derived delegates to load the so in the static initializer (i.e: the recomended approch for so loading): https://www.internalfb.com/code/fbsource/[91c4e41c49ed191ac864250ccaec52c01ddaeccc]/fbandroid/libraries/soloader/java/com/facebook/soloader/SoLoader.java?lines=52-54%2C60-61%2C63-67 This way: 1. The So's are loaded plenty early (the method not found error went away). 2. We don't create our own so loading infra, which complicates this abstraction, and makes it harder to work with, even more. Changelog: [Internal] Reviewed By: javache Differential Revision: D51550622 fbshipit-source-id: f4782d6fa9387f21fbf611191e9483e2a58b3a34 --- .../facebook/react/runtime/cxxreactpackage/CxxReactPackage.kt | 3 --- 1 file changed, 3 deletions(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/cxxreactpackage/CxxReactPackage.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/cxxreactpackage/CxxReactPackage.kt index 34a77fa21542c0..bba110e72361fd 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/cxxreactpackage/CxxReactPackage.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/cxxreactpackage/CxxReactPackage.kt @@ -22,12 +22,9 @@ abstract class CxxReactPackage { protected abstract fun initHybrid(): HybridData protected constructor() { - maybeLoadOtherSoLibraries() mHybridData = initHybrid() } - @Synchronized protected open fun maybeLoadOtherSoLibraries(): Unit {} - companion object { init { SoLoader.loadLibrary("react_cxxreactpackage") From 129bd9d813b10a9eee461b9315c41a12b04afc4b Mon Sep 17 00:00:00 2001 From: Ramanpreet Nara Date: Tue, 28 Nov 2023 13:17:22 -0800 Subject: [PATCH 117/162] Ensure C++ default tmmd can access the CxxReactPackage (#41673) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41673 ## The Problem The cxxReactPackage property isn't initialized by the time initHybrid was executed. So, initHybrid was being called with null as the cxxReactPackage. Why; 1. The default turbomodule manager delegate receives cxxReactPackage as a constructor param. 2. Java then executes all the constructors of the class hierarchy. This executes initHybrid. 3. Java finally initializes the properties of the derived class: default tmmd.cxxReactPackage (i.e: the parameter to initHybrid). **This is too late** ## The Fix Refactor the code such that hybrid data creation doesn't depend on property initialization: 1. Create a static initHybrid method in default tmmd. 2. Call this static method with the cxxReactPackage, and assign the resultant HybridData to mHybridData (in tmmd). Changelog: [Internal] Reviewed By: javache Differential Revision: D51550623 fbshipit-source-id: ed2b7587351cfca408cda3c8cef4dcf7547e5f1e --- ...eactPackageTurboModuleManagerDelegate.java | 14 +++++++++++-- .../DefaultTurboModuleManagerDelegate.kt | 20 +++++++++++-------- .../core/TurboModuleManagerDelegate.java | 7 +++++++ .../DefaultTurboModuleManagerDelegate.cpp | 11 ++++++---- .../DefaultTurboModuleManagerDelegate.h | 4 ++-- 5 files changed, 40 insertions(+), 16 deletions(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactPackageTurboModuleManagerDelegate.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactPackageTurboModuleManagerDelegate.java index 30ef9e019b3783..949276ec20b195 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactPackageTurboModuleManagerDelegate.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactPackageTurboModuleManagerDelegate.java @@ -10,6 +10,7 @@ import androidx.annotation.Nullable; import com.facebook.common.logging.FLog; import com.facebook.infer.annotation.Assertions; +import com.facebook.jni.HybridData; import com.facebook.react.bridge.CxxModuleWrapper; import com.facebook.react.bridge.ModuleSpec; import com.facebook.react.bridge.NativeModule; @@ -53,13 +54,22 @@ interface ModuleProvider { private List mPackages; private ReactApplicationContext mReactContext; - protected ReactPackageTurboModuleManagerDelegate() { + protected ReactPackageTurboModuleManagerDelegate( + ReactApplicationContext reactApplicationContext, List packages) { super(); + initialize(reactApplicationContext, packages); } protected ReactPackageTurboModuleManagerDelegate( + ReactApplicationContext reactApplicationContext, + List packages, + HybridData hybridData) { + super(hybridData); + initialize(reactApplicationContext, packages); + } + + private void initialize( ReactApplicationContext reactApplicationContext, List packages) { - super(); if (mIsLazy) { mPackages = packages; mReactContext = reactApplicationContext; diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultTurboModuleManagerDelegate.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultTurboModuleManagerDelegate.kt index 10a7dc7c5d2f75..ad38bb31f10e61 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultTurboModuleManagerDelegate.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultTurboModuleManagerDelegate.kt @@ -28,12 +28,13 @@ private constructor( context: ReactApplicationContext, packages: List, private val eagerlyInitializedModules: List, - private val cxxReactPackage: CxxReactPackage?, -) : ReactPackageTurboModuleManagerDelegate(context, packages) { + cxxReactPackage: CxxReactPackage?, +) : ReactPackageTurboModuleManagerDelegate(context, packages, initHybrid(cxxReactPackage)) { - @DoNotStrip override fun initHybrid() = initHybrid(cxxReactPackage) - - external fun initHybrid(cxxReactPackage: CxxReactPackage?): HybridData? + override fun initHybrid(): HybridData? { + throw UnsupportedOperationException( + "DefaultTurboModuleManagerDelegate.initHybrid() must never be called!") + } override fun getEagerInitModuleNames(): List { if (unstable_isLazyTurboModuleDelegate()) { @@ -62,8 +63,11 @@ private constructor( DefaultTurboModuleManagerDelegate(context, packages, eagerInitModuleNames, cxxReactPackage) } - @Synchronized - override fun maybeLoadOtherSoLibraries() { - DefaultSoLoader.maybeLoadSoLibrary() + companion object { + init { + DefaultSoLoader.maybeLoadSoLibrary() + } + + @DoNotStrip @JvmStatic external fun initHybrid(cxxReactPackage: CxxReactPackage?): HybridData? } } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/turbomodule/core/TurboModuleManagerDelegate.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/turbomodule/core/TurboModuleManagerDelegate.java index 2740fa7208ae7d..7cb82679a3aefa 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/turbomodule/core/TurboModuleManagerDelegate.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/turbomodule/core/TurboModuleManagerDelegate.java @@ -31,6 +31,11 @@ protected TurboModuleManagerDelegate() { mHybridData = initHybrid(); } + protected TurboModuleManagerDelegate(HybridData hybridData) { + maybeLoadOtherSoLibraries(); + mHybridData = hybridData; + } + /** * Create and return a TurboModule Java object with name `moduleName`. If `moduleName` isn't a * TurboModule, return null. @@ -77,5 +82,7 @@ public boolean unstable_enableSyncVoidMethods() { return false; } + // TODO(T171231381): Consider removing this method: could we just use the static initializer + // of derived classes instead? protected synchronized void maybeLoadOtherSoLibraries() {} } diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/newarchdefaults/DefaultTurboModuleManagerDelegate.cpp b/packages/react-native/ReactAndroid/src/main/jni/react/newarchdefaults/DefaultTurboModuleManagerDelegate.cpp index 86944f2e6c4a20..fc480af328b6ee 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/newarchdefaults/DefaultTurboModuleManagerDelegate.cpp +++ b/packages/react-native/ReactAndroid/src/main/jni/react/newarchdefaults/DefaultTurboModuleManagerDelegate.cpp @@ -27,7 +27,7 @@ std::function( jni::local_ref DefaultTurboModuleManagerDelegate::initHybrid( - jni::alias_ref, + jni::alias_ref jClass, jni::alias_ref cxxReactPackage) { return makeCxxInstance(cxxReactPackage); } @@ -43,9 +43,12 @@ std::shared_ptr DefaultTurboModuleManagerDelegate::getTurboModule( const std::string& name, const std::shared_ptr& jsInvoker) { if (cxxReactPackage_) { - auto module = cxxReactPackage_->cthis()->getModule(name, jsInvoker); - if (module) { - return module; + auto cppPart = cxxReactPackage_->cthis(); + if (cppPart) { + auto module = cppPart->getModule(name, jsInvoker); + if (module) { + return module; + } } } diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/newarchdefaults/DefaultTurboModuleManagerDelegate.h b/packages/react-native/ReactAndroid/src/main/jni/react/newarchdefaults/DefaultTurboModuleManagerDelegate.h index e175a574bc394b..687a23b0c29062 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/newarchdefaults/DefaultTurboModuleManagerDelegate.h +++ b/packages/react-native/ReactAndroid/src/main/jni/react/newarchdefaults/DefaultTurboModuleManagerDelegate.h @@ -24,7 +24,7 @@ class DefaultTurboModuleManagerDelegate : public jni::HybridClass< "Lcom/facebook/react/defaults/DefaultTurboModuleManagerDelegate;"; static jni::local_ref initHybrid( - jni::alias_ref, + jni::alias_ref, jni::alias_ref); static void registerNatives(); @@ -53,7 +53,7 @@ class DefaultTurboModuleManagerDelegate : public jni::HybridClass< jni::global_ref cxxReactPackage_; DefaultTurboModuleManagerDelegate( - jni::alias_ref); + jni::alias_ref cxxReactPackage); }; } // namespace facebook::react From aa9e824a756a86f61873c270b17603468a2166ec Mon Sep 17 00:00:00 2001 From: zhongwuzw Date: Tue, 28 Nov 2023 15:14:54 -0800 Subject: [PATCH 118/162] Move ActionSheet UI operation to main thread (#41666) Summary: Fixes UI operation not on the main thread. ![image](https://github.com/facebook/react-native/assets/5061845/276f7e9c-dcf8-4ba1-af2d-c9fa990d41a1) ![image](https://github.com/facebook/react-native/assets/5061845/cfe85921-3cc9-4f32-b794-a6a8bc00ee1d) ## Changelog: [IOS] [FIXED] - Move ActionSheet UI operation to main thread Pull Request resolved: https://github.com/facebook/react-native/pull/41666 Test Plan: None. Reviewed By: philIip Differential Revision: D51613525 Pulled By: cipolleschi fbshipit-source-id: e5f543bbcc9bc0f5b6dda5bc2deb20279e851946 --- .../react-native/React/CoreModules/RCTActionSheetManager.mm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/react-native/React/CoreModules/RCTActionSheetManager.mm b/packages/react-native/React/CoreModules/RCTActionSheetManager.mm index dbe389a1eced46..f8df74b2401604 100644 --- a/packages/react-native/React/CoreModules/RCTActionSheetManager.mm +++ b/packages/react-native/React/CoreModules/RCTActionSheetManager.mm @@ -100,9 +100,9 @@ - (void)presentViewController:(UIViewController *)alertController [RCTConvert UIColor:options.cancelButtonTintColor() ? @(*options.cancelButtonTintColor()) : nil]; NSString *userInterfaceStyle = [RCTConvert NSString:options.userInterfaceStyle()]; - UIViewController *controller = RCTPresentedViewController(); - dispatch_async(dispatch_get_main_queue(), ^{ + UIViewController *controller = RCTPresentedViewController(); + if (controller == nil) { RCTLogError( @"Tried to display action sheet but there is no application window. options: %@", @{ From 40c7736a1d12dffa5223598bfa3e8336d2bdc7a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Norte?= Date: Tue, 28 Nov 2023 16:36:35 -0800 Subject: [PATCH 119/162] Fix incorrect wrapping of refs in Image component (#41679) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41679 This fixes a bug in the original implementation of image attached callbacks (still experimental). The problem was that we were unconditionally caching the ref passed to the underlying image component, which meant that whenever users passed new ref setters we wouldn't call them again. This fixes that by forcing the creation of a new ref value whenever a new ref is passed to the image component. Changelog: [internal] Reviewed By: jehartzog Differential Revision: D51618512 fbshipit-source-id: ac15160c528563c2131e8b3444dea4a6096f20bc --- .../Libraries/Image/Image.android.js | 13 +++- .../react-native/Libraries/Image/Image.ios.js | 12 +++- .../Libraries/Image/ImageInjection.js | 15 +---- .../Libraries/Image/__tests__/Image-test.js | 61 +++++++++++++++++++ 4 files changed, 85 insertions(+), 16 deletions(-) diff --git a/packages/react-native/Libraries/Image/Image.android.js b/packages/react-native/Libraries/Image/Image.android.js index e5c5d9f223b616..eeec72e2724aea 100644 --- a/packages/react-native/Libraries/Image/Image.android.js +++ b/packages/react-native/Libraries/Image/Image.android.js @@ -15,10 +15,11 @@ import type {AbstractImageAndroid, ImageAndroid} from './ImageTypes.flow'; import flattenStyle from '../StyleSheet/flattenStyle'; import StyleSheet from '../StyleSheet/StyleSheet'; import TextAncestor from '../Text/TextAncestor'; +import useMergeRefs from '../Utilities/useMergeRefs'; import ImageAnalyticsTagContext from './ImageAnalyticsTagContext'; import { unstable_getImageComponentDecorator, - useWrapRefWithImageAttachedCallbacks, + useRefWithImageAttachedCallbacks, } from './ImageInjection'; import {getImageSourcesFromImageProps} from './ImageSourceUtils'; import {convertObjectFitToResizeMode} from './ImageUtils'; @@ -199,7 +200,15 @@ let BaseImage: AbstractImageAndroid = React.forwardRef( const resizeMode = objectFit || props.resizeMode || style?.resizeMode || 'cover'; - const actualRef = useWrapRefWithImageAttachedCallbacks(forwardedRef); + const imageAttachedCallbacksRef = useRefWithImageAttachedCallbacks(); + + const actualRef = + useMergeRefs | null>( + // $FlowFixMe[incompatible-call] + forwardedRef, + // $FlowFixMe[incompatible-call] + imageAttachedCallbacksRef, + ); return ( diff --git a/packages/react-native/Libraries/Image/Image.ios.js b/packages/react-native/Libraries/Image/Image.ios.js index ce21b5b4edf049..2dabd798485eb5 100644 --- a/packages/react-native/Libraries/Image/Image.ios.js +++ b/packages/react-native/Libraries/Image/Image.ios.js @@ -15,10 +15,11 @@ import type {AbstractImageIOS, ImageIOS} from './ImageTypes.flow'; import {createRootTag} from '../ReactNative/RootTag'; import flattenStyle from '../StyleSheet/flattenStyle'; import StyleSheet from '../StyleSheet/StyleSheet'; +import useMergeRefs from '../Utilities/useMergeRefs'; import ImageAnalyticsTagContext from './ImageAnalyticsTagContext'; import { unstable_getImageComponentDecorator, - useWrapRefWithImageAttachedCallbacks, + useRefWithImageAttachedCallbacks, } from './ImageInjection'; import {getImageSourcesFromImageProps} from './ImageSourceUtils'; import {convertObjectFitToResizeMode} from './ImageUtils'; @@ -161,7 +162,14 @@ let BaseImage: AbstractImageIOS = React.forwardRef((props, forwardedRef) => { }; const accessibilityLabel = props['aria-label'] ?? props.accessibilityLabel; - const actualRef = useWrapRefWithImageAttachedCallbacks(forwardedRef); + const imageAttachedCallbacksRef = useRefWithImageAttachedCallbacks(); + + const actualRef = useMergeRefs | null>( + // $FlowFixMe[incompatible-call] + forwardedRef, + // $FlowFixMe[incompatible-call] + imageAttachedCallbacksRef, + ); return ( diff --git a/packages/react-native/Libraries/Image/ImageInjection.js b/packages/react-native/Libraries/Image/ImageInjection.js index 38515d46e32799..7a2e59ca9a45a3 100644 --- a/packages/react-native/Libraries/Image/ImageInjection.js +++ b/packages/react-native/Libraries/Image/ImageInjection.js @@ -52,19 +52,10 @@ export function unstable_unregisterImageAttachedCallback( imageAttachedCallbacks.delete(callback); } -type ProxyRef = (ImageInstance | null) => void; - -export function useWrapRefWithImageAttachedCallbacks( - forwardedRef?: React.Ref, -): ProxyRef { +export function useRefWithImageAttachedCallbacks(): React.RefSetter { const pendingCleanupCallbacks = useRef void>>([]); - const proxyRef = useRef(node => { - if (typeof forwardedRef === 'function') { - forwardedRef(node); - } else if (typeof forwardedRef === 'object' && forwardedRef != null) { - forwardedRef.current = node; - } + const ref = useRef((node: ImageInstance | null) => { if (node == null) { if (pendingCleanupCallbacks.current.length > 0) { pendingCleanupCallbacks.current.forEach(cb => cb()); @@ -80,5 +71,5 @@ export function useWrapRefWithImageAttachedCallbacks( } }); - return proxyRef.current; + return ref.current; } diff --git a/packages/react-native/Libraries/Image/__tests__/Image-test.js b/packages/react-native/Libraries/Image/__tests__/Image-test.js index 4cc8d11176d090..46124adc88ef2a 100644 --- a/packages/react-native/Libraries/Image/__tests__/Image-test.js +++ b/packages/react-native/Libraries/Image/__tests__/Image-test.js @@ -45,6 +45,67 @@ describe('', () => { expect(instance).toMatchSnapshot(); }); + it('should invoke original ref callbacks correctly when using image attached callbacks', () => { + jest.dontMock('../Image'); + + let imageInstanceFromCallback = null; + let imageInstanceFromRef1 = null; + let imageInstanceFromRef2 = null; + + const callback = jest.fn((instance: ElementRef) => { + imageInstanceFromCallback = instance; + + return () => { + imageInstanceFromCallback = null; + }; + }); + + ImageInjection.unstable_registerImageAttachedCallback(callback); + + expect(imageInstanceFromCallback).toBe(null); + + let testRenderer; + + const ref1 = jest.fn(instance => { + imageInstanceFromRef1 = instance; + }); + + act(() => { + testRenderer = create(); + }); + + expect(imageInstanceFromCallback).not.toBe(null); + expect(imageInstanceFromRef1).not.toBe(null); + expect(imageInstanceFromCallback).toBe(imageInstanceFromRef1); + expect(callback).toHaveBeenCalledTimes(1); + expect(ref1).toHaveBeenCalledTimes(1); + + const ref2 = jest.fn( + (instance: React.ElementRef | null): void => { + imageInstanceFromRef2 = instance; + }, + ); + + act(() => { + testRenderer.update(); + }); + + expect(imageInstanceFromCallback).not.toBe(null); + expect(imageInstanceFromRef1).toBe(null); + expect(imageInstanceFromRef2).not.toBe(null); + expect(imageInstanceFromCallback).toBe(imageInstanceFromRef2); + expect(callback).toHaveBeenCalledTimes(2); + expect(ref1).toHaveBeenCalledTimes(2); + expect(ref2).toHaveBeenCalledTimes(1); + + act(() => { + testRenderer.update(); + }); + + expect(callback).toHaveBeenCalledTimes(2); + expect(ref2).toHaveBeenCalledTimes(1); + }); + it('should call image attached callbacks (basic)', () => { jest.dontMock('../Image'); From 9e4fa20b7546febb6aa668bd0053914ecd5d8638 Mon Sep 17 00:00:00 2001 From: Ramanpreet Nara Date: Tue, 28 Nov 2023 16:46:27 -0800 Subject: [PATCH 120/162] Extend default tmmdelegate to support many cxxreactpackages (#41680) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41680 Just like how React Native can have n ReactPackages, it will support n CxxReactPackages. This way, many applications can share common CxxReactPackages. Changelog: [Internal] Reviewed By: christophpurrer Differential Revision: D51484844 fbshipit-source-id: b9b70cab719e80a7ff7e635057d710f1a86fb1c9 --- .../DefaultTurboModuleManagerDelegate.kt | 16 ++++++------ .../DefaultTurboModuleManagerDelegate.cpp | 25 ++++++++++++++----- .../DefaultTurboModuleManagerDelegate.h | 8 +++--- 3 files changed, 33 insertions(+), 16 deletions(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultTurboModuleManagerDelegate.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultTurboModuleManagerDelegate.kt index ad38bb31f10e61..a8644376293d43 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultTurboModuleManagerDelegate.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultTurboModuleManagerDelegate.kt @@ -28,8 +28,8 @@ private constructor( context: ReactApplicationContext, packages: List, private val eagerlyInitializedModules: List, - cxxReactPackage: CxxReactPackage?, -) : ReactPackageTurboModuleManagerDelegate(context, packages, initHybrid(cxxReactPackage)) { + cxxReactPackages: List, +) : ReactPackageTurboModuleManagerDelegate(context, packages, initHybrid(cxxReactPackages)) { override fun initHybrid(): HybridData? { throw UnsupportedOperationException( @@ -47,20 +47,20 @@ private constructor( class Builder : ReactPackageTurboModuleManagerDelegate.Builder() { private var eagerInitModuleNames: List = emptyList() - private var cxxReactPackage: CxxReactPackage? = null + private var cxxReactPackages: MutableList = mutableListOf() fun setEagerInitModuleNames(eagerInitModuleNames: List): Builder { this.eagerInitModuleNames = eagerInitModuleNames return this } - fun setCxxReactPackage(cxxReactPackage: CxxReactPackage): Builder { - this.cxxReactPackage = cxxReactPackage + fun addCxxReactPackage(cxxReactPackage: CxxReactPackage): Builder { + this.cxxReactPackages.add(cxxReactPackage) return this } override fun build(context: ReactApplicationContext, packages: List) = - DefaultTurboModuleManagerDelegate(context, packages, eagerInitModuleNames, cxxReactPackage) + DefaultTurboModuleManagerDelegate(context, packages, eagerInitModuleNames, cxxReactPackages) } companion object { @@ -68,6 +68,8 @@ private constructor( DefaultSoLoader.maybeLoadSoLibrary() } - @DoNotStrip @JvmStatic external fun initHybrid(cxxReactPackage: CxxReactPackage?): HybridData? + @DoNotStrip + @JvmStatic + external fun initHybrid(cxxReactPackages: List): HybridData? } } diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/newarchdefaults/DefaultTurboModuleManagerDelegate.cpp b/packages/react-native/ReactAndroid/src/main/jni/react/newarchdefaults/DefaultTurboModuleManagerDelegate.cpp index fc480af328b6ee..e202896abc7bad 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/newarchdefaults/DefaultTurboModuleManagerDelegate.cpp +++ b/packages/react-native/ReactAndroid/src/main/jni/react/newarchdefaults/DefaultTurboModuleManagerDelegate.cpp @@ -7,13 +7,25 @@ #include "DefaultTurboModuleManagerDelegate.h" +#include + #include namespace facebook::react { DefaultTurboModuleManagerDelegate::DefaultTurboModuleManagerDelegate( - jni::alias_ref cxxReactPackage) - : cxxReactPackage_(jni::make_global(cxxReactPackage)){}; + jni::alias_ref::javaobject> + cxxReactPackages) + : cxxReactPackages_() { + cxxReactPackages_.reserve(cxxReactPackages->size()); + std::transform( + cxxReactPackages->begin(), + cxxReactPackages->end(), + std::back_inserter(cxxReactPackages_), + [](jni::alias_ref elem) { + return jni::make_global(elem); + }); +}; std::function( const std::string&, @@ -28,8 +40,9 @@ std::function( jni::local_ref DefaultTurboModuleManagerDelegate::initHybrid( jni::alias_ref jClass, - jni::alias_ref cxxReactPackage) { - return makeCxxInstance(cxxReactPackage); + jni::alias_ref::javaobject> + cxxReactPackages) { + return makeCxxInstance(cxxReactPackages); } void DefaultTurboModuleManagerDelegate::registerNatives() { @@ -42,8 +55,8 @@ void DefaultTurboModuleManagerDelegate::registerNatives() { std::shared_ptr DefaultTurboModuleManagerDelegate::getTurboModule( const std::string& name, const std::shared_ptr& jsInvoker) { - if (cxxReactPackage_) { - auto cppPart = cxxReactPackage_->cthis(); + for (const auto& cxxReactPackage : cxxReactPackages_) { + auto cppPart = cxxReactPackage->cthis(); if (cppPart) { auto module = cppPart->getModule(name, jsInvoker); if (module) { diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/newarchdefaults/DefaultTurboModuleManagerDelegate.h b/packages/react-native/ReactAndroid/src/main/jni/react/newarchdefaults/DefaultTurboModuleManagerDelegate.h index 687a23b0c29062..099c245f574df9 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/newarchdefaults/DefaultTurboModuleManagerDelegate.h +++ b/packages/react-native/ReactAndroid/src/main/jni/react/newarchdefaults/DefaultTurboModuleManagerDelegate.h @@ -7,6 +7,7 @@ #include #include +#include #include #include @@ -25,7 +26,7 @@ class DefaultTurboModuleManagerDelegate : public jni::HybridClass< static jni::local_ref initHybrid( jni::alias_ref, - jni::alias_ref); + jni::alias_ref::javaobject>); static void registerNatives(); @@ -50,10 +51,11 @@ class DefaultTurboModuleManagerDelegate : public jni::HybridClass< friend HybridBase; using HybridBase::HybridBase; - jni::global_ref cxxReactPackage_; + std::vector> cxxReactPackages_; DefaultTurboModuleManagerDelegate( - jni::alias_ref cxxReactPackage); + jni::alias_ref::javaobject> + cxxReactPackage); }; } // namespace facebook::react From 02b94476af0680dc3521116e2a71aba5fe5acade Mon Sep 17 00:00:00 2001 From: Neil Dhar Date: Tue, 28 Nov 2023 16:50:06 -0800 Subject: [PATCH 121/162] Handle UTF8 in native exception message (#41575) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41575 We currently do not validate the incoming native exception message before passing it to the char* constructor of TwineChar16. Treat it as UTF-8 and convert it to UTF-16 before creating the JavaScript exception. Changelog: [Internal] Reviewed By: tmikov Differential Revision: D49551640 fbshipit-source-id: 762f8038b29818d804bda5a7f3b4762621c94336 --- .../ReactCommon/jsi/jsi/test/testlib.cpp | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/packages/react-native/ReactCommon/jsi/jsi/test/testlib.cpp b/packages/react-native/ReactCommon/jsi/jsi/test/testlib.cpp index e24284112beb89..abb008e164226f 100644 --- a/packages/react-native/ReactCommon/jsi/jsi/test/testlib.cpp +++ b/packages/react-native/ReactCommon/jsi/jsi/test/testlib.cpp @@ -1520,6 +1520,25 @@ TEST_P(JSITest, NativeStateSymbolOverrides) { 42); } +TEST_P(JSITest, UTF8ExceptionTest) { + // Test that a native exception containing UTF-8 characters is correctly + // passed through. + Function throwUtf8 = Function::createFromHostFunction( + rt, + PropNameID::forAscii(rt, "throwUtf8"), + 1, + [](Runtime& rt, const Value&, const Value* args, size_t) -> Value { + throw JSINativeException(args[0].asString(rt).utf8(rt)); + }); + std::string utf8 = "👍"; + try { + throwUtf8.call(rt, utf8); + FAIL(); + } catch (const JSError& e) { + EXPECT_NE(e.getMessage().find(utf8), std::string::npos); + } +} + INSTANTIATE_TEST_CASE_P( Runtimes, JSITest, From 2ddd9cd5f50417e0d66a08fe8ad46b61a2539ac9 Mon Sep 17 00:00:00 2001 From: Arushi Kesarwani Date: Tue, 28 Nov 2023 18:29:04 -0800 Subject: [PATCH 122/162] Adding getFabricUIManager() APIs to ReactContext (#41506) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41506 Adding APIs for `getFabricUIManager()` to ReactContext and it's subclasses. This will replace the `getJSIModule()` post JSI module deletion. Thereby replacing the callsite to context.getFabricUIManager() in UIManagerHelper. NOTE: This still has fallback to getJSIModule() in case the UIManagerProvider is not set Changelog: [Internal] internal Reviewed By: philIip Differential Revision: D50926218 fbshipit-source-id: f311affb0f82895b254fd4664aa8ea23ab31bac0 --- .../facebook/react/bridge/ReactContext.java | 20 +++++++++++++++++++ .../react/runtime/BridgelessReactContext.java | 6 ++++++ .../react/uimanager/ThemedReactContext.java | 9 +++++++++ .../react/uimanager/UIManagerHelper.java | 5 ++--- .../NativeAnimatedNodeTraversalTest.kt | 1 + 5 files changed, 38 insertions(+), 3 deletions(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactContext.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactContext.java index b57513cb67216e..78c385ce157643 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactContext.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactContext.java @@ -26,6 +26,7 @@ import com.facebook.react.bridge.queue.ReactQueueConfiguration; import com.facebook.react.common.LifecycleState; import com.facebook.react.common.ReactConstants; +import com.facebook.react.common.annotations.DeprecatedInNewArchitecture; import java.lang.ref.WeakReference; import java.util.Collection; import java.util.concurrent.CopyOnWriteArraySet; @@ -554,6 +555,25 @@ public boolean isBridgeless() { return mCatalystInstance.getJSIModule(moduleType); } + @DeprecatedInNewArchitecture( + message = + "This method will be deprecated later as part of Stable APIs with bridge removal and not encouraged usage.") + /** + * Get the UIManager for Fabric from the CatalystInstance. + * + * @return The UIManager when CatalystInstance is active. + */ + public @Nullable UIManager getFabricUIManager() { + if (!hasActiveReactInstance()) { + throw new IllegalStateException( + "Unable to retrieve a UIManager if CatalystInstance is not active."); + } + UIManager uiManager = mCatalystInstance.getFabricUIManager(); + return uiManager != null + ? uiManager + : (UIManager) mCatalystInstance.getJSIModule(JSIModuleType.UIManager); + } + /** * Get the sourceURL for the JS bundle from the CatalystInstance. This method is needed for * compatibility with bridgeless mode, which has no CatalystInstance. diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/BridgelessReactContext.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/BridgelessReactContext.java index ad4b76d4b549dc..6e1994a3804d00 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/BridgelessReactContext.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/BridgelessReactContext.java @@ -21,6 +21,7 @@ import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactNoCrashBridgeNotAllowedSoftException; import com.facebook.react.bridge.ReactSoftExceptionLogger; +import com.facebook.react.bridge.UIManager; import com.facebook.react.bridge.WritableNativeArray; import com.facebook.react.config.ReactFeatureFlags; import com.facebook.react.devsupport.interfaces.DevSupportManager; @@ -84,6 +85,11 @@ public void setSourceURL(String sourceURL) { + moduleType.name()); } + @Override + public @Nullable UIManager getFabricUIManager() { + return mReactHost.getUIManager(); + } + @Override public CatalystInstance getCatalystInstance() { ReactSoftExceptionLogger.logSoftExceptionVerbose( diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ThemedReactContext.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ThemedReactContext.java index b10d2d9b3c0681..eded794637a424 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ThemedReactContext.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ThemedReactContext.java @@ -15,6 +15,7 @@ import com.facebook.react.bridge.LifecycleEventListener; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactContext; +import com.facebook.react.bridge.UIManager; /** * Wraps {@link ReactContext} with the base {@link Context} passed into the constructor. It provides @@ -116,4 +117,12 @@ public JSIModule getJSIModule(JSIModuleType moduleType) { } return super.getJSIModule(moduleType); } + + @Override + public UIManager getFabricUIManager() { + if (isBridgeless()) { + return mReactApplicationContext.getFabricUIManager(); + } + return super.getFabricUIManager(); + } } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerHelper.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerHelper.java index c4a3902d1e3d6a..52f635eaa6aac0 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerHelper.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerHelper.java @@ -17,7 +17,6 @@ import androidx.annotation.Nullable; import androidx.core.view.ViewCompat; import com.facebook.react.bridge.CatalystInstance; -import com.facebook.react.bridge.JSIModuleType; import com.facebook.react.bridge.ReactContext; import com.facebook.react.bridge.ReactNoCrashSoftException; import com.facebook.react.bridge.ReactSoftExceptionLogger; @@ -53,7 +52,7 @@ private static UIManager getUIManager( @UIManagerType int uiManagerType, boolean returnNullIfCatalystIsInactive) { if (context.isBridgeless()) { - @Nullable UIManager uiManager = (UIManager) context.getJSIModule(JSIModuleType.UIManager); + @Nullable UIManager uiManager = context.getFabricUIManager(); if (uiManager == null) { ReactSoftExceptionLogger.logSoftException( TAG, @@ -85,7 +84,7 @@ private static UIManager getUIManager( CatalystInstance catalystInstance = context.getCatalystInstance(); try { return uiManagerType == FABRIC - ? (UIManager) catalystInstance.getJSIModule(JSIModuleType.UIManager) + ? context.getFabricUIManager() : catalystInstance.getNativeModule(UIManagerModule.class); } catch (IllegalArgumentException ex) { // TODO T67518514 Clean this up once we migrate everything over to bridgeless mode diff --git a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/animated/NativeAnimatedNodeTraversalTest.kt b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/animated/NativeAnimatedNodeTraversalTest.kt index b5eb4fc91d6c1e..96d15479cd901e 100644 --- a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/animated/NativeAnimatedNodeTraversalTest.kt +++ b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/animated/NativeAnimatedNodeTraversalTest.kt @@ -83,6 +83,7 @@ class NativeAnimatedNodeTraversalTest { whenever(catalystInstanceMock.getJSIModule(any(JSIModuleType::class.java))).thenAnswer { uiManagerMock } + whenever(reactApplicationContextMock.getFabricUIManager()).thenAnswer { uiManagerMock } whenever(catalystInstanceMock.getNativeModule(UIManagerModule::class.java)).thenAnswer { uiManagerMock } From fa436b4a63845730be2c6c43b63a72e5b7852f56 Mon Sep 17 00:00:00 2001 From: Nick Gerleman Date: Tue, 28 Nov 2023 18:51:34 -0800 Subject: [PATCH 123/162] Explicitly default Fabric to `position: "static"` (#41481) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41481 This will allow us to keep RN on it's "pseudo-static" mode, while changing the Yoga default back to relative, to avoid breaking existing layouts. Changelog: [Internal] Reviewed By: sammy-SC Differential Revision: D51182861 fbshipit-source-id: 25489d7f0642c4ff78340438c2b266e95a5fb207 --- .../components/view/YogaStylableProps.cpp | 144 +++++++++--------- .../components/view/YogaStylableProps.h | 4 +- .../components/view/propsConversions.h | 3 +- 3 files changed, 80 insertions(+), 71 deletions(-) diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/YogaStylableProps.cpp b/packages/react-native/ReactCommon/react/renderer/components/view/YogaStylableProps.cpp index 67c2a530b3bb08..7c888d1e3d9959 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/YogaStylableProps.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/view/YogaStylableProps.cpp @@ -35,6 +35,16 @@ YogaStylableProps::YogaStylableProps( } }; +/*static*/ const yoga::Style& YogaStylableProps::defaultStyle() { + static const auto defaultStyle = []() { + yoga::Style style; + style.setPositionType(yoga::PositionType::Static); + return style; + }(); + + return defaultStyle; +} + template static inline T const getFieldValue( const PropsParserContext& context, @@ -49,10 +59,10 @@ static inline T const getFieldValue( return defaultValue; } -#define REBUILD_FIELD_SWITCH_CASE2(field, setter, fieldName) \ - case CONSTEXPR_RAW_PROPS_KEY_HASH(fieldName): { \ - yogaStyle.setter(getFieldValue(context, value, ygDefaults.field())); \ - return; \ +#define REBUILD_FIELD_SWITCH_CASE2(field, setter, fieldName) \ + case CONSTEXPR_RAW_PROPS_KEY_HASH(fieldName): { \ + yogaStyle.setter(getFieldValue(context, value, defaultStyle().field())); \ + return; \ } #define REBUILD_FIELD_SWITCH_CASE_YSP(field, setter) \ @@ -61,7 +71,7 @@ static inline T const getFieldValue( #define REBUILD_YG_FIELD_SWITCH_CASE_INDEXED(field, setter, index, fieldName) \ case CONSTEXPR_RAW_PROPS_KEY_HASH(fieldName): { \ yogaStyle.setter( \ - index, getFieldValue(context, value, ygDefaults.field(index))); \ + index, getFieldValue(context, value, defaultStyle().field(index))); \ return; \ } @@ -125,7 +135,6 @@ void YogaStylableProps::setProp( RawPropsPropNameHash hash, const char* propName, const RawValue& value) { - static const auto ygDefaults = yoga::Style{}; static const auto defaults = YogaStylableProps{}; Props::setProp(context, hash, propName, value); @@ -181,228 +190,225 @@ void YogaStylableProps::setProp( #if RN_DEBUG_STRING_CONVERTIBLE SharedDebugStringConvertibleList YogaStylableProps::getDebugProps() const { - const auto defaultYogaStyle = yoga::Style{}; return { debugStringConvertibleItem( - "direction", yogaStyle.direction(), defaultYogaStyle.direction()), + "direction", yogaStyle.direction(), defaultStyle().direction()), debugStringConvertibleItem( "flexDirection", yogaStyle.flexDirection(), - defaultYogaStyle.flexDirection()), + defaultStyle().flexDirection()), debugStringConvertibleItem( "justifyContent", yogaStyle.justifyContent(), - defaultYogaStyle.justifyContent()), + defaultStyle().justifyContent()), debugStringConvertibleItem( "alignContent", yogaStyle.alignContent(), - defaultYogaStyle.alignContent()), + defaultStyle().alignContent()), debugStringConvertibleItem( - "alignItems", yogaStyle.alignItems(), defaultYogaStyle.alignItems()), + "alignItems", yogaStyle.alignItems(), defaultStyle().alignItems()), debugStringConvertibleItem( - "alignSelf", yogaStyle.alignSelf(), defaultYogaStyle.alignSelf()), + "alignSelf", yogaStyle.alignSelf(), defaultStyle().alignSelf()), debugStringConvertibleItem( "positionType", yogaStyle.positionType(), - defaultYogaStyle.positionType()), + defaultStyle().positionType()), debugStringConvertibleItem( - "flexWrap", yogaStyle.flexWrap(), defaultYogaStyle.flexWrap()), + "flexWrap", yogaStyle.flexWrap(), defaultStyle().flexWrap()), debugStringConvertibleItem( - "overflow", yogaStyle.overflow(), defaultYogaStyle.overflow()), + "overflow", yogaStyle.overflow(), defaultStyle().overflow()), debugStringConvertibleItem( - "display", yogaStyle.display(), defaultYogaStyle.display()), + "display", yogaStyle.display(), defaultStyle().display()), debugStringConvertibleItem( - "flex", yogaStyle.flex(), defaultYogaStyle.flex()), + "flex", yogaStyle.flex(), defaultStyle().flex()), debugStringConvertibleItem( - "flexGrow", yogaStyle.flexGrow(), defaultYogaStyle.flexGrow()), + "flexGrow", yogaStyle.flexGrow(), defaultStyle().flexGrow()), debugStringConvertibleItem( "rowGap", yogaStyle.gap(yoga::Gutter::Row), - defaultYogaStyle.gap(yoga::Gutter::Row)), + defaultStyle().gap(yoga::Gutter::Row)), debugStringConvertibleItem( "columnGap", yogaStyle.gap(yoga::Gutter::Column), - defaultYogaStyle.gap(yoga::Gutter::Column)), + defaultStyle().gap(yoga::Gutter::Column)), debugStringConvertibleItem( "gap", yogaStyle.gap(yoga::Gutter::All), - defaultYogaStyle.gap(yoga::Gutter::All)), + defaultStyle().gap(yoga::Gutter::All)), debugStringConvertibleItem( - "flexShrink", yogaStyle.flexShrink(), defaultYogaStyle.flexShrink()), + "flexShrink", yogaStyle.flexShrink(), defaultStyle().flexShrink()), debugStringConvertibleItem( - "flexBasis", yogaStyle.flexBasis(), defaultYogaStyle.flexBasis()), + "flexBasis", yogaStyle.flexBasis(), defaultStyle().flexBasis()), debugStringConvertibleItem( "marginLeft", yogaStyle.margin(yoga::Edge::Left), - defaultYogaStyle.margin(yoga::Edge::Left)), + defaultStyle().margin(yoga::Edge::Left)), debugStringConvertibleItem( "marginTop", yogaStyle.margin(yoga::Edge::Top), - defaultYogaStyle.margin(yoga::Edge::Top)), + defaultStyle().margin(yoga::Edge::Top)), debugStringConvertibleItem( "marginRight", yogaStyle.margin(yoga::Edge::Right), - defaultYogaStyle.margin(yoga::Edge::Right)), + defaultStyle().margin(yoga::Edge::Right)), debugStringConvertibleItem( "marginBottom", yogaStyle.margin(yoga::Edge::Bottom), - defaultYogaStyle.margin(yoga::Edge::Bottom)), + defaultStyle().margin(yoga::Edge::Bottom)), debugStringConvertibleItem( "marginStart", yogaStyle.margin(yoga::Edge::Start), - defaultYogaStyle.margin(yoga::Edge::Start)), + defaultStyle().margin(yoga::Edge::Start)), debugStringConvertibleItem( "marginEnd", yogaStyle.margin(yoga::Edge::End), - defaultYogaStyle.margin(yoga::Edge::End)), + defaultStyle().margin(yoga::Edge::End)), debugStringConvertibleItem( "marginHorizontal", yogaStyle.margin(yoga::Edge::Horizontal), - defaultYogaStyle.margin(yoga::Edge::Horizontal)), + defaultStyle().margin(yoga::Edge::Horizontal)), debugStringConvertibleItem( "marginVertical", yogaStyle.margin(yoga::Edge::Vertical), - defaultYogaStyle.margin(yoga::Edge::Vertical)), + defaultStyle().margin(yoga::Edge::Vertical)), debugStringConvertibleItem( "margin", yogaStyle.margin(yoga::Edge::All), - defaultYogaStyle.margin(yoga::Edge::All)), + defaultStyle().margin(yoga::Edge::All)), debugStringConvertibleItem( "left", yogaStyle.position(yoga::Edge::Left), - defaultYogaStyle.position(yoga::Edge::Left)), + defaultStyle().position(yoga::Edge::Left)), debugStringConvertibleItem( "top", yogaStyle.position(yoga::Edge::Top), - defaultYogaStyle.position(yoga::Edge::Top)), + defaultStyle().position(yoga::Edge::Top)), debugStringConvertibleItem( "right", yogaStyle.position(yoga::Edge::Right), - defaultYogaStyle.position(yoga::Edge::Right)), + defaultStyle().position(yoga::Edge::Right)), debugStringConvertibleItem( "bottom", yogaStyle.position(yoga::Edge::Bottom), - defaultYogaStyle.position(yoga::Edge::Bottom)), + defaultStyle().position(yoga::Edge::Bottom)), debugStringConvertibleItem( "start", yogaStyle.position(yoga::Edge::Start), - defaultYogaStyle.position(yoga::Edge::Start)), + defaultStyle().position(yoga::Edge::Start)), debugStringConvertibleItem( "end", yogaStyle.position(yoga::Edge::End), - defaultYogaStyle.position(yoga::Edge::End)), + defaultStyle().position(yoga::Edge::End)), debugStringConvertibleItem( "inseInline", yogaStyle.position(yoga::Edge::Horizontal), - defaultYogaStyle.position(yoga::Edge::Horizontal)), + defaultStyle().position(yoga::Edge::Horizontal)), debugStringConvertibleItem( "insetBlock", yogaStyle.position(yoga::Edge::Vertical), - defaultYogaStyle.position(yoga::Edge::Vertical)), + defaultStyle().position(yoga::Edge::Vertical)), debugStringConvertibleItem( "inset", yogaStyle.position(yoga::Edge::All), - defaultYogaStyle.position(yoga::Edge::All)), + defaultStyle().position(yoga::Edge::All)), debugStringConvertibleItem( "paddingLeft", yogaStyle.padding(yoga::Edge::Left), - defaultYogaStyle.padding(yoga::Edge::Left)), + defaultStyle().padding(yoga::Edge::Left)), debugStringConvertibleItem( "paddingTop", yogaStyle.padding(yoga::Edge::Top), - defaultYogaStyle.padding(yoga::Edge::Top)), + defaultStyle().padding(yoga::Edge::Top)), debugStringConvertibleItem( "paddingRight", yogaStyle.padding(yoga::Edge::Right), - defaultYogaStyle.padding(yoga::Edge::Right)), + defaultStyle().padding(yoga::Edge::Right)), debugStringConvertibleItem( "paddingBottom", yogaStyle.padding(yoga::Edge::Bottom), - defaultYogaStyle.padding(yoga::Edge::Bottom)), + defaultStyle().padding(yoga::Edge::Bottom)), debugStringConvertibleItem( "paddingStart", yogaStyle.padding(yoga::Edge::Start), - defaultYogaStyle.padding(yoga::Edge::Start)), + defaultStyle().padding(yoga::Edge::Start)), debugStringConvertibleItem( "paddingEnd", yogaStyle.padding(yoga::Edge::End), - defaultYogaStyle.padding(yoga::Edge::End)), + defaultStyle().padding(yoga::Edge::End)), debugStringConvertibleItem( "paddingHorizontal", yogaStyle.padding(yoga::Edge::Horizontal), - defaultYogaStyle.padding(yoga::Edge::Horizontal)), + defaultStyle().padding(yoga::Edge::Horizontal)), debugStringConvertibleItem( "paddingVertical", yogaStyle.padding(yoga::Edge::Vertical), - defaultYogaStyle.padding(yoga::Edge::Vertical)), + defaultStyle().padding(yoga::Edge::Vertical)), debugStringConvertibleItem( "padding", yogaStyle.padding(yoga::Edge::All), - defaultYogaStyle.padding(yoga::Edge::All)), + defaultStyle().padding(yoga::Edge::All)), debugStringConvertibleItem( "borderLeftWidth", yogaStyle.border(yoga::Edge::Left), - defaultYogaStyle.border(yoga::Edge::Left)), + defaultStyle().border(yoga::Edge::Left)), debugStringConvertibleItem( "borderTopWidth", yogaStyle.border(yoga::Edge::Top), - defaultYogaStyle.border(yoga::Edge::Top)), + defaultStyle().border(yoga::Edge::Top)), debugStringConvertibleItem( "borderRightWidth", yogaStyle.border(yoga::Edge::Right), - defaultYogaStyle.border(yoga::Edge::Right)), + defaultStyle().border(yoga::Edge::Right)), debugStringConvertibleItem( "borderBottomWidth", yogaStyle.border(yoga::Edge::Bottom), - defaultYogaStyle.border(yoga::Edge::Bottom)), + defaultStyle().border(yoga::Edge::Bottom)), debugStringConvertibleItem( "borderStartWidth", yogaStyle.border(yoga::Edge::Start), - defaultYogaStyle.border(yoga::Edge::Start)), + defaultStyle().border(yoga::Edge::Start)), debugStringConvertibleItem( "borderEndWidth", yogaStyle.border(yoga::Edge::End), - defaultYogaStyle.border(yoga::Edge::End)), + defaultStyle().border(yoga::Edge::End)), debugStringConvertibleItem( "borderHorizontalWidth", yogaStyle.border(yoga::Edge::Horizontal), - defaultYogaStyle.border(yoga::Edge::Horizontal)), + defaultStyle().border(yoga::Edge::Horizontal)), debugStringConvertibleItem( "borderVerticalWidth", yogaStyle.border(yoga::Edge::Vertical), - defaultYogaStyle.border(yoga::Edge::Vertical)), + defaultStyle().border(yoga::Edge::Vertical)), debugStringConvertibleItem( "bordeWidth", yogaStyle.border(yoga::Edge::All), - defaultYogaStyle.border(yoga::Edge::All)), + defaultStyle().border(yoga::Edge::All)), debugStringConvertibleItem( "width", yogaStyle.dimension(yoga::Dimension::Width), - defaultYogaStyle.dimension(yoga::Dimension::Width)), + defaultStyle().dimension(yoga::Dimension::Width)), debugStringConvertibleItem( "height", yogaStyle.dimension(yoga::Dimension::Height), - defaultYogaStyle.dimension(yoga::Dimension::Height)), + defaultStyle().dimension(yoga::Dimension::Height)), debugStringConvertibleItem( "minWidth", yogaStyle.minDimension(yoga::Dimension::Width), - defaultYogaStyle.minDimension(yoga::Dimension::Width)), + defaultStyle().minDimension(yoga::Dimension::Width)), debugStringConvertibleItem( "minHeight", yogaStyle.minDimension(yoga::Dimension::Height), - defaultYogaStyle.minDimension(yoga::Dimension::Height)), + defaultStyle().minDimension(yoga::Dimension::Height)), debugStringConvertibleItem( "maxWidth", yogaStyle.maxDimension(yoga::Dimension::Width), - defaultYogaStyle.maxDimension(yoga::Dimension::Width)), + defaultStyle().maxDimension(yoga::Dimension::Width)), debugStringConvertibleItem( "maxHeight", yogaStyle.maxDimension(yoga::Dimension::Height), - defaultYogaStyle.maxDimension(yoga::Dimension::Height)), + defaultStyle().maxDimension(yoga::Dimension::Height)), debugStringConvertibleItem( - "aspectRatio", - yogaStyle.aspectRatio(), - defaultYogaStyle.aspectRatio()), + "aspectRatio", yogaStyle.aspectRatio(), defaultStyle().aspectRatio()), }; } #endif diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/YogaStylableProps.h b/packages/react-native/ReactCommon/react/renderer/components/view/YogaStylableProps.h index 165209183725ff..fea1c2609e2272 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/YogaStylableProps.h +++ b/packages/react-native/ReactCommon/react/renderer/components/view/YogaStylableProps.h @@ -23,6 +23,8 @@ class YogaStylableProps : public Props { const YogaStylableProps& sourceProps, const RawProps& rawProps); + static const yoga::Style& defaultStyle(); + void setProp( const PropsParserContext& context, RawPropsPropNameHash hash, @@ -35,7 +37,7 @@ class YogaStylableProps : public Props { #endif #pragma mark - Props - yoga::Style yogaStyle{}; + yoga::Style yogaStyle{defaultStyle()}; // Duplicates of existing properties with different names, taking // precedence. E.g. "marginBlock" instead of "marginVertical" diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/propsConversions.h b/packages/react-native/ReactCommon/react/renderer/components/view/propsConversions.h index e68f15740c2fa2..df078b1dd23cc6 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/propsConversions.h +++ b/packages/react-native/ReactCommon/react/renderer/components/view/propsConversions.h @@ -7,6 +7,7 @@ #pragma once +#include #include #include #include @@ -22,7 +23,7 @@ static inline yoga::Style convertRawProp( const PropsParserContext& context, const RawProps& rawProps, const yoga::Style& sourceValue) { - yoga::Style yogaStyle{}; + auto yogaStyle = YogaStylableProps::defaultStyle(); yogaStyle.setDirection(convertRawProp( context, From 88a55baeaaa68619d815f53a51e32edb937e291f Mon Sep 17 00:00:00 2001 From: Nick Gerleman Date: Tue, 28 Nov 2023 18:51:34 -0800 Subject: [PATCH 124/162] Change default back to `position: "relative"` (#41480) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41480 X-link: https://github.com/facebook/yoga/pull/1469 The previous version of static didn't do anything inside of Yoga. Now that we're making it do something, this changes the default back to relative so that users with no errata set don't see their deafult styles changing. Reviewed By: joevilches Differential Revision: D51182955 fbshipit-source-id: c0ea357694e1367fb6786f1907dfff784b19a4bc --- packages/react-native/ReactCommon/yoga/yoga/style/Style.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/react-native/ReactCommon/yoga/yoga/style/Style.h b/packages/react-native/ReactCommon/yoga/yoga/style/Style.h index 30f631f279b602..530cbb75c309ed 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/style/Style.h +++ b/packages/react-native/ReactCommon/yoga/yoga/style/Style.h @@ -270,7 +270,8 @@ class YG_EXPORT Style { Align alignContent_ : bitCount() = Align::FlexStart; Align alignItems_ : bitCount() = Align::Stretch; Align alignSelf_ : bitCount() = Align::Auto; - PositionType positionType_ : bitCount() = PositionType::Static; + PositionType positionType_ + : bitCount() = PositionType::Relative; Wrap flexWrap_ : bitCount() = Wrap::NoWrap; Overflow overflow_ : bitCount() = Overflow::Visible; Display display_ : bitCount() = Display::Flex; From 44109dc2c01a76baf37b836a378e6a28d96ea66c Mon Sep 17 00:00:00 2001 From: Xin Chen Date: Tue, 28 Nov 2023 19:27:51 -0800 Subject: [PATCH 125/162] Fix warm start logging for ReactMarker (#41693) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41693 This diff fixes app warm start time. Before this change, we cache the first time when app start timing is logged, and ignore future loggings. Some apps are warm started and the startup time should be updated. Reviewed By: dmitry-voronkevich Differential Revision: D50481710 fbshipit-source-id: 03e00b75ee7ac578209ae3478adabe567e92a950 --- .../ReactCommon/cxxreact/ReactMarker.cpp | 17 +++++++++++++++-- .../ReactCommon/cxxreact/ReactMarker.h | 1 + 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/packages/react-native/ReactCommon/cxxreact/ReactMarker.cpp b/packages/react-native/ReactCommon/cxxreact/ReactMarker.cpp index e9059dac7137c8..86c3a03c9df5bf 100644 --- a/packages/react-native/ReactCommon/cxxreact/ReactMarker.cpp +++ b/packages/react-native/ReactCommon/cxxreact/ReactMarker.cpp @@ -53,9 +53,13 @@ void StartupLogger::logStartupEvent( double markerTime) { switch (markerId) { case ReactMarkerId::APP_STARTUP_START: - if (std::isnan(appStartupStartTime)) { - appStartupStartTime = markerTime; + if (!std::isnan(appStartupStartTime)) { + // We had a startup start time, which indicates a warm start (user + // closed the app and start again). In this case we need to invalidate + // all other startup timings. + reset(); } + appStartupStartTime = markerTime; return; case ReactMarkerId::APP_STARTUP_STOP: @@ -93,6 +97,15 @@ void StartupLogger::logStartupEvent( } } +void StartupLogger::reset() { + appStartupStartTime = std::nan(""); + appStartupEndTime = std::nan(""); + initReactRuntimeStartTime = std::nan(""); + initReactRuntimeEndTime = std::nan(""); + runJSBundleStartTime = std::nan(""); + runJSBundleEndTime = std::nan(""); +} + double StartupLogger::getAppStartupStartTime() { return appStartupStartTime; } diff --git a/packages/react-native/ReactCommon/cxxreact/ReactMarker.h b/packages/react-native/ReactCommon/cxxreact/ReactMarker.h index 8d3a532e2c4e0d..e50746780d4867 100644 --- a/packages/react-native/ReactCommon/cxxreact/ReactMarker.h +++ b/packages/react-native/ReactCommon/cxxreact/ReactMarker.h @@ -74,6 +74,7 @@ class RN_EXPORT StartupLogger { static StartupLogger& getInstance(); void logStartupEvent(const ReactMarkerId markerName, double markerTime); + void reset(); double getAppStartupStartTime(); double getInitReactRuntimeStartTime(); double getInitReactRuntimeEndTime(); From 56b57e2db4d75b32706ebbaa5bee02d48beab945 Mon Sep 17 00:00:00 2001 From: Nick Gerleman Date: Tue, 28 Nov 2023 20:06:12 -0800 Subject: [PATCH 126/162] Ship "disableScrollEventThrottleRequirement" (#41676) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41676 This has been used in a significant amount of production for about 2 months, with no consistently statistically significant metric impact. Let's ship it. Note that we would not want to keep this change in a holdout if we remove the warning, since new usages could be added that relied on the behavior not in the holdout. It didn't seem worth the churn to make the same change to Paper, which leaves a question on how to handle the JS-side warning. Instead of jimmying in impl detection, I thought it might be more sane to remove the warning, though that also has a potential hit to Paper DevX. Changelog: [iOS][Changed] - `scrollEventThrottle` no longer needs to be set for continuous scroll events when using the new architecture. Reviewed By: javache Differential Revision: D51608970 fbshipit-source-id: 193019de208f3088519e6f6333dbec4e6b45a1eb --- .../Libraries/Components/ScrollView/ScrollView.js | 15 --------------- .../ScrollView/RCTScrollViewComponentView.mm | 6 +----- .../React/Fabric/RCTSurfacePresenter.mm | 4 ---- .../ReactCommon/react/utils/CoreFeatures.cpp | 1 - .../ReactCommon/react/utils/CoreFeatures.h | 4 ---- 5 files changed, 1 insertion(+), 29 deletions(-) diff --git a/packages/react-native/Libraries/Components/ScrollView/ScrollView.js b/packages/react-native/Libraries/Components/ScrollView/ScrollView.js index 2e2264afedbd2b..30ec946848cc63 100644 --- a/packages/react-native/Libraries/Components/ScrollView/ScrollView.js +++ b/packages/react-native/Libraries/Components/ScrollView/ScrollView.js @@ -1148,21 +1148,6 @@ class ScrollView extends React.Component { } _handleScroll = (e: ScrollEvent) => { - if (__DEV__) { - if ( - this.props.onScroll && - this.props.scrollEventThrottle == null && - Platform.OS === 'ios' - ) { - console.log( - 'You specified `onScroll` on a but not ' + - '`scrollEventThrottle`. You will only receive one event. ' + - 'Using `16` you get all the events but be aware that it may ' + - "cause frame drops, use a bigger number if you don't need as " + - 'much precision.', - ); - } - } this._observedScrollSinceBecomingResponder = true; this.props.onScroll && this.props.onScroll(e); }; diff --git a/packages/react-native/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm b/packages/react-native/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm index 8272db8c85082c..41e5ebc3cf1a35 100644 --- a/packages/react-native/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm +++ b/packages/react-native/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm @@ -133,11 +133,7 @@ - (instancetype)initWithFrame:(CGRect)frame [self.scrollViewDelegateSplitter addDelegate:self]; - if (CoreFeatures::disableScrollEventThrottleRequirement) { - _scrollEventThrottle = 0; - } else { - _scrollEventThrottle = INFINITY; - } + _scrollEventThrottle = 0; } return self; diff --git a/packages/react-native/React/Fabric/RCTSurfacePresenter.mm b/packages/react-native/React/Fabric/RCTSurfacePresenter.mm index df069c0865553b..9c2c7aba96a6d5 100644 --- a/packages/react-native/React/Fabric/RCTSurfacePresenter.mm +++ b/packages/react-native/React/Fabric/RCTSurfacePresenter.mm @@ -276,10 +276,6 @@ - (RCTScheduler *)_createScheduler CoreFeatures::enableMountHooks = true; } - if (reactNativeConfig && reactNativeConfig->getBool("react_fabric:disable_scroll_event_throttle_requirement")) { - CoreFeatures::disableScrollEventThrottleRequirement = true; - } - if (reactNativeConfig && reactNativeConfig->getBool("react_fabric:enable_default_async_batched_priority")) { CoreFeatures::enableDefaultAsyncBatchedPriority = true; } diff --git a/packages/react-native/ReactCommon/react/utils/CoreFeatures.cpp b/packages/react-native/ReactCommon/react/utils/CoreFeatures.cpp index 6bdcc5d651e05e..c967febaac7a21 100644 --- a/packages/react-native/ReactCommon/react/utils/CoreFeatures.cpp +++ b/packages/react-native/ReactCommon/react/utils/CoreFeatures.cpp @@ -17,7 +17,6 @@ bool CoreFeatures::enableGranularScrollViewStateUpdatesIOS = false; bool CoreFeatures::enableMountHooks = false; bool CoreFeatures::doNotSwapLeftAndRightOnAndroidInLTR = false; bool CoreFeatures::enableCleanParagraphYogaNode = false; -bool CoreFeatures::disableScrollEventThrottleRequirement = false; bool CoreFeatures::enableGranularShadowTreeStateReconciliation = false; bool CoreFeatures::enableDefaultAsyncBatchedPriority = false; bool CoreFeatures::enableClonelessStateProgression = false; diff --git a/packages/react-native/ReactCommon/react/utils/CoreFeatures.h b/packages/react-native/ReactCommon/react/utils/CoreFeatures.h index 2a377625791e66..3ad24c5e02e4d8 100644 --- a/packages/react-native/ReactCommon/react/utils/CoreFeatures.h +++ b/packages/react-native/ReactCommon/react/utils/CoreFeatures.h @@ -47,10 +47,6 @@ class CoreFeatures { // Clean yoga node when does not change. static bool enableCleanParagraphYogaNode; - // Fire `onScroll` events continuously on iOS without a `scrollEventThrottle` - // props, and provide continuous `onScroll` upates like other platforms. - static bool disableScrollEventThrottleRequirement; - // When enabled, the renderer would only fail commits when they propagate // state and the last commit that updated state changed before committing. static bool enableGranularShadowTreeStateReconciliation; From 667d85bddada31a51bcf6e05b3b042efb93ddb78 Mon Sep 17 00:00:00 2001 From: Arushi Kesarwani Date: Tue, 28 Nov 2023 23:34:57 -0800 Subject: [PATCH 127/162] Refactor DefaultReactNativeHost to use the new way of Fabric initialization (#41496) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41496 Refactoring `DefaultReactNativeHost` to use the new way of Fabric initialization through `FabricUIManagerProviderImpl` Reviewed By: christophpurrer Differential Revision: D51224854 fbshipit-source-id: 2af8021404365fa2adc9388f44bcc7c6301137dc --- .../react/defaults/DefaultReactNativeHost.kt | 36 ++++++------------- 1 file changed, 11 insertions(+), 25 deletions(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultReactNativeHost.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultReactNativeHost.kt index 60c1e791912b42..e5683059a68bdb 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultReactNativeHost.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultReactNativeHost.kt @@ -14,12 +14,8 @@ import com.facebook.react.ReactHost import com.facebook.react.ReactInstanceManager import com.facebook.react.ReactNativeHost import com.facebook.react.ReactPackageTurboModuleManagerDelegate -import com.facebook.react.bridge.JSIModulePackage -import com.facebook.react.bridge.JSIModuleProvider -import com.facebook.react.bridge.JSIModuleSpec -import com.facebook.react.bridge.JSIModuleType import com.facebook.react.bridge.ReactApplicationContext -import com.facebook.react.bridge.UIManager +import com.facebook.react.bridge.UIManagerProvider import com.facebook.react.fabric.ComponentFactory import com.facebook.react.fabric.FabricUIManagerProviderImpl import com.facebook.react.fabric.ReactNativeConfig @@ -46,30 +42,20 @@ protected constructor( null } - override fun getJSIModulePackage(): JSIModulePackage? = + override fun getUIManagerProvider(): UIManagerProvider? = if (isNewArchEnabled) { - JSIModulePackage { reactApplicationContext: ReactApplicationContext, _ -> - listOf( - object : JSIModuleSpec { - override fun getJSIModuleType(): JSIModuleType = JSIModuleType.UIManager + UIManagerProvider { reactApplicationContext: ReactApplicationContext -> + val componentFactory = ComponentFactory() - override fun getJSIModuleProvider(): JSIModuleProvider { - val componentFactory = ComponentFactory() + DefaultComponentsRegistry.register(componentFactory) - DefaultComponentsRegistry.register(componentFactory) + val reactInstanceManager: ReactInstanceManager = getReactInstanceManager() - val reactInstanceManager: ReactInstanceManager = getReactInstanceManager() - - val viewManagers = - reactInstanceManager.getOrCreateViewManagers(reactApplicationContext) - val viewManagerRegistry = ViewManagerRegistry(viewManagers) - return FabricUIManagerProviderImpl( - reactApplicationContext, - componentFactory, - ReactNativeConfig.DEFAULT_CONFIG, - viewManagerRegistry) - } - }) + val viewManagers = reactInstanceManager.getOrCreateViewManagers(reactApplicationContext) + val viewManagerRegistry = ViewManagerRegistry(viewManagers) + FabricUIManagerProviderImpl( + componentFactory, ReactNativeConfig.DEFAULT_CONFIG, viewManagerRegistry) + .createUIManager(reactApplicationContext) } } else { null From 4a35f2512e21deacf3e26e811875a9b8e4388a58 Mon Sep 17 00:00:00 2001 From: Riccardo Cipolleschi Date: Wed, 29 Nov 2023 04:17:48 -0800 Subject: [PATCH 128/162] Make sure that third party libraries include Fabric code (#41669) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41669 In some previous changes ([a607692](https://github.com/facebook/react-native/commit/a6076924bf43dff6cf4d38d51df279edba3882d0) and [6b53205](https://github.com/facebook/react-native/commit/6b5320540adfe16803ef41353f23115d08819309)) we make sure to always include all the pods (including Fabric) and we unify codegen to run in the same way on both architectures. While doing so, we enabled codegen to run on libraries tat already migrated to Fabric. These makes those libraries to fail when building as they were not including the Fabric code when the New Architecture is disabled. This change will make sue that the code is always included, thus the library should always build, and it also make sure that we can control the New/Old Architecture at build time. ## Changelog [iOS][Changed] - Make sure that libraries always include Fabric code also in the old architecture Reviewed By: dmytrorykun Differential Revision: D51617542 fbshipit-source-id: 883d1e258c341feb0405ad389bb8af34d64b59b8 --- .../Libraries/AppDelegate/RCTAppDelegate.mm | 54 +++++++++---------- .../AppDelegate/React-RCTAppDelegate.podspec | 4 +- .../react-native/scripts/react_native_pods.rb | 5 +- 3 files changed, 32 insertions(+), 31 deletions(-) diff --git a/packages/react-native/Libraries/AppDelegate/RCTAppDelegate.mm b/packages/react-native/Libraries/AppDelegate/RCTAppDelegate.mm index 924664e6cd6a40..13aee73117cb1f 100644 --- a/packages/react-native/Libraries/AppDelegate/RCTAppDelegate.mm +++ b/packages/react-native/Libraries/AppDelegate/RCTAppDelegate.mm @@ -81,7 +81,6 @@ - (instancetype)init - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { BOOL enableTM = self.turboModuleEnabled; - ; BOOL enableBridgeless = self.bridgelessEnabled; BOOL fabricEnabled = self.fabricEnabled; @@ -112,14 +111,14 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:( if (!self.bridge) { self.bridge = [self createBridgeWithDelegate:self launchOptions:launchOptions]; } -#if RCT_NEW_ARCH_ENABLED - self.bridgeAdapter = [[RCTSurfacePresenterBridgeAdapter alloc] initWithBridge:self.bridge - contextContainer:_contextContainer]; - self.bridge.surfacePresenter = self.bridgeAdapter.surfacePresenter; + if ([self newArchEnabled]) { + self.bridgeAdapter = [[RCTSurfacePresenterBridgeAdapter alloc] initWithBridge:self.bridge + contextContainer:_contextContainer]; + self.bridge.surfacePresenter = self.bridgeAdapter.surfacePresenter; - [self unstable_registerLegacyComponents]; - [RCTComponentViewFactory currentComponentViewFactory].thirdPartyFabricComponentsProvider = self; -#endif + [self unstable_registerLegacyComponents]; + [RCTComponentViewFactory currentComponentViewFactory].thirdPartyFabricComponentsProvider = self; + } rootView = [self createRootViewWithBridge:self.bridge moduleName:self.moduleName initProps:initProps]; } @@ -190,38 +189,39 @@ - (void)windowScene:(UIWindowScene *)windowScene - (std::unique_ptr)jsExecutorFactoryForBridge:(RCTBridge *)bridge { _runtimeScheduler = std::make_shared(RCTRuntimeExecutorFromBridge(bridge)); -#if RCT_NEW_ARCH_ENABLED - std::shared_ptr callInvoker = - std::make_shared(_runtimeScheduler); - RCTTurboModuleManager *turboModuleManager = [[RCTTurboModuleManager alloc] initWithBridge:bridge - delegate:self - jsInvoker:callInvoker]; - _contextContainer->erase("RuntimeScheduler"); - _contextContainer->insert("RuntimeScheduler", _runtimeScheduler); - return RCTAppSetupDefaultJsExecutorFactory(bridge, turboModuleManager, _runtimeScheduler); -#else - return RCTAppSetupJsExecutorFactoryForOldArch(bridge, _runtimeScheduler); -#endif + if ([self newArchEnabled]) { + std::shared_ptr callInvoker = + std::make_shared(_runtimeScheduler); + RCTTurboModuleManager *turboModuleManager = [[RCTTurboModuleManager alloc] initWithBridge:bridge + delegate:self + jsInvoker:callInvoker]; + _contextContainer->erase("RuntimeScheduler"); + _contextContainer->insert("RuntimeScheduler", _runtimeScheduler); + return RCTAppSetupDefaultJsExecutorFactory(bridge, turboModuleManager, _runtimeScheduler); + } else { + return RCTAppSetupJsExecutorFactoryForOldArch(bridge, _runtimeScheduler); + } } #pragma mark - New Arch Enabled settings -- (BOOL)turboModuleEnabled +- (BOOL)newArchEnabled { -#if RCT_NEW_ARCH_ENABLED +#if USE_NEW_ARCH return YES; #else return NO; #endif } +- (BOOL)turboModuleEnabled +{ + return [self newArchEnabled]; +} + - (BOOL)fabricEnabled { -#if RCT_NEW_ARCH_ENABLED - return YES; -#else - return NO; -#endif + return [self newArchEnabled]; } - (BOOL)bridgelessEnabled diff --git a/packages/react-native/Libraries/AppDelegate/React-RCTAppDelegate.podspec b/packages/react-native/Libraries/AppDelegate/React-RCTAppDelegate.podspec index ad7fee87cfe967..fe4a4bbd021528 100644 --- a/packages/react-native/Libraries/AppDelegate/React-RCTAppDelegate.podspec +++ b/packages/react-native/Libraries/AppDelegate/React-RCTAppDelegate.podspec @@ -19,10 +19,10 @@ end folly_flags = ' -DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -DFOLLY_CFG_NO_COROUTINES=1 -DFOLLY_HAVE_CLOCK_GETTIME=1' folly_compiler_flags = folly_flags + ' ' + '-Wno-comma -Wno-shorten-64-to-32' -is_new_arch_enabled = ENV["RCT_NEW_ARCH_ENABLED"] == "1" +is_new_arch_enabled = ENV["USE_NEW_ARCH"] == "1" use_hermes = ENV['USE_HERMES'] == nil || ENV['USE_HERMES'] == '1' -new_arch_enabled_flag = (is_new_arch_enabled ? " -DRCT_NEW_ARCH_ENABLED" : "") +new_arch_enabled_flag = (is_new_arch_enabled ? " -DUSE_NEW_ARCH" : "") is_fabric_enabled = is_new_arch_enabled || ENV["RCT_FABRIC_ENABLED"] hermes_flag = (use_hermes ? " -DUSE_HERMES" : "") other_cflags = "$(inherited)" + folly_flags + new_arch_enabled_flag + hermes_flag diff --git a/packages/react-native/scripts/react_native_pods.rb b/packages/react-native/scripts/react_native_pods.rb index f0a0ba120cfcba..a2a6e1d23e7305 100644 --- a/packages/react-native/scripts/react_native_pods.rb +++ b/packages/react-native/scripts/react_native_pods.rb @@ -93,9 +93,10 @@ def use_react_native! ( # Better to rely and enable this environment flag if the new architecture is turned on using flags. relative_path_from_current = Pod::Config.instance.installation_root.relative_path_from(Pathname.pwd) react_native_version = NewArchitectureHelper.extract_react_native_version(File.join(relative_path_from_current, path)) - ENV['RCT_NEW_ARCH_ENABLED'] = NewArchitectureHelper.compute_new_arch_enabled(new_arch_enabled, react_native_version) - + ENV['USE_NEW_ARCH'] = NewArchitectureHelper.compute_new_arch_enabled(new_arch_enabled, react_native_version) fabric_enabled = fabric_enabled || NewArchitectureHelper.new_arch_enabled + + ENV['RCT_NEW_ARCH_ENABLED'] = "1" ENV['RCT_FABRIC_ENABLED'] = fabric_enabled ? "1" : "0" ENV['USE_HERMES'] = hermes_enabled ? "1" : "0" From dc9556837588b2fb11a29ef25ad75cced07c6ac5 Mon Sep 17 00:00:00 2001 From: Riccardo Cipolleschi Date: Wed, 29 Nov 2023 04:17:48 -0800 Subject: [PATCH 129/162] Remove duplicated jobs in CircleCI (#41698) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41698 With the previous changes on the Pod configuration, the build setup for the New and Old architecture are the same. The only observable difference happens at runtime. This change: 1. Removes the build job that are split by architecture (which is now duplicated work) 2. Add two more test jobs to run runtime tests (unit and integration test) to make sure that the two architectures continue working. ## Changelog: [Internal] - [CI] Remove duplicated build jobs, add tests jobs Reviewed By: cortinico Differential Revision: D51659275 fbshipit-source-id: 769c9ee004e7f4f1a7444f39c02b7083e007b780 --- .../configurations/test_workflows/testAll.yml | 18 +++++++----------- .../configurations/test_workflows/testIOS.yml | 18 +++++++----------- 2 files changed, 14 insertions(+), 22 deletions(-) diff --git a/.circleci/configurations/test_workflows/testAll.yml b/.circleci/configurations/test_workflows/testAll.yml index fe497a7922a973..7afd7d2171f57d 100644 --- a/.circleci/configurations/test_workflows/testAll.yml +++ b/.circleci/configurations/test_workflows/testAll.yml @@ -62,18 +62,17 @@ flavor: "Debug" executor: reactnativeios-lts - test_ios_template: + architecture: "OldArch" requires: - build_npm_package matrix: parameters: - architecture: ["NewArch", "OldArch"] flavor: ["Debug", "Release"] jsengine: ["Hermes", "JSC"] use_frameworks: ["StaticLibraries", "DynamicFrameworks"] exclude: # This config is tested with Ruby 3.2.0. Let's not double test it. - - architecture: "NewArch" - flavor: "Debug" + - flavor: "Debug" jsengine: "Hermes" use_frameworks: "StaticLibraries" - test_ios_rntester: @@ -84,33 +83,30 @@ architecture: "NewArch" executor: reactnativeios-lts - test_ios_rntester: + architecture: "NewArch" requires: - build_hermes_macos matrix: parameters: - architecture: ["NewArch", "OldArch"] jsengine: ["Hermes", "JSC"] use_frameworks: ["StaticLibraries", "DynamicFrameworks"] exclude: # Tested by test_ios-Hermes - - architecture: "OldArch" - jsengine: "Hermes" + - jsengine: "Hermes" use_frameworks: "StaticLibraries" # Tested by test_ios-JSC - - architecture: "OldArch" - jsengine: "JSC" + - jsengine: "JSC" use_frameworks: "StaticLibraries" # Tested with Ruby 3.2.0, do not test this twice. - - architecture: "NewArch" - jsengine: "Hermes" + - jsengine: "Hermes" use_frameworks: "StaticLibraries" - test_ios_rntester: run_unit_tests: true - architecture: "OldArch" use_frameworks: "StaticLibraries" ruby_version: "2.6.10" requires: - build_hermes_macos matrix: parameters: + architecture: ["OldArch", "NewArch"] jsengine: ["Hermes", "JSC"] diff --git a/.circleci/configurations/test_workflows/testIOS.yml b/.circleci/configurations/test_workflows/testIOS.yml index bff9e73786d795..eb6cf50a527aa3 100644 --- a/.circleci/configurations/test_workflows/testIOS.yml +++ b/.circleci/configurations/test_workflows/testIOS.yml @@ -53,18 +53,17 @@ flavor: "Debug" executor: reactnativeios-lts - test_ios_template: + architecture: "OldArch" requires: - build_npm_package matrix: parameters: - architecture: ["NewArch", "OldArch"] flavor: ["Debug", "Release"] jsengine: ["Hermes", "JSC"] use_frameworks: ["StaticLibraries", "DynamicFrameworks"] exclude: # Tested with Ruby 3.2.0, let's not double test this - - architecture: "NewArch" - flavor: "Debug" + - flavor: "Debug" jsengine: "Hermes" use_frameworks: "StaticLibraries" - test_ios_rntester: @@ -75,33 +74,30 @@ architecture: "NewArch" executor: reactnativeios-lts - test_ios_rntester: + architecture: "NewArch" requires: - build_hermes_macos matrix: parameters: - architecture: ["NewArch", "OldArch"] jsengine: ["Hermes", "JSC"] use_frameworks: ["StaticLibraries", "DynamicFrameworks"] exclude: # Tested by test_ios-Hermes - - architecture: "OldArch" - jsengine: "Hermes" + - jsengine: "Hermes" use_frameworks: "StaticLibraries" # Tested by test_ios-JSC - - architecture: "OldArch" - jsengine: "JSC" + - jsengine: "JSC" use_frameworks: "StaticLibraries" # Tested with Ruby 3.2.0, let's not double test this - - architecture: "NewArch" - jsengine: "Hermes" + - jsengine: "Hermes" use_frameworks: "StaticLibraries" - test_ios_rntester: run_unit_tests: true - architecture: "OldArch" use_frameworks: "StaticLibraries" ruby_version: "2.6.10" requires: - build_hermes_macos matrix: parameters: + architecture: ["NewArch", "OldArch"] jsengine: ["Hermes", "JSC"] From bb075d785deb3732689bf6aacdc5247187e81391 Mon Sep 17 00:00:00 2001 From: Will Schurman Date: Wed, 29 Nov 2023 04:53:31 -0800 Subject: [PATCH 130/162] Fix android root view group removal during instance re-creation (#41678) Summary: This is my proposed solution to https://github.com/facebook/react-native/issues/41677. Fixes https://github.com/facebook/react-native/issues/41677. ## Changelog: [ANDROID] [FIXED] - Fix android root view group removal during instance re-creation Pull Request resolved: https://github.com/facebook/react-native/pull/41678 Test Plan: Both with fabric enabled and disabled (new architecture): 1. Clone repro repo: https://github.com/wschurman/rn-reload-repro 2. Build and run on android (I use android studio) 3. Click reload button, see timestamp doesn't change (indicating that the view is not removed) 4. Apply this PR as a patch. 5. Re-build and run. 6. Click reload button, see view is correctly disposed of and the new view is set. Reviewed By: cortinico Differential Revision: D51658524 Pulled By: javache fbshipit-source-id: d9a026cde677ad1ec113230bc31bd9297bca8bfc --- .../main/java/com/facebook/react/ReactInstanceManager.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java index be0ca24b62f2ad..a1801d5627c933 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java @@ -1296,14 +1296,12 @@ private void detachRootViewFromInstance(ReactRoot reactRoot, ReactContext reactC uiManager.stopSurface(surfaceId); } else { FLog.w(ReactConstants.TAG, "Failed to stop surface, UIManager has already gone away"); - reactRoot.getRootViewGroup().removeAllViews(); } } else { ReactSoftExceptionLogger.logSoftException( TAG, new RuntimeException( "detachRootViewFromInstance called with ReactRootView with invalid id")); - reactRoot.getRootViewGroup().removeAllViews(); } } else { reactContext @@ -1312,8 +1310,7 @@ private void detachRootViewFromInstance(ReactRoot reactRoot, ReactContext reactC .unmountApplicationComponentAtRootTag(reactRoot.getRootViewTag()); } - // The view is no longer attached, so mark it as such by resetting its ID. - reactRoot.getRootViewGroup().setId(View.NO_ID); + clearReactRoot(reactRoot); } @ThreadConfined(UI) From 4ccd6e124278abf3c63765195715ee3ae39a769e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oskar=20Kwas=CC=81niewski?= Date: Wed, 29 Nov 2023 05:53:54 -0800 Subject: [PATCH 131/162] feat: allow OOT platforms to use custom resolver.resolveRequest (#41697) Summary: Currently, when we have an additional platform in `react-native.config.js`, users cannot use custom `resolver.resolveRequest` functions as they are overwritten by `reactNativePlatformResolver`. Goal of this PR is to allow OOT platforms to use additional custom resolvers besides remapping react native imports. ## Changelog: [GENERAL] [FIXED] - Allow Out Of Tree platforms to pass custom resolvers Pull Request resolved: https://github.com/facebook/react-native/pull/41697 Test Plan: 1. Add additional platform in `react-native.config.js` 2. Pass custom resolver to `metro.config.js`: ```js resolveRequest: (context, moduleName, platform) => { console.log('resolveRequest', moduleName, platform); return context.resolveRequest(context, moduleName, platform); } ``` 3. Check if user's `resolveRequest` function is called. Reviewed By: huntie Differential Revision: D51659721 Pulled By: robhogan fbshipit-source-id: 952589b59a6fa34e9406d36c900be53a7c1a79c3 --- .../src/utils/loadMetroConfig.js | 23 +++++++++++-------- .../src/utils/metroPlatformResolver.js | 12 +++++++--- 2 files changed, 22 insertions(+), 13 deletions(-) diff --git a/packages/community-cli-plugin/src/utils/loadMetroConfig.js b/packages/community-cli-plugin/src/utils/loadMetroConfig.js index c8430c9b9e4686..44d0d275cb0e64 100644 --- a/packages/community-cli-plugin/src/utils/loadMetroConfig.js +++ b/packages/community-cli-plugin/src/utils/loadMetroConfig.js @@ -29,7 +29,10 @@ export type ConfigLoadingContext = $ReadOnly<{ /** * Get the config options to override based on RN CLI inputs. */ -function getOverrideConfig(ctx: ConfigLoadingContext): InputConfigT { +function getOverrideConfig( + ctx: ConfigLoadingContext, + config: ConfigT, +): InputConfigT { const outOfTreePlatforms = Object.keys(ctx.platforms).filter( platform => ctx.platforms[platform].npmPackageName, ); @@ -46,6 +49,7 @@ function getOverrideConfig(ctx: ConfigLoadingContext): InputConfigT { }, {}, ), + config.resolver?.resolveRequest, ); } @@ -79,8 +83,6 @@ export default async function loadMetroConfig( ctx: ConfigLoadingContext, options: YargArguments = {}, ): Promise { - const overrideConfig = getOverrideConfig(ctx); - const cwd = ctx.root; const projectConfig = await resolveConfig(options.config, cwd); @@ -105,11 +107,12 @@ This warning will be removed in future (https://github.com/facebook/metro/issues } } - return mergeConfig( - await loadConfig({ - cwd, - ...options, - }), - overrideConfig, - ); + const config = await loadConfig({ + cwd, + ...options, + }); + + const overrideConfig = getOverrideConfig(ctx, config); + + return mergeConfig(config, overrideConfig); } diff --git a/packages/community-cli-plugin/src/utils/metroPlatformResolver.js b/packages/community-cli-plugin/src/utils/metroPlatformResolver.js index e03264f0c6442e..134ce7d2dad3d4 100644 --- a/packages/community-cli-plugin/src/utils/metroPlatformResolver.js +++ b/packages/community-cli-plugin/src/utils/metroPlatformResolver.js @@ -25,9 +25,12 @@ import type {CustomResolver} from 'metro-resolver'; * macos: 'react-native-macos' * } */ -export function reactNativePlatformResolver(platformImplementations: { - [platform: string]: string, -}): CustomResolver { +export function reactNativePlatformResolver( + platformImplementations: { + [platform: string]: string, + }, + customResolver: ?CustomResolver, +): CustomResolver { return (context, moduleName, platform) => { let modifiedModuleName = moduleName; if (platform != null && platformImplementations[platform]) { @@ -39,6 +42,9 @@ export function reactNativePlatformResolver(platformImplementations: { }/${modifiedModuleName.slice('react-native/'.length)}`; } } + if (customResolver) { + return customResolver(context, modifiedModuleName, platform); + } return context.resolveRequest(context, modifiedModuleName, platform); }; } From 3654089b0ee925c443db853197a3d402a9b787c7 Mon Sep 17 00:00:00 2001 From: Marcel Canhisares Date: Wed, 29 Nov 2023 07:25:26 -0800 Subject: [PATCH 132/162] (refactor): kotlinify layout property applicator test (#41649) Summary: This PR converts to kotlin the java code for LayoutPropertyApplicatorTest, as requested in: https://github.com/facebook/react-native/issues/38825 ## Changelog: [INTERNAL][CHANGED]: Convert LayoutPropertyApplicatorTest to Kotlin Pull Request resolved: https://github.com/facebook/react-native/pull/41649 Test Plan: `./gradlew :packages:react-native:ReactAndroid:test ` Reviewed By: rshest Differential Revision: D51614921 Pulled By: cortinico fbshipit-source-id: 06ee403a496f34afc9abeabc0c406391e316538a --- .../LayoutPropertyApplicatorTest.java | 462 ----------------- .../uimanager/LayoutPropertyApplicatorTest.kt | 464 ++++++++++++++++++ 2 files changed, 464 insertions(+), 462 deletions(-) delete mode 100644 packages/react-native/ReactAndroid/src/test/java/com/facebook/react/uimanager/LayoutPropertyApplicatorTest.java create mode 100644 packages/react-native/ReactAndroid/src/test/java/com/facebook/react/uimanager/LayoutPropertyApplicatorTest.kt diff --git a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/uimanager/LayoutPropertyApplicatorTest.java b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/uimanager/LayoutPropertyApplicatorTest.java deleted file mode 100644 index 2de130c9a5cc8e..00000000000000 --- a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/uimanager/LayoutPropertyApplicatorTest.java +++ /dev/null @@ -1,462 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and 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.uimanager; - -import static junit.framework.Assert.assertEquals; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyFloat; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.mockStatic; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.reset; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.verify; - -import android.util.DisplayMetrics; -import com.facebook.react.bridge.JavaOnlyMap; -import com.facebook.yoga.YogaAlign; -import com.facebook.yoga.YogaConstants; -import com.facebook.yoga.YogaFlexDirection; -import com.facebook.yoga.YogaJustify; -import com.facebook.yoga.YogaPositionType; -import org.junit.After; -import org.junit.Before; -import org.junit.Ignore; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.MockedStatic; -import org.mockito.stubbing.Answer; -import org.robolectric.RobolectricTestRunner; - -@RunWith(RobolectricTestRunner.class) -@Ignore // TODO T14964130 -public class LayoutPropertyApplicatorTest { - - @Before - public void setup() { - DisplayMetricsHolder.setWindowDisplayMetrics(new DisplayMetrics()); - DisplayMetricsHolder.setScreenDisplayMetrics(new DisplayMetrics()); - } - - @After - public void teardown() { - DisplayMetricsHolder.setWindowDisplayMetrics(null); - DisplayMetricsHolder.setScreenDisplayMetrics(null); - } - - public ReactStylesDiffMap buildStyles(Object... keysAndValues) { - return new ReactStylesDiffMap(JavaOnlyMap.of(keysAndValues)); - } - - @Test - public void testDimensions() { - LayoutShadowNode reactShadowNode = spy(new LayoutShadowNode()); - ReactStylesDiffMap map = - spy(buildStyles("width", 10.0, "height", 10.0, "left", 10.0, "top", 10.0)); - - reactShadowNode.updateProperties(map); - verify(reactShadowNode).setStyleWidth(anyFloat()); - verify(map).getFloat(eq("width"), anyFloat()); - verify(reactShadowNode).setStyleHeight(anyFloat()); - verify(map).getFloat(eq("height"), anyFloat()); - verify(reactShadowNode).setPosition(eq(Spacing.START), anyFloat()); - verify(map).getFloat(eq("left"), anyFloat()); - verify(reactShadowNode).setPosition(eq(Spacing.TOP), anyFloat()); - verify(map).getFloat(eq("top"), anyFloat()); - - reactShadowNode = spy(new LayoutShadowNode()); - map = spy(buildStyles()); - - reactShadowNode.updateProperties(map); - verify(reactShadowNode, never()).setStyleWidth(anyFloat()); - verify(map, never()).getFloat(eq("width"), anyFloat()); - verify(reactShadowNode, never()).setStyleHeight(anyFloat()); - verify(map, never()).getFloat(eq("height"), anyFloat()); - verify(reactShadowNode, never()).setPosition(eq(Spacing.START), anyFloat()); - verify(map, never()).getFloat(eq("left"), anyFloat()); - verify(reactShadowNode, never()).setPosition(eq(Spacing.TOP), anyFloat()); - verify(map, never()).getFloat(eq("top"), anyFloat()); - } - - @Test - public void testFlex() { - LayoutShadowNode reactShadowNode = spy(new LayoutShadowNode()); - ReactStylesDiffMap map = spy(buildStyles("flex", 10.0)); - - reactShadowNode.updateProperties(map); - verify(reactShadowNode).setFlex(anyFloat()); - verify(map).getFloat("flex", 0.f); - - reactShadowNode = spy(new LayoutShadowNode()); - map = spy(buildStyles()); - - reactShadowNode.updateProperties(map); - verify(reactShadowNode, never()).setFlex(anyFloat()); - verify(map, never()).getFloat("flex", 0.f); - } - - @Test - public void testPosition() { - LayoutShadowNode reactShadowNode = spy(new LayoutShadowNode()); - ReactStylesDiffMap map = spy(buildStyles("position", "absolute", "bottom", 10.0, "right", 5.0)); - - reactShadowNode.updateProperties(map); - verify(reactShadowNode).setPosition(eq(Spacing.BOTTOM), anyFloat()); - verify(reactShadowNode).setPosition(eq(Spacing.END), anyFloat()); - verify(reactShadowNode).setPositionType(any(YogaPositionType.class)); - verify(map).getFloat("bottom", Float.NaN); - verify(map).getFloat("right", Float.NaN); - - reactShadowNode = spy(new LayoutShadowNode()); - map = spy(buildStyles()); - - reactShadowNode.updateProperties(map); - verify(reactShadowNode, never()).setPosition(eq(Spacing.BOTTOM), anyFloat()); - verify(reactShadowNode, never()).setPosition(eq(Spacing.END), anyFloat()); - verify(reactShadowNode, never()).setPositionType(any(YogaPositionType.class)); - verify(map, never()).getFloat("bottom", Float.NaN); - verify(map, never()).getFloat("right", Float.NaN); - } - - @Test - public void testMargin() { - // margin - LayoutShadowNode reactShadowNode = spy(new LayoutShadowNode()); - ReactStylesDiffMap map = spy(buildStyles("margin", 10.0)); - - reactShadowNode.updateProperties(map); - verify(reactShadowNode).setMargin(eq(Spacing.ALL), anyFloat()); - verify(map).getFloat("margin", YogaConstants.UNDEFINED); - - // marginVertical - reactShadowNode = spy(new LayoutShadowNode()); - map = spy(buildStyles("marginVertical", 10.0)); - - reactShadowNode.updateProperties(map); - verify(reactShadowNode).setMargin(eq(Spacing.VERTICAL), anyFloat()); - verify(map).getFloat("marginVertical", YogaConstants.UNDEFINED); - - // marginHorizontal - reactShadowNode = spy(new LayoutShadowNode()); - map = spy(buildStyles("marginHorizontal", 10.0)); - - reactShadowNode.updateProperties(map); - verify(reactShadowNode).setMargin(eq(Spacing.HORIZONTAL), anyFloat()); - verify(map).getFloat("marginHorizontal", YogaConstants.UNDEFINED); - - // marginTop - reactShadowNode = spy(new LayoutShadowNode()); - map = spy(buildStyles("marginTop", 10.0)); - - reactShadowNode.updateProperties(map); - verify(reactShadowNode).setMargin(eq(Spacing.TOP), anyFloat()); - verify(map).getFloat("marginTop", YogaConstants.UNDEFINED); - - // marginBottom - reactShadowNode = spy(new LayoutShadowNode()); - map = spy(buildStyles("marginBottom", 10.0)); - - reactShadowNode.updateProperties(map); - verify(reactShadowNode).setMargin(eq(Spacing.BOTTOM), anyFloat()); - verify(map).getFloat("marginBottom", YogaConstants.UNDEFINED); - - // marginLeft - reactShadowNode = spy(new LayoutShadowNode()); - map = spy(buildStyles("marginLeft", 10.0)); - - reactShadowNode.updateProperties(map); - verify(reactShadowNode).setMargin(eq(Spacing.START), anyFloat()); - verify(map).getFloat("marginLeft", YogaConstants.UNDEFINED); - - // marginRight - reactShadowNode = spy(new LayoutShadowNode()); - map = spy(buildStyles("marginRight", 10.0)); - - reactShadowNode.updateProperties(map); - verify(reactShadowNode).setMargin(eq(Spacing.END), anyFloat()); - verify(map).getFloat("marginRight", YogaConstants.UNDEFINED); - - // no margin - reactShadowNode = spy(new LayoutShadowNode()); - map = spy(buildStyles()); - - reactShadowNode.updateProperties(map); - verify(reactShadowNode, never()).setMargin(anyInt(), anyFloat()); - verify(map, never()).getFloat("margin", YogaConstants.UNDEFINED); - } - - @Test - public void testPadding() { - // padding - LayoutShadowNode reactShadowNode = spy(new LayoutShadowNode()); - ReactStylesDiffMap map = spy(buildStyles("padding", 10.0)); - - reactShadowNode.updateProperties(map); - verify(reactShadowNode).setPadding(eq(Spacing.ALL), anyFloat()); - verify(map).getFloat("padding", YogaConstants.UNDEFINED); - - // paddingVertical - reactShadowNode = spy(new LayoutShadowNode()); - map = spy(buildStyles("paddingVertical", 10.0)); - - reactShadowNode.updateProperties(map); - verify(reactShadowNode).setPadding(eq(Spacing.VERTICAL), anyFloat()); - verify(map).getFloat("paddingVertical", YogaConstants.UNDEFINED); - - // paddingHorizontal - reactShadowNode = spy(new LayoutShadowNode()); - map = spy(buildStyles("paddingHorizontal", 10.0)); - - reactShadowNode.updateProperties(map); - verify(reactShadowNode).setPadding(eq(Spacing.HORIZONTAL), anyFloat()); - verify(map).getFloat("paddingHorizontal", YogaConstants.UNDEFINED); - - // paddingTop - reactShadowNode = spy(new LayoutShadowNode()); - map = spy(buildStyles("paddingTop", 10.0)); - - reactShadowNode.updateProperties(map); - verify(reactShadowNode).setPadding(eq(Spacing.TOP), anyFloat()); - verify(map).getFloat("paddingTop", YogaConstants.UNDEFINED); - - // paddingBottom - reactShadowNode = spy(new LayoutShadowNode()); - map = spy(buildStyles("paddingBottom", 10.0)); - - reactShadowNode.updateProperties(map); - verify(reactShadowNode).setPadding(eq(Spacing.BOTTOM), anyFloat()); - verify(map).getFloat("paddingBottom", YogaConstants.UNDEFINED); - - // paddingLeft - reactShadowNode = spy(new LayoutShadowNode()); - map = spy(buildStyles("paddingLeft", 10.0)); - - reactShadowNode.updateProperties(map); - verify(reactShadowNode).setPadding(eq(Spacing.START), anyFloat()); - verify(map).getFloat("paddingLeft", YogaConstants.UNDEFINED); - - // paddingRight - reactShadowNode = spy(new LayoutShadowNode()); - map = spy(buildStyles("paddingRight", 10.0)); - - reactShadowNode.updateProperties(map); - verify(reactShadowNode).setPadding(eq(Spacing.END), anyFloat()); - verify(map).getFloat("paddingRight", YogaConstants.UNDEFINED); - - // no padding - reactShadowNode = spy(new LayoutShadowNode()); - map = spy(buildStyles()); - - reactShadowNode.updateProperties(map); - verify(reactShadowNode, never()).setPadding(anyInt(), anyFloat()); - verify(map, never()).getFloat("padding", YogaConstants.UNDEFINED); - } - - @Test - public void testEnumerations() { - LayoutShadowNode reactShadowNode = spy(new LayoutShadowNode()); - ReactStylesDiffMap map = - buildStyles( - "flexDirection", - "column", - "alignSelf", - "stretch", - "alignItems", - "center", - "justifyContent", - "space_between", - "position", - "relative"); - - reactShadowNode.updateProperties(map); - verify(reactShadowNode).setFlexDirection(YogaFlexDirection.COLUMN); - verify(reactShadowNode).setAlignSelf(YogaAlign.STRETCH); - verify(reactShadowNode).setAlignItems(YogaAlign.CENTER); - verify(reactShadowNode).setJustifyContent(YogaJustify.SPACE_BETWEEN); - verify(reactShadowNode).setPositionType(YogaPositionType.RELATIVE); - - reactShadowNode = spy(new LayoutShadowNode()); - map = buildStyles(); - reactShadowNode.updateProperties(map); - - verify(reactShadowNode, never()).setFlexDirection(any(YogaFlexDirection.class)); - verify(reactShadowNode, never()).setAlignSelf(any(YogaAlign.class)); - verify(reactShadowNode, never()).setAlignItems(any(YogaAlign.class)); - verify(reactShadowNode, never()).setJustifyContent(any(YogaJustify.class)); - verify(reactShadowNode, never()).setPositionType(any(YogaPositionType.class)); - } - - @Test - public void testPropertiesResetToDefault() { - DisplayMetrics displayMetrics = new DisplayMetrics(); - displayMetrics.density = 1.0f; - DisplayMetricsHolder.setWindowDisplayMetrics(displayMetrics); - - LayoutShadowNode reactShadowNode = spy(new LayoutShadowNode()); - ReactStylesDiffMap map = - buildStyles( - "width", - 10.0, - "height", - 10.0, - "left", - 10.0, - "top", - 10.0, - "flex", - 1.0, - "padding", - 10.0, - "marginLeft", - 10.0, - "borderTopWidth", - 10.0, - "flexDirection", - "row", - "alignSelf", - "stretch", - "alignItems", - "center", - "justifyContent", - "space_between", - "position", - "absolute"); - - reactShadowNode.updateProperties(map); - verify(reactShadowNode).setStyleWidth(10.f); - verify(reactShadowNode).setStyleHeight(10.f); - verify(reactShadowNode).setPosition(Spacing.START, 10.f); - verify(reactShadowNode).setPosition(Spacing.TOP, 10.f); - verify(reactShadowNode).setFlex(1.0f); - verify(reactShadowNode).setPadding(Spacing.ALL, 10.f); - verify(reactShadowNode).setMargin(Spacing.START, 10.f); - verify(reactShadowNode).setBorder(Spacing.TOP, 10.f); - verify(reactShadowNode).setFlexDirection(YogaFlexDirection.ROW); - verify(reactShadowNode).setAlignSelf(YogaAlign.STRETCH); - verify(reactShadowNode).setAlignItems(YogaAlign.CENTER); - verify(reactShadowNode).setJustifyContent(YogaJustify.SPACE_BETWEEN); - verify(reactShadowNode).setPositionType(YogaPositionType.ABSOLUTE); - - map = - buildStyles( - "width", - null, - "height", - null, - "left", - null, - "top", - null, - "flex", - null, - "padding", - null, - "marginLeft", - null, - "borderTopWidth", - null, - "flexDirection", - null, - "alignSelf", - null, - "alignItems", - null, - "justifyContent", - null, - "position", - null); - - reset(reactShadowNode); - reactShadowNode.updateProperties(map); - verify(reactShadowNode).setStyleWidth(YogaConstants.UNDEFINED); - verify(reactShadowNode).setStyleHeight(YogaConstants.UNDEFINED); - verify(reactShadowNode).setPosition(Spacing.START, YogaConstants.UNDEFINED); - verify(reactShadowNode).setPosition(Spacing.TOP, YogaConstants.UNDEFINED); - verify(reactShadowNode).setFlex(0.f); - verify(reactShadowNode).setPadding(Spacing.ALL, YogaConstants.UNDEFINED); - verify(reactShadowNode).setMargin(Spacing.START, YogaConstants.UNDEFINED); - verify(reactShadowNode).setBorder(Spacing.TOP, YogaConstants.UNDEFINED); - verify(reactShadowNode).setFlexDirection(YogaFlexDirection.COLUMN); - verify(reactShadowNode).setAlignSelf(YogaAlign.AUTO); - verify(reactShadowNode).setAlignItems(YogaAlign.STRETCH); - verify(reactShadowNode).setJustifyContent(YogaJustify.FLEX_START); - verify(reactShadowNode).setPositionType(YogaPositionType.RELATIVE); - } - - @Test - public void testSettingDefaultStyleValues() { - MockedStatic pixelUtil = mockStatic(PixelUtil.class); - pixelUtil - .when(() -> PixelUtil.toPixelFromDIP(anyFloat())) - .thenAnswer( - (Answer) - invocation -> { - Object[] args = invocation.getArguments(); - return (Float) args[0]; - }); - - LayoutShadowNode[] nodes = new LayoutShadowNode[7]; - for (int idx = 0; idx < nodes.length; idx++) { - nodes[idx] = new LayoutShadowNode(); - nodes[idx].setDefaultPadding(Spacing.START, 15); - nodes[idx].setDefaultPadding(Spacing.TOP, 25); - nodes[idx].setDefaultPadding(Spacing.END, 35); - nodes[idx].setDefaultPadding(Spacing.BOTTOM, 45); - } - - ReactStylesDiffMap[] mapNodes = new ReactStylesDiffMap[7]; - mapNodes[0] = buildStyles("paddingLeft", 10.0, "paddingHorizontal", 5.0); - mapNodes[1] = buildStyles("padding", 10.0, "paddingTop", 5.0); - mapNodes[2] = buildStyles("paddingLeft", 10.0, "paddingVertical", 5.0); - mapNodes[3] = buildStyles("paddingBottom", 10.0, "paddingHorizontal", 5.0); - mapNodes[4] = buildStyles("padding", null, "paddingTop", 5.0); - mapNodes[5] = - buildStyles("paddingRight", 10.0, "paddingHorizontal", null, "paddingVertical", 7.0); - mapNodes[6] = buildStyles("margin", 5.0); - - for (int idx = 0; idx < nodes.length; idx++) { - nodes[idx].updateProperties(mapNodes[idx]); - } - - assertEquals(10.0, nodes[0].getPadding(Spacing.START), .0001); - assertEquals(25.0, nodes[0].getPadding(Spacing.TOP), .0001); - assertEquals(5.0, nodes[0].getPadding(Spacing.END), .0001); - assertEquals(45.0, nodes[0].getPadding(Spacing.BOTTOM), .0001); - - assertEquals(10.0, nodes[1].getPadding(Spacing.START), .0001); - assertEquals(5.0, nodes[1].getPadding(Spacing.TOP), .0001); - assertEquals(10.0, nodes[1].getPadding(Spacing.END), .0001); - assertEquals(10.0, nodes[1].getPadding(Spacing.BOTTOM), .0001); - - assertEquals(10.0, nodes[2].getPadding(Spacing.START), .0001); - assertEquals(5.0, nodes[2].getPadding(Spacing.TOP), .0001); - assertEquals(35.0, nodes[2].getPadding(Spacing.END), .0001); - assertEquals(5.0, nodes[2].getPadding(Spacing.BOTTOM), .0001); - - assertEquals(5.0, nodes[3].getPadding(Spacing.START), .0001); - assertEquals(25.0, nodes[3].getPadding(Spacing.TOP), .0001); - assertEquals(5.0, nodes[3].getPadding(Spacing.END), .0001); - assertEquals(10.0, nodes[3].getPadding(Spacing.BOTTOM), .0001); - - assertEquals(15.0, nodes[4].getPadding(Spacing.START), .0001); - assertEquals(5.0, nodes[4].getPadding(Spacing.TOP), .0001); - assertEquals(35.0, nodes[4].getPadding(Spacing.END), .0001); - assertEquals(45.0, nodes[4].getPadding(Spacing.BOTTOM), .0001); - - assertEquals(15.0, nodes[5].getPadding(Spacing.START), .0001); - assertEquals(7.0, nodes[5].getPadding(Spacing.TOP), .0001); - assertEquals(10.0, nodes[5].getPadding(Spacing.END), .0001); - assertEquals(7.0, nodes[5].getPadding(Spacing.BOTTOM), .0001); - - assertEquals(15.0, nodes[6].getPadding(Spacing.START), .0001); - assertEquals(25.0, nodes[6].getPadding(Spacing.TOP), .0001); - assertEquals(35.0, nodes[6].getPadding(Spacing.END), .0001); - assertEquals(45.0, nodes[6].getPadding(Spacing.BOTTOM), .0001); - } -} diff --git a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/uimanager/LayoutPropertyApplicatorTest.kt b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/uimanager/LayoutPropertyApplicatorTest.kt new file mode 100644 index 00000000000000..5f83847bd54109 --- /dev/null +++ b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/uimanager/LayoutPropertyApplicatorTest.kt @@ -0,0 +1,464 @@ +/* + * Copyright (c) Meta Platforms, Inc. and 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.uimanager + +import android.util.DisplayMetrics +import com.facebook.react.bridge.JavaOnlyMap +import com.facebook.react.uimanager.Spacing.* +import com.facebook.yoga.YogaAlign +import com.facebook.yoga.YogaConstants +import com.facebook.yoga.YogaFlexDirection +import com.facebook.yoga.YogaJustify +import com.facebook.yoga.YogaPositionType +import org.junit.After +import org.junit.Assert.* +import org.junit.Before +import org.junit.Ignore +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.ArgumentMatchers.any +import org.mockito.ArgumentMatchers.anyFloat +import org.mockito.ArgumentMatchers.anyInt +import org.mockito.ArgumentMatchers.eq +import org.mockito.Mockito.mockStatic +import org.mockito.Mockito.never +import org.mockito.Mockito.reset +import org.mockito.Mockito.spy +import org.mockito.Mockito.verify +import org.robolectric.RobolectricTestRunner + +@RunWith(RobolectricTestRunner::class) +@Ignore +class LayoutPropertyApplicatorTest { + @Before + fun setup() { + DisplayMetricsHolder.setWindowDisplayMetrics(DisplayMetrics()) + DisplayMetricsHolder.setScreenDisplayMetrics(DisplayMetrics()) + } + + @After + fun teardown() { + DisplayMetricsHolder.setWindowDisplayMetrics(null) + DisplayMetricsHolder.setScreenDisplayMetrics(null) + } + + private fun buildStyles(vararg keysAndValues: Any?): ReactStylesDiffMap { + return ReactStylesDiffMap(JavaOnlyMap.of(*keysAndValues)) + } + + @Test + fun testDimensions() { + var reactShadowNode = spy(LayoutShadowNode()) + var map = spy(buildStyles("width", 10.0f, "height", 10.0f, "left", 10.0f, "top", 10.0f)) + + reactShadowNode.updateProperties(map) + verify(reactShadowNode).setStyleWidth(anyFloat()) + verify(map).getFloat(eq("width"), anyFloat()) + verify(reactShadowNode).setStyleHeight(anyFloat()) + verify(map).getFloat(eq("height"), anyFloat()) + verify(reactShadowNode).setPosition(eq(START), anyFloat()) + verify(map).getFloat(eq("left"), anyFloat()) + verify(reactShadowNode).setPosition(eq(TOP), anyFloat()) + verify(map).getFloat(eq("top"), anyFloat()) + + reactShadowNode = spy(LayoutShadowNode()) + map = spy(buildStyles()) + + reactShadowNode.updateProperties(map) + verify(reactShadowNode, never()).setStyleWidth(anyFloat()) + verify(map, never()).getFloat(eq("width"), anyFloat()) + verify(reactShadowNode, never()).setStyleHeight(anyFloat()) + verify(map, never()).getFloat(eq("height"), anyFloat()) + verify(reactShadowNode, never()).setPosition(eq(START), anyFloat()) + verify(map, never()).getFloat(eq("left"), anyFloat()) + verify(reactShadowNode, never()).setPosition(eq(TOP), anyFloat()) + verify(map, never()).getFloat(eq("top"), anyFloat()) + } + + @Test + fun testFlex() { + var reactShadowNode = spy(LayoutShadowNode()) + var map = spy(buildStyles("flex", 10.0f)) + + reactShadowNode.updateProperties(map) + verify(reactShadowNode).flex = anyFloat() + verify(map).getFloat("flex", 0.0f) + + reactShadowNode = spy(LayoutShadowNode()) + map = spy(buildStyles()) + + reactShadowNode.updateProperties(map) + verify(reactShadowNode, never()).flex = anyFloat() + verify(map, never()).getFloat("flex", 0.0f) + } + + @Test + fun testPosition() { + var reactShadowNode = spy(LayoutShadowNode()) + var map = spy(buildStyles("position", "absolute", "bottom", 10.0f, "right", 5.0f)) + + reactShadowNode.updateProperties(map) + verify(reactShadowNode).setPosition(eq(BOTTOM), anyFloat()) + verify(reactShadowNode).setPosition(eq(END), anyFloat()) + verify(reactShadowNode).setPositionType(any(YogaPositionType::class.java)) + verify(map).getFloat("bottom", Float.NaN) + verify(map).getFloat("right", Float.NaN) + + reactShadowNode = spy(LayoutShadowNode()) + map = spy(buildStyles()) + + reactShadowNode.updateProperties(map) + verify(reactShadowNode, never()).setPosition(eq(BOTTOM), anyFloat()) + verify(reactShadowNode, never()).setPosition(eq(END), anyFloat()) + verify(reactShadowNode, never()).setPositionType(any(YogaPositionType::class.java)) + verify(map, never()).getFloat("bottom", Float.NaN) + verify(map, never()).getFloat("right", Float.NaN) + } + + @Test + fun testMargin() { + // margin + var reactShadowNode = spy(LayoutShadowNode()) + var map = spy(buildStyles("margin", 10.0f)) + + reactShadowNode.updateProperties(map) + verify(reactShadowNode).setMargin(eq(ALL), anyFloat()) + verify(map).getFloat("margin", YogaConstants.UNDEFINED) + + // marginVertical + reactShadowNode = spy(LayoutShadowNode()) + map = spy(buildStyles("marginVertical", 10.0f)) + + reactShadowNode.updateProperties(map) + verify(reactShadowNode).setMargin(eq(VERTICAL), anyFloat()) + verify(map).getFloat("marginVertical", YogaConstants.UNDEFINED) + + // marginHorizontal + reactShadowNode = spy(LayoutShadowNode()) + map = spy(buildStyles("marginHorizontal", 10.0f)) + + reactShadowNode.updateProperties(map) + verify(reactShadowNode).setMargin(eq(HORIZONTAL), anyFloat()) + verify(map).getFloat("marginHorizontal", YogaConstants.UNDEFINED) + + // marginTop + reactShadowNode = spy(LayoutShadowNode()) + map = spy(buildStyles("marginTop", 10.0f)) + + reactShadowNode.updateProperties(map) + verify(reactShadowNode).setMargin(eq(TOP), anyFloat()) + verify(map).getFloat("marginTop", YogaConstants.UNDEFINED) + + // marginBottom + reactShadowNode = spy(LayoutShadowNode()) + map = spy(buildStyles("marginBottom", 10.0f)) + + reactShadowNode.updateProperties(map) + verify(reactShadowNode).setMargin(eq(BOTTOM), anyFloat()) + verify(map).getFloat("marginBottom", YogaConstants.UNDEFINED) + + // marginLeft + reactShadowNode = spy(LayoutShadowNode()) + map = spy(buildStyles("marginLeft", 10.0f)) + + reactShadowNode.updateProperties(map) + verify(reactShadowNode).setMargin(eq(START), anyFloat()) + verify(map).getFloat("marginLeft", YogaConstants.UNDEFINED) + + // marginRight + reactShadowNode = spy(LayoutShadowNode()) + map = spy(buildStyles("marginRight", 10.0f)) + + reactShadowNode.updateProperties(map) + verify(reactShadowNode).setMargin(eq(END), anyFloat()) + verify(map).getFloat("marginRight", YogaConstants.UNDEFINED) + + // no margin + reactShadowNode = spy(LayoutShadowNode()) + map = spy(buildStyles()) + + reactShadowNode.updateProperties(map) + verify(reactShadowNode, never()).setMargin(anyInt(), anyFloat()) + verify(map, never()).getFloat("margin", YogaConstants.UNDEFINED) + } + + @Test + fun testPadding() { + // padding + var reactShadowNode = spy(LayoutShadowNode()) + var map = spy(buildStyles("padding", 10.0f)) + + reactShadowNode.updateProperties(map) + verify(reactShadowNode).setPadding(eq(ALL), anyFloat()) + verify(map).getFloat("padding", YogaConstants.UNDEFINED) + + // paddingVertical + reactShadowNode = spy(LayoutShadowNode()) + map = spy(buildStyles("paddingVertical", 10.0f)) + + reactShadowNode.updateProperties(map) + verify(reactShadowNode).setPadding(eq(VERTICAL), anyFloat()) + verify(map).getFloat("paddingVertical", YogaConstants.UNDEFINED) + + // paddingHorizontal + reactShadowNode = spy(LayoutShadowNode()) + map = spy(buildStyles("paddingHorizontal", 10.0f)) + + reactShadowNode.updateProperties(map) + verify(reactShadowNode).setPadding(eq(HORIZONTAL), anyFloat()) + verify(map).getFloat("paddingHorizontal", YogaConstants.UNDEFINED) + + // paddingTop + reactShadowNode = spy(LayoutShadowNode()) + map = spy(buildStyles("paddingTop", 10.0f)) + + reactShadowNode.updateProperties(map) + verify(reactShadowNode).setPadding(eq(TOP), anyFloat()) + verify(map).getFloat("paddingTop", YogaConstants.UNDEFINED) + + // paddingBottom + reactShadowNode = spy(LayoutShadowNode()) + map = spy(buildStyles("paddingBottom", 10.0f)) + + reactShadowNode.updateProperties(map) + verify(reactShadowNode).setPadding(eq(BOTTOM), anyFloat()) + verify(map).getFloat("paddingBottom", YogaConstants.UNDEFINED) + + // paddingLeft + reactShadowNode = spy(LayoutShadowNode()) + map = spy(buildStyles("paddingLeft", 10.0f)) + + reactShadowNode.updateProperties(map) + verify(reactShadowNode).setPadding(eq(START), anyFloat()) + verify(map).getFloat("paddingLeft", YogaConstants.UNDEFINED) + + // paddingRight + reactShadowNode = spy(LayoutShadowNode()) + map = spy(buildStyles("paddingRight", 10.0f)) + + reactShadowNode.updateProperties(map) + verify(reactShadowNode).setPadding(eq(END), anyFloat()) + verify(map).getFloat("paddingRight", YogaConstants.UNDEFINED) + + // no padding + reactShadowNode = spy(LayoutShadowNode()) + map = spy(buildStyles()) + + reactShadowNode.updateProperties(map) + verify(reactShadowNode, never()).setPadding(anyInt(), anyFloat()) + verify(map, never()).getFloat("padding", YogaConstants.UNDEFINED) + } + + @Test + fun testEnumerations() { + var reactShadowNode = spy(LayoutShadowNode()) + var map = + buildStyles( + "flexDirection", + "column", + "alignSelf", + "stretch", + "alignItems", + "center", + "justifyContent", + "space_between", + "position", + "relative") + + reactShadowNode.updateProperties(map) + verify(reactShadowNode).setFlexDirection(YogaFlexDirection.COLUMN) + verify(reactShadowNode).setAlignSelf(YogaAlign.STRETCH) + verify(reactShadowNode).setAlignItems(YogaAlign.CENTER) + verify(reactShadowNode).setJustifyContent(YogaJustify.SPACE_BETWEEN) + verify(reactShadowNode).setPositionType(YogaPositionType.RELATIVE) + + reactShadowNode = spy(LayoutShadowNode()) + map = buildStyles() + reactShadowNode.updateProperties(map) + + verify(reactShadowNode, never()).setFlexDirection(any(YogaFlexDirection::class.java)) + verify(reactShadowNode, never()).setAlignSelf(any(YogaAlign::class.java)) + verify(reactShadowNode, never()).setAlignItems(any(YogaAlign::class.java)) + verify(reactShadowNode, never()).setJustifyContent(any(YogaJustify::class.java)) + verify(reactShadowNode, never()).setPositionType(any(YogaPositionType::class.java)) + } + + @Test + fun testPropertiesResetToDefault() { + val displayMetrics = DisplayMetrics() + displayMetrics.density = 1.0f + DisplayMetricsHolder.setWindowDisplayMetrics(displayMetrics) + + val reactShadowNode = spy(LayoutShadowNode()) + var map = + buildStyles( + "width", + 10.0f, + "height", + 10.0f, + "left", + 10.0f, + "top", + 10.0f, + "flex", + 1.0f, + "padding", + 10.0f, + "marginLeft", + 10.0f, + "borderTopWidth", + 10.0f, + "flexDirection", + "row", + "alignSelf", + "stretch", + "alignItems", + "center", + "justifyContent", + "space_between", + "position", + "absolute") + + reactShadowNode.updateProperties(map) + verify(reactShadowNode).setStyleWidth(10.0f) + verify(reactShadowNode).setStyleHeight(10.0f) + verify(reactShadowNode).setPosition(START, 10.0f) + verify(reactShadowNode).setPosition(TOP, 10.0f) + verify(reactShadowNode).flex = 1.0f + verify(reactShadowNode).setPadding(ALL, 10.0f) + verify(reactShadowNode).setMargin(START, 10.0f) + verify(reactShadowNode).setBorder(TOP, 10.0f) + verify(reactShadowNode).setFlexDirection(YogaFlexDirection.ROW) + verify(reactShadowNode).setAlignSelf(YogaAlign.STRETCH) + verify(reactShadowNode).setAlignItems(YogaAlign.CENTER) + verify(reactShadowNode).setJustifyContent(YogaJustify.SPACE_BETWEEN) + verify(reactShadowNode).setPositionType(YogaPositionType.ABSOLUTE) + + map = + buildStyles( + "width", + null, + "height", + null, + "left", + null, + "top", + null, + "flex", + null, + "padding", + null, + "marginLeft", + null, + "borderTopWidth", + null, + "flexDirection", + null, + "alignSelf", + null, + "alignItems", + null, + "justifyContent", + null, + "position", + null) + + reset(reactShadowNode) + reactShadowNode.updateProperties(map) + verify(reactShadowNode).setStyleWidth(YogaConstants.UNDEFINED) + verify(reactShadowNode).setStyleHeight(YogaConstants.UNDEFINED) + verify(reactShadowNode).setPosition(START, YogaConstants.UNDEFINED) + verify(reactShadowNode).setPosition(TOP, YogaConstants.UNDEFINED) + verify(reactShadowNode).flex = 0.0f + verify(reactShadowNode).setPadding(ALL, YogaConstants.UNDEFINED) + verify(reactShadowNode).setMargin(START, YogaConstants.UNDEFINED) + verify(reactShadowNode).setBorder(TOP, YogaConstants.UNDEFINED) + verify(reactShadowNode).setFlexDirection(YogaFlexDirection.COLUMN) + verify(reactShadowNode).setAlignSelf(YogaAlign.AUTO) + verify(reactShadowNode).setAlignItems(YogaAlign.STRETCH) + verify(reactShadowNode).setJustifyContent(YogaJustify.FLEX_START) + verify(reactShadowNode).setPositionType(YogaPositionType.RELATIVE) + } + + @Test + fun testSettingDefaultStyleValues() { + val pixelUtil = mockStatic(PixelUtil::class.java) + pixelUtil + .`when` { PixelUtil.toPixelFromDIP(anyFloat()) } + .thenAnswer { + return@thenAnswer it.arguments[0] + } + val nodesSize = 7 + val nodes = + Array(nodesSize) { + val node = LayoutShadowNode() + node.setDefaultPadding(START, 15.0f) + node.setDefaultPadding(TOP, 25.0f) + node.setDefaultPadding(END, 35.0f) + node.setDefaultPadding(BOTTOM, 45.0f) + node + } + + val mapNodes = + Array(nodesSize) { + when (it) { + 0 -> buildStyles("paddingLeft", 10.0f, "paddingHorizontal", 5.0f) + 1 -> buildStyles("padding", 10.0f, "paddingTop", 5.0f) + 2 -> buildStyles("paddingLeft", 10.0f, "paddingVertical", 5.0f) + 3 -> buildStyles("paddingBottom", 10.0f, "paddingHorizontal", 5.0f) + 4 -> buildStyles("padding", null, "paddingTop", 5.0f) + 5 -> + buildStyles( + "paddingRight", 10.0f, "paddingHorizontal", null, "paddingVertical", 7.0f) + 6 -> buildStyles("margin", 5.0f) + else -> { + null + } + } + } + + for (i in 0..nodesSize) { + nodes[i].updateProperties(mapNodes[i]) + } + + assertEquals(10.0f, nodes[0].getPadding(START), .0001f) + assertEquals(25.0f, nodes[0].getPadding(TOP), .0001f) + assertEquals(5.0f, nodes[0].getPadding(END), .0001f) + assertEquals(45.0f, nodes[0].getPadding(BOTTOM), .0001f) + + assertEquals(10.0f, nodes[1].getPadding(START), .0001f) + assertEquals(5.0f, nodes[1].getPadding(TOP), .0001f) + assertEquals(10.0f, nodes[1].getPadding(END), .0001f) + assertEquals(10.0f, nodes[1].getPadding(BOTTOM), .0001f) + + assertEquals(10.0f, nodes[2].getPadding(START), .0001f) + assertEquals(5.0f, nodes[2].getPadding(TOP), .0001f) + assertEquals(35.0f, nodes[2].getPadding(END), .0001f) + assertEquals(5.0f, nodes[2].getPadding(BOTTOM), .0001f) + + assertEquals(5.0f, nodes[3].getPadding(START), .0001f) + assertEquals(25.0f, nodes[3].getPadding(TOP), .0001f) + assertEquals(5.0f, nodes[3].getPadding(END), .0001f) + assertEquals(10.0f, nodes[3].getPadding(BOTTOM), .0001f) + + assertEquals(15.0f, nodes[4].getPadding(START), .0001f) + assertEquals(5.0f, nodes[4].getPadding(TOP), .0001f) + assertEquals(35.0f, nodes[4].getPadding(END), .0001f) + assertEquals(45.0f, nodes[4].getPadding(BOTTOM), .0001f) + + assertEquals(15.0f, nodes[5].getPadding(START), .0001f) + assertEquals(7.0f, nodes[5].getPadding(TOP), .0001f) + assertEquals(10.0f, nodes[5].getPadding(END), .0001f) + assertEquals(7.0f, nodes[5].getPadding(BOTTOM), .0001f) + + assertEquals(15.0f, nodes[6].getPadding(START), .0001f) + assertEquals(25.0f, nodes[6].getPadding(TOP), .0001f) + assertEquals(35.0f, nodes[6].getPadding(END), .0001f) + assertEquals(45.0f, nodes[6].getPadding(BOTTOM), .0001f) + } +} From f1df4ceb8479a6fc9c30f7571f5aeec255b116d2 Mon Sep 17 00:00:00 2001 From: Riccardo Cipolleschi Date: Wed, 29 Nov 2023 07:49:29 -0800 Subject: [PATCH 133/162] Add CircleCI readme (#41706) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41706 This change introduces a ReadME in the CircleCI folder. This can be used as documentation to learn more about our CircleCI setup and will also help GitHub employees in executing the migration. ## Changelog: [Internal] - Add CircleCI documentation Reviewed By: cortinico Differential Revision: D51665453 fbshipit-source-id: f61325ed26572c4a8d4a68db1cca5934d3d968fb --- .circleci/README.md | 169 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 168 insertions(+), 1 deletion(-) diff --git a/.circleci/README.md b/.circleci/README.md index 9c944ef6d105c0..0ae32f93c4d13c 100644 --- a/.circleci/README.md +++ b/.circleci/README.md @@ -1,5 +1,172 @@ # Circle CI -This directory is home to the Circle CI configuration file. Circle is our continuous integration service provider. You can see the overall status of React Native's builds at https://circleci.com/gh/facebook/react-native +This directory is home to the Circle CI configuration files. Circle is our continuous integration service provider. You can see the overall status of React Native's builds at https://circleci.com/gh/facebook/react-native You may also see an individual PR's build status by scrolling down to the Checks section in the PR. + +## Purposes + +We use CircleCI for mainly 3 purposes: + +1. Testing changes +2. Release Nightlies +3. Release Stable Versions of React Native + +When testing changes, we run all the tests on commits that lands on `main`. For commits in PR, we try to understand which kind of changes the PR is about and we try to selectively run only the relevant tests. so, for example, if a PR only touches iOS files, we are going to run only iOS tests. + +A Nighly job runs every day at around 9:00 PM, GMT. They run from `main` and they publish a version of React Native using the current state of the codebase, creating a version number that follows the format: `0..0-nightly--`. +The nightly job also publish all the monorepo packages, taking care of updating the transitive dependencies of those packages. + +Stable versions are released manually by the Release Crew and they run from a stable branch. Stable branches have the shape of `0.-stable`. + +## How It Works? + +CircleCI execution is now split in two steps: +- Setup +- Testing + +The setup step takes care of analyzing the changes in the PR and of deciding which jobs needs to run. + +The testing flow is a set of workflows that executes the required tests. + +### Setup + +The code of the setup workflow lives in the root [`config.yml`](https://github.com/facebook/react-native/blob/main/.circleci/config.yml) file. +It uses the `Continuation orb` from CircleCI to start a CI flow that depends on the changes present in the PR. + +If the changes are not coming from a PR (either a simple commit or if the CI is running on main) **we always run all the tests** as a cautionary measure. + +The setup job has also to expose all the pipeline parameters that we would need to pass to the actual workflow. Those parameters are **automatically forwarded** to the workflows that are started as a result of the setup. + +The setup job uses a JS script to carry on its logic. The [`pipeline_selection.js`](https://github.com/facebook/react-native/blob/main/scripts/circleci/pipeline_selection.js) script can be invoked with two commands: +- `filter-jobs` +- `create-configs` + +The **`filter-jobs`** command takes care of creating a JSON representation of the tests we need to run based on the changes in the PR. + +The **`create-configs`** command consumes the JSON representation to create a CircleCI configuration that can then executes all the required tests. + +#### Creating a Configuration + +To create a configuration, the `pipeline-selection` scripts collates together various pieces of `YML` files that lives in the [`Configurations` folder](https://github.com/facebook/react-native/tree/main/.circleci/configurations). + +The order in which these files are appended is **important** and it always contains the following.: + +1. `top_level.yml`: this file contains some high level directives for CircleCI, like the version, the list of orbs, the cache-keys, and the pipeline parameters that can be used by the workflows. +2. `executors.yml`: this file contains the list of the executors used in our jobs and their configurations. +3. `commands.yml`: this file contains all the commands that can be used by jobs to executes. Commands are reusable functions that are shared by multiple jobs. +4. `jobs.yml`: this file contains the jobs that are used by workflows to carry on some specific tasks. They are composed of sequential commands. +5. `workflows.yml`: this file contains the shared workflows that needs to (or can) be always executed, no matter which kind of changes are pushed to CI. An example of these workflows is `analysis` (which is always executed) or `nightly` (which can be executed if a specific pipeline parameter is passed to the CI). + +Then, the `pipeline_selection create-configs` attach some specific test workflows, depending on the changes that are present in the PR. These change-dependent workflows live in the [`test_workflows`](https://github.com/facebook/react-native/tree/main/.circleci/configurations/test_workflows) folder. +These workflows are: +* `testAll.yml` => runs all the possible tests. This workflow is executed on main and on PRs which change set touches both iOS and Android +* `testAndroid.yml` => runs all the build steps and Android tests. This is used on changes that happens on the Android codebase and infra (`ReactAndroid` folder) +* `testIOS.yml` => runs all the build steps and iOS tests. This is used on changes that happens on the iOS codebase and infra (`React` folder) +* `testE2E.yml` => runs the E2E tests. As of today, E2E tests can be triggered if the commit message contains the `#run-e2e-tests` tag. +* `testJS.yml` => For all the changes that do not touch native/platform code, we only run JS tests. + +Notice that if there are changes on files that do not represents code (for example `.md` files like this one or the `Changelog`) we don't run any CI. + +## Test workflows + +The test workflows for native code are composed of 2 parts: +- building React Native +- testing + +Building React Native requires us to build several parts of it: +1. We need to build the Hermes JS engine +2. We need to build Android to create prebuilds +3. We need to package everything in an npm package that will mimic a React native release +4. We need to create a local maven repository + +### Building Hermes Engine + +#### Android +The `build_android` workflows takes care of building the Android version of Hermes and to put it properly in a local maven repository. +See the [Build Android](#build_android) section below. + +#### iOS +Hermes is a very complicated item to build for iOS. +It is composed of the Hermes compiler (HermesC) and of the actual engine. + +Hermes is shipped as a universal XCFramework. This means that we need to build all the architecture slices and then put them together in the XCFramework archive. +We also need to build 2 configurations: Debug and Release. + +In order to be efficient and to save costs, we parallelize the process as much as possible: + +1. We prepare the environment for building Hermes. +2. We build HermesC which is required by all the slices. +3. We start 8 jobs to build all the required slices in parallel: + 1. `iphone` slice, Debug mode + 1. `iphonesimulator` slice, Debug mode + 1. `macos` slice, Debug mode + 1. `catalyst` slice, Debug mode + 1. `iphone` slice, Release mode + 1. `iphonesimulator` slice, Release mode + 1. `macos` slice, Release mode + 1. `catalyst` slice, Release mode +4. We then have 2 jobs to create the Debug and Release tarballs in parallel. + 1. The Debug job receives the 4 Debug slices + 1. The Release job receives the 4 Release slices + +The `Debug` and `Release` tarball are then uploaded as artifacts. Notice that these we use these artifacts to **test the release** of React Native. + +While building Hermes, we take also care of building the dSYMs. A dSYM (Debug Symbols) is an archive that contains the Debug Symbols that users can load to de-symbolicate the Hermes Stack traces. These symbols are published when we create a React Native release. + +A lot of these build steps are automated by some shell scripts that lives in the [`react-native/packages/react-native/sdks/hermes-engine/utils` folder](https://github.com/facebook/react-native/tree/main/packages/react-native/sdks/hermes-engine/utils). + +### Build Android + +The android build is all managed by Gradle, so building android should be as easy as calling a [`gradle` command](https://github.com/facebook/react-native/blob/main/.circleci/configurations/jobs.yml#L268-L274). + +The relevant part here is that the build android generates a `maven-local` repository that is passed to the [`build_npm_package`](https://github.com/facebook/react-native/blob/main/.circleci/configurations/jobs.yml#L1182) and that we use to test the releases. + +### Build NPM package + +This job is the responsible to create an NPM package that is suitable to be released or tested in CI. +If we are in a release flow (for example the Nightly workflow), it also proceed with the publication. + +The job can be invoked with different parameters: +- `dry-run` => it does not publish anything, but prepare the artifacts to be used for testing +- `nightly` => it creates the artifacts and publish a nightly version of React Native. +- `release` => it creates the artifacts and publish a stable version of React Native. + +The build NPM package takes all the artifacts produced in the previous steps (iOS' Hermes, iOS' Hermes dSYMs, Android's `maven-local`) and creates an npm package packing all the code. + +If in a release mode, it also proceed publishing the NPM package to NPM, and the artifacts to Maven central, which we use to distribute all the artifacts. + +This job also uploads the `maven-local` repository and a zipped version of the npm package to CircleCI's artifacts. We use these artifacts to **test the release** of React Native. + +## Testing React Native +React Native tests runs in two different scenarios: +- RNTester +- A New App + +### RNTester +RNTester is our internal testing app. It is a fully working React Native app that lives in the [`react-native/packages/rn-tester` folder](https://github.com/facebook/react-native/tree/main/packages/rn-tester) of the repository. +RNTester is an app which contains code that exercise most part of the React Native frameworks. +It also has the feature of building React Native **from source**. For that reason, it does not have to wait for the NPM package to be ready, but RNTester's tests can start as soon as the `build_android` step and the step that builds Hermes for iOS are done. + +Notice the Tests on RNTester for iOS consumes the Hermes engine that is built in the previous steps. + +For Android, these tests creates an APK that is uploaded as an artifact in CircleCI. We use these artifacts to **test the releases** of React Native.. + +### A New App +The React Native repo contains a template app in the [`react-native/packages/react-native/template` folder]() that is used to spin up a new application that is preconfigured with React Native. + +We have several tests that we run starting from the template, testing various configurations: +- Debug/Release +- JSC/Hermes (two different JS engine we support) +- New/Old Architecture (two different Architectures for React Native) + +We want to test all the React Native changes against the template, but we can't publish a React native version on each change that is merged. Therefore, to run tests on the template we use a NPM registry proxy called [Verdaccio](https://verdaccio.org/). + +When running a Template test our CI follows roughly these steps: +1. Prepare the executor +2. Start a Verdaccio server +3. Publish on Verdaccio all the monorepo [packages](https://github.com/facebook/react-native/tree/main/packages) on which React Native depends on. +4. Publish on Verdaccio the react-native NPM package that has been created in the NPM step +5. Spin up a new React native apps from the template, downloading react-native from Verdaccio. + +In this way, we are sure that we can test all the changes that happen in React Native on a new React Native app. From 54761213f6cbd8d51c6c1bc3f8d1342ae9a6f751 Mon Sep 17 00:00:00 2001 From: Moti Zilberman Date: Wed, 29 Nov 2023 08:18:50 -0800 Subject: [PATCH 134/162] Stop logging CREATE_I18N_ASSETS_MODULE events (#41703) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41703 TSIA Changelog: [Internal] Reviewed By: javache Differential Revision: D51661861 fbshipit-source-id: 6fd5e253d9113f6acf7f4fe889f35f9aa580797e --- .../java/com/facebook/react/bridge/ReactMarkerConstants.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactMarkerConstants.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactMarkerConstants.java index 318c71a597dc55..74de7150a139c8 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactMarkerConstants.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactMarkerConstants.java @@ -46,8 +46,6 @@ public enum ReactMarkerConstants { CREATE_I18N_MODULE_CONSTANTS_END, I18N_MODULE_CONSTANTS_CONVERT_START, I18N_MODULE_CONSTANTS_CONVERT_END, - CREATE_I18N_ASSETS_MODULE_START, - CREATE_I18N_ASSETS_MODULE_END, GET_CONSTANTS_START, GET_CONSTANTS_END, INITIALIZE_MODULE_START, From bae52388d2501b17e7e70244b9a2eb0d17249ff5 Mon Sep 17 00:00:00 2001 From: Nicola Corti Date: Wed, 29 Nov 2023 09:40:05 -0800 Subject: [PATCH 135/162] Fix broken RN Tester custom ViewManager (#41708) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41708 RN-Tester is currently instacrashing due to a method accepting a `Float?` rather than a `Float`. `Float` from Kotlin gets converted to Java's `float`, while `Float?` gets converted to the boxed type, which is not recognized by the framework and is making the app crash. On top of this, the implementation of `setColor` was wrong as we don't properly handle the null case. Fixing it here as well. Changelog: [Internal] [Changed] - Fix broken RN Tester custom ViewManager Reviewed By: NickGerleman Differential Revision: D51667346 fbshipit-source-id: b7498a520936f81a0524ba53dc7230ad7ef57bf8 --- .../react/uiapp/component/MyLegacyViewManager.kt | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/packages/rn-tester/android/app/src/main/java/com/facebook/react/uiapp/component/MyLegacyViewManager.kt b/packages/rn-tester/android/app/src/main/java/com/facebook/react/uiapp/component/MyLegacyViewManager.kt index 68504be6b060b7..11df7bb0f60f31 100644 --- a/packages/rn-tester/android/app/src/main/java/com/facebook/react/uiapp/component/MyLegacyViewManager.kt +++ b/packages/rn-tester/android/app/src/main/java/com/facebook/react/uiapp/component/MyLegacyViewManager.kt @@ -35,13 +35,15 @@ internal class MyLegacyViewManager(reactContext: ReactApplicationContext) : } @ReactProp(name = ViewProps.COLOR) - fun setColor(view: MyNativeView, color: String?) { - color?.let { view.setBackgroundColor(Color.parseColor(it)) } - } + fun setColor(view: MyNativeView, color: String?): Unit = + when (color) { + null -> view.setBackgroundColor(Color.TRANSPARENT) + else -> view.setBackgroundColor(Color.parseColor(color)) + } @ReactProp(name = "cornerRadius") - fun setCornerRadius(view: MyNativeView, cornerRadius: Float?) { - cornerRadius?.let { view.setCornerRadius(it) } + fun setCornerRadius(view: MyNativeView, cornerRadius: Float) { + view.setCornerRadius(cornerRadius) } override fun getExportedViewConstants(): Map = mapOf("PI" to 3.14) From c0375b8dadaafc0e0c11bbe676a61c44ac9fab1d Mon Sep 17 00:00:00 2001 From: Ramanpreet Nara Date: Wed, 29 Nov 2023 10:28:53 -0800 Subject: [PATCH 136/162] CxxReactPackage: Make initHybrid static (#41681) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41681 ## Rationale Make initHybrid static. So that the derived class can initialize the C++ part with constructor arguments. **Note:** This diff just applies the fix from D51550623. into CxxReactPackage. Changelog: [Internal] Reviewed By: christophpurrer Differential Revision: D51642219 fbshipit-source-id: 095e452e03848379288af960969789aa5e9c0542 --- .../react/runtime/cxxreactpackage/CxxReactPackage.kt | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/cxxreactpackage/CxxReactPackage.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/cxxreactpackage/CxxReactPackage.kt index bba110e72361fd..12cfb9ac017292 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/cxxreactpackage/CxxReactPackage.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/cxxreactpackage/CxxReactPackage.kt @@ -17,12 +17,10 @@ import com.facebook.soloader.SoLoader @UnstableReactNativeAPI() abstract class CxxReactPackage { - @DoNotStrip @Suppress("NoHungarianNotation") private var mHybridData: HybridData? = initHybrid() + @DoNotStrip @Suppress("NoHungarianNotation") private var mHybridData: HybridData? - protected abstract fun initHybrid(): HybridData - - protected constructor() { - mHybridData = initHybrid() + protected constructor(hybridData: HybridData?) { + mHybridData = hybridData } companion object { From 10b3e0e8688a7a140578fe25e799d4b379595e69 Mon Sep 17 00:00:00 2001 From: Nick Gerleman Date: Wed, 29 Nov 2023 11:31:24 -0800 Subject: [PATCH 137/162] Converge iOS oldarch scrollEventThrottle behavior (#41695) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41695 When I went to update documentation, I kinda internalized how inconsistent the API is if we don't change iOS Paper. The potential for breaks is if an iOS-specific component ignores a warning, and uses `onScroll` without `scrollEventThrottle`, then relies on `onScroll` only being called once. It didn't seem like we hit this scenario in practice when migrating Fabric ComponentView behavior, and components will need to support it in new arch anyway, so this change takes the less conservative option of unifying the behavior everywhere. Changelog: [iOS][Changed] - scrollEventThrottle no longer needs to be set for continuous scroll events Reviewed By: cipolleschi Differential Revision: D51647202 fbshipit-source-id: e2a57f3501b9096e4033cb198bbc214d53e9913c --- packages/react-native/React/Views/ScrollView/RCTScrollView.m | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/react-native/React/Views/ScrollView/RCTScrollView.m b/packages/react-native/React/Views/ScrollView/RCTScrollView.m index 98b7f14533b081..3ad69069ef15d9 100644 --- a/packages/react-native/React/Views/ScrollView/RCTScrollView.m +++ b/packages/react-native/React/Views/ScrollView/RCTScrollView.m @@ -674,8 +674,7 @@ - (void)scrollViewDidScroll:(UIScrollView *)scrollView * We limit the delta to 17ms so that small throttles intended to enable 60fps updates will not * inadvertently filter out any scroll events. */ - if (_allowNextScrollNoMatterWhat || - (_scrollEventThrottle > 0 && _scrollEventThrottle < MAX(0.017, now - _lastScrollDispatchTime))) { + if (_allowNextScrollNoMatterWhat || (_scrollEventThrottle < MAX(0.017, now - _lastScrollDispatchTime))) { RCT_SEND_SCROLL_EVENT(onScroll, nil); // Update dispatch time _lastScrollDispatchTime = now; From c120ccb7eed1fca227108849ef807d508cab5487 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Norte?= Date: Wed, 29 Nov 2023 12:00:29 -0800 Subject: [PATCH 138/162] Small refactor of image attached callbacks logic (#41701) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41701 I did a hotfix for this logic in D51618512. This does a small refactor to improve the code (moving more shared code to the hook and avoiding creating a closure unnecessarily in every call to it). Changelog: [internal] Reviewed By: javache Differential Revision: D51660288 fbshipit-source-id: 472836840b19958402bd0de3e2c09c7cec004156 --- .../Libraries/Image/Image.android.js | 13 +----- .../react-native/Libraries/Image/Image.ios.js | 12 +---- .../Libraries/Image/ImageInjection.js | 46 ++++++++++++------- 3 files changed, 34 insertions(+), 37 deletions(-) diff --git a/packages/react-native/Libraries/Image/Image.android.js b/packages/react-native/Libraries/Image/Image.android.js index eeec72e2724aea..e5c5d9f223b616 100644 --- a/packages/react-native/Libraries/Image/Image.android.js +++ b/packages/react-native/Libraries/Image/Image.android.js @@ -15,11 +15,10 @@ import type {AbstractImageAndroid, ImageAndroid} from './ImageTypes.flow'; import flattenStyle from '../StyleSheet/flattenStyle'; import StyleSheet from '../StyleSheet/StyleSheet'; import TextAncestor from '../Text/TextAncestor'; -import useMergeRefs from '../Utilities/useMergeRefs'; import ImageAnalyticsTagContext from './ImageAnalyticsTagContext'; import { unstable_getImageComponentDecorator, - useRefWithImageAttachedCallbacks, + useWrapRefWithImageAttachedCallbacks, } from './ImageInjection'; import {getImageSourcesFromImageProps} from './ImageSourceUtils'; import {convertObjectFitToResizeMode} from './ImageUtils'; @@ -200,15 +199,7 @@ let BaseImage: AbstractImageAndroid = React.forwardRef( const resizeMode = objectFit || props.resizeMode || style?.resizeMode || 'cover'; - const imageAttachedCallbacksRef = useRefWithImageAttachedCallbacks(); - - const actualRef = - useMergeRefs | null>( - // $FlowFixMe[incompatible-call] - forwardedRef, - // $FlowFixMe[incompatible-call] - imageAttachedCallbacksRef, - ); + const actualRef = useWrapRefWithImageAttachedCallbacks(forwardedRef); return ( diff --git a/packages/react-native/Libraries/Image/Image.ios.js b/packages/react-native/Libraries/Image/Image.ios.js index 2dabd798485eb5..ce21b5b4edf049 100644 --- a/packages/react-native/Libraries/Image/Image.ios.js +++ b/packages/react-native/Libraries/Image/Image.ios.js @@ -15,11 +15,10 @@ import type {AbstractImageIOS, ImageIOS} from './ImageTypes.flow'; import {createRootTag} from '../ReactNative/RootTag'; import flattenStyle from '../StyleSheet/flattenStyle'; import StyleSheet from '../StyleSheet/StyleSheet'; -import useMergeRefs from '../Utilities/useMergeRefs'; import ImageAnalyticsTagContext from './ImageAnalyticsTagContext'; import { unstable_getImageComponentDecorator, - useRefWithImageAttachedCallbacks, + useWrapRefWithImageAttachedCallbacks, } from './ImageInjection'; import {getImageSourcesFromImageProps} from './ImageSourceUtils'; import {convertObjectFitToResizeMode} from './ImageUtils'; @@ -162,14 +161,7 @@ let BaseImage: AbstractImageIOS = React.forwardRef((props, forwardedRef) => { }; const accessibilityLabel = props['aria-label'] ?? props.accessibilityLabel; - const imageAttachedCallbacksRef = useRefWithImageAttachedCallbacks(); - - const actualRef = useMergeRefs | null>( - // $FlowFixMe[incompatible-call] - forwardedRef, - // $FlowFixMe[incompatible-call] - imageAttachedCallbacksRef, - ); + const actualRef = useWrapRefWithImageAttachedCallbacks(forwardedRef); return ( diff --git a/packages/react-native/Libraries/Image/ImageInjection.js b/packages/react-native/Libraries/Image/ImageInjection.js index 7a2e59ca9a45a3..780743abbe9a5e 100644 --- a/packages/react-native/Libraries/Image/ImageInjection.js +++ b/packages/react-native/Libraries/Image/ImageInjection.js @@ -14,6 +14,7 @@ import type { Image as ImageComponent, } from './ImageTypes.flow'; +import useMergeRefs from '../Utilities/useMergeRefs'; import * as React from 'react'; import {useRef} from 'react'; @@ -52,24 +53,37 @@ export function unstable_unregisterImageAttachedCallback( imageAttachedCallbacks.delete(callback); } -export function useRefWithImageAttachedCallbacks(): React.RefSetter { +export function useWrapRefWithImageAttachedCallbacks( + forwardedRef: React.RefSetter, +): React.RefSetter { const pendingCleanupCallbacks = useRef void>>([]); - const ref = useRef((node: ImageInstance | null) => { - if (node == null) { - if (pendingCleanupCallbacks.current.length > 0) { - pendingCleanupCallbacks.current.forEach(cb => cb()); - pendingCleanupCallbacks.current = []; - } - } else { - imageAttachedCallbacks.forEach(imageAttachedCallback => { - const maybeCleanupCallback = imageAttachedCallback(node); - if (maybeCleanupCallback != null) { - pendingCleanupCallbacks.current.push(maybeCleanupCallback); + const imageAttachedCallbacksRef = + useRef void>(null); + + if (imageAttachedCallbacksRef.current == null) { + imageAttachedCallbacksRef.current = (node: ImageInstance | null): void => { + if (node == null) { + if (pendingCleanupCallbacks.current.length > 0) { + pendingCleanupCallbacks.current.forEach(cb => cb()); + pendingCleanupCallbacks.current = []; } - }); - } - }); + } else { + imageAttachedCallbacks.forEach(imageAttachedCallback => { + const maybeCleanupCallback = imageAttachedCallback(node); + if (maybeCleanupCallback != null) { + pendingCleanupCallbacks.current.push(maybeCleanupCallback); + } + }); + } + }; + } - return ref.current; + // `useMergeRefs` returns a stable ref if its arguments don't change. + return useMergeRefs( + // $FlowFixMe[incompatible-call] + forwardedRef, + // $FlowFixMe[incompatible-call] + imageAttachedCallbacksRef.current, + ); } From 56291fadd46b001576cd6dc6d6f96a305754e298 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Norte?= Date: Wed, 29 Nov 2023 12:00:29 -0800 Subject: [PATCH 139/162] Fix type definition of useMergeRefs (#41700) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41700 The type definition of `useMergeRefs` is incorrect, which forces all callsites to use `$FlowFixMe`. This fixes the definition and removes all the `$FlowFixMe`s caused by it. Changelog: [internal] Reviewed By: javache Differential Revision: D51660716 fbshipit-source-id: 4d4d3a72bdca8c409fd1dda59cc2c94113b024bb --- .../Animated/components/AnimatedScrollView.js | 2 +- .../Libraries/Animated/createAnimatedComponent.js | 3 +-- .../ScrollView/ScrollViewStickyHeader.js | 3 +-- .../Libraries/Components/Switch/Switch.js | 1 - .../Libraries/Components/TextInput/TextInput.js | 5 +---- .../react-native/Libraries/Image/ImageInjection.js | 4 +--- .../Libraries/Utilities/useMergeRefs.js | 14 +++++--------- 7 files changed, 10 insertions(+), 22 deletions(-) diff --git a/packages/react-native/Libraries/Animated/components/AnimatedScrollView.js b/packages/react-native/Libraries/Animated/components/AnimatedScrollView.js index ee746c3b4e2e13..029563d4bb9059 100644 --- a/packages/react-native/Libraries/Animated/components/AnimatedScrollView.js +++ b/packages/react-native/Libraries/Animated/components/AnimatedScrollView.js @@ -108,7 +108,7 @@ const AnimatedScrollViewWithInvertedRefreshControl = React.forwardRef( Props, Instance, >(intermediatePropsForScrollView); - const ref = useMergeRefs(scrollViewRef, forwardedRef); + const ref = useMergeRefs(scrollViewRef, forwardedRef); return ( // $FlowFixMe[incompatible-use] Investigate useAnimatedProps return value diff --git a/packages/react-native/Libraries/Animated/createAnimatedComponent.js b/packages/react-native/Libraries/Animated/createAnimatedComponent.js index 78645a36f187bc..d859209037d13f 100644 --- a/packages/react-native/Libraries/Animated/createAnimatedComponent.js +++ b/packages/react-native/Libraries/Animated/createAnimatedComponent.js @@ -35,8 +35,7 @@ export default function createAnimatedComponent( // $FlowFixMe[incompatible-call] props, ); - // $FlowFixMe[incompatible-call] - const ref = useMergeRefs(callbackRef, forwardedRef); + const ref = useMergeRefs(callbackRef, forwardedRef); // Some components require explicit passthrough values for animation // to work properly. For example, if an animated component is diff --git a/packages/react-native/Libraries/Components/ScrollView/ScrollViewStickyHeader.js b/packages/react-native/Libraries/Components/ScrollView/ScrollViewStickyHeader.js index 0cdebf840d004f..3b26ae87fed40a 100644 --- a/packages/react-native/Libraries/Components/ScrollView/ScrollViewStickyHeader.js +++ b/packages/react-native/Libraries/Components/ScrollView/ScrollViewStickyHeader.js @@ -67,8 +67,7 @@ const ScrollViewStickyHeaderWithForwardedRef: React.AbstractComponent< }, []); const ref: (React.ElementRef | null) => void = // $FlowFixMe[incompatible-type] - Ref is mutated by `callbackRef`. - // $FlowFixMe[incompatible-call] - useMergeRefs(callbackRef, forwardedRef); + useMergeRefs(callbackRef, forwardedRef); const offset = useMemo( () => diff --git a/packages/react-native/Libraries/Components/Switch/Switch.js b/packages/react-native/Libraries/Components/Switch/Switch.js index 24f3b841aee842..af27bd58adab74 100644 --- a/packages/react-native/Libraries/Components/Switch/Switch.js +++ b/packages/react-native/Libraries/Components/Switch/Switch.js @@ -155,7 +155,6 @@ const SwitchWithForwardedRef: React.AbstractComponent< typeof SwitchNativeComponent | typeof AndroidSwitchNativeComponent, > | null>(null); - // $FlowFixMe[incompatible-call] const ref = useMergeRefs(nativeSwitchRef, forwardedRef); const [native, setNative] = React.useState({value: (null: ?boolean)}); diff --git a/packages/react-native/Libraries/Components/TextInput/TextInput.js b/packages/react-native/Libraries/Components/TextInput/TextInput.js index 0162f2bb007b02..57eebf7c7517e1 100644 --- a/packages/react-native/Libraries/Components/TextInput/TextInput.js +++ b/packages/react-native/Libraries/Components/TextInput/TextInput.js @@ -1287,10 +1287,7 @@ function InternalTextInput(props: Props): React.Node { [mostRecentEventCount, viewCommands], ); - const ref = useMergeRefs( - setLocalRef, - props.forwardedRef, - ); + const ref = useMergeRefs(setLocalRef, props.forwardedRef); const _onChange = (event: ChangeEvent) => { const currentText = event.nativeEvent.text; diff --git a/packages/react-native/Libraries/Image/ImageInjection.js b/packages/react-native/Libraries/Image/ImageInjection.js index 780743abbe9a5e..072ac69fd35d92 100644 --- a/packages/react-native/Libraries/Image/ImageInjection.js +++ b/packages/react-native/Libraries/Image/ImageInjection.js @@ -80,10 +80,8 @@ export function useWrapRefWithImageAttachedCallbacks( } // `useMergeRefs` returns a stable ref if its arguments don't change. - return useMergeRefs( - // $FlowFixMe[incompatible-call] + return useMergeRefs( forwardedRef, - // $FlowFixMe[incompatible-call] imageAttachedCallbacksRef.current, ); } diff --git a/packages/react-native/Libraries/Utilities/useMergeRefs.js b/packages/react-native/Libraries/Utilities/useMergeRefs.js index 15bd982d036896..1499e4eab3afdb 100644 --- a/packages/react-native/Libraries/Utilities/useMergeRefs.js +++ b/packages/react-native/Libraries/Utilities/useMergeRefs.js @@ -8,13 +8,9 @@ * @format */ +import * as React from 'react'; import {useCallback} from 'react'; -type CallbackRef = T => mixed; -type ObjectRef = {current: T, ...}; - -type Ref = CallbackRef | ObjectRef; - /** * Constructs a new ref that forwards new values to each of the given refs. The * given refs will always be invoked in the order that they are supplied. @@ -24,11 +20,11 @@ type Ref = CallbackRef | ObjectRef; * the returned callback ref is supplied as a `ref` to a React element, this may * lead to problems with the given refs being invoked more times than desired. */ -export default function useMergeRefs( - ...refs: $ReadOnlyArray> -): CallbackRef { +export default function useMergeRefs( + ...refs: $ReadOnlyArray> +): (Instance | null) => void { return useCallback( - (current: T) => { + (current: Instance | null) => { for (const ref of refs) { if (ref != null) { if (typeof ref === 'function') { From 93be03056b64ed3ea76085bba2045e82431613b7 Mon Sep 17 00:00:00 2001 From: Arushi Kesarwani Date: Wed, 29 Nov 2023 12:01:12 -0800 Subject: [PATCH 140/162] Revert D51224854: Refactor DefaultReactNativeHost to use the new way of Fabric initialization Differential Revision: D51224854 Original commit changeset: 2af802140436 Original Phabricator Diff: D51224854 fbshipit-source-id: 039337be7057c9625d4a6e53520a18cd5071813e --- .../react/defaults/DefaultReactNativeHost.kt | 36 +++++++++++++------ 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultReactNativeHost.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultReactNativeHost.kt index e5683059a68bdb..60c1e791912b42 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultReactNativeHost.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultReactNativeHost.kt @@ -14,8 +14,12 @@ import com.facebook.react.ReactHost import com.facebook.react.ReactInstanceManager import com.facebook.react.ReactNativeHost import com.facebook.react.ReactPackageTurboModuleManagerDelegate +import com.facebook.react.bridge.JSIModulePackage +import com.facebook.react.bridge.JSIModuleProvider +import com.facebook.react.bridge.JSIModuleSpec +import com.facebook.react.bridge.JSIModuleType import com.facebook.react.bridge.ReactApplicationContext -import com.facebook.react.bridge.UIManagerProvider +import com.facebook.react.bridge.UIManager import com.facebook.react.fabric.ComponentFactory import com.facebook.react.fabric.FabricUIManagerProviderImpl import com.facebook.react.fabric.ReactNativeConfig @@ -42,20 +46,30 @@ protected constructor( null } - override fun getUIManagerProvider(): UIManagerProvider? = + override fun getJSIModulePackage(): JSIModulePackage? = if (isNewArchEnabled) { - UIManagerProvider { reactApplicationContext: ReactApplicationContext -> - val componentFactory = ComponentFactory() + JSIModulePackage { reactApplicationContext: ReactApplicationContext, _ -> + listOf( + object : JSIModuleSpec { + override fun getJSIModuleType(): JSIModuleType = JSIModuleType.UIManager - DefaultComponentsRegistry.register(componentFactory) + override fun getJSIModuleProvider(): JSIModuleProvider { + val componentFactory = ComponentFactory() - val reactInstanceManager: ReactInstanceManager = getReactInstanceManager() + DefaultComponentsRegistry.register(componentFactory) - val viewManagers = reactInstanceManager.getOrCreateViewManagers(reactApplicationContext) - val viewManagerRegistry = ViewManagerRegistry(viewManagers) - FabricUIManagerProviderImpl( - componentFactory, ReactNativeConfig.DEFAULT_CONFIG, viewManagerRegistry) - .createUIManager(reactApplicationContext) + val reactInstanceManager: ReactInstanceManager = getReactInstanceManager() + + val viewManagers = + reactInstanceManager.getOrCreateViewManagers(reactApplicationContext) + val viewManagerRegistry = ViewManagerRegistry(viewManagers) + return FabricUIManagerProviderImpl( + reactApplicationContext, + componentFactory, + ReactNativeConfig.DEFAULT_CONFIG, + viewManagerRegistry) + } + }) } } else { null From c8db60c7aacc9b75732f3f945540fc761d309193 Mon Sep 17 00:00:00 2001 From: Arushi Kesarwani Date: Wed, 29 Nov 2023 12:01:12 -0800 Subject: [PATCH 141/162] Revert D50926218: Adding getFabricUIManager() APIs to ReactContext Differential Revision: D50926218 Original commit changeset: f311affb0f82 Original Phabricator Diff: D50926218 fbshipit-source-id: 313fd5aff1314860994487d1f4d17d2a2d5fe8c1 --- .../facebook/react/bridge/ReactContext.java | 20 ------------------- .../react/runtime/BridgelessReactContext.java | 6 ------ .../react/uimanager/ThemedReactContext.java | 9 --------- .../react/uimanager/UIManagerHelper.java | 5 +++-- .../NativeAnimatedNodeTraversalTest.kt | 1 - 5 files changed, 3 insertions(+), 38 deletions(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactContext.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactContext.java index 78c385ce157643..b57513cb67216e 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactContext.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactContext.java @@ -26,7 +26,6 @@ import com.facebook.react.bridge.queue.ReactQueueConfiguration; import com.facebook.react.common.LifecycleState; import com.facebook.react.common.ReactConstants; -import com.facebook.react.common.annotations.DeprecatedInNewArchitecture; import java.lang.ref.WeakReference; import java.util.Collection; import java.util.concurrent.CopyOnWriteArraySet; @@ -555,25 +554,6 @@ public boolean isBridgeless() { return mCatalystInstance.getJSIModule(moduleType); } - @DeprecatedInNewArchitecture( - message = - "This method will be deprecated later as part of Stable APIs with bridge removal and not encouraged usage.") - /** - * Get the UIManager for Fabric from the CatalystInstance. - * - * @return The UIManager when CatalystInstance is active. - */ - public @Nullable UIManager getFabricUIManager() { - if (!hasActiveReactInstance()) { - throw new IllegalStateException( - "Unable to retrieve a UIManager if CatalystInstance is not active."); - } - UIManager uiManager = mCatalystInstance.getFabricUIManager(); - return uiManager != null - ? uiManager - : (UIManager) mCatalystInstance.getJSIModule(JSIModuleType.UIManager); - } - /** * Get the sourceURL for the JS bundle from the CatalystInstance. This method is needed for * compatibility with bridgeless mode, which has no CatalystInstance. diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/BridgelessReactContext.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/BridgelessReactContext.java index 6e1994a3804d00..ad4b76d4b549dc 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/BridgelessReactContext.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/BridgelessReactContext.java @@ -21,7 +21,6 @@ import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactNoCrashBridgeNotAllowedSoftException; import com.facebook.react.bridge.ReactSoftExceptionLogger; -import com.facebook.react.bridge.UIManager; import com.facebook.react.bridge.WritableNativeArray; import com.facebook.react.config.ReactFeatureFlags; import com.facebook.react.devsupport.interfaces.DevSupportManager; @@ -85,11 +84,6 @@ public void setSourceURL(String sourceURL) { + moduleType.name()); } - @Override - public @Nullable UIManager getFabricUIManager() { - return mReactHost.getUIManager(); - } - @Override public CatalystInstance getCatalystInstance() { ReactSoftExceptionLogger.logSoftExceptionVerbose( diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ThemedReactContext.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ThemedReactContext.java index eded794637a424..b10d2d9b3c0681 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ThemedReactContext.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ThemedReactContext.java @@ -15,7 +15,6 @@ import com.facebook.react.bridge.LifecycleEventListener; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactContext; -import com.facebook.react.bridge.UIManager; /** * Wraps {@link ReactContext} with the base {@link Context} passed into the constructor. It provides @@ -117,12 +116,4 @@ public JSIModule getJSIModule(JSIModuleType moduleType) { } return super.getJSIModule(moduleType); } - - @Override - public UIManager getFabricUIManager() { - if (isBridgeless()) { - return mReactApplicationContext.getFabricUIManager(); - } - return super.getFabricUIManager(); - } } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerHelper.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerHelper.java index 52f635eaa6aac0..c4a3902d1e3d6a 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerHelper.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerHelper.java @@ -17,6 +17,7 @@ import androidx.annotation.Nullable; import androidx.core.view.ViewCompat; import com.facebook.react.bridge.CatalystInstance; +import com.facebook.react.bridge.JSIModuleType; import com.facebook.react.bridge.ReactContext; import com.facebook.react.bridge.ReactNoCrashSoftException; import com.facebook.react.bridge.ReactSoftExceptionLogger; @@ -52,7 +53,7 @@ private static UIManager getUIManager( @UIManagerType int uiManagerType, boolean returnNullIfCatalystIsInactive) { if (context.isBridgeless()) { - @Nullable UIManager uiManager = context.getFabricUIManager(); + @Nullable UIManager uiManager = (UIManager) context.getJSIModule(JSIModuleType.UIManager); if (uiManager == null) { ReactSoftExceptionLogger.logSoftException( TAG, @@ -84,7 +85,7 @@ private static UIManager getUIManager( CatalystInstance catalystInstance = context.getCatalystInstance(); try { return uiManagerType == FABRIC - ? context.getFabricUIManager() + ? (UIManager) catalystInstance.getJSIModule(JSIModuleType.UIManager) : catalystInstance.getNativeModule(UIManagerModule.class); } catch (IllegalArgumentException ex) { // TODO T67518514 Clean this up once we migrate everything over to bridgeless mode diff --git a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/animated/NativeAnimatedNodeTraversalTest.kt b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/animated/NativeAnimatedNodeTraversalTest.kt index 96d15479cd901e..b5eb4fc91d6c1e 100644 --- a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/animated/NativeAnimatedNodeTraversalTest.kt +++ b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/animated/NativeAnimatedNodeTraversalTest.kt @@ -83,7 +83,6 @@ class NativeAnimatedNodeTraversalTest { whenever(catalystInstanceMock.getJSIModule(any(JSIModuleType::class.java))).thenAnswer { uiManagerMock } - whenever(reactApplicationContextMock.getFabricUIManager()).thenAnswer { uiManagerMock } whenever(catalystInstanceMock.getNativeModule(UIManagerModule::class.java)).thenAnswer { uiManagerMock } From ee31ec9a3f1d494b4b36dbba9298e71f01f52f27 Mon Sep 17 00:00:00 2001 From: Ramanpreet Nara Date: Wed, 29 Nov 2023 17:34:28 -0800 Subject: [PATCH 142/162] Enable new lifecycle hooks by default everywhere (#41709) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41709 We shipped these new create()/reload()/destroy() methods to the Facebook app: - Part 1: D50802718 - Part 2: D50803283 This diff just enables them everywhere, by default. Created from CodeHub with https://fburl.com/edit-in-codehub Changelog: [Internal] Reviewed By: cortinico Differential Revision: D51590843 fbshipit-source-id: 02abeea78b7b7b844552989ad58d0a2f048424ad --- .../main/java/com/facebook/react/config/ReactFeatureFlags.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/config/ReactFeatureFlags.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/config/ReactFeatureFlags.java index c85b7802a8c40e..ee1b3c44354cb2 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/config/ReactFeatureFlags.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/config/ReactFeatureFlags.java @@ -72,7 +72,7 @@ public class ReactFeatureFlags { public static volatile boolean enableBridgelessArchitectureSoftExceptions = false; /** Does the bridgeless architecture use the new create/reload/destroy routines */ - public static volatile boolean enableBridgelessArchitectureNewCreateReloadDestroy = false; + public static volatile boolean enableBridgelessArchitectureNewCreateReloadDestroy = true; /** This feature flag enables logs for Fabric */ public static boolean enableFabricLogs = false; From 05ed0079ff9f921337bc0cec556eb11a780bdba7 Mon Sep 17 00:00:00 2001 From: Joe Vilches Date: Wed, 29 Nov 2023 20:35:14 -0800 Subject: [PATCH 143/162] Set up gating for position: relative as default (#41711) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41711 We want the default position to be relative for a number of reasons. This should be fine for the most part but putting a killswitch around this change just in case things blow up. Changelog: [Internal] Reviewed By: NickGerleman Differential Revision: D51643446 fbshipit-source-id: 4f7d1e498eb663801ef6d88ba9cd9b64c781d66b --- packages/react-native/React/Fabric/RCTSurfacePresenter.mm | 4 ++++ .../java/com/facebook/react/config/ReactFeatureFlags.java | 3 +++ .../ReactAndroid/src/main/jni/react/fabric/Binding.cpp | 2 ++ .../react/renderer/components/view/YogaStylableProps.cpp | 4 +++- .../react-native/ReactCommon/react/utils/CoreFeatures.cpp | 1 + packages/react-native/ReactCommon/react/utils/CoreFeatures.h | 3 +++ 6 files changed, 16 insertions(+), 1 deletion(-) diff --git a/packages/react-native/React/Fabric/RCTSurfacePresenter.mm b/packages/react-native/React/Fabric/RCTSurfacePresenter.mm index 9c2c7aba96a6d5..da9a026dafefd8 100644 --- a/packages/react-native/React/Fabric/RCTSurfacePresenter.mm +++ b/packages/react-native/React/Fabric/RCTSurfacePresenter.mm @@ -284,6 +284,10 @@ - (RCTScheduler *)_createScheduler CoreFeatures::enableClonelessStateProgression = true; } + if (reactNativeConfig && reactNativeConfig->getBool("react_fabric:position_relative_default")) { + CoreFeatures::positionRelativeDefault = true; + } + auto componentRegistryFactory = [factory = wrapManagedObject(_mountingManager.componentViewRegistry.componentViewFactory)]( const EventDispatcher::Weak &eventDispatcher, const ContextContainer::Shared &contextContainer) { diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/config/ReactFeatureFlags.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/config/ReactFeatureFlags.java index ee1b3c44354cb2..ea1b2ba963749b 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/config/ReactFeatureFlags.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/config/ReactFeatureFlags.java @@ -182,4 +182,7 @@ public class ReactFeatureFlags { * when there is work to do. */ public static boolean enableOnDemandReactChoreographer = false; + + /** When enabled, the default value of the position style property is relative. */ + public static boolean positionRelativeDefault = false; } diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/fabric/Binding.cpp b/packages/react-native/ReactAndroid/src/main/jni/react/fabric/Binding.cpp index 0f89b1ee8fe29b..1024afce2b7c9a 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/fabric/Binding.cpp +++ b/packages/react-native/ReactAndroid/src/main/jni/react/fabric/Binding.cpp @@ -424,6 +424,8 @@ void Binding::installFabricUIManager( getFeatureFlagValue("enableClonelessStateProgression"); CoreFeatures::excludeYogaFromRawProps = getFeatureFlagValue("excludeYogaFromRawProps"); + CoreFeatures::positionRelativeDefault = + getFeatureFlagValue("positionRelativeDefault"); // RemoveDelete mega-op ShadowViewMutation::PlatformSupportsRemoveDeleteTreeInstruction = diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/YogaStylableProps.cpp b/packages/react-native/ReactCommon/react/renderer/components/view/YogaStylableProps.cpp index 7c888d1e3d9959..996b976bae4294 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/YogaStylableProps.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/view/YogaStylableProps.cpp @@ -38,7 +38,9 @@ YogaStylableProps::YogaStylableProps( /*static*/ const yoga::Style& YogaStylableProps::defaultStyle() { static const auto defaultStyle = []() { yoga::Style style; - style.setPositionType(yoga::PositionType::Static); + style.setPositionType( + CoreFeatures::positionRelativeDefault ? yoga::PositionType::Relative + : yoga::PositionType::Static); return style; }(); diff --git a/packages/react-native/ReactCommon/react/utils/CoreFeatures.cpp b/packages/react-native/ReactCommon/react/utils/CoreFeatures.cpp index c967febaac7a21..2cd2e161c530c7 100644 --- a/packages/react-native/ReactCommon/react/utils/CoreFeatures.cpp +++ b/packages/react-native/ReactCommon/react/utils/CoreFeatures.cpp @@ -23,5 +23,6 @@ bool CoreFeatures::enableClonelessStateProgression = false; bool CoreFeatures::excludeYogaFromRawProps = false; bool CoreFeatures::enableMicrotasks = false; bool CoreFeatures::enableReportEventPaintTime = false; +bool CoreFeatures::positionRelativeDefault = false; } // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/utils/CoreFeatures.h b/packages/react-native/ReactCommon/react/utils/CoreFeatures.h index 3ad24c5e02e4d8..ffc81e01e7247b 100644 --- a/packages/react-native/ReactCommon/react/utils/CoreFeatures.h +++ b/packages/react-native/ReactCommon/react/utils/CoreFeatures.h @@ -67,6 +67,9 @@ class CoreFeatures { // Report paint time inside the Event Timing API implementation // (PerformanceObserver). static bool enableReportEventPaintTime; + + // Sets the default position of nodes to be relative instead of static + static bool positionRelativeDefault; }; } // namespace facebook::react From 31d8a93bf3199432bcd2b577738fbf49e84c207d Mon Sep 17 00:00:00 2001 From: Krzysztof Piaskowy Date: Thu, 30 Nov 2023 04:32:16 -0800 Subject: [PATCH 144/162] Fix Binding JNI type (#41657) Summary: New implementation: This PR adds cast from interface Binding to BindingImpl class. Previous implementation: The changes made in this PR make the `mBinding` field of `FabricUIManager` visible for JNI. Without these changes, calling the method `JFabricUIManager::getBinding()` would result in an error. Screenshot 2023-11-27 at 13 55 44 In the `react-native-reanimated` library, we utilize `JFabricUIManager::getBinding()`, and we have noticed this issue since version 0.73. This isn't perfect solution, but I'm not certain which change in RN or FBJNI is the source of the problem. If there are any alternative solutions worth considering, I am open to discussing them. Usage of `getBinding()` in Reanimated: https://github.com/software-mansion/react-native-reanimated/blob/main/android/src/main/cpp/NativeProxy.cpp#L57 ## Changelog: [ANDROID] [FIXED] - Fix type for unrecognisable field mBinding Pull Request resolved: https://github.com/facebook/react-native/pull/41657 Test Plan: Just call `JFabricUIManager::getBinding` method (https://github.com/facebook/react-native/blob/v0.73.0-rc.5/packages/react-native/ReactAndroid/src/main/jni/react/fabric/JFabricUIManager.cpp#L14) or run app with repro: https://github.com/piaskowyk/missing-mBinding-repro after the app lunch you will receive error from above screenshot. Co-author: tomekzaw Reviewed By: NickGerleman Differential Revision: D51661873 Pulled By: javache fbshipit-source-id: 1891c36bf25c503ebc9b0501211df03be6f74115 --- .../ReactAndroid/src/main/jni/react/fabric/Binding.h | 6 +++++- .../src/main/jni/react/fabric/JFabricUIManager.cpp | 5 +++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/fabric/Binding.h b/packages/react-native/ReactAndroid/src/main/jni/react/fabric/Binding.h index d447a501ef0394..b310f3bd2962be 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/fabric/Binding.h +++ b/packages/react-native/ReactAndroid/src/main/jni/react/fabric/Binding.h @@ -34,7 +34,11 @@ class ReactNativeConfig; class Scheduler; class SurfaceHandlerBinding; -class Binding : public jni::HybridClass, +struct JBinding : public jni::JavaClass { + constexpr static auto kJavaDescriptor = "Lcom/facebook/react/fabric/Binding;"; +}; + +class Binding : public jni::HybridClass, public SchedulerDelegate, public LayoutAnimationStatusDelegate { public: diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/fabric/JFabricUIManager.cpp b/packages/react-native/ReactAndroid/src/main/jni/react/fabric/JFabricUIManager.cpp index a2ccdbf5d57078..48326b97c260b3 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/fabric/JFabricUIManager.cpp +++ b/packages/react-native/ReactAndroid/src/main/jni/react/fabric/JFabricUIManager.cpp @@ -13,8 +13,9 @@ namespace facebook::react { Binding* JFabricUIManager::getBinding() { static const auto bindingField = - javaClassStatic()->getField("mBinding"); + javaClassStatic()->getField("mBinding"); - return getFieldValue(bindingField)->cthis(); + return jni::static_ref_cast(getFieldValue(bindingField)) + ->cthis(); } } // namespace facebook::react From 424ac63861a0e183a645fca4ce6e6292961f5108 Mon Sep 17 00:00:00 2001 From: Pieter De Baets Date: Thu, 30 Nov 2023 04:38:19 -0800 Subject: [PATCH 145/162] Clarify threading of OnViewAttach mount items (#41704) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41704 `mOnViewAttachItems` was set to be be concurrent, but this would be unexpected, as all mount item operations occur solely on the main thread. Simplify this to be just a LinkedList and annotate the methods as being UI thread only. Changelog: [Internal] Reviewed By: NickGerleman Differential Revision: D51662154 fbshipit-source-id: 9fe5784bce8a38d1339b5e3675791414676b6f4d --- .../fabric/mounting/MountItemDispatcher.java | 2 +- .../mounting/SurfaceMountingManager.java | 19 ++++++++++--------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/MountItemDispatcher.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/MountItemDispatcher.java index 7a083c9870b322..3261a598b041f3 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/MountItemDispatcher.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/MountItemDispatcher.java @@ -362,7 +362,7 @@ private void executeOrEnqueue(MountItem item) { } SurfaceMountingManager surfaceMountingManager = mMountingManager.getSurfaceManager(item.getSurfaceId()); - surfaceMountingManager.executeOnViewAttach(item); + surfaceMountingManager.scheduleMountItemOnViewAttach(item); } else { item.execute(mMountingManager); } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/SurfaceMountingManager.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/SurfaceMountingManager.java index 87b15e454f3127..90267da55b369a 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/SurfaceMountingManager.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/SurfaceMountingManager.java @@ -52,6 +52,7 @@ import com.facebook.react.uimanager.events.EventCategoryDef; import com.facebook.react.views.view.ReactMapBufferViewManager; import com.facebook.react.views.view.ReactViewManagerWrapper; +import java.util.ArrayDeque; import java.util.HashSet; import java.util.LinkedList; import java.util.Map; @@ -59,7 +60,6 @@ import java.util.Set; import java.util.Stack; import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentLinkedQueue; public class SurfaceMountingManager { public static final String TAG = SurfaceMountingManager.class.getSimpleName(); @@ -74,7 +74,7 @@ public class SurfaceMountingManager { // These are all non-null, until StopSurface is called private ConcurrentHashMap mTagToViewState = new ConcurrentHashMap<>(); // any thread - private ConcurrentLinkedQueue mOnViewAttachItems = new ConcurrentLinkedQueue<>(); + private Queue mOnViewAttachMountItems = new ArrayDeque<>(); private JSResponderHandler mJSResponderHandler; private ViewManagerRegistry mViewManagerRegistry; private RootViewManager mRootViewManager; @@ -181,9 +181,10 @@ public boolean getViewExists(int tag) { return mTagToViewState.containsKey(tag); } - @AnyThread - public void executeOnViewAttach(MountItem item) { - mOnViewAttachItems.add(item); + @UiThread + @ThreadConfined(UI) + public void scheduleMountItemOnViewAttach(MountItem item) { + mOnViewAttachMountItems.add(item); } @AnyThread @@ -233,7 +234,7 @@ private void addRootView(@NonNull final View rootView) { } mRootViewAttached = true; - executeViewAttachMountItems(); + executeMountItemsOnViewAttach(); }; if (UiThreadUtil.isOnUiThread()) { @@ -245,8 +246,8 @@ private void addRootView(@NonNull final View rootView) { @UiThread @ThreadConfined(UI) - private void executeViewAttachMountItems() { - mMountItemExecutor.executeItems(mOnViewAttachItems); + private void executeMountItemsOnViewAttach() { + mMountItemExecutor.executeItems(mOnViewAttachMountItems); } /** @@ -319,7 +320,7 @@ public void stopSurface() { mRootViewManager = null; mMountItemExecutor = null; mThemedReactContext = null; - mOnViewAttachItems.clear(); + mOnViewAttachMountItems.clear(); if (ReactFeatureFlags.enableViewRecycling) { mViewManagerRegistry.onSurfaceStopped(mSurfaceId); From b41937e549a633e5b321fdb537f0777420d2e047 Mon Sep 17 00:00:00 2001 From: Pieter De Baets Date: Thu, 30 Nov 2023 07:29:31 -0800 Subject: [PATCH 146/162] Fix ReactInstanceManager leak (#41719) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41719 We leak ReactInstanceManager into a static singleton in `ReactCxxErrorHandler.setHandleErrorFunc`. Clean it up in `destroy()`. Changelog: [Internal] Reviewed By: cortinico Differential Revision: D51706624 fbshipit-source-id: 642825ba14ff0a9710b4435f5fb6026b3a81b711 --- .../com/facebook/react/ReactInstanceManager.java | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java index a1801d5627c933..4bf3fbbfca982e 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java @@ -387,7 +387,7 @@ public void handleCxxError(Exception e) { mDevSupportManager.handleException(e); } - public void registerCxxErrorHandlerFunc() { + private void registerCxxErrorHandlerFunc() { Class[] parameterTypes = new Class[1]; parameterTypes[0] = Exception.class; Method handleCxxErrorFunc = null; @@ -399,6 +399,10 @@ public void registerCxxErrorHandlerFunc() { ReactCxxErrorHandler.setHandleErrorFunc(this, handleCxxErrorFunc); } + private void unregisterCxxErrorHandlerFunc() { + ReactCxxErrorHandler.setHandleErrorFunc(null, null); + } + static void initializeSoLoaderIfNecessary(Context applicationContext) { // Call SoLoader.initialize here, this is required for apps that does not use exopackage and // does not use SoLoader for loading other native code except from the one used by React Native @@ -747,23 +751,22 @@ public void destroy() { } moveToBeforeCreateLifecycleState(); - - if (mCreateReactContextThread != null) { - mCreateReactContextThread = null; - } - mMemoryPressureRouter.destroy(mApplicationContext); + unregisterCxxErrorHandlerFunc(); + mCreateReactContextThread = null; synchronized (mReactContextLock) { if (mCurrentReactContext != null) { mCurrentReactContext.destroy(); mCurrentReactContext = null; } } + mHasStartedCreatingInitialContext = false; mCurrentActivity = null; ResourceDrawableIdHelper.getInstance().clear(); + mHasStartedDestroying = false; synchronized (mHasStartedDestroying) { mHasStartedDestroying.notifyAll(); From cfe129c8329ef62c7fcd3ed25c17656b0e218d95 Mon Sep 17 00:00:00 2001 From: Neil Dhar Date: Thu, 30 Nov 2023 08:58:02 -0800 Subject: [PATCH 147/162] Add JSI method for setting external memory size (#41436) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41436 Add a JSI API for associating some native memory with a JS object. This is intended to provide a mechanism to trigger more frequent garbage collection when JS retains large external memory allocations, in order to avoid memory buildup. This diff just adds the JSI method, without any implementations. Changelog: [General][Added] - Added JSI method for reporting native memory to the GC. Reviewed By: tmikov Differential Revision: D50524912 fbshipit-source-id: c8df0e18b0415d9523e0a00f6d0ed2faa648ac68 --- .../react-native/ReactCommon/jsc/JSCRuntime.cpp | 3 +++ .../react-native/ReactCommon/jsi/jsi/decorator.h | 4 ++++ .../react-native/ReactCommon/jsi/jsi/jsi-inl.h | 5 +++++ packages/react-native/ReactCommon/jsi/jsi/jsi.h | 15 +++++++++++++++ 4 files changed, 27 insertions(+) diff --git a/packages/react-native/ReactCommon/jsc/JSCRuntime.cpp b/packages/react-native/ReactCommon/jsc/JSCRuntime.cpp index 40633656596873..c42d4f3008e4a6 100644 --- a/packages/react-native/ReactCommon/jsc/JSCRuntime.cpp +++ b/packages/react-native/ReactCommon/jsc/JSCRuntime.cpp @@ -233,6 +233,7 @@ class JSCRuntime : public jsi::Runtime { bool strictEquals(const jsi::String& a, const jsi::String& b) const override; bool strictEquals(const jsi::Object& a, const jsi::Object& b) const override; bool instanceOf(const jsi::Object& o, const jsi::Function& f) override; + void setExternalMemoryPressure(const jsi::Object&, size_t) override; private: // Basically convenience casts @@ -1392,6 +1393,8 @@ bool JSCRuntime::instanceOf(const jsi::Object& o, const jsi::Function& f) { return res; } +void JSCRuntime::setExternalMemoryPressure(const jsi::Object&, size_t) {} + jsi::Runtime::PointerValue* JSCRuntime::makeSymbolValue( JSValueRef symbolRef) const { #ifndef NDEBUG diff --git a/packages/react-native/ReactCommon/jsi/jsi/decorator.h b/packages/react-native/ReactCommon/jsi/jsi/decorator.h index baece80fe71d0f..7bddd1fad80a52 100644 --- a/packages/react-native/ReactCommon/jsi/jsi/decorator.h +++ b/packages/react-native/ReactCommon/jsi/jsi/decorator.h @@ -252,6 +252,10 @@ class RuntimeDecorator : public Base, private jsi::Instrumentation { plain_.setNativeState(o, state); } + void setExternalMemoryPressure(const Object& obj, size_t amt) override { + plain_.setExternalMemoryPressure(obj, amt); + } + Value getProperty(const Object& o, const PropNameID& name) override { return plain_.getProperty(o, name); }; diff --git a/packages/react-native/ReactCommon/jsi/jsi/jsi-inl.h b/packages/react-native/ReactCommon/jsi/jsi/jsi-inl.h index 4ce00adb883c59..f3955815e41f06 100644 --- a/packages/react-native/ReactCommon/jsi/jsi/jsi-inl.h +++ b/packages/react-native/ReactCommon/jsi/jsi/jsi-inl.h @@ -227,6 +227,11 @@ inline void Object::setNativeState( runtime.setNativeState(*this, state); } +inline void Object::setExternalMemoryPressure(Runtime& runtime, size_t amt) + const { + runtime.setExternalMemoryPressure(*this, amt); +} + inline Array Object::getPropertyNames(Runtime& runtime) const { return runtime.getPropertyNames(*this); } diff --git a/packages/react-native/ReactCommon/jsi/jsi/jsi.h b/packages/react-native/ReactCommon/jsi/jsi/jsi.h index e5112b753b69d1..962dae93609423 100644 --- a/packages/react-native/ReactCommon/jsi/jsi/jsi.h +++ b/packages/react-native/ReactCommon/jsi/jsi/jsi.h @@ -387,6 +387,11 @@ class JSI_EXPORT Runtime { virtual bool instanceOf(const Object& o, const Function& f) = 0; + /// See Object::setExternalMemoryPressure. + virtual void setExternalMemoryPressure( + const jsi::Object& obj, + size_t amount) = 0; + // These exist so derived classes can access the private parts of // Value, Symbol, String, and Object, which are all friends of Runtime. template @@ -834,6 +839,16 @@ class JSI_EXPORT Object : public Pointer { /// works. I only need it in one place.) Array getPropertyNames(Runtime& runtime) const; + /// Inform the runtime that there is additional memory associated with a given + /// JavaScript object that is not visible to the GC. This can be used if an + /// object is known to retain some native memory, and may be used to guide + /// decisions about when to run garbage collection. + /// This method may be invoked multiple times on an object, and subsequent + /// calls will overwrite any previously set value. Once the object is garbage + /// collected, the associated external memory will be considered freed and may + /// no longer factor into GC decisions. + void setExternalMemoryPressure(Runtime& runtime, size_t amt) const; + protected: void setPropertyValue( Runtime& runtime, From c98fa9ce8bc6f2345103eb6036c2452c7e9f9a07 Mon Sep 17 00:00:00 2001 From: "Alex Taylor (alta)" Date: Thu, 30 Nov 2023 10:35:12 -0800 Subject: [PATCH 148/162] Update hermes-parser and related packages in fbsource to 0.18.0 (#41689) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41689 Bump hermes-parser and related packages to 0.18.0. Changelog: [internal] Reviewed By: SamChou19815 Differential Revision: D51642821 fbshipit-source-id: b7abde7d3e0de195c18a5cb18d4cdd0a1d435127 --- package.json | 6 +- .../package.json | 2 +- packages/react-native-codegen/package.json | 4 +- yarn.lock | 74 +++++++++---------- 4 files changed, 43 insertions(+), 43 deletions(-) diff --git a/package.json b/package.json index d5b2ea0e01b9fc..dfbb772ed508ab 100644 --- a/package.json +++ b/package.json @@ -83,10 +83,10 @@ "eslint-plugin-react-native": "^4.0.0", "eslint-plugin-redundant-undefined": "^0.4.0", "eslint-plugin-relay": "^1.8.3", - "flow-api-translator": "0.17.1", + "flow-api-translator": "0.18.0", "flow-bin": "^0.222.0", "glob": "^7.1.1", - "hermes-eslint": "0.17.1", + "hermes-eslint": "0.18.0", "inquirer": "^7.1.0", "jest": "^29.6.3", "jest-junit": "^10.0.0", @@ -98,7 +98,7 @@ "mock-fs": "^5.1.4", "nullthrows": "^1.1.1", "prettier": "2.8.8", - "prettier-plugin-hermes-parser": "0.17.1", + "prettier-plugin-hermes-parser": "0.18.0", "react": "18.2.0", "react-test-renderer": "18.2.0", "rimraf": "^3.0.2", diff --git a/packages/react-native-babel-transformer/package.json b/packages/react-native-babel-transformer/package.json index 677d5c654d4c03..a835dc80a1bdef 100644 --- a/packages/react-native-babel-transformer/package.json +++ b/packages/react-native-babel-transformer/package.json @@ -17,7 +17,7 @@ "dependencies": { "@babel/core": "^7.20.0", "@react-native/babel-preset": "*", - "hermes-parser": "0.17.1", + "hermes-parser": "0.18.0", "nullthrows": "^1.1.1" }, "peerDependencies": { diff --git a/packages/react-native-codegen/package.json b/packages/react-native-codegen/package.json index 19e6afe09e9886..bc53457e773391 100644 --- a/packages/react-native-codegen/package.json +++ b/packages/react-native-codegen/package.json @@ -31,7 +31,7 @@ "dependencies": { "@babel/parser": "^7.20.0", "glob": "^7.1.1", - "hermes-parser": "0.17.1", + "hermes-parser": "0.18.0", "invariant": "^2.2.4", "jscodeshift": "^0.14.0", "mkdirp": "^0.5.1", @@ -49,7 +49,7 @@ "@babel/plugin-transform-flow-strip-types": "^7.20.0", "@babel/preset-env": "^7.20.0", "chalk": "^4.0.0", - "hermes-estree": "0.17.1", + "hermes-estree": "0.18.0", "micromatch": "^4.0.4", "prettier": "2.8.8", "rimraf": "^3.0.2" diff --git a/yarn.lock b/yarn.lock index 14c94894550844..6c6bb246f6d8be 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5143,18 +5143,18 @@ flatted@^3.1.0: resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.2.tgz#64bfed5cb68fe3ca78b3eb214ad97b63bedce561" integrity sha512-JaTY/wtrcSyvXJl4IMFHPKyFur1sE9AUqc0QnhOaJ0CxHtAoIV8pYDzeEfAaNEtGkOfq4gr3LBFmdXW5mOQFnA== -flow-api-translator@0.17.1: - version "0.17.1" - resolved "https://registry.yarnpkg.com/flow-api-translator/-/flow-api-translator-0.17.1.tgz#fee650b8c975338aea46be9e40464bcab81fbedf" - integrity sha512-TzOWylttBRQ8zco5Nmu7+11c45WpLgO1BPXe9R0nCoUo6x2IU4baC1AjnQEistsrMkG+Imlp2q3TFk6pRcJp0w== +flow-api-translator@0.18.0: + version "0.18.0" + resolved "https://registry.yarnpkg.com/flow-api-translator/-/flow-api-translator-0.18.0.tgz#c8fe149c3211638bba565d4ebbde10f05424acc2" + integrity sha512-X6LMMTGsYtJWJmaye0W10UOFQoxVQxm5nJkUDcX6nT3O0KpsV/5SNo7uf4KWzNGnb4u60p1IKx7ghBRJbUqV1w== dependencies: "@babel/code-frame" "^7.16.0" "@typescript-eslint/visitor-keys" "^5.42.0" flow-enums-runtime "^0.0.6" - hermes-eslint "0.17.1" - hermes-estree "0.17.1" - hermes-parser "0.17.1" - hermes-transform "0.17.1" + hermes-eslint "0.18.0" + hermes-estree "0.18.0" + hermes-parser "0.18.0" + hermes-transform "0.18.0" flow-bin@^0.222.0: version "0.222.0" @@ -5543,24 +5543,24 @@ has@^1.0.3: dependencies: function-bind "^1.1.1" -hermes-eslint@0.17.1: - version "0.17.1" - resolved "https://registry.yarnpkg.com/hermes-eslint/-/hermes-eslint-0.17.1.tgz#e5e43091082dc53a060e0b002324e68943104b71" - integrity sha512-g3z4L84pHKrBMRtbfifalpbNbNear0cEygAe+geCmCj1GUrqQu+RDeBZOYERHv0HOq0aDxjTZhj3m4fD/YVUwg== +hermes-eslint@0.18.0: + version "0.18.0" + resolved "https://registry.yarnpkg.com/hermes-eslint/-/hermes-eslint-0.18.0.tgz#16e7d5c7742f709d814d6a5a5d955803e81b328d" + integrity sha512-NIh8Utqk32+voL1b4ngCRnMQ0XCRzFbon7IG25lhnSYCTezX5besIK+79pUHw1YEDZVGrVrMxeIYxXiamLzcUQ== dependencies: esrecurse "^4.3.0" - hermes-estree "0.17.1" - hermes-parser "0.17.1" + hermes-estree "0.18.0" + hermes-parser "0.18.0" hermes-estree@0.17.0: version "0.17.0" resolved "https://registry.yarnpkg.com/hermes-estree/-/hermes-estree-0.17.0.tgz#4b1b0d8131826178f0af79a317ceaca3723e9012" integrity sha512-bW9+bMZqnro+0+l6dUqTJW0VaNUvs4HRHh/J7VotTGnMmhBFRIcJz6ZxrRE7xIXmK7S5bJE9qrEooSiig4N70g== -hermes-estree@0.17.1: - version "0.17.1" - resolved "https://registry.yarnpkg.com/hermes-estree/-/hermes-estree-0.17.1.tgz#902806a900c185720424ffcf958027821d23c051" - integrity sha512-EdUJms+eRE40OQxysFlPr1mPpvUbbMi7uDAKlScBw8o3tQY22BZ5yx56OYyp1bVaBm+7Cjc3NQz24sJEFXkPxg== +hermes-estree@0.18.0: + version "0.18.0" + resolved "https://registry.yarnpkg.com/hermes-estree/-/hermes-estree-0.18.0.tgz#6c202d8c78ddefadf3eb595a584dfa55b51a0508" + integrity sha512-WaIudIVKo5QWFqz1ta53HqSDuVxYST/MUuP9X7dqUpbHse3E2gzJq/7hEtgx84hh2XSNWN1AhYho3ThOA85uCA== hermes-parser@0.17.0: version "0.17.0" @@ -5569,12 +5569,12 @@ hermes-parser@0.17.0: dependencies: hermes-estree "0.17.0" -hermes-parser@0.17.1: - version "0.17.1" - resolved "https://registry.yarnpkg.com/hermes-parser/-/hermes-parser-0.17.1.tgz#8b5cbaff235fed28487812ad718f9c7182d0db0f" - integrity sha512-yErtFLMEL6490fFJPurNn23OI2ciGAtaUfKUg9VPdcde9CmItCjOVQkJt1Xzawv5kuRzeIx0RE2E2Q9TbIgdzA== +hermes-parser@0.18.0: + version "0.18.0" + resolved "https://registry.yarnpkg.com/hermes-parser/-/hermes-parser-0.18.0.tgz#dd9878f70e9ca2570e7626181ae0465115f7f78d" + integrity sha512-DIIM6vsy30BU5hNkOXh6MR2r4ZAxVhbfyTnmfo/rqUf3KySlNWn9fWiOcpuGAdDN2o5sdPCpu6cep3a23d1Klw== dependencies: - hermes-estree "0.17.1" + hermes-estree "0.18.0" hermes-profile-transformer@^0.0.6: version "0.0.6" @@ -5583,17 +5583,17 @@ hermes-profile-transformer@^0.0.6: dependencies: source-map "^0.7.3" -hermes-transform@0.17.1: - version "0.17.1" - resolved "https://registry.yarnpkg.com/hermes-transform/-/hermes-transform-0.17.1.tgz#8dc60f4744137b936c15aac9231a951268450600" - integrity sha512-0QlknKahueDHeswUjruzyvdfqtaw4OC4JuWYNWqAr8HP+1YGx3J2lwsGuQeaJhkC04eh9lhO9cc5/xfJLBr74A== +hermes-transform@0.18.0: + version "0.18.0" + resolved "https://registry.yarnpkg.com/hermes-transform/-/hermes-transform-0.18.0.tgz#e5718960ddf5c2c938397523085c0ac58159cc20" + integrity sha512-jbzeRDseWlUNhErS0ovt6/IpNcSEtYEytg6LTFox+4qDbrX5Tg6AO5xdNwMLgxPxD/03xAicBZL44/yI+4YXgA== dependencies: "@babel/code-frame" "^7.16.0" esquery "^1.4.0" flow-enums-runtime "^0.0.6" - hermes-eslint "0.17.1" - hermes-estree "0.17.1" - hermes-parser "0.17.1" + hermes-eslint "0.18.0" + hermes-estree "0.18.0" + hermes-parser "0.18.0" homedir-polyfill@^1.0.0, homedir-polyfill@^1.0.1: version "1.0.3" @@ -7877,14 +7877,14 @@ prettier-linter-helpers@^1.0.0: dependencies: fast-diff "^1.1.2" -prettier-plugin-hermes-parser@0.17.1: - version "0.17.1" - resolved "https://registry.yarnpkg.com/prettier-plugin-hermes-parser/-/prettier-plugin-hermes-parser-0.17.1.tgz#f7c461fe875f7a365442fc69a51434b7e3ff88e4" - integrity sha512-ULX366DyQrrFW//a6Zgj0r/CF4a4Ijg+TCaplOtYCPCu4qThUp9XrMRSYWeB0lacD1lmWFqRDFL5R8Oxmhpw3A== +prettier-plugin-hermes-parser@0.18.0: + version "0.18.0" + resolved "https://registry.yarnpkg.com/prettier-plugin-hermes-parser/-/prettier-plugin-hermes-parser-0.18.0.tgz#00b6d979f8068c4fab72500c1abb5a8dcc107645" + integrity sha512-gU/K9jjJYDzdn1PLJdjhaHk+27POGrSbxVxBUOVm9qOiIpnwW1IeYA3sHg2PpCJLUQyJM7R6jiesQgPgvUHkmA== dependencies: - hermes-estree "0.17.1" - hermes-parser "0.17.1" - prettier-plugin-hermes-parser "0.17.1" + hermes-estree "0.18.0" + hermes-parser "0.18.0" + prettier-plugin-hermes-parser "0.18.0" prettier@2.8.8: version "2.8.8" From ede35df1639b4eec45cc87f10de5ce467bec7084 Mon Sep 17 00:00:00 2001 From: Pieter Vanderwerff Date: Thu, 30 Nov 2023 11:25:47 -0800 Subject: [PATCH 149/162] Deploy 0.223.0 to fbsource (#41725) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41725 Reviewed By: SamChou19815 Differential Revision: D51713020 fbshipit-source-id: 84dc8c882f7603d642cb4ccb735fad0fb7e25d4d --- .flowconfig | 2 +- package.json | 2 +- yarn.lock | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.flowconfig b/.flowconfig index b50e7305d63be3..e50161b27b6e65 100644 --- a/.flowconfig +++ b/.flowconfig @@ -82,4 +82,4 @@ untyped-import untyped-type-import [version] -^0.222.0 +^0.223.0 diff --git a/package.json b/package.json index dfbb772ed508ab..f7fe82fd37d5ef 100644 --- a/package.json +++ b/package.json @@ -84,7 +84,7 @@ "eslint-plugin-redundant-undefined": "^0.4.0", "eslint-plugin-relay": "^1.8.3", "flow-api-translator": "0.18.0", - "flow-bin": "^0.222.0", + "flow-bin": "^0.223.0", "glob": "^7.1.1", "hermes-eslint": "0.18.0", "inquirer": "^7.1.0", diff --git a/yarn.lock b/yarn.lock index 6c6bb246f6d8be..d90db7f0cd2126 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5156,10 +5156,10 @@ flow-api-translator@0.18.0: hermes-parser "0.18.0" hermes-transform "0.18.0" -flow-bin@^0.222.0: - version "0.222.0" - resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.222.0.tgz#b4ca588c77fbd79db1edf38615cd04d114c1e933" - integrity sha512-U2047+pOX1EutHGykcjtamAlP8UIHrxbkexB5zPVQ8PH+WcVmD4PtRE6J8Jc3S6odyo0AqVnQsI4rE/2x2fGmQ== +flow-bin@^0.223.0: + version "0.223.0" + resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.223.0.tgz#38fb6efd6c202b774d01834ded0620eb8eebad89" + integrity sha512-E+GmTcBTPIRfnX/Dk19zJewX9grxoVQU+RG3Ypd/Os0OkUSOF7K3Sxo2I+8Oz1EpnPMGhnbM4WRAUuY0JaHRsw== flow-enums-runtime@^0.0.6: version "0.0.6" From 7e5f15b889a1571be655d1fbaa503319bfc1f305 Mon Sep 17 00:00:00 2001 From: Nick Gerleman Date: Thu, 30 Nov 2023 12:10:50 -0800 Subject: [PATCH 150/162] Remove unneeded const_cast (#41712) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41712 I fixed the const correctness of YGConfigGetErrata a while back when fixing up other YGConfig accessors. Changelog: [Internal] Reviewed By: christophpurrer Differential Revision: D51689323 fbshipit-source-id: 1af3deb44ec03a8a65643fa1496c534ac8f6d057 --- .../renderer/components/view/YogaLayoutableShadowNode.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/YogaLayoutableShadowNode.cpp b/packages/react-native/ReactCommon/react/renderer/components/view/YogaLayoutableShadowNode.cpp index 96e3cb75a7e7af..d828c84b08cd49 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/YogaLayoutableShadowNode.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/view/YogaLayoutableShadowNode.cpp @@ -470,8 +470,7 @@ void YogaLayoutableShadowNode::configureYogaTree( for (size_t i = 0; i < yogaLayoutableChildren_.size(); i++) { const auto& child = *yogaLayoutableChildren_[i]; auto childLayoutMetrics = child.getLayoutMetrics(); - auto childErrata = - YGConfigGetErrata(const_cast(&child.yogaConfig_)); + auto childErrata = YGConfigGetErrata(&child.yogaConfig_); if (child.yogaTreeHasBeenConfigured_ && childLayoutMetrics.pointScaleFactor == pointScaleFactor && From 89ec746b52f88814be0b1c3d5bd2aa59db1c5989 Mon Sep 17 00:00:00 2001 From: Joe Vilches Date: Thu, 30 Nov 2023 18:28:24 -0800 Subject: [PATCH 151/162] Change comment on Yoga measure modes in RN (#41732) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41732 Was reading the code in this file and noticed that this comment is no longer true after D51068417 (https://github.com/facebook/yoga/pull/1460). Updated the comment to reflect the current state of things Changelog: [Internal] Reviewed By: NickGerleman Differential Revision: D51730986 fbshipit-source-id: beaa5de9576d86e56def35f6e970376c7be8f7ee --- .../components/view/YogaLayoutableShadowNode.cpp | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/YogaLayoutableShadowNode.cpp b/packages/react-native/ReactCommon/react/renderer/components/view/YogaLayoutableShadowNode.cpp index d828c84b08cd49..7757bd6695dbf6 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/YogaLayoutableShadowNode.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/view/YogaLayoutableShadowNode.cpp @@ -604,13 +604,11 @@ void YogaLayoutableShadowNode::layoutTree( react_native_assert(!std::isinf(minimumSize.width)); react_native_assert(!std::isinf(minimumSize.height)); - // Internally Yoga uses three different measurement modes controlling layout - // constraints: `Undefined`, `Exactly`, and `AtMost`. These modes are an - // implementation detail and are not defined in `CSS Flexible Box Layout - // Module`. Yoga C++ API (and `YGNodeCalculateLayout` function particularly) - // does not allow to specify the measure modes explicitly. Instead, it infers - // these from styles associated with the root node. - // To pass the actual layout constraints to Yoga we represent them as + // Yoga C++ API (and `YGNodeCalculateLayout` function particularly) + // does not allow to specify sizing modes (see + // https://www.w3.org/TR/css-sizing-3/#auto-box-sizes) explicitly. Instead, it + // infers these from styles associated with the root node. To pass the actual + // layout constraints to Yoga we represent them as // `(min/max)(Height/Width)` style properties. Also, we pass `ownerWidth` & // `ownerHeight` to allow proper calculation of relative (e.g. specified in // percents) style values. From cd9b1d9e4338ab353095c629fa632247505d1d6e Mon Sep 17 00:00:00 2001 From: Sam Zhou Date: Thu, 30 Nov 2023 19:40:12 -0800 Subject: [PATCH 152/162] Replace $Call in babel-traverse libdef with conditional type (#41736) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41736 Changelog: [Internal] Reviewed By: gkz Differential Revision: D51735062 fbshipit-source-id: 942264cdc9f71e4aaa6f730d68f5a2a6e2fc7493 --- flow-typed/npm/babel-traverse_v7.x.x.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/flow-typed/npm/babel-traverse_v7.x.x.js b/flow-typed/npm/babel-traverse_v7.x.x.js index 2e3520dd23b98a..b35fd7863068c5 100644 --- a/flow-typed/npm/babel-traverse_v7.x.x.js +++ b/flow-typed/npm/babel-traverse_v7.x.x.js @@ -293,9 +293,6 @@ declare module '@babel/traverse' { dereference(): void; } - declare function getNodePathType(node: BabelNode): NodePath<>; - declare function getNodePathType(nodes: Array): Array>; - declare type Opts = {...}; declare export class NodePath<+TNode: BabelNode = BabelNode> { @@ -733,7 +730,7 @@ declare module '@babel/traverse' { get>( key: TKey, context?: boolean | TraversalContext, - ): $Call; + ): TNode[TKey] extends BabelNode ? NodePath<> : Array>; get( key: string, From f941f939bfea5a5619ecabe6a0d401037e8df6f1 Mon Sep 17 00:00:00 2001 From: Arushi Kesarwani Date: Thu, 30 Nov 2023 21:24:54 -0800 Subject: [PATCH 153/162] Adding getFabricUIManager() APIs to ReactContext (#41728) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41728 Adding APIs for `getFabricUIManager()` to ReactContext and it's subclasses. This will replace the `getJSIModule()` post JSI module deletion. Reviewed By: philIip Differential Revision: D51718430 fbshipit-source-id: c897ab0ee9e755e3fdb3d1e5629177818870f293 --- .../facebook/react/bridge/ReactContext.java | 20 +++++++++++++++++++ .../react/runtime/BridgelessReactContext.java | 6 ++++++ .../react/uimanager/ThemedReactContext.java | 9 +++++++++ 3 files changed, 35 insertions(+) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactContext.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactContext.java index b57513cb67216e..78c385ce157643 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactContext.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactContext.java @@ -26,6 +26,7 @@ import com.facebook.react.bridge.queue.ReactQueueConfiguration; import com.facebook.react.common.LifecycleState; import com.facebook.react.common.ReactConstants; +import com.facebook.react.common.annotations.DeprecatedInNewArchitecture; import java.lang.ref.WeakReference; import java.util.Collection; import java.util.concurrent.CopyOnWriteArraySet; @@ -554,6 +555,25 @@ public boolean isBridgeless() { return mCatalystInstance.getJSIModule(moduleType); } + @DeprecatedInNewArchitecture( + message = + "This method will be deprecated later as part of Stable APIs with bridge removal and not encouraged usage.") + /** + * Get the UIManager for Fabric from the CatalystInstance. + * + * @return The UIManager when CatalystInstance is active. + */ + public @Nullable UIManager getFabricUIManager() { + if (!hasActiveReactInstance()) { + throw new IllegalStateException( + "Unable to retrieve a UIManager if CatalystInstance is not active."); + } + UIManager uiManager = mCatalystInstance.getFabricUIManager(); + return uiManager != null + ? uiManager + : (UIManager) mCatalystInstance.getJSIModule(JSIModuleType.UIManager); + } + /** * Get the sourceURL for the JS bundle from the CatalystInstance. This method is needed for * compatibility with bridgeless mode, which has no CatalystInstance. diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/BridgelessReactContext.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/BridgelessReactContext.java index ad4b76d4b549dc..6e1994a3804d00 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/BridgelessReactContext.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/BridgelessReactContext.java @@ -21,6 +21,7 @@ import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactNoCrashBridgeNotAllowedSoftException; import com.facebook.react.bridge.ReactSoftExceptionLogger; +import com.facebook.react.bridge.UIManager; import com.facebook.react.bridge.WritableNativeArray; import com.facebook.react.config.ReactFeatureFlags; import com.facebook.react.devsupport.interfaces.DevSupportManager; @@ -84,6 +85,11 @@ public void setSourceURL(String sourceURL) { + moduleType.name()); } + @Override + public @Nullable UIManager getFabricUIManager() { + return mReactHost.getUIManager(); + } + @Override public CatalystInstance getCatalystInstance() { ReactSoftExceptionLogger.logSoftExceptionVerbose( diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ThemedReactContext.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ThemedReactContext.java index b10d2d9b3c0681..eded794637a424 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ThemedReactContext.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ThemedReactContext.java @@ -15,6 +15,7 @@ import com.facebook.react.bridge.LifecycleEventListener; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactContext; +import com.facebook.react.bridge.UIManager; /** * Wraps {@link ReactContext} with the base {@link Context} passed into the constructor. It provides @@ -116,4 +117,12 @@ public JSIModule getJSIModule(JSIModuleType moduleType) { } return super.getJSIModule(moduleType); } + + @Override + public UIManager getFabricUIManager() { + if (isBridgeless()) { + return mReactApplicationContext.getFabricUIManager(); + } + return super.getFabricUIManager(); + } } From 847f5dedccd89fdfe7aa9f264c8bc2c8cb4190a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oskar=20Kwa=C5=9Bniewski?= Date: Fri, 1 Dec 2023 04:35:19 -0800 Subject: [PATCH 154/162] Fix typo in circleci config (#41727) Summary: This PR fixes typo in CircleCI config ## Changelog: [INTERNAL] [FIXED] - Typo in circleci config Pull Request resolved: https://github.com/facebook/react-native/pull/41727 Test Plan: CI Green Reviewed By: cipolleschi Differential Revision: D51748329 Pulled By: cortinico fbshipit-source-id: 99f54c5b9ec4113205642076c010b748ab6229f6 --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 8430e0e37ec756..94fed2af278951 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -60,7 +60,7 @@ jobs: value: << pipeline.git.branch >> steps: - run: - name: "[Main or Stable] Create input fo config to test everything" + name: "[Main or Stable] Create input for config to test everything" command: | mkdir -p /tmp/circleci/ echo '{ "run_all": true }' > /tmp/circleci/pipeline_config.json From dbf0984682a32323ee511eaeeb28f8c1100e2a19 Mon Sep 17 00:00:00 2001 From: Pieter De Baets Date: Fri, 1 Dec 2023 06:52:48 -0800 Subject: [PATCH 155/162] Schedule CatalystInstanceImpl destruction using new thread (#41720) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41720 We currently go via the UI thread, so we can use AsyncTask to schedule the final bit of async ReactContext destruction. This is a requirement for the AsyncTask API, which is also deprecated. We should figure out a better way to schedule and re-use threads across React Native Android, but until then, we can just create a new Thread here, which is also what we do for instance creation. Changelog: [Internal] Reviewed By: NickGerleman Differential Revision: D51706689 fbshipit-source-id: cf17e20e91b195b956b1701e6d91d563fdba4d15 --- .../react/bridge/CatalystInstanceImpl.java | 41 ++++++++----------- 1 file changed, 17 insertions(+), 24 deletions(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/CatalystInstanceImpl.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/CatalystInstanceImpl.java index be3c61b6dc3622..621372533b22e6 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/CatalystInstanceImpl.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/CatalystInstanceImpl.java @@ -11,7 +11,6 @@ import static com.facebook.systrace.Systrace.TRACE_TAG_REACT_JAVA_BRIDGE; import android.content.res.AssetManager; -import android.os.AsyncTask; import androidx.annotation.Nullable; import com.facebook.common.logging.FLog; import com.facebook.infer.annotation.Assertions; @@ -374,30 +373,24 @@ public void destroy() { mTurboModuleRegistry.invalidate(); } - getReactQueueConfiguration() - .getUIQueueThread() - .runOnQueue( + // Kill non-UI threads from neutral third party + // potentially expensive, so don't run on UI thread + new Thread( () -> { - // AsyncTask.execute must be executed from the UI Thread - AsyncTask.execute( - () -> { - // Kill non-UI threads from neutral third party - // potentially expensive, so don't run on UI thread - - // contextHolder is used as a lock to guard against - // other users of the JS VM having the VM destroyed - // underneath them, so notify them before we reset - // Native - mJavaScriptContextHolder.clear(); - - mHybridData.resetNative(); - getReactQueueConfiguration().destroy(); - FLog.d( - ReactConstants.TAG, "CatalystInstanceImpl.destroy() end"); - ReactMarker.logMarker( - ReactMarkerConstants.DESTROY_CATALYST_INSTANCE_END); - }); - }); + // contextHolder is used as a lock to guard against + // other users of the JS VM having the VM destroyed + // underneath them, so notify them before we reset + // Native + mJavaScriptContextHolder.clear(); + + mHybridData.resetNative(); + getReactQueueConfiguration().destroy(); + FLog.w(ReactConstants.TAG, "CatalystInstanceImpl.destroy() end"); + ReactMarker.logMarker( + ReactMarkerConstants.DESTROY_CATALYST_INSTANCE_END); + }, + "destroy_react_context") + .start(); }); }); From 1a0e1741c0ab4f22b57a6a7ee86ff4287fa09103 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20=C5=BBelawski?= Date: Fri, 1 Dec 2023 07:03:26 -0800 Subject: [PATCH 156/162] Add `NDEBUG` flag for Release builds for both architectures (#41715) Summary: Currently React Native defines `NDEBUG` flag for all pods in Fabric only. This is useful for other libraries, like Reanimated, because they have no easy way of defining their compilation flags (at least none that I know of). Therefore defining `NDEBUG` for both architectures would be beneficial. ## Changelog: Pick one each for the category and type tags: [IOS] [CHANGED] - Add `NDEBUG` flag for Release builds for both architectures Pull Request resolved: https://github.com/facebook/react-native/pull/41715 Test Plan: Run ruby test suite. ## Notes For the time being I just copied `prepare_pod_target_installation_results_mock` and `def prepare_installer_for_cpp_flags` to `utils-test.rb` since I wasn't sure how to handle the installer mock. Reviewed By: cortinico Differential Revision: D51708382 Pulled By: cipolleschi fbshipit-source-id: ff206f8fc151934dbae89aacd1bc69c57b4f28ee --- .../__tests__/new_architecture-test.rb | 8 +- .../scripts/cocoapods/__tests__/utils-test.rb | 101 ++++++++++++++++++ .../scripts/cocoapods/new_architecture.rb | 24 +---- .../react-native/scripts/cocoapods/utils.rb | 42 ++++++++ .../react-native/scripts/react_native_pods.rb | 1 + 5 files changed, 152 insertions(+), 24 deletions(-) diff --git a/packages/react-native/scripts/cocoapods/__tests__/new_architecture-test.rb b/packages/react-native/scripts/cocoapods/__tests__/new_architecture-test.rb index fc698ae2166940..0b5f77d9ee4667 100644 --- a/packages/react-native/scripts/cocoapods/__tests__/new_architecture-test.rb +++ b/packages/react-native/scripts/cocoapods/__tests__/new_architecture-test.rb @@ -120,12 +120,12 @@ def test_modifyFlagsForNewArch_whenOnNewArchAndIsRelease_updateFlags assert_equal(second_xcconfig.save_as_invocation, ["a/path/Second.xcconfig"]) assert_equal(react_core_debug_config.build_settings["OTHER_CPLUSPLUSFLAGS"], "$(inherited) -DRCT_NEW_ARCH_ENABLED=1 -DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -DFOLLY_CFG_NO_COROUTINES=1 -DFOLLY_HAVE_CLOCK_GETTIME=1") assert_nil(react_core_debug_config.build_settings["OTHER_CFLAGS"]) - assert_equal(react_core_release_config.build_settings["OTHER_CPLUSPLUSFLAGS"], "$(inherited) -DRCT_NEW_ARCH_ENABLED=1 -DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -DFOLLY_CFG_NO_COROUTINES=1 -DFOLLY_HAVE_CLOCK_GETTIME=1 -DNDEBUG") - assert_equal(react_core_release_config.build_settings["OTHER_CFLAGS"], "$(inherited) -DNDEBUG") + assert_equal(react_core_release_config.build_settings["OTHER_CPLUSPLUSFLAGS"], "$(inherited) -DRCT_NEW_ARCH_ENABLED=1 -DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -DFOLLY_CFG_NO_COROUTINES=1 -DFOLLY_HAVE_CLOCK_GETTIME=1") + assert_nil(react_core_release_config.build_settings["OTHER_CFLAGS"]) assert_equal(yoga_debug_config.build_settings["OTHER_CPLUSPLUSFLAGS"], "$(inherited)") assert_nil(yoga_debug_config.build_settings["OTHER_CFLAGS"]) - assert_equal(yoga_release_config.build_settings["OTHER_CPLUSPLUSFLAGS"], "$(inherited) -DNDEBUG") - assert_equal(yoga_release_config.build_settings["OTHER_CFLAGS"], "$(inherited) -DNDEBUG") + assert_equal(yoga_release_config.build_settings["OTHER_CPLUSPLUSFLAGS"], "$(inherited)") + assert_nil(yoga_release_config.build_settings["OTHER_CFLAGS"]) end # =================================== # diff --git a/packages/react-native/scripts/cocoapods/__tests__/utils-test.rb b/packages/react-native/scripts/cocoapods/__tests__/utils-test.rb index cf9988492dafb7..cc6963c73a4fc0 100644 --- a/packages/react-native/scripts/cocoapods/__tests__/utils-test.rb +++ b/packages/react-native/scripts/cocoapods/__tests__/utils-test.rb @@ -16,6 +16,7 @@ require_relative "./test_utils/XcodeprojMock.rb" require_relative "./test_utils/XcodebuildMock.rb" require_relative "./test_utils/SpecMock.rb" +require_relative "./test_utils/InstallerMock.rb" class UtilsTests < Test::Unit::TestCase def setup @@ -1008,6 +1009,78 @@ def test_addDependencies_whenSubspecsAndHeaderSearchPathAndVersionWithAdditional assert_equal(spec.to_hash["pod_target_xcconfig"], { "HEADER_SEARCH_PATHS" => expected_search_paths}) end + + def test_add_flag_to_map_with_inheritance_whenUsedWithBuildConfigBuildSettings + # Arrange + empty_config = BuildConfigurationMock.new("EmptyConfig") + initialized_config = BuildConfigurationMock.new("InitializedConfig", { + "OTHER_CPLUSPLUSFLAGS" => "INIT_FLAG" + }) + twiceProcessed_config = BuildConfigurationMock.new("TwiceProcessedConfig"); + test_flag = " -DTEST_FLAG=1" + + # Act + ReactNativePodsUtils.add_flag_to_map_with_inheritance(empty_config.build_settings, "OTHER_CPLUSPLUSFLAGS", test_flag) + ReactNativePodsUtils.add_flag_to_map_with_inheritance(initialized_config.build_settings, "OTHER_CPLUSPLUSFLAGS", test_flag) + ReactNativePodsUtils.add_flag_to_map_with_inheritance(twiceProcessed_config.build_settings, "OTHER_CPLUSPLUSFLAGS", test_flag) + ReactNativePodsUtils.add_flag_to_map_with_inheritance(twiceProcessed_config.build_settings, "OTHER_CPLUSPLUSFLAGS", test_flag) + + # Assert + assert_equal("$(inherited)" + test_flag, empty_config.build_settings["OTHER_CPLUSPLUSFLAGS"]) + assert_equal("$(inherited) INIT_FLAG" + test_flag, initialized_config.build_settings["OTHER_CPLUSPLUSFLAGS"]) + assert_equal("$(inherited)" + test_flag, twiceProcessed_config.build_settings["OTHER_CPLUSPLUSFLAGS"]) + end + + def test_add_flag_to_map_with_inheritance_whenUsedWithXCConfigAttributes + # Arrange + empty_xcconfig = XCConfigMock.new("EmptyConfig") + initialized_xcconfig = XCConfigMock.new("InitializedConfig", attributes: { + "OTHER_CPLUSPLUSFLAGS" => "INIT_FLAG" + }) + twiceProcessed_xcconfig = XCConfigMock.new("TwiceProcessedConfig"); + test_flag = " -DTEST_FLAG=1" + + # Act + ReactNativePodsUtils.add_flag_to_map_with_inheritance(empty_xcconfig.attributes, "OTHER_CPLUSPLUSFLAGS", test_flag) + ReactNativePodsUtils.add_flag_to_map_with_inheritance(initialized_xcconfig.attributes, "OTHER_CPLUSPLUSFLAGS", test_flag) + ReactNativePodsUtils.add_flag_to_map_with_inheritance(twiceProcessed_xcconfig.attributes, "OTHER_CPLUSPLUSFLAGS", test_flag) + ReactNativePodsUtils.add_flag_to_map_with_inheritance(twiceProcessed_xcconfig.attributes, "OTHER_CPLUSPLUSFLAGS", test_flag) + + # Assert + assert_equal("$(inherited)" + test_flag, empty_xcconfig.attributes["OTHER_CPLUSPLUSFLAGS"]) + assert_equal("$(inherited) INIT_FLAG" + test_flag, initialized_xcconfig.attributes["OTHER_CPLUSPLUSFLAGS"]) + assert_equal("$(inherited)" + test_flag, twiceProcessed_xcconfig.attributes["OTHER_CPLUSPLUSFLAGS"]) + end + + def test_add_ndebug_flag_to_pods_in_release + # Arrange + xcconfig = XCConfigMock.new("Config") + default_debug_config = BuildConfigurationMock.new("Debug") + default_release_config = BuildConfigurationMock.new("Release") + custom_debug_config1 = BuildConfigurationMock.new("CustomDebug") + custom_debug_config2 = BuildConfigurationMock.new("Custom") + custom_release_config1 = BuildConfigurationMock.new("CustomRelease") + custom_release_config2 = BuildConfigurationMock.new("Production") + + installer = prepare_installer_for_cpp_flags( + [ xcconfig ], + { + "Default" => [ default_debug_config, default_release_config ], + "Custom1" => [ custom_debug_config1, custom_release_config1 ], + "Custom2" => [ custom_debug_config2, custom_release_config2 ] + } + ) + # Act + ReactNativePodsUtils.add_ndebug_flag_to_pods_in_release(installer) + + # Assert + assert_equal(nil, default_debug_config.build_settings["OTHER_CPLUSPLUSFLAGS"]) + assert_equal("$(inherited) -DNDEBUG", default_release_config.build_settings["OTHER_CPLUSPLUSFLAGS"]) + assert_equal(nil, custom_debug_config1.build_settings["OTHER_CPLUSPLUSFLAGS"]) + assert_equal("$(inherited) -DNDEBUG", custom_release_config1.build_settings["OTHER_CPLUSPLUSFLAGS"]) + assert_equal(nil, custom_debug_config2.build_settings["OTHER_CPLUSPLUSFLAGS"]) + assert_equal("$(inherited) -DNDEBUG", custom_release_config2.build_settings["OTHER_CPLUSPLUSFLAGS"]) + end end # ===== # @@ -1050,3 +1123,31 @@ def prepare_Code_Signing_build_configuration(name, param) "CODE_SIGNING_ALLOWED" => param }) end + +def prepare_pod_target_installation_results_mock(name, configs) + target = TargetMock.new(name, configs) + return TargetInstallationResultMock.new(target, target) +end + +def prepare_installer_for_cpp_flags(xcconfigs, build_configs) + xcconfigs_map = {} + xcconfigs.each do |config| + xcconfigs_map[config.name.to_s] = config + end + + pod_target_installation_results_map = {} + build_configs.each do |name, build_configs| + pod_target_installation_results_map[name.to_s] = prepare_pod_target_installation_results_mock( + name.to_s, build_configs + ) + end + + return InstallerMock.new( + PodsProjectMock.new, + [ + AggregatedProjectMock.new(:xcconfigs => xcconfigs_map, :base_path => "a/path/") + ], + :pod_target_installation_results => pod_target_installation_results_map + ) +end + diff --git a/packages/react-native/scripts/cocoapods/new_architecture.rb b/packages/react-native/scripts/cocoapods/new_architecture.rb index 7bf30e43f604e1..0d2aa46333d3f1 100644 --- a/packages/react-native/scripts/cocoapods/new_architecture.rb +++ b/packages/react-native/scripts/cocoapods/new_architecture.rb @@ -12,7 +12,7 @@ class NewArchitectureHelper @@folly_compiler_flags = "#{@@shared_flags} -Wno-comma -Wno-shorten-64-to-32" - @@new_arch_cpp_flags = "$(inherited) -DRCT_NEW_ARCH_ENABLED=1 #{@@shared_flags}" + @@new_arch_cpp_flags = " -DRCT_NEW_ARCH_ENABLED=1 #{@@shared_flags}" @@cplusplus_version = "c++20" @@ -49,17 +49,10 @@ def self.modify_flags_for_new_architecture(installer, is_new_arch_enabled) unless is_new_arch_enabled return end - ndebug_flag = " -DNDEBUG" # Add RCT_NEW_ARCH_ENABLED to Target pods xcconfig installer.aggregate_targets.each do |aggregate_target| aggregate_target.xcconfigs.each do |config_name, config_file| - config_file.attributes['OTHER_CPLUSPLUSFLAGS'] = @@new_arch_cpp_flags - - if config_name == "Release" - config_file.attributes['OTHER_CPLUSPLUSFLAGS'] = config_file.attributes['OTHER_CPLUSPLUSFLAGS'] + ndebug_flag - other_cflags = config_file.attributes['OTHER_CFLAGS'] != nil ? config_file.attributes['OTHER_CFLAGS'] : "$(inherited)" - config_file.attributes['OTHER_CFLAGS'] = other_cflags + ndebug_flag - end + ReactNativePodsUtils.add_flag_to_map_with_inheritance(config_file.attributes, "OTHER_CPLUSPLUSFLAGS", @@new_arch_cpp_flags) xcconfig_path = aggregate_target.xcconfig_path(config_name) config_file.save_as(xcconfig_path) @@ -71,16 +64,7 @@ def self.modify_flags_for_new_architecture(installer, is_new_arch_enabled) # The React-Core pod may have a suffix added by Cocoapods, so we test whether 'React-Core' is a substring, and do not require exact match if pod_name.include? 'React-Core' target_installation_result.native_target.build_configurations.each do |config| - config.build_settings['OTHER_CPLUSPLUSFLAGS'] = @@new_arch_cpp_flags - end - end - - target_installation_result.native_target.build_configurations.each do |config| - if config.name == "Release" - current_flags = config.build_settings['OTHER_CPLUSPLUSFLAGS'] != nil ? config.build_settings['OTHER_CPLUSPLUSFLAGS'] : "$(inherited)" - config.build_settings['OTHER_CPLUSPLUSFLAGS'] = current_flags + ndebug_flag - current_cflags = config.build_settings['OTHER_CFLAGS'] != nil ? config.build_settings['OTHER_CFLAGS'] : "$(inherited)" - config.build_settings['OTHER_CFLAGS'] = current_cflags + ndebug_flag + ReactNativePodsUtils.add_flag_to_map_with_inheritance(config.build_settings, "OTHER_CPLUSPLUSFLAGS", @@new_arch_cpp_flags) end end end @@ -126,7 +110,7 @@ def self.install_modules_dependencies(spec, new_arch_enabled, folly_version) spec.dependency "glog" if new_arch_enabled - current_config["OTHER_CPLUSPLUSFLAGS"] = @@new_arch_cpp_flags + ReactNativePodsUtils.add_flag_to_map_with_inheritance(current_config, "OTHER_CPLUSPLUSFLAGS", @@new_arch_cpp_flags) end spec.dependency "React-RCTFabric" # This is for Fabric Component diff --git a/packages/react-native/scripts/cocoapods/utils.rb b/packages/react-native/scripts/cocoapods/utils.rb index 11cb59a62c528f..ace3848aa849d7 100644 --- a/packages/react-native/scripts/cocoapods/utils.rb +++ b/packages/react-native/scripts/cocoapods/utils.rb @@ -613,4 +613,46 @@ def self.add_search_path_to_result(result, base_path, additional_paths, include_ } return result end + + def self.add_ndebug_flag_to_pods_in_release(installer) + ndebug_flag = " -DNDEBUG" + + installer.aggregate_targets.each do |aggregate_target| + aggregate_target.xcconfigs.each do |config_name, config_file| + is_release = config_name.downcase.include?("release") || config_name.downcase.include?("production") + unless is_release + next + end + self.add_flag_to_map_with_inheritance(config_file.attributes, 'OTHER_CPLUSPLUSFLAGS', ndebug_flag); + self.add_flag_to_map_with_inheritance(config_file.attributes, 'OTHER_CFLAGS', ndebug_flag); + + xcconfig_path = aggregate_target.xcconfig_path(config_name) + config_file.save_as(xcconfig_path) + end + end + + installer.target_installation_results.pod_target_installation_results.each do |pod_name, target_installation_result| + target_installation_result.native_target.build_configurations.each do |config| + is_release = config.name.downcase.include?("release") || config.name.downcase.include?("production") + unless is_release + next + end + self.add_flag_to_map_with_inheritance(config.build_settings, 'OTHER_CPLUSPLUSFLAGS', ndebug_flag); + self.add_flag_to_map_with_inheritance(config.build_settings, 'OTHER_CFLAGS', ndebug_flag); + end + end + end + + def self.add_flag_to_map_with_inheritance(map, field, flag) + if map[field] == nil + map[field] = "$(inherited)" + flag + else + unless map[field].include?(flag) + map[field] = map[field] + flag + end + unless map[field].include?("$(inherited)") + map[field] = "$(inherited) " + map[field] + end + end + end end diff --git a/packages/react-native/scripts/react_native_pods.rb b/packages/react-native/scripts/react_native_pods.rb index a2a6e1d23e7305..1f6591eb1e361b 100644 --- a/packages/react-native/scripts/react_native_pods.rb +++ b/packages/react-native/scripts/react_native_pods.rb @@ -280,6 +280,7 @@ def react_native_post_install( ReactNativePodsUtils.apply_ats_config(installer) ReactNativePodsUtils.updateOSDeploymentTarget(installer) ReactNativePodsUtils.set_dynamic_frameworks_flags(installer) + ReactNativePodsUtils.add_ndebug_flag_to_pods_in_release(installer) NewArchitectureHelper.set_clang_cxx_language_standard_if_needed(installer) NewArchitectureHelper.modify_flags_for_new_architecture(installer, NewArchitectureHelper.new_arch_enabled) From 0e9c93c14d6a8891472e37a9d46e50da791bbd1a Mon Sep 17 00:00:00 2001 From: Nicola Corti Date: Fri, 1 Dec 2023 08:41:02 -0800 Subject: [PATCH 157/162] Gradle to 8.5 (#41748) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41748 Bumping to the latest stable of Gradle Changelog: [Internal] [Changed] - Gradle to 8.5 Reviewed By: cipolleschi Differential Revision: D51749139 fbshipit-source-id: 2ee0f9a6c910dd5221f7f63c0c599d4ab181e10a --- gradle/wrapper/gradle-wrapper.jar | Bin 63721 -> 43462 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- .../gradle/wrapper/gradle-wrapper.jar | Bin 63721 -> 43462 bytes .../gradle/wrapper/gradle-wrapper.properties | 2 +- .../template/android/gradle-wrapper.jar | Bin 0 -> 43462 bytes .../android/gradle-wrapper.properties | 7 +++++++ 6 files changed, 9 insertions(+), 2 deletions(-) create mode 100644 packages/react-native/template/android/gradle-wrapper.jar create mode 100644 packages/react-native/template/android/gradle-wrapper.properties diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 7f93135c49b765f8051ef9d0a6055ff8e46073d8..d64cd4917707c1f8861d8cb53dd15194d4248596 100644 GIT binary patch literal 43462 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 literal 63721 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鯊%1Et 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⁢ zv5o9#E7!G0XmdzfsS{efPNi`1b44~SZ4Z8fuX!I}#8g+(wxzQwUT#Xb2(tbY1+EUhGKoT@KEU9Ktl>_0 z%bjDJg;#*gtJZv!-Zs`?^}v5eKmnbjqlvnSzE@_SP|LG_PJ6CYU+6zY6>92%E+ z=j@TZf-iW4(%U{lnYxQA;7Q!b;^brF8n0D>)`q5>|WDDXLrqYU_tKN2>=#@~OE7grMnNh?UOz-O~6 z6%rHy{#h9K0AT+lDC7q4{hw^|q6*Ry;;L%Q@)Ga}$60_q%D)rv(CtS$CQbpq9|y1e zRSrN4;$Jyl{m5bZw`$8TGvb}(LpY{-cQ)fcyJv7l3S52TLXVDsphtv&aPuDk1OzCA z4A^QtC(!11`IsNx_HnSy?>EKpHJWT^wmS~hc^p^zIIh@9f6U@I2 zC=Mve{j2^)mS#U$e{@Q?SO6%LDsXz@SY+=cK_QMmXBIU)j!$ajc-zLx3V60EXJ!qC zi<%2x8Q24YN+&8U@CIlN zrZkcT9yh%LrlGS9`G)KdP(@9Eo-AQz@8GEFWcb7U=a0H^ZVbLmz{+&M7W(nXJ4sN8 zJLR7eeK(K8`2-}j(T7JsO`L!+CvbueT%izanm-^A1Dn{`1Nw`9P?cq;7no+XfC`K(GO9?O^5zNIt4M+M8LM0=7Gz8UA@Z0N+lg+cX)NfazRu z5D)~HA^(u%w^cz+@2@_#S|u>GpB+j4KzQ^&Wcl9f z&hG#bCA(Yk0D&t&aJE^xME^&E-&xGHhXn%}psEIj641H+Nl-}boj;)Zt*t(4wZ5DN z@GXF$bL=&pBq-#vkTkh>7hl%K5|3 z{`Vn9b$iR-SoGENp}bn4;fR3>9sA%X2@1L3aE9yTra;Wb#_`xWwLSLdfu+PAu+o3| zGVnpzPr=ch{uuoHjtw7+_!L_2;knQ!DuDl0R`|%jr+}jFzXtrHIKc323?JO{l&;VF z*L1+}JU7%QJOg|5|Tc|D8fN zJORAg=_vsy{ak|o);@)Yh8Lkcg@$FG3k@ep36BRa^>~UmnRPziS>Z=`Jb2x*Q#`%A zU*i3&Vg?TluO@X0O;r2Jl6LKLUOVhSqg1*qOt^|8*c7 zo(298@+r$k_wQNGHv{|$tW(T8L+4_`FQ{kEW5Jgg{yf7ey4ss_(SNKfz(N9lx&a;< je(UuV8hP?p&}TPdm1I$XmG#(RzlD&B2izSj9sl%y5~4qc diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 8838ba97ba0914..e6aba2515d5428 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-all.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/packages/react-native-gradle-plugin/gradle/wrapper/gradle-wrapper.jar b/packages/react-native-gradle-plugin/gradle/wrapper/gradle-wrapper.jar index 7f93135c49b765f8051ef9d0a6055ff8e46073d8..d64cd4917707c1f8861d8cb53dd15194d4248596 100644 GIT binary patch literal 43462 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 literal 63721 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鯊%1Et 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⁢ zv5o9#E7!G0XmdzfsS{efPNi`1b44~SZ4Z8fuX!I}#8g+(wxzQwUT#Xb2(tbY1+EUhGKoT@KEU9Ktl>_0 z%bjDJg;#*gtJZv!-Zs`?^}v5eKmnbjqlvnSzE@_SP|LG_PJ6CYU+6zY6>92%E+ z=j@TZf-iW4(%U{lnYxQA;7Q!b;^brF8n0D>)`q5>|WDDXLrqYU_tKN2>=#@~OE7grMnNh?UOz-O~6 z6%rHy{#h9K0AT+lDC7q4{hw^|q6*Ry;;L%Q@)Ga}$60_q%D)rv(CtS$CQbpq9|y1e zRSrN4;$Jyl{m5bZw`$8TGvb}(LpY{-cQ)fcyJv7l3S52TLXVDsphtv&aPuDk1OzCA z4A^QtC(!11`IsNx_HnSy?>EKpHJWT^wmS~hc^p^zIIh@9f6U@I2 zC=Mve{j2^)mS#U$e{@Q?SO6%LDsXz@SY+=cK_QMmXBIU)j!$ajc-zLx3V60EXJ!qC zi<%2x8Q24YN+&8U@CIlN zrZkcT9yh%LrlGS9`G)KdP(@9Eo-AQz@8GEFWcb7U=a0H^ZVbLmz{+&M7W(nXJ4sN8 zJLR7eeK(K8`2-}j(T7JsO`L!+CvbueT%izanm-^A1Dn{`1Nw`9P?cq;7no+XfC`K(GO9?O^5zNIt4M+M8LM0=7Gz8UA@Z0N+lg+cX)NfazRu z5D)~HA^(u%w^cz+@2@_#S|u>GpB+j4KzQ^&Wcl9f z&hG#bCA(Yk0D&t&aJE^xME^&E-&xGHhXn%}psEIj641H+Nl-}boj;)Zt*t(4wZ5DN z@GXF$bL=&pBq-#vkTkh>7hl%K5|3 z{`Vn9b$iR-SoGENp}bn4;fR3>9sA%X2@1L3aE9yTra;Wb#_`xWwLSLdfu+PAu+o3| zGVnpzPr=ch{uuoHjtw7+_!L_2;knQ!DuDl0R`|%jr+}jFzXtrHIKc323?JO{l&;VF z*L1+}JU7%QJOg|5|Tc|D8fN zJORAg=_vsy{ak|o);@)Yh8Lkcg@$FG3k@ep36BRa^>~UmnRPziS>Z=`Jb2x*Q#`%A zU*i3&Vg?TluO@X0O;r2Jl6LKLUOVhSqg1*qOt^|8*c7 zo(298@+r$k_wQNGHv{|$tW(T8L+4_`FQ{kEW5Jgg{yf7ey4ss_(SNKfz(N9lx&a;< je(UuV8hP?p&}TPdm1I$XmG#(RzlD&B2izSj9sl%y5~4qc diff --git a/packages/react-native-gradle-plugin/gradle/wrapper/gradle-wrapper.properties b/packages/react-native-gradle-plugin/gradle/wrapper/gradle-wrapper.properties index 8838ba97ba0914..e6aba2515d5428 100644 --- a/packages/react-native-gradle-plugin/gradle/wrapper/gradle-wrapper.properties +++ b/packages/react-native-gradle-plugin/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-all.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/packages/react-native/template/android/gradle-wrapper.jar b/packages/react-native/template/android/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..d64cd4917707c1f8861d8cb53dd15194d4248596 GIT binary patch literal 43462 zcma&NWl&^owk(X(xVyW%ySuwf;qI=D6|RlDJ2cR^yEKh!@I- zp9QeisK*rlxC>+~7Dk4IxIRsKBHqdR9b3+fyL=ynHmIDe&|>O*VlvO+%z5;9Z$|DJ zb4dO}-R=MKr^6EKJiOrJdLnCJn>np?~vU-1sSFgPu;pthGwf}bG z(1db%xwr#x)r+`4AGu$j7~u2MpVs3VpLp|mx&;>`0p0vH6kF+D2CY0fVdQOZ@h;A` z{infNyvmFUiu*XG}RNMNwXrbec_*a3N=2zJ|Wh5z* z5rAX$JJR{#zP>KY**>xHTuw?|-Rg|o24V)74HcfVT;WtQHXlE+_4iPE8QE#DUm%x0 zEKr75ur~W%w#-My3Tj`hH6EuEW+8K-^5P62$7Sc5OK+22qj&Pd1;)1#4tKihi=~8C zHiQSst0cpri6%OeaR`PY>HH_;CPaRNty%WTm4{wDK8V6gCZlG@U3$~JQZ;HPvDJcT1V{ z?>H@13MJcCNe#5z+MecYNi@VT5|&UiN1D4ATT+%M+h4c$t;C#UAs3O_q=GxK0}8%8 z8J(_M9bayxN}69ex4dzM_P3oh@ZGREjVvn%%r7=xjkqxJP4kj}5tlf;QosR=%4L5y zWhgejO=vao5oX%mOHbhJ8V+SG&K5dABn6!WiKl{|oPkq(9z8l&Mm%(=qGcFzI=eLu zWc_oCLyf;hVlB@dnwY98?75B20=n$>u3b|NB28H0u-6Rpl((%KWEBOfElVWJx+5yg z#SGqwza7f}$z;n~g%4HDU{;V{gXIhft*q2=4zSezGK~nBgu9-Q*rZ#2f=Q}i2|qOp z!!y4p)4o=LVUNhlkp#JL{tfkhXNbB=Ox>M=n6soptJw-IDI|_$is2w}(XY>a=H52d z3zE$tjPUhWWS+5h=KVH&uqQS=$v3nRs&p$%11b%5qtF}S2#Pc`IiyBIF4%A!;AVoI zXU8-Rpv!DQNcF~(qQnyyMy=-AN~U>#&X1j5BLDP{?K!%h!;hfJI>$mdLSvktEr*89 zdJHvby^$xEX0^l9g$xW-d?J;L0#(`UT~zpL&*cEh$L|HPAu=P8`OQZV!-}l`noSp_ zQ-1$q$R-gDL)?6YaM!=8H=QGW$NT2SeZlb8PKJdc=F-cT@j7Xags+Pr*jPtlHFnf- zh?q<6;)27IdPc^Wdy-mX%2s84C1xZq9Xms+==F4);O`VUASmu3(RlgE#0+#giLh-& zcxm3_e}n4{%|X zJp{G_j+%`j_q5}k{eW&TlP}J2wtZ2^<^E(O)4OQX8FDp6RJq!F{(6eHWSD3=f~(h} zJXCf7=r<16X{pHkm%yzYI_=VDP&9bmI1*)YXZeB}F? z(%QsB5fo*FUZxK$oX~X^69;x~j7ms8xlzpt-T15e9}$4T-pC z6PFg@;B-j|Ywajpe4~bk#S6(fO^|mm1hKOPfA%8-_iGCfICE|=P_~e;Wz6my&)h_~ zkv&_xSAw7AZ%ThYF(4jADW4vg=oEdJGVOs>FqamoL3Np8>?!W#!R-0%2Bg4h?kz5I zKV-rKN2n(vUL%D<4oj@|`eJ>0i#TmYBtYmfla;c!ATW%;xGQ0*TW@PTlGG><@dxUI zg>+3SiGdZ%?5N=8uoLA|$4isK$aJ%i{hECP$bK{J#0W2gQ3YEa zZQ50Stn6hqdfxJ*9#NuSLwKFCUGk@c=(igyVL;;2^wi4o30YXSIb2g_ud$ zgpCr@H0qWtk2hK8Q|&wx)}4+hTYlf;$a4#oUM=V@Cw#!$(nOFFpZ;0lc!qd=c$S}Z zGGI-0jg~S~cgVT=4Vo)b)|4phjStD49*EqC)IPwyeKBLcN;Wu@Aeph;emROAwJ-0< z_#>wVm$)ygH|qyxZaet&(Vf%pVdnvKWJn9`%DAxj3ot;v>S$I}jJ$FLBF*~iZ!ZXE zkvui&p}fI0Y=IDX)mm0@tAd|fEHl~J&K}ZX(Mm3cm1UAuwJ42+AO5@HwYfDH7ipIc zmI;1J;J@+aCNG1M`Btf>YT>~c&3j~Qi@Py5JT6;zjx$cvOQW@3oQ>|}GH?TW-E z1R;q^QFjm5W~7f}c3Ww|awg1BAJ^slEV~Pk`Kd`PS$7;SqJZNj->it4DW2l15}xP6 zoCl$kyEF%yJni0(L!Z&14m!1urXh6Btj_5JYt1{#+H8w?5QI%% zo-$KYWNMJVH?Hh@1n7OSu~QhSswL8x0=$<8QG_zepi_`y_79=nK=_ZP_`Em2UI*tyQoB+r{1QYZCpb?2OrgUw#oRH$?^Tj!Req>XiE#~B|~ z+%HB;=ic+R@px4Ld8mwpY;W^A%8%l8$@B@1m5n`TlKI6bz2mp*^^^1mK$COW$HOfp zUGTz-cN9?BGEp}5A!mDFjaiWa2_J2Iq8qj0mXzk; z66JBKRP{p%wN7XobR0YjhAuW9T1Gw3FDvR5dWJ8ElNYF94eF3ebu+QwKjtvVu4L zI9ip#mQ@4uqVdkl-TUQMb^XBJVLW(-$s;Nq;@5gr4`UfLgF$adIhd?rHOa%D);whv z=;krPp~@I+-Z|r#s3yCH+c1US?dnm+C*)r{m+86sTJusLdNu^sqLrfWed^ndHXH`m zd3#cOe3>w-ga(Dus_^ppG9AC>Iq{y%%CK+Cro_sqLCs{VLuK=dev>OL1dis4(PQ5R zcz)>DjEkfV+MO;~>VUlYF00SgfUo~@(&9$Iy2|G0T9BSP?&T22>K46D zL*~j#yJ?)^*%J3!16f)@Y2Z^kS*BzwfAQ7K96rFRIh>#$*$_Io;z>ux@}G98!fWR@ zGTFxv4r~v)Gsd|pF91*-eaZ3Qw1MH$K^7JhWIdX%o$2kCbvGDXy)a?@8T&1dY4`;L z4Kn+f%SSFWE_rpEpL9bnlmYq`D!6F%di<&Hh=+!VI~j)2mfil03T#jJ_s?}VV0_hp z7T9bWxc>Jm2Z0WMU?`Z$xE74Gu~%s{mW!d4uvKCx@WD+gPUQ zV0vQS(Ig++z=EHN)BR44*EDSWIyT~R4$FcF*VEY*8@l=218Q05D2$|fXKFhRgBIEE zdDFB}1dKkoO^7}{5crKX!p?dZWNz$m>1icsXG2N+((x0OIST9Zo^DW_tytvlwXGpn zs8?pJXjEG;T@qrZi%#h93?FP$!&P4JA(&H61tqQi=opRzNpm zkrG}$^t9&XduK*Qa1?355wd8G2CI6QEh@Ua>AsD;7oRUNLPb76m4HG3K?)wF~IyS3`fXuNM>${?wmB zpVz;?6_(Fiadfd{vUCBM*_kt$+F3J+IojI;9L(gc9n3{sEZyzR9o!_mOwFC#tQ{Q~ zP3-`#uK#tP3Q7~Q;4H|wjZHO8h7e4IuBxl&vz2w~D8)w=Wtg31zpZhz%+kzSzL*dV zwp@{WU4i;hJ7c2f1O;7Mz6qRKeASoIv0_bV=i@NMG*l<#+;INk-^`5w@}Dj~;k=|}qM1vq_P z|GpBGe_IKq|LNy9SJhKOQ$c=5L{Dv|Q_lZl=-ky*BFBJLW9&y_C|!vyM~rQx=!vun z?rZJQB5t}Dctmui5i31C_;_}CEn}_W%>oSXtt>@kE1=JW*4*v4tPp;O6 zmAk{)m!)}34pTWg8{i>($%NQ(Tl;QC@J@FfBoc%Gr&m560^kgSfodAFrIjF}aIw)X zoXZ`@IsMkc8_=w%-7`D6Y4e*CG8k%Ud=GXhsTR50jUnm+R*0A(O3UKFg0`K;qp1bl z7``HN=?39ic_kR|^R^~w-*pa?Vj#7|e9F1iRx{GN2?wK!xR1GW!qa=~pjJb-#u1K8 zeR?Y2i-pt}yJq;SCiVHODIvQJX|ZJaT8nO+(?HXbLefulKKgM^B(UIO1r+S=7;kLJ zcH}1J=Px2jsh3Tec&v8Jcbng8;V-`#*UHt?hB(pmOipKwf3Lz8rG$heEB30Sg*2rx zV<|KN86$soN(I!BwO`1n^^uF2*x&vJ$2d$>+`(romzHP|)K_KkO6Hc>_dwMW-M(#S zK(~SiXT1@fvc#U+?|?PniDRm01)f^#55;nhM|wi?oG>yBsa?~?^xTU|fX-R(sTA+5 zaq}-8Tx7zrOy#3*JLIIVsBmHYLdD}!0NP!+ITW+Thn0)8SS!$@)HXwB3tY!fMxc#1 zMp3H?q3eD?u&Njx4;KQ5G>32+GRp1Ee5qMO0lZjaRRu&{W<&~DoJNGkcYF<5(Ab+J zgO>VhBl{okDPn78<%&e2mR{jwVCz5Og;*Z;;3%VvoGo_;HaGLWYF7q#jDX=Z#Ml`H z858YVV$%J|e<1n`%6Vsvq7GmnAV0wW4$5qQ3uR@1i>tW{xrl|ExywIc?fNgYlA?C5 zh$ezAFb5{rQu6i7BSS5*J-|9DQ{6^BVQ{b*lq`xS@RyrsJN?-t=MTMPY;WYeKBCNg z^2|pN!Q^WPJuuO4!|P@jzt&tY1Y8d%FNK5xK(!@`jO2aEA*4 zkO6b|UVBipci?){-Ke=+1;mGlND8)6+P;8sq}UXw2hn;fc7nM>g}GSMWu&v&fqh

iViYT=fZ(|3Ox^$aWPp4a8h24tD<|8-!aK0lHgL$N7Efw}J zVIB!7=T$U`ao1?upi5V4Et*-lTG0XvExbf!ya{cua==$WJyVG(CmA6Of*8E@DSE%L z`V^$qz&RU$7G5mg;8;=#`@rRG`-uS18$0WPN@!v2d{H2sOqP|!(cQ@ zUHo!d>>yFArLPf1q`uBvY32miqShLT1B@gDL4XoVTK&@owOoD)OIHXrYK-a1d$B{v zF^}8D3Y^g%^cnvScOSJR5QNH+BI%d|;J;wWM3~l>${fb8DNPg)wrf|GBP8p%LNGN# z3EaIiItgwtGgT&iYCFy9-LG}bMI|4LdmmJt@V@% zb6B)1kc=T)(|L@0;wr<>=?r04N;E&ef+7C^`wPWtyQe(*pD1pI_&XHy|0gIGHMekd zF_*M4yi6J&Z4LQj65)S zXwdM{SwUo%3SbPwFsHgqF@V|6afT|R6?&S;lw=8% z3}@9B=#JI3@B*#4s!O))~z zc>2_4Q_#&+5V`GFd?88^;c1i7;Vv_I*qt!_Yx*n=;rj!82rrR2rQ8u5(Ejlo{15P% zs~!{%XJ>FmJ})H^I9bn^Re&38H{xA!0l3^89k(oU;bZWXM@kn$#aoS&Y4l^-WEn-fH39Jb9lA%s*WsKJQl?n9B7_~P z-XM&WL7Z!PcoF6_D>V@$CvUIEy=+Z&0kt{szMk=f1|M+r*a43^$$B^MidrT0J;RI` z(?f!O<8UZkm$_Ny$Hth1J#^4ni+im8M9mr&k|3cIgwvjAgjH z8`N&h25xV#v*d$qBX5jkI|xOhQn!>IYZK7l5#^P4M&twe9&Ey@@GxYMxBZq2e7?`q z$~Szs0!g{2fGcp9PZEt|rdQ6bhAgpcLHPz?f-vB?$dc*!9OL?Q8mn7->bFD2Si60* z!O%y)fCdMSV|lkF9w%x~J*A&srMyYY3{=&$}H zGQ4VG_?$2X(0|vT0{=;W$~icCI{b6W{B!Q8xdGhF|D{25G_5_+%s(46lhvNLkik~R z>nr(&C#5wwOzJZQo9m|U<;&Wk!_#q|V>fsmj1g<6%hB{jGoNUPjgJslld>xmODzGjYc?7JSuA?A_QzjDw5AsRgi@Y|Z0{F{!1=!NES-#*f^s4l0Hu zz468))2IY5dmD9pa*(yT5{EyP^G>@ZWumealS-*WeRcZ}B%gxq{MiJ|RyX-^C1V=0 z@iKdrGi1jTe8Ya^x7yyH$kBNvM4R~`fbPq$BzHum-3Zo8C6=KW@||>zsA8-Y9uV5V z#oq-f5L5}V<&wF4@X@<3^C%ptp6+Ce)~hGl`kwj)bsAjmo_GU^r940Z-|`<)oGnh7 zFF0Tde3>ui?8Yj{sF-Z@)yQd~CGZ*w-6p2U<8}JO-sRsVI5dBji`01W8A&3$?}lxBaC&vn0E$c5tW* zX>5(zzZ=qn&!J~KdsPl;P@bmA-Pr8T*)eh_+Dv5=Ma|XSle6t(k8qcgNyar{*ReQ8 zTXwi=8vr>!3Ywr+BhggHDw8ke==NTQVMCK`$69fhzEFB*4+H9LIvdt-#IbhZvpS}} zO3lz;P?zr0*0$%-Rq_y^k(?I{Mk}h@w}cZpMUp|ucs55bcloL2)($u%mXQw({Wzc~ z;6nu5MkjP)0C(@%6Q_I_vsWrfhl7Zpoxw#WoE~r&GOSCz;_ro6i(^hM>I$8y>`!wW z*U^@?B!MMmb89I}2(hcE4zN2G^kwyWCZp5JG>$Ez7zP~D=J^LMjSM)27_0B_X^C(M z`fFT+%DcKlu?^)FCK>QzSnV%IsXVcUFhFdBP!6~se&xxrIxsvySAWu++IrH;FbcY$ z2DWTvSBRfLwdhr0nMx+URA$j3i7_*6BWv#DXfym?ZRDcX9C?cY9sD3q)uBDR3uWg= z(lUIzB)G$Hr!){>E{s4Dew+tb9kvToZp-1&c?y2wn@Z~(VBhqz`cB;{E4(P3N2*nJ z_>~g@;UF2iG{Kt(<1PyePTKahF8<)pozZ*xH~U-kfoAayCwJViIrnqwqO}7{0pHw$ zs2Kx?s#vQr7XZ264>5RNKSL8|Ty^=PsIx^}QqOOcfpGUU4tRkUc|kc7-!Ae6!+B{o~7nFpm3|G5^=0#Bnm6`V}oSQlrX(u%OWnC zoLPy&Q;1Jui&7ST0~#+}I^&?vcE*t47~Xq#YwvA^6^} z`WkC)$AkNub|t@S!$8CBlwbV~?yp&@9h{D|3z-vJXgzRC5^nYm+PyPcgRzAnEi6Q^gslXYRv4nycsy-SJu?lMps-? zV`U*#WnFsdPLL)Q$AmD|0`UaC4ND07+&UmOu!eHruzV|OUox<+Jl|Mr@6~C`T@P%s zW7sgXLF2SSe9Fl^O(I*{9wsFSYb2l%-;&Pi^dpv!{)C3d0AlNY6!4fgmSgj_wQ*7Am7&$z;Jg&wgR-Ih;lUvWS|KTSg!&s_E9_bXBkZvGiC6bFKDWZxsD$*NZ#_8bl zG1P-#@?OQzED7@jlMJTH@V!6k;W>auvft)}g zhoV{7$q=*;=l{O>Q4a@ ziMjf_u*o^PsO)#BjC%0^h>Xp@;5$p{JSYDt)zbb}s{Kbt!T*I@Pk@X0zds6wsefuU zW$XY%yyRGC94=6mf?x+bbA5CDQ2AgW1T-jVAJbm7K(gp+;v6E0WI#kuACgV$r}6L? zd|Tj?^%^*N&b>Dd{Wr$FS2qI#Ucs1yd4N+RBUQiSZGujH`#I)mG&VKoDh=KKFl4=G z&MagXl6*<)$6P}*Tiebpz5L=oMaPrN+caUXRJ`D?=K9!e0f{@D&cZLKN?iNP@X0aF zE(^pl+;*T5qt?1jRC=5PMgV!XNITRLS_=9{CJExaQj;lt!&pdzpK?8p>%Mb+D z?yO*uSung=-`QQ@yX@Hyd4@CI^r{2oiu`%^bNkz+Nkk!IunjwNC|WcqvX~k=><-I3 zDQdbdb|!v+Iz01$w@aMl!R)koD77Xp;eZwzSl-AT zr@Vu{=xvgfq9akRrrM)}=!=xcs+U1JO}{t(avgz`6RqiiX<|hGG1pmop8k6Q+G_mv zJv|RfDheUp2L3=^C=4aCBMBn0aRCU(DQwX-W(RkRwmLeuJYF<0urcaf(=7)JPg<3P zQs!~G)9CT18o!J4{zX{_e}4eS)U-E)0FAt}wEI(c0%HkxgggW;(1E=>J17_hsH^sP z%lT0LGgbUXHx-K*CI-MCrP66UP0PvGqM$MkeLyqHdbgP|_Cm!7te~b8p+e6sQ_3k| zVcwTh6d83ltdnR>D^)BYQpDKlLk3g0Hdcgz2}%qUs9~~Rie)A-BV1mS&naYai#xcZ z(d{8=-LVpTp}2*y)|gR~;qc7fp26}lPcLZ#=JpYcn3AT9(UIdOyg+d(P5T7D&*P}# zQCYplZO5|7+r19%9e`v^vfSS1sbX1c%=w1;oyruXB%Kl$ACgKQ6=qNWLsc=28xJjg zwvsI5-%SGU|3p>&zXVl^vVtQT3o-#$UT9LI@Npz~6=4!>mc431VRNN8od&Ul^+G_kHC`G=6WVWM z%9eWNyy(FTO|A+@x}Ou3CH)oi;t#7rAxdIXfNFwOj_@Y&TGz6P_sqiB`Q6Lxy|Q{`|fgmRG(k+!#b*M+Z9zFce)f-7;?Km5O=LHV9f9_87; zF7%R2B+$?@sH&&-$@tzaPYkw0;=i|;vWdI|Wl3q_Zu>l;XdIw2FjV=;Mq5t1Q0|f< zs08j54Bp`3RzqE=2enlkZxmX6OF+@|2<)A^RNQpBd6o@OXl+i)zO%D4iGiQNuXd+zIR{_lb96{lc~bxsBveIw6umhShTX+3@ZJ=YHh@ zWY3(d0azg;7oHn>H<>?4@*RQbi>SmM=JrHvIG(~BrvI)#W(EAeO6fS+}mxxcc+X~W6&YVl86W9WFSS}Vz-f9vS?XUDBk)3TcF z8V?$4Q)`uKFq>xT=)Y9mMFVTUk*NIA!0$?RP6Ig0TBmUFrq*Q-Agq~DzxjStQyJ({ zBeZ;o5qUUKg=4Hypm|}>>L=XKsZ!F$yNTDO)jt4H0gdQ5$f|d&bnVCMMXhNh)~mN z@_UV6D7MVlsWz+zM+inZZp&P4fj=tm6fX)SG5H>OsQf_I8c~uGCig$GzuwViK54bcgL;VN|FnyQl>Ed7(@>=8$a_UKIz|V6CeVSd2(P z0Uu>A8A+muM%HLFJQ9UZ5c)BSAv_zH#1f02x?h9C}@pN@6{>UiAp>({Fn(T9Q8B z^`zB;kJ5b`>%dLm+Ol}ty!3;8f1XDSVX0AUe5P#@I+FQ-`$(a;zNgz)4x5hz$Hfbg z!Q(z26wHLXko(1`;(BAOg_wShpX0ixfWq3ponndY+u%1gyX)_h=v1zR#V}#q{au6; z!3K=7fQwnRfg6FXtNQmP>`<;!N137paFS%y?;lb1@BEdbvQHYC{976l`cLqn;b8lp zIDY>~m{gDj(wfnK!lpW6pli)HyLEiUrNc%eXTil|F2s(AY+LW5hkKb>TQ3|Q4S9rr zpDs4uK_co6XPsn_z$LeS{K4jFF`2>U`tbgKdyDne`xmR<@6AA+_hPNKCOR-Zqv;xk zu5!HsBUb^!4uJ7v0RuH-7?l?}b=w5lzzXJ~gZcxRKOovSk@|#V+MuX%Y+=;14i*%{)_gSW9(#4%)AV#3__kac1|qUy!uyP{>?U#5wYNq}y$S9pCc zFc~4mgSC*G~j0u#qqp9 z${>3HV~@->GqEhr_Xwoxq?Hjn#=s2;i~g^&Hn|aDKpA>Oc%HlW(KA1?BXqpxB;Ydx)w;2z^MpjJ(Qi(X!$5RC z*P{~%JGDQqojV>2JbEeCE*OEu!$XJ>bWA9Oa_Hd;y)F%MhBRi*LPcdqR8X`NQ&1L# z5#9L*@qxrx8n}LfeB^J{%-?SU{FCwiWyHp682F+|pa+CQa3ZLzBqN1{)h4d6+vBbV zC#NEbQLC;}me3eeYnOG*nXOJZEU$xLZ1<1Y=7r0(-U0P6-AqwMAM`a(Ed#7vJkn6plb4eI4?2y3yOTGmmDQ!z9`wzbf z_OY#0@5=bnep;MV0X_;;SJJWEf^E6Bd^tVJ9znWx&Ks8t*B>AM@?;D4oWUGc z!H*`6d7Cxo6VuyS4Eye&L1ZRhrRmN6Lr`{NL(wDbif|y&z)JN>Fl5#Wi&mMIr5i;x zBx}3YfF>>8EC(fYnmpu~)CYHuHCyr5*`ECap%t@y=jD>!_%3iiE|LN$mK9>- zHdtpy8fGZtkZF?%TW~29JIAfi2jZT8>OA7=h;8T{{k?c2`nCEx9$r zS+*&vt~2o^^J+}RDG@+9&M^K*z4p{5#IEVbz`1%`m5c2};aGt=V?~vIM}ZdPECDI)47|CWBCfDWUbxBCnmYivQ*0Nu_xb*C>~C9(VjHM zxe<*D<#dQ8TlpMX2c@M<9$w!RP$hpG4cs%AI){jp*Sj|*`m)5(Bw*A0$*i-(CA5#%>a)$+jI2C9r6|(>J8InryENI z$NohnxDUB;wAYDwrb*!N3noBTKPpPN}~09SEL18tkG zxgz(RYU_;DPT{l?Q$+eaZaxnsWCA^ds^0PVRkIM%bOd|G2IEBBiz{&^JtNsODs;5z zICt_Zj8wo^KT$7Bg4H+y!Df#3mbl%%?|EXe!&(Vmac1DJ*y~3+kRKAD=Ovde4^^%~ zw<9av18HLyrf*_>Slp;^i`Uy~`mvBjZ|?Ad63yQa#YK`4+c6;pW4?XIY9G1(Xh9WO8{F-Aju+nS9Vmv=$Ac0ienZ+p9*O%NG zMZKy5?%Z6TAJTE?o5vEr0r>f>hb#2w2U3DL64*au_@P!J!TL`oH2r*{>ffu6|A7tv zL4juf$DZ1MW5ZPsG!5)`k8d8c$J$o;%EIL0va9&GzWvkS%ZsGb#S(?{!UFOZ9<$a| zY|a+5kmD5N&{vRqkgY>aHsBT&`rg|&kezoD)gP0fsNYHsO#TRc_$n6Lf1Z{?+DLziXlHrq4sf(!>O{?Tj;Eh@%)+nRE_2VxbN&&%%caU#JDU%vL3}Cb zsb4AazPI{>8H&d=jUaZDS$-0^AxE@utGs;-Ez_F(qC9T=UZX=>ok2k2 ziTn{K?y~a5reD2A)P${NoI^>JXn>`IeArow(41c-Wm~)wiryEP(OS{YXWi7;%dG9v zI?mwu1MxD{yp_rrk!j^cKM)dc4@p4Ezyo%lRN|XyD}}>v=Xoib0gOcdXrQ^*61HNj z=NP|pd>@yfvr-=m{8$3A8TQGMTE7g=z!%yt`8`Bk-0MMwW~h^++;qyUP!J~ykh1GO z(FZ59xuFR$(WE;F@UUyE@Sp>`aVNjyj=Ty>_Vo}xf`e7`F;j-IgL5`1~-#70$9_=uBMq!2&1l zomRgpD58@)YYfvLtPW}{C5B35R;ZVvB<<#)x%srmc_S=A7F@DW8>QOEGwD6suhwCg z>Pa+YyULhmw%BA*4yjDp|2{!T98~<6Yfd(wo1mQ!KWwq0eg+6)o1>W~f~kL<-S+P@$wx*zeI|1t7z#Sxr5 zt6w+;YblPQNplq4Z#T$GLX#j6yldXAqj>4gAnnWtBICUnA&-dtnlh=t0Ho_vEKwV` z)DlJi#!@nkYV#$!)@>udAU*hF?V`2$Hf=V&6PP_|r#Iv*J$9)pF@X3`k;5})9^o4y z&)~?EjX5yX12O(BsFy-l6}nYeuKkiq`u9145&3Ssg^y{5G3Pse z9w(YVa0)N-fLaBq1`P!_#>SS(8fh_5!f{UrgZ~uEdeMJIz7DzI5!NHHqQtm~#CPij z?=N|J>nPR6_sL7!f4hD_|KH`vf8(Wpnj-(gPWH+ZvID}%?~68SwhPTC3u1_cB`otq z)U?6qo!ZLi5b>*KnYHWW=3F!p%h1;h{L&(Q&{qY6)_qxNfbP6E3yYpW!EO+IW3?@J z);4>g4gnl^8klu7uA>eGF6rIGSynacogr)KUwE_R4E5Xzi*Qir@b-jy55-JPC8c~( zo!W8y9OGZ&`xmc8;=4-U9=h{vCqfCNzYirONmGbRQlR`WWlgnY+1wCXbMz&NT~9*| z6@FrzP!LX&{no2!Ln_3|I==_4`@}V?4a;YZKTdw;vT<+K+z=uWbW(&bXEaWJ^W8Td z-3&1bY^Z*oM<=M}LVt>_j+p=2Iu7pZmbXrhQ_k)ysE9yXKygFNw$5hwDn(M>H+e1&9BM5!|81vd%r%vEm zqxY3?F@fb6O#5UunwgAHR9jp_W2zZ}NGp2%mTW@(hz7$^+a`A?mb8|_G*GNMJ) zjqegXQio=i@AINre&%ofexAr95aop5C+0MZ0m-l=MeO8m3epm7U%vZB8+I+C*iNFM z#T3l`gknX;D$-`2XT^Cg*vrv=RH+P;_dfF++cP?B_msQI4j+lt&rX2)3GaJx%W*Nn zkML%D{z5tpHH=dksQ*gzc|}gzW;lwAbxoR07VNgS*-c3d&8J|;@3t^ zVUz*J*&r7DFRuFVDCJDK8V9NN5hvpgGjwx+5n)qa;YCKe8TKtdnh{I7NU9BCN!0dq zczrBk8pE{{@vJa9ywR@mq*J=v+PG;?fwqlJVhijG!3VmIKs>9T6r7MJpC)m!Tc#>g zMtVsU>wbwFJEfwZ{vB|ZlttNe83)$iz`~#8UJ^r)lJ@HA&G#}W&ZH*;k{=TavpjWE z7hdyLZPf*X%Gm}i`Y{OGeeu^~nB8=`{r#TUrM-`;1cBvEd#d!kPqIgYySYhN-*1;L z^byj%Yi}Gx)Wnkosi337BKs}+5H5dth1JA{Ir-JKN$7zC)*}hqeoD(WfaUDPT>0`- z(6sa0AoIqASwF`>hP}^|)a_j2s^PQn*qVC{Q}htR z5-)duBFXT_V56-+UohKXlq~^6uf!6sA#ttk1o~*QEy_Y-S$gAvq47J9Vtk$5oA$Ct zYhYJ@8{hsC^98${!#Ho?4y5MCa7iGnfz}b9jE~h%EAAv~Qxu)_rAV;^cygV~5r_~?l=B`zObj7S=H=~$W zPtI_m%g$`kL_fVUk9J@>EiBH zOO&jtn~&`hIFMS5S`g8w94R4H40mdNUH4W@@XQk1sr17b{@y|JB*G9z1|CrQjd+GX z6+KyURG3;!*BQrentw{B2R&@2&`2}n(z-2&X7#r!{yg@Soy}cRD~j zj9@UBW+N|4HW4AWapy4wfUI- zZ`gSL6DUlgj*f1hSOGXG0IVH8HxK?o2|3HZ;KW{K+yPAlxtb)NV_2AwJm|E)FRs&& z=c^e7bvUsztY|+f^k7NXs$o1EUq>cR7C0$UKi6IooHWlK_#?IWDkvywnzg&ThWo^? z2O_N{5X39#?eV9l)xI(>@!vSB{DLt*oY!K1R8}_?%+0^C{d9a%N4 zoxHVT1&Lm|uDX%$QrBun5e-F`HJ^T$ zmzv)p@4ZHd_w9!%Hf9UYNvGCw2TTTbrj9pl+T9%-_-}L(tES>Or-}Z4F*{##n3~L~TuxjirGuIY#H7{%$E${?p{Q01 zi6T`n;rbK1yIB9jmQNycD~yZq&mbIsFWHo|ZAChSFPQa<(%d8mGw*V3fh|yFoxOOiWJd(qvVb!Z$b88cg->N=qO*4k~6;R==|9ihg&riu#P~s4Oap9O7f%crSr^rljeIfXDEg>wi)&v*a%7zpz<9w z*r!3q9J|390x`Zk;g$&OeN&ctp)VKRpDSV@kU2Q>jtok($Y-*x8_$2piTxun81@vt z!Vj?COa0fg2RPXMSIo26T=~0d`{oGP*eV+$!0I<(4azk&Vj3SiG=Q!6mX0p$z7I}; z9BJUFgT-K9MQQ-0@Z=^7R<{bn2Fm48endsSs`V7_@%8?Bxkqv>BDoVcj?K#dV#uUP zL1ND~?D-|VGKe3Rw_7-Idpht>H6XRLh*U7epS6byiGvJpr%d}XwfusjH9g;Z98H`x zyde%%5mhGOiL4wljCaWCk-&uE4_OOccb9c!ZaWt4B(wYl!?vyzl%7n~QepN&eFUrw zFIOl9c({``6~QD+43*_tzP{f2x41h(?b43^y6=iwyB)2os5hBE!@YUS5?N_tXd=h( z)WE286Fbd>R4M^P{!G)f;h<3Q>Fipuy+d2q-)!RyTgt;wr$(?9ox3;q+{E*ZQHhOn;lM`cjnu9 zXa48ks-v(~b*;MAI<>YZH(^NV8vjb34beE<_cwKlJoR;k6lJNSP6v}uiyRD?|0w+X@o1ONrH8a$fCxXpf? z?$DL0)7|X}Oc%h^zrMKWc-NS9I0Utu@>*j}b@tJ=ixQSJ={4@854wzW@E>VSL+Y{i z#0b=WpbCZS>kUCO_iQz)LoE>P5LIG-hv9E+oG}DtlIDF>$tJ1aw9^LuhLEHt?BCj& z(O4I8v1s#HUi5A>nIS-JK{v!7dJx)^Yg%XjNmlkWAq2*cv#tHgz`Y(bETc6CuO1VkN^L-L3j_x<4NqYb5rzrLC-7uOv z!5e`GZt%B782C5-fGnn*GhDF$%(qP<74Z}3xx+{$4cYKy2ikxI7B2N+2r07DN;|-T->nU&!=Cm#rZt%O_5c&1Z%nlWq3TKAW0w zQqemZw_ue--2uKQsx+niCUou?HjD`xhEjjQd3%rrBi82crq*~#uA4+>vR<_S{~5ce z-2EIl?~s z1=GVL{NxP1N3%=AOaC}j_Fv=ur&THz zyO!d9kHq|c73kpq`$+t+8Bw7MgeR5~`d7ChYyGCBWSteTB>8WAU(NPYt2Dk`@#+}= zI4SvLlyk#pBgVigEe`?NG*vl7V6m+<}%FwPV=~PvvA)=#ths==DRTDEYh4V5}Cf$z@#;< zyWfLY_5sP$gc3LLl2x+Ii)#b2nhNXJ{R~vk`s5U7Nyu^3yFg&D%Txwj6QezMX`V(x z=C`{76*mNb!qHHs)#GgGZ_7|vkt9izl_&PBrsu@}L`X{95-2jf99K)0=*N)VxBX2q z((vkpP2RneSIiIUEnGb?VqbMb=Zia+rF~+iqslydE34cSLJ&BJW^3knX@M;t*b=EA zNvGzv41Ld_T+WT#XjDB840vovUU^FtN_)G}7v)1lPetgpEK9YS^OWFkPoE{ovj^=@ zO9N$S=G$1ecndT_=5ehth2Lmd1II-PuT~C9`XVePw$y8J#dpZ?Tss<6wtVglm(Ok7 z3?^oi@pPio6l&!z8JY(pJvG=*pI?GIOu}e^EB6QYk$#FJQ%^AIK$I4epJ+9t?KjqA+bkj&PQ*|vLttme+`9G=L% ziadyMw_7-M)hS(3E$QGNCu|o23|%O+VN7;Qggp?PB3K-iSeBa2b}V4_wY`G1Jsfz4 z9|SdB^;|I8E8gWqHKx!vj_@SMY^hLEIbSMCuE?WKq=c2mJK z8LoG-pnY!uhqFv&L?yEuxo{dpMTsmCn)95xanqBrNPTgXP((H$9N${Ow~Is-FBg%h z53;|Y5$MUN)9W2HBe2TD`ct^LHI<(xWrw}$qSoei?}s)&w$;&!14w6B6>Yr6Y8b)S z0r71`WmAvJJ`1h&poLftLUS6Ir zC$bG9!Im_4Zjse)#K=oJM9mHW1{%l8sz$1o?ltdKlLTxWWPB>Vk22czVt|1%^wnN@*!l)}?EgtvhC>vlHm^t+ogpgHI1_$1ox9e;>0!+b(tBrmXRB`PY1vp-R**8N7 zGP|QqI$m(Rdu#=(?!(N}G9QhQ%o!aXE=aN{&wtGP8|_qh+7a_j_sU5|J^)vxq;# zjvzLn%_QPHZZIWu1&mRAj;Sa_97p_lLq_{~j!M9N^1yp3U_SxRqK&JnR%6VI#^E12 z>CdOVI^_9aPK2eZ4h&^{pQs}xsijXgFYRIxJ~N7&BB9jUR1fm!(xl)mvy|3e6-B3j zJn#ajL;bFTYJ2+Q)tDjx=3IklO@Q+FFM}6UJr6km7hj7th9n_&JR7fnqC!hTZoM~T zBeaVFp%)0cbPhejX<8pf5HyRUj2>aXnXBqDJe73~J%P(2C?-RT{c3NjE`)om! zl$uewSgWkE66$Kb34+QZZvRn`fob~Cl9=cRk@Es}KQm=?E~CE%spXaMO6YmrMl%9Q zlA3Q$3|L1QJ4?->UjT&CBd!~ru{Ih^in&JXO=|<6J!&qp zRe*OZ*cj5bHYlz!!~iEKcuE|;U4vN1rk$xq6>bUWD*u(V@8sG^7>kVuo(QL@Ki;yL zWC!FT(q{E8#on>%1iAS0HMZDJg{Z{^!De(vSIq&;1$+b)oRMwA3nc3mdTSG#3uYO_ z>+x;7p4I;uHz?ZB>dA-BKl+t-3IB!jBRgdvAbW!aJ(Q{aT>+iz?91`C-xbe)IBoND z9_Xth{6?(y3rddwY$GD65IT#f3<(0o#`di{sh2gm{dw*#-Vnc3r=4==&PU^hCv$qd zjw;>i&?L*Wq#TxG$mFIUf>eK+170KG;~+o&1;Tom9}}mKo23KwdEM6UonXgc z!6N(@k8q@HPw{O8O!lAyi{rZv|DpgfU{py+j(X_cwpKqcalcqKIr0kM^%Br3SdeD> zHSKV94Yxw;pjzDHo!Q?8^0bb%L|wC;4U^9I#pd5O&eexX+Im{ z?jKnCcsE|H?{uGMqVie_C~w7GX)kYGWAg%-?8|N_1#W-|4F)3YTDC+QSq1s!DnOML3@d`mG%o2YbYd#jww|jD$gotpa)kntakp#K;+yo-_ZF9qrNZw<%#C zuPE@#3RocLgPyiBZ+R_-FJ_$xP!RzWm|aN)S+{$LY9vvN+IW~Kf3TsEIvP+B9Mtm! zpfNNxObWQpLoaO&cJh5>%slZnHl_Q~(-Tfh!DMz(dTWld@LG1VRF`9`DYKhyNv z2pU|UZ$#_yUx_B_|MxUq^glT}O5Xt(Vm4Mr02><%C)@v;vPb@pT$*yzJ4aPc_FZ3z z3}PLoMBIM>q_9U2rl^sGhk1VUJ89=*?7|v`{!Z{6bqFMq(mYiA?%KbsI~JwuqVA9$H5vDE+VocjX+G^%bieqx->s;XWlKcuv(s%y%D5Xbc9+ zc(_2nYS1&^yL*ey664&4`IoOeDIig}y-E~_GS?m;D!xv5-xwz+G`5l6V+}CpeJDi^ z%4ed$qowm88=iYG+(`ld5Uh&>Dgs4uPHSJ^TngXP_V6fPyl~>2bhi20QB%lSd#yYn zO05?KT1z@?^-bqO8Cg`;ft>ilejsw@2%RR7;`$Vs;FmO(Yr3Fp`pHGr@P2hC%QcA|X&N2Dn zYf`MqXdHi%cGR@%y7Rg7?d3?an){s$zA{!H;Ie5exE#c~@NhQUFG8V=SQh%UxUeiV zd7#UcYqD=lk-}sEwlpu&H^T_V0{#G?lZMxL7ih_&{(g)MWBnCZxtXg znr#}>U^6!jA%e}@Gj49LWG@*&t0V>Cxc3?oO7LSG%~)Y5}f7vqUUnQ;STjdDU}P9IF9d9<$;=QaXc zL1^X7>fa^jHBu_}9}J~#-oz3Oq^JmGR#?GO7b9a(=R@fw@}Q{{@`Wy1vIQ#Bw?>@X z-_RGG@wt|%u`XUc%W{J z>iSeiz8C3H7@St3mOr_mU+&bL#Uif;+Xw-aZdNYUpdf>Rvu0i0t6k*}vwU`XNO2he z%miH|1tQ8~ZK!zmL&wa3E;l?!!XzgV#%PMVU!0xrDsNNZUWKlbiOjzH-1Uoxm8E#r`#2Sz;-o&qcqB zC-O_R{QGuynW14@)7&@yw1U}uP(1cov)twxeLus0s|7ayrtT8c#`&2~Fiu2=R;1_4bCaD=*E@cYI>7YSnt)nQc zohw5CsK%m?8Ack)qNx`W0_v$5S}nO|(V|RZKBD+btO?JXe|~^Qqur%@eO~<8-L^9d z=GA3-V14ng9L29~XJ>a5k~xT2152zLhM*@zlp2P5Eu}bywkcqR;ISbas&#T#;HZSf z2m69qTV(V@EkY(1Dk3`}j)JMo%ZVJ*5eB zYOjIisi+igK0#yW*gBGj?@I{~mUOvRFQR^pJbEbzFxTubnrw(Muk%}jI+vXmJ;{Q6 zrSobKD>T%}jV4Ub?L1+MGOD~0Ir%-`iTnWZN^~YPrcP5y3VMAzQ+&en^VzKEb$K!Q z<7Dbg&DNXuow*eD5yMr+#08nF!;%4vGrJI++5HdCFcGLfMW!KS*Oi@=7hFwDG!h2< zPunUEAF+HncQkbfFj&pbzp|MU*~60Z(|Ik%Tn{BXMN!hZOosNIseT?R;A`W?=d?5X zK(FB=9mZusYahp|K-wyb={rOpdn=@;4YI2W0EcbMKyo~-#^?h`BA9~o285%oY zfifCh5Lk$SY@|2A@a!T2V+{^!psQkx4?x0HSV`(w9{l75QxMk!)U52Lbhn{8ol?S) zCKo*7R(z!uk<6*qO=wh!Pul{(qq6g6xW;X68GI_CXp`XwO zxuSgPRAtM8K7}5E#-GM!*ydOOG_{A{)hkCII<|2=ma*71ci_-}VPARm3crFQjLYV! z9zbz82$|l01mv`$WahE2$=fAGWkd^X2kY(J7iz}WGS z@%MyBEO=A?HB9=^?nX`@nh;7;laAjs+fbo!|K^mE!tOB>$2a_O0y-*uaIn8k^6Y zSbuv;5~##*4Y~+y7Z5O*3w4qgI5V^17u*ZeupVGH^nM&$qmAk|anf*>r zWc5CV;-JY-Z@Uq1Irpb^O`L_7AGiqd*YpGUShb==os$uN3yYvb`wm6d=?T*it&pDk zo`vhw)RZX|91^^Wa_ti2zBFyWy4cJu#g)_S6~jT}CC{DJ_kKpT`$oAL%b^!2M;JgT zM3ZNbUB?}kP(*YYvXDIH8^7LUxz5oE%kMhF!rnPqv!GiY0o}NR$OD=ITDo9r%4E>E0Y^R(rS^~XjWyVI6 zMOR5rPXhTp*G*M&X#NTL`Hu*R+u*QNoiOKg4CtNPrjgH>c?Hi4MUG#I917fx**+pJfOo!zFM&*da&G_x)L(`k&TPI*t3e^{crd zX<4I$5nBQ8Ax_lmNRa~E*zS-R0sxkz`|>7q_?*e%7bxqNm3_eRG#1ae3gtV9!fQpY z+!^a38o4ZGy9!J5sylDxZTx$JmG!wg7;>&5H1)>f4dXj;B+@6tMlL=)cLl={jLMxY zbbf1ax3S4>bwB9-$;SN2?+GULu;UA-35;VY*^9Blx)Jwyb$=U!D>HhB&=jSsd^6yw zL)?a|>GxU!W}ocTC(?-%z3!IUhw^uzc`Vz_g>-tv)(XA#JK^)ZnC|l1`@CdX1@|!| z_9gQ)7uOf?cR@KDp97*>6X|;t@Y`k_N@)aH7gY27)COv^P3ya9I{4z~vUjLR9~z1Z z5=G{mVtKH*&$*t0@}-i_v|3B$AHHYale7>E+jP`ClqG%L{u;*ff_h@)al?RuL7tOO z->;I}>%WI{;vbLP3VIQ^iA$4wl6@0sDj|~112Y4OFjMs`13!$JGkp%b&E8QzJw_L5 zOnw9joc0^;O%OpF$Qp)W1HI!$4BaXX84`%@#^dk^hFp^pQ@rx4g(8Xjy#!X%+X5Jd@fs3amGT`}mhq#L97R>OwT5-m|h#yT_-v@(k$q7P*9X~T*3)LTdzP!*B} z+SldbVWrrwQo9wX*%FyK+sRXTa@O?WM^FGWOE?S`R(0P{<6p#f?0NJvnBia?k^fX2 zNQs7K-?EijgHJY}&zsr;qJ<*PCZUd*x|dD=IQPUK_nn)@X4KWtqoJNHkT?ZWL_hF? zS8lp2(q>;RXR|F;1O}EE#}gCrY~#n^O`_I&?&z5~7N;zL0)3Tup`%)oHMK-^r$NT% zbFg|o?b9w(q@)6w5V%si<$!U<#}s#x@0aX-hP>zwS#9*75VXA4K*%gUc>+yzupTDBOKH8WR4V0pM(HrfbQ&eJ79>HdCvE=F z|J>s;;iDLB^3(9}?biKbxf1$lI!*Z%*0&8UUq}wMyPs_hclyQQi4;NUY+x2qy|0J; zhn8;5)4ED1oHwg+VZF|80<4MrL97tGGXc5Sw$wAI#|2*cvQ=jB5+{AjMiDHmhUC*a zlmiZ`LAuAn_}hftXh;`Kq0zblDk8?O-`tnilIh|;3lZp@F_osJUV9`*R29M?7H{Fy z`nfVEIDIWXmU&YW;NjU8)EJpXhxe5t+scf|VXM!^bBlwNh)~7|3?fWwo_~ZFk(22% zTMesYw+LNx3J-_|DM~`v93yXe=jPD{q;li;5PD?Dyk+b? zo21|XpT@)$BM$%F=P9J19Vi&1#{jM3!^Y&fr&_`toi`XB1!n>sbL%U9I5<7!@?t)~ z;&H%z>bAaQ4f$wIzkjH70;<8tpUoxzKrPhn#IQfS%9l5=Iu))^XC<58D!-O z{B+o5R^Z21H0T9JQ5gNJnqh#qH^na|z92=hONIM~@_iuOi|F>jBh-?aA20}Qx~EpDGElELNn~|7WRXRFnw+Wdo`|# zBpU=Cz3z%cUJ0mx_1($X<40XEIYz(`noWeO+x#yb_pwj6)R(__%@_Cf>txOQ74wSJ z0#F3(zWWaR-jMEY$7C*3HJrohc79>MCUu26mfYN)f4M~4gD`}EX4e}A!U}QV8!S47 z6y-U-%+h`1n`*pQuKE%Av0@)+wBZr9mH}@vH@i{v(m-6QK7Ncf17x_D=)32`FOjjo zg|^VPf5c6-!FxN{25dvVh#fog=NNpXz zfB$o+0jbRkHH{!TKhE709f+jI^$3#v1Nmf80w`@7-5$1Iv_`)W^px8P-({xwb;D0y z7LKDAHgX<84?l!I*Dvi2#D@oAE^J|g$3!)x1Ua;_;<@#l1fD}lqU2_tS^6Ht$1Wl} zBESo7o^)9-Tjuz$8YQSGhfs{BQV6zW7dA?0b(Dbt=UnQs&4zHfe_sj{RJ4uS-vQpC zX;Bbsuju4%!o8?&m4UZU@~ZZjeFF6ex2ss5_60_JS_|iNc+R0GIjH1@Z z=rLT9%B|WWgOrR7IiIwr2=T;Ne?30M!@{%Qf8o`!>=s<2CBpCK_TWc(DX51>e^xh8 z&@$^b6CgOd7KXQV&Y4%}_#uN*mbanXq(2=Nj`L7H7*k(6F8s6{FOw@(DzU`4-*77{ zF+dxpv}%mFpYK?>N_2*#Y?oB*qEKB}VoQ@bzm>ptmVS_EC(#}Lxxx730trt0G)#$b zE=wVvtqOct1%*9}U{q<)2?{+0TzZzP0jgf9*)arV)*e!f`|jgT{7_9iS@e)recI#z zbzolURQ+TOzE!ymqvBY7+5NnAbWxvMLsLTwEbFqW=CPyCsmJ}P1^V30|D5E|p3BC5 z)3|qgw@ra7aXb-wsa|l^in~1_fm{7bS9jhVRkYVO#U{qMp z)Wce+|DJ}4<2gp8r0_xfZpMo#{Hl2MfjLcZdRB9(B(A(f;+4s*FxV{1F|4d`*sRNd zp4#@sEY|?^FIJ;tmH{@keZ$P(sLh5IdOk@k^0uB^BWr@pk6mHy$qf&~rI>P*a;h0C{%oA*i!VjWn&D~O#MxN&f@1Po# zKN+ zrGrkSjcr?^R#nGl<#Q722^wbYcgW@{+6CBS<1@%dPA8HC!~a`jTz<`g_l5N1M@9wn9GOAZ>nqNgq!yOCbZ@1z`U_N`Z>}+1HIZxk*5RDc&rd5{3qjRh8QmT$VyS;jK z;AF+r6XnnCp=wQYoG|rT2@8&IvKq*IB_WvS%nt%e{MCFm`&W*#LXc|HrD?nVBo=(8*=Aq?u$sDA_sC_RPDUiQ+wnIJET8vx$&fxkW~kP9qXKt zozR)@xGC!P)CTkjeWvXW5&@2?)qt)jiYWWBU?AUtzAN}{JE1I)dfz~7$;}~BmQF`k zpn11qmObXwRB8&rnEG*#4Xax3XBkKlw(;tb?Np^i+H8m(Wyz9k{~ogba@laiEk;2! zV*QV^6g6(QG%vX5Um#^sT&_e`B1pBW5yVth~xUs#0}nv?~C#l?W+9Lsb_5)!71rirGvY zTIJ$OPOY516Y|_014sNv+Z8cc5t_V=i>lWV=vNu#!58y9Zl&GsMEW#pPYPYGHQ|;vFvd*9eM==$_=vc7xnyz0~ zY}r??$<`wAO?JQk@?RGvkWVJlq2dk9vB(yV^vm{=NVI8dhsX<)O(#nr9YD?I?(VmQ z^r7VfUBn<~p3()8yOBjm$#KWx!5hRW)5Jl7wY@ky9lNM^jaT##8QGVsYeaVywmpv>X|Xj7gWE1Ezai&wVLt3p)k4w~yrskT-!PR!kiyQlaxl(( zXhF%Q9x}1TMt3~u@|#wWm-Vq?ZerK={8@~&@9r5JW}r#45#rWii};t`{5#&3$W)|@ zbAf2yDNe0q}NEUvq_Quq3cTjcw z@H_;$hu&xllCI9CFDLuScEMg|x{S7GdV8<&Mq=ezDnRZAyX-8gv97YTm0bg=d)(>N z+B2FcqvI9>jGtnK%eO%y zoBPkJTk%y`8TLf4)IXPBn`U|9>O~WL2C~C$z~9|0m*YH<-vg2CD^SX#&)B4ngOSG$ zV^wmy_iQk>dfN@Pv(ckfy&#ak@MLC7&Q6Ro#!ezM*VEh`+b3Jt%m(^T&p&WJ2Oqvj zs-4nq0TW6cv~(YI$n0UkfwN}kg3_fp?(ijSV#tR9L0}l2qjc7W?i*q01=St0eZ=4h zyGQbEw`9OEH>NMuIe)hVwYHsGERWOD;JxEiO7cQv%pFCeR+IyhwQ|y@&^24k+|8fD zLiOWFNJ2&vu2&`Jv96_z-Cd5RLgmeY3*4rDOQo?Jm`;I_(+ejsPM03!ly!*Cu}Cco zrQSrEDHNyzT(D5s1rZq!8#?f6@v6dB7a-aWs(Qk>N?UGAo{gytlh$%_IhyL7h?DLXDGx zgxGEBQoCAWo-$LRvM=F5MTle`M})t3vVv;2j0HZY&G z22^iGhV@uaJh(XyyY%} zd4iH_UfdV#T=3n}(Lj^|n;O4|$;xhu*8T3hR1mc_A}fK}jfZ7LX~*n5+`8N2q#rI$ z@<_2VANlYF$vIH$ zl<)+*tIWW78IIINA7Rr7i{<;#^yzxoLNkXL)eSs=%|P>$YQIh+ea_3k z_s7r4%j7%&*NHSl?R4k%1>Z=M9o#zxY!n8sL5>BO-ZP;T3Gut>iLS@U%IBrX6BA3k z)&@q}V8a{X<5B}K5s(c(LQ=%v1ocr`t$EqqY0EqVjr65usa=0bkf|O#ky{j3)WBR(((L^wmyHRzoWuL2~WTC=`yZ zn%VX`L=|Ok0v7?s>IHg?yArBcync5rG#^+u)>a%qjES%dRZoIyA8gQ;StH z1Ao7{<&}6U=5}4v<)1T7t!J_CL%U}CKNs-0xWoTTeqj{5{?Be$L0_tk>M9o8 zo371}S#30rKZFM{`H_(L`EM9DGp+Mifk&IP|C2Zu_)Ghr4Qtpmkm1osCf@%Z$%t+7 zYH$Cr)Ro@3-QDeQJ8m+x6%;?YYT;k6Z0E-?kr>x33`H%*ueBD7Zx~3&HtWn0?2Wt} zTG}*|v?{$ajzt}xPzV%lL1t-URi8*Zn)YljXNGDb>;!905Td|mpa@mHjIH%VIiGx- zd@MqhpYFu4_?y5N4xiHn3vX&|e6r~Xt> zZG`aGq|yTNjv;9E+Txuoa@A(9V7g?1_T5FzRI;!=NP1Kqou1z5?%X~Wwb{trRfd>i z8&y^H)8YnKyA_Fyx>}RNmQIczT?w2J4SNvI{5J&}Wto|8FR(W;Qw#b1G<1%#tmYzQ zQ2mZA-PAdi%RQOhkHy9Ea#TPSw?WxwL@H@cbkZwIq0B!@ns}niALidmn&W?!Vd4Gj zO7FiuV4*6Mr^2xlFSvM;Cp_#r8UaqIzHJQg_z^rEJw&OMm_8NGAY2)rKvki|o1bH~ z$2IbfVeY2L(^*rMRU1lM5Y_sgrDS`Z??nR2lX;zyR=c%UyGb*%TC-Dil?SihkjrQy~TMv6;BMs7P8il`H7DmpVm@rJ;b)hW)BL)GjS154b*xq-NXq2cwE z^;VP7ua2pxvCmxrnqUYQMH%a%nHmwmI33nJM(>4LznvY*k&C0{8f*%?zggpDgkuz&JBx{9mfb@wegEl2v!=}Sq2Gaty0<)UrOT0{MZtZ~j5y&w zXlYa_jY)I_+VA-^#mEox#+G>UgvM!Ac8zI<%JRXM_73Q!#i3O|)lOP*qBeJG#BST0 zqohi)O!|$|2SeJQo(w6w7%*92S})XfnhrH_Z8qe!G5>CglP=nI7JAOW?(Z29;pXJ9 zR9`KzQ=WEhy*)WH>$;7Cdz|>*i>=##0bB)oU0OR>>N<21e4rMCHDemNi2LD>Nc$;& zQRFthpWniC1J6@Zh~iJCoLOxN`oCKD5Q4r%ynwgUKPlIEd#?QViIqovY|czyK8>6B zSP%{2-<;%;1`#0mG^B(8KbtXF;Nf>K#Di72UWE4gQ%(_26Koiad)q$xRL~?pN71ZZ zujaaCx~jXjygw;rI!WB=xrOJO6HJ!!w}7eiivtCg5K|F6$EXa)=xUC za^JXSX98W`7g-tm@uo|BKj39Dl;sg5ta;4qjo^pCh~{-HdLl6qI9Ix6f$+qiZ$}s= zNguKrU;u+T@ko(Vr1>)Q%h$?UKXCY>3se%&;h2osl2D zE4A9bd7_|^njDd)6cI*FupHpE3){4NQ*$k*cOWZ_?CZ>Z4_fl@n(mMnYK62Q1d@+I zr&O))G4hMihgBqRIAJkLdk(p(D~X{-oBUA+If@B}j& zsHbeJ3RzTq96lB7d($h$xTeZ^gP0c{t!Y0c)aQE;$FY2!mACg!GDEMKXFOPI^)nHZ z`aSPJpvV0|bbrzhWWkuPURlDeN%VT8tndV8?d)eN*i4I@u zVKl^6{?}A?P)Fsy?3oi#clf}L18t;TjNI2>eI&(ezDK7RyqFxcv%>?oxUlonv(px) z$vnPzRH`y5A(x!yOIfL0bmgeMQB$H5wenx~!ujQK*nUBW;@Em&6Xv2%s(~H5WcU2R z;%Nw<$tI)a`Ve!>x+qegJnQsN2N7HaKzrFqM>`6R*gvh%O*-%THt zrB$Nk;lE;z{s{r^PPm5qz(&lM{sO*g+W{sK+m3M_z=4=&CC>T`{X}1Vg2PEfSj2x_ zmT*(x;ov%3F?qoEeeM>dUn$a*?SIGyO8m806J1W1o+4HRhc2`9$s6hM#qAm zChQ87b~GEw{ADfs+5}FJ8+|bIlIv(jT$Ap#hSHoXdd9#w<#cA<1Rkq^*EEkknUd4& zoIWIY)sAswy6fSERVm&!SO~#iN$OgOX*{9@_BWFyJTvC%S++ilSfCrO(?u=Dc?CXZ zzCG&0yVR{Z`|ZF0eEApWEo#s9osV>F{uK{QA@BES#&;#KsScf>y zvs?vIbI>VrT<*!;XmQS=bhq%46-aambZ(8KU-wOO2=en~D}MCToB_u;Yz{)1ySrPZ z@=$}EvjTdzTWU7c0ZI6L8=yP+YRD_eMMos}b5vY^S*~VZysrkq<`cK3>>v%uy7jgq z0ilW9KjVDHLv0b<1K_`1IkbTOINs0=m-22c%M~l=^S}%hbli-3?BnNq?b`hx^HX2J zIe6ECljRL0uBWb`%{EA=%!i^4sMcj+U_TaTZRb+~GOk z^ZW!nky0n*Wb*r+Q|9H@ml@Z5gU&W`(z4-j!OzC1wOke`TRAYGZVl$PmQ16{3196( zO*?`--I}Qf(2HIwb2&1FB^!faPA2=sLg(@6P4mN)>Dc3i(B0;@O-y2;lM4akD>@^v z=u>*|!s&9zem70g7zfw9FXl1bpJW(C#5w#uy5!V?Q(U35A~$dR%LDVnq@}kQm13{} zd53q3N(s$Eu{R}k2esbftfjfOITCL;jWa$}(mmm}d(&7JZ6d3%IABCapFFYjdEjdK z&4Edqf$G^MNAtL=uCDRs&Fu@FXRgX{*0<(@c3|PNHa>L%zvxWS={L8%qw`STm+=Rd zA}FLspESSIpE_^41~#5yI2bJ=9`oc;GIL!JuW&7YetZ?0H}$$%8rW@*J37L-~Rsx!)8($nI4 zZhcZ2^=Y+p4YPl%j!nFJA|*M^gc(0o$i3nlphe+~-_m}jVkRN{spFs(o0ajW@f3K{ zDV!#BwL322CET$}Y}^0ixYj2w>&Xh12|R8&yEw|wLDvF!lZ#dOTHM9pK6@Nm-@9Lnng4ZHBgBSrr7KI8YCC9DX5Kg|`HsiwJHg2(7#nS;A{b3tVO?Z% za{m5b3rFV6EpX;=;n#wltDv1LE*|g5pQ+OY&*6qCJZc5oDS6Z6JD#6F)bWxZSF@q% z+1WV;m!lRB!n^PC>RgQCI#D1br_o^#iPk>;K2hB~0^<~)?p}LG%kigm@moD#q3PE+ zA^Qca)(xnqw6x>XFhV6ku9r$E>bWNrVH9fum0?4s?Rn2LG{Vm_+QJHse6xa%nzQ?k zKug4PW~#Gtb;#5+9!QBgyB@q=sk9=$S{4T>wjFICStOM?__fr+Kei1 z3j~xPqW;W@YkiUM;HngG!;>@AITg}vAE`M2Pj9Irl4w1fo4w<|Bu!%rh%a(Ai^Zhi zs92>v5;@Y(Zi#RI*ua*h`d_7;byQSa*v9E{2x$<-_=5Z<7{%)}4XExANcz@rK69T0x3%H<@frW>RA8^swA+^a(FxK| zFl3LD*ImHN=XDUkrRhp6RY5$rQ{bRgSO*(vEHYV)3Mo6Jy3puiLmU&g82p{qr0F?ohmbz)f2r{X2|T2 z$4fdQ=>0BeKbiVM!e-lIIs8wVTuC_m7}y4A_%ikI;Wm5$9j(^Y z(cD%U%k)X>_>9~t8;pGzL6L-fmQO@K; zo&vQzMlgY95;1BSkngY)e{`n0!NfVgf}2mB3t}D9@*N;FQ{HZ3Pb%BK6;5#-O|WI( zb6h@qTLU~AbVW#_6?c!?Dj65Now7*pU{h!1+eCV^KCuPAGs28~3k@ueL5+u|Z-7}t z9|lskE`4B7W8wMs@xJa{#bsCGDFoRSNSnmNYB&U7 zVGKWe%+kFB6kb)e;TyHfqtU6~fRg)f|>=5(N36)0+C z`hv65J<$B}WUc!wFAb^QtY31yNleq4dzmG`1wHTj=c*=hay9iD071Hc?oYoUk|M*_ zU1GihAMBsM@5rUJ(qS?9ZYJ6@{bNqJ`2Mr+5#hKf?doa?F|+^IR!8lq9)wS3tF_9n zW_?hm)G(M+MYb?V9YoX^_mu5h-LP^TL^!Q9Z7|@sO(rg_4+@=PdI)WL(B7`!K^ND- z-uIuVDCVEdH_C@c71YGYT^_Scf_dhB8Z2Xy6vGtBSlYud9vggOqv^L~F{BraSE_t} zIkP+Hp2&nH^-MNEs}^`oMLy11`PQW$T|K(`Bu*(f@)mv1-qY(_YG&J2M2<7k;;RK~ zL{Fqj9yCz8(S{}@c)S!65aF<=&eLI{hAMErCx&>i7OeDN>okvegO87OaG{Jmi<|}D zaT@b|0X{d@OIJ7zvT>r+eTzgLq~|Dpu)Z&db-P4z*`M$UL51lf>FLlq6rfG)%doyp z)3kk_YIM!03eQ8Vu_2fg{+osaEJPtJ-s36R+5_AEG12`NG)IQ#TF9c@$99%0iye+ zUzZ57=m2)$D(5Nx!n)=5Au&O0BBgwxIBaeI(mro$#&UGCr<;C{UjJVAbVi%|+WP(a zL$U@TYCxJ=1{Z~}rnW;7UVb7+ZnzgmrogDxhjLGo>c~MiJAWs&&;AGg@%U?Y^0JhL ze(x6Z74JG6FlOFK(T}SXQfhr}RIFl@QXKnIcXYF)5|V~e-}suHILKT-k|<*~Ij|VF zC;t@=uj=hot~*!C68G8hTA%8SzOfETOXQ|3FSaIEjvBJp(A)7SWUi5!Eu#yWgY+;n zlm<$+UDou*V+246_o#V4kMdto8hF%%Lki#zPh}KYXmMf?hrN0;>Mv%`@{0Qn`Ujp) z=lZe+13>^Q!9zT);H<(#bIeRWz%#*}sgUX9P|9($kexOyKIOc`dLux}c$7It4u|Rl z6SSkY*V~g_B-hMPo_ak>>z@AVQ(_N)VY2kB3IZ0G(iDUYw+2d7W^~(Jq}KY=JnWS( z#rzEa&0uNhJ>QE8iiyz;n2H|SV#Og+wEZv=f2%1ELX!SX-(d3tEj$5$1}70Mp<&eI zCkfbByL7af=qQE@5vDVxx1}FSGt_a1DoE3SDI+G)mBAna)KBG4p8Epxl9QZ4BfdAN zFnF|Y(umr;gRgG6NLQ$?ZWgllEeeq~z^ZS7L?<(~O&$5|y)Al^iMKy}&W+eMm1W z7EMU)u^ke(A1#XCV>CZ71}P}0x)4wtHO8#JRG3MA-6g=`ZM!FcICCZ{IEw8Dm2&LQ z1|r)BUG^0GzI6f946RrBlfB1Vs)~8toZf~7)+G;pv&XiUO(%5bm)pl=p>nV^o*;&T z;}@oZSibzto$arQgfkp|z4Z($P>dTXE{4O=vY0!)kDO* zGF8a4wq#VaFpLfK!iELy@?-SeRrdz%F*}hjKcA*y@mj~VD3!it9lhRhX}5YOaR9$} z3mS%$2Be7{l(+MVx3 z(4?h;P!jnRmX9J9sYN#7i=iyj_5q7n#X(!cdqI2lnr8T$IfOW<_v`eB!d9xY1P=2q&WtOXY=D9QYteP)De?S4}FK6#6Ma z=E*V+#s8>L;8aVroK^6iKo=MH{4yEZ_>N-N z`(|;aOATba1^asjxlILk<4}f~`39dBFlxj>Dw(hMYKPO3EEt1@S`1lxFNM+J@uB7T zZ8WKjz7HF1-5&2=l=fqF-*@>n5J}jIxdDwpT?oKM3s8Nr`x8JnN-kCE?~aM1H!hAE z%%w(3kHfGwMnMmNj(SU(w42OrC-euI>Dsjk&jz3ts}WHqmMpzQ3vZrsXrZ|}+MHA7 z068obeXZTsO*6RS@o3x80E4ok``rV^Y3hr&C1;|ZZ0|*EKO`$lECUYG2gVFtUTw)R z4Um<0ZzlON`zTdvVdL#KFoMFQX*a5wM0Czp%wTtfK4Sjs)P**RW&?lP$(<}q%r68Z zS53Y!d@&~ne9O)A^tNrXHhXBkj~$8j%pT1%%mypa9AW5E&s9)rjF4@O3ytH{0z6riz|@< zB~UPh*wRFg2^7EbQrHf0y?E~dHlkOxof_a?M{LqQ^C!i2dawHTPYUE=X@2(3<=OOxs8qn_(y>pU>u^}3y&df{JarR0@VJn0f+U%UiF=$Wyq zQvnVHESil@d|8&R<%}uidGh7@u^(%?$#|&J$pvFC-n8&A>utA=n3#)yMkz+qnG3wd zP7xCnF|$9Dif@N~L)Vde3hW8W!UY0BgT2v(wzp;tlLmyk2%N|0jfG$%<;A&IVrOI< z!L)o>j>;dFaqA3pL}b-Je(bB@VJ4%!JeX@3x!i{yIeIso^=n?fDX`3bU=eG7sTc%g%ye8$v8P@yKE^XD=NYxTb zbf!Mk=h|otpqjFaA-vs5YOF-*GwWPc7VbaOW&stlANnCN8iftFMMrUdYNJ_Bnn5Vt zxfz@Ah|+4&P;reZxp;MmEI7C|FOv8NKUm8njF7Wb6Gi7DeODLl&G~}G4be&*Hi0Qw z5}77vL0P+7-B%UL@3n1&JPxW^d@vVwp?u#gVcJqY9#@-3X{ok#UfW3<1fb%FT`|)V~ggq z(3AUoUS-;7)^hCjdT0Kf{i}h)mBg4qhtHHBti=~h^n^OTH5U*XMgDLIR@sre`AaB$ zg)IGBET_4??m@cx&c~bA80O7B8CHR7(LX7%HThkeC*@vi{-pL%e)yXp!B2InafbDF zjPXf1mko3h59{lT6EEbxKO1Z5GF71)WwowO6kY|6tjSVSWdQ}NsK2x{>i|MKZK8%Q zfu&_0D;CO-Jg0#YmyfctyJ!mRJp)e#@O0mYdp|8x;G1%OZQ3Q847YWTyy|%^cpA;m zze0(5p{tMu^lDkpe?HynyO?a1$_LJl2L&mpeKu%8YvgRNr=%2z${%WThHG=vrWY@4 zsA`OP#O&)TetZ>s%h!=+CE15lOOls&nvC~$Qz0Ph7tHiP;O$i|eDwpT{cp>+)0-|; zY$|bB+Gbel>5aRN3>c0x)4U=|X+z+{ zn*_p*EQoquRL+=+p;=lm`d71&1NqBz&_ph)MXu(Nv6&XE7(RsS)^MGj5Q?Fwude-(sq zjJ>aOq!7!EN>@(fK7EE#;i_BGvli`5U;r!YA{JRodLBc6-`n8K+Fjgwb%sX;j=qHQ z7&Tr!)!{HXoO<2BQrV9Sw?JRaLXV8HrsNevvnf>Y-6|{T!pYLl7jp$-nEE z#X!4G4L#K0qG_4Z;Cj6=;b|Be$hi4JvMH!-voxqx^@8cXp`B??eFBz2lLD8RRaRGh zn7kUfy!YV~p(R|p7iC1Rdgt$_24i0cd-S8HpG|`@my70g^y`gu%#Tf_L21-k?sRRZHK&at(*ED0P8iw{7?R$9~OF$Ko;Iu5)ur5<->x!m93Eb zFYpIx60s=Wxxw=`$aS-O&dCO_9?b1yKiPCQmSQb>T)963`*U+Ydj5kI(B(B?HNP8r z*bfSBpSu)w(Z3j7HQoRjUG(+d=IaE~tv}y14zHHs|0UcN52fT8V_<@2ep_ee{QgZG zmgp8iv4V{k;~8@I%M3<#B;2R>Ef(Gg_cQM7%}0s*^)SK6!Ym+~P^58*wnwV1BW@eG z4sZLqsUvBbFsr#8u7S1r4teQ;t)Y@jnn_m5jS$CsW1um!p&PqAcc8!zyiXHVta9QC zY~wCwCF0U%xiQPD_INKtTb;A|Zf29(mu9NI;E zc-e>*1%(LSXB`g}kd`#}O;veb<(sk~RWL|f3ljxCnEZDdNSTDV6#Td({6l&y4IjKF z^}lIUq*ZUqgTPumD)RrCN{M^jhY>E~1pn|KOZ5((%F)G|*ZQ|r4zIbrEiV%42hJV8 z3xS)=!X1+=olbdGJ=yZil?oXLct8FM{(6ikLL3E%=q#O6(H$p~gQu6T8N!plf!96| z&Q3=`L~>U0zZh;z(pGR2^S^{#PrPxTRHD1RQOON&f)Siaf`GLj#UOk&(|@0?zm;Sx ztsGt8=29-MZs5CSf1l1jNFtNt5rFNZxJPvkNu~2}7*9468TWm>nN9TP&^!;J{-h)_ z7WsHH9|F%I`Pb!>KAS3jQWKfGivTVkMJLO-HUGM_a4UQ_%RgL6WZvrW+Z4ujZn;y@ zz9$=oO!7qVTaQAA^BhX&ZxS*|5dj803M=k&2%QrXda`-Q#IoZL6E(g+tN!6CA!CP* zCpWtCujIea)ENl0liwVfj)Nc<9mV%+e@=d`haoZ*`B7+PNjEbXBkv=B+Pi^~L#EO$D$ZqTiD8f<5$eyb54-(=3 zh)6i8i|jp(@OnRrY5B8t|LFXFQVQ895n*P16cEKTrT*~yLH6Z4e*bZ5otpRDri&+A zfNbK1D5@O=sm`fN=WzWyse!za5n%^+6dHPGX#8DyIK>?9qyX}2XvBWVqbP%%D)7$= z=#$WulZlZR<{m#gU7lwqK4WS1Ne$#_P{b17qe$~UOXCl>5b|6WVh;5vVnR<%d+Lnp z$uEmML38}U4vaW8>shm6CzB(Wei3s#NAWE3)a2)z@i{4jTn;;aQS)O@l{rUM`J@K& l00vQ5JBs~;vo!vr%%-k{2_Fq1Mn4QF81S)AQ99zk{{c4yR+0b! literal 0 HcmV?d00001 diff --git a/packages/react-native/template/android/gradle-wrapper.properties b/packages/react-native/template/android/gradle-wrapper.properties new file mode 100644 index 00000000000000..e6aba2515d5428 --- /dev/null +++ b/packages/react-native/template/android/gradle-wrapper.properties @@ -0,0 +1,7 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-all.zip +networkTimeout=10000 +validateDistributionUrl=true +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists From a3f238a44e7e6896d689bf370e8df483c352eb38 Mon Sep 17 00:00:00 2001 From: Nicola Corti Date: Fri, 1 Dec 2023 08:41:02 -0800 Subject: [PATCH 158/162] AGP to 8.2.0 (#41747) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41747 Let's update AGP to the latest minor Changelog: [Internal] [Changed] - AGP to 8.2.0 Reviewed By: cipolleschi Differential Revision: D51749138 fbshipit-source-id: fe473b6d1613b73e60e65848c20098e3f77d3a61 --- packages/react-native-gradle-plugin/gradle/libs.versions.toml | 2 +- packages/react-native/gradle/libs.versions.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/react-native-gradle-plugin/gradle/libs.versions.toml b/packages/react-native-gradle-plugin/gradle/libs.versions.toml index 38856f8132ecb2..985424bfa011d1 100644 --- a/packages/react-native-gradle-plugin/gradle/libs.versions.toml +++ b/packages/react-native-gradle-plugin/gradle/libs.versions.toml @@ -1,5 +1,5 @@ [versions] -agp = "8.1.4" +agp = "8.2.0" gson = "2.8.9" guava = "31.0.1-jre" javapoet = "1.13.0" diff --git a/packages/react-native/gradle/libs.versions.toml b/packages/react-native/gradle/libs.versions.toml index 35f899193977b7..b95a8de23c2755 100644 --- a/packages/react-native/gradle/libs.versions.toml +++ b/packages/react-native/gradle/libs.versions.toml @@ -5,7 +5,7 @@ targetSdk = "34" compileSdk = "34" buildTools = "34.0.0" # Dependencies versions -agp = "8.1.4" +agp = "8.2.0" androidx-annotation = "1.6.0" androidx-appcompat = "1.6.1" androidx-autofill = "1.1.0" From 75019c870743481d25d853c6f922dabd476b1a5e Mon Sep 17 00:00:00 2001 From: Arushi Kesarwani Date: Fri, 1 Dec 2023 09:38:54 -0800 Subject: [PATCH 159/162] Using UIManagerProvider instead of JSIModule in UIManagerHelper (#41738) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41738 Replacing the callsite to `context.getFabricUIManager()` in UIManagerHelper instead of `getJSIModule()` Fixing the crash by directly making `getFabricUIManager()` of `ReactContext` independent of the assertion. Reviewed By: philIip Differential Revision: D51719040 fbshipit-source-id: f9118b16614724a1d6dabe59d5c4d25dd4bdbc73 --- .../java/com/facebook/react/bridge/ReactContext.java | 4 ---- .../com/facebook/react/uimanager/UIManagerHelper.java | 9 ++++++--- .../react/animated/NativeAnimatedNodeTraversalTest.kt | 1 + 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactContext.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactContext.java index 78c385ce157643..f1f1c83dffc681 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactContext.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactContext.java @@ -564,10 +564,6 @@ public boolean isBridgeless() { * @return The UIManager when CatalystInstance is active. */ public @Nullable UIManager getFabricUIManager() { - if (!hasActiveReactInstance()) { - throw new IllegalStateException( - "Unable to retrieve a UIManager if CatalystInstance is not active."); - } UIManager uiManager = mCatalystInstance.getFabricUIManager(); return uiManager != null ? uiManager diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerHelper.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerHelper.java index c4a3902d1e3d6a..daa1295fc7b59f 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerHelper.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerHelper.java @@ -17,7 +17,6 @@ import androidx.annotation.Nullable; import androidx.core.view.ViewCompat; import com.facebook.react.bridge.CatalystInstance; -import com.facebook.react.bridge.JSIModuleType; import com.facebook.react.bridge.ReactContext; import com.facebook.react.bridge.ReactNoCrashSoftException; import com.facebook.react.bridge.ReactSoftExceptionLogger; @@ -53,7 +52,11 @@ private static UIManager getUIManager( @UIManagerType int uiManagerType, boolean returnNullIfCatalystIsInactive) { if (context.isBridgeless()) { - @Nullable UIManager uiManager = (UIManager) context.getJSIModule(JSIModuleType.UIManager); + if (!context.hasActiveReactInstance()) { + throw new IllegalStateException( + "Unable to retrieve a UIManager if CatalystInstance is not active."); + } + @Nullable UIManager uiManager = context.getFabricUIManager(); if (uiManager == null) { ReactSoftExceptionLogger.logSoftException( TAG, @@ -85,7 +88,7 @@ private static UIManager getUIManager( CatalystInstance catalystInstance = context.getCatalystInstance(); try { return uiManagerType == FABRIC - ? (UIManager) catalystInstance.getJSIModule(JSIModuleType.UIManager) + ? context.getFabricUIManager() : catalystInstance.getNativeModule(UIManagerModule.class); } catch (IllegalArgumentException ex) { // TODO T67518514 Clean this up once we migrate everything over to bridgeless mode diff --git a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/animated/NativeAnimatedNodeTraversalTest.kt b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/animated/NativeAnimatedNodeTraversalTest.kt index b5eb4fc91d6c1e..96d15479cd901e 100644 --- a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/animated/NativeAnimatedNodeTraversalTest.kt +++ b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/animated/NativeAnimatedNodeTraversalTest.kt @@ -83,6 +83,7 @@ class NativeAnimatedNodeTraversalTest { whenever(catalystInstanceMock.getJSIModule(any(JSIModuleType::class.java))).thenAnswer { uiManagerMock } + whenever(reactApplicationContextMock.getFabricUIManager()).thenAnswer { uiManagerMock } whenever(catalystInstanceMock.getNativeModule(UIManagerModule::class.java)).thenAnswer { uiManagerMock } From 84b0027028b38e560690928e10e2c86a28db1a92 Mon Sep 17 00:00:00 2001 From: Thibault Malbranche Date: Fri, 1 Dec 2023 10:32:55 -0800 Subject: [PATCH 160/162] feat: improve e2e local testing script (#41751) Summary: iOS?ios?android?Android? Always making typos when using the local testing script with the platform argument... No more! ## Changelog: [INTERNAL][ADDED] - Improved E2E local testing script to be more flexible Pull Request resolved: https://github.com/facebook/react-native/pull/41751 Reviewed By: cortinico Differential Revision: D51758529 Pulled By: huntie fbshipit-source-id: d9e633567a59fcfac1057cf1f21714ccef27ebb2 --- scripts/test-e2e-local.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/scripts/test-e2e-local.js b/scripts/test-e2e-local.js index 410cb199283cd2..353490696d47cf 100644 --- a/scripts/test-e2e-local.js +++ b/scripts/test-e2e-local.js @@ -37,8 +37,9 @@ const argv = yargs }) .option('p', { alias: 'platform', - default: 'iOS', - choices: ['iOS', 'Android'], + default: 'ios', + coerce: platform => platform.toLowerCase(), + choices: ['ios', 'android'], }) .option('h', { alias: 'hermes', @@ -167,7 +168,7 @@ async function testRNTester(circleCIArtifacts, onReleaseBranch) { // see also https://github.com/shelljs/shelljs/issues/86 pushd('packages/rn-tester'); - if (argv.platform === 'iOS') { + if (argv.platform === 'ios') { await testRNTesterIOS(circleCIArtifacts, onReleaseBranch); } else { await testRNTesterAndroid(circleCIArtifacts); @@ -248,7 +249,7 @@ async function testRNTestProject(circleCIArtifacts) { ); } - if (argv.platform === 'iOS') { + if (argv.platform === 'ios') { // doing the pod install here so that it's easier to play around RNTestProject cd('ios'); exec('bundle install'); From 288708f4114f3b7a695baaa2bd4bfd9263c8918e Mon Sep 17 00:00:00 2001 From: Christoph Purrer Date: Fri, 1 Dec 2023 10:34:12 -0800 Subject: [PATCH 161/162] react-native: Platformize android|ios textinput (#41600) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41600 Changelog: [Internal] Reviewed By: cipolleschi Differential Revision: D51515743 fbshipit-source-id: 156d9119d84d82f31b62b89b1916365547ce0afe --- packages/react-native/React/React-RCTFabric.podspec | 2 +- packages/react-native/ReactCommon/React-Fabric.podspec | 5 ++--- packages/react-native/ReactCommon/React-FabricImage.podspec | 2 +- .../react/renderer/components/textinput/CMakeLists.txt | 4 ++-- .../androidtextinput/AndroidTextInputComponentDescriptor.h | 0 .../androidtextinput/AndroidTextInputEventEmitter.h | 0 .../components/androidtextinput/AndroidTextInputProps.cpp | 0 .../components/androidtextinput/AndroidTextInputProps.h | 0 .../androidtextinput/AndroidTextInputShadowNode.cpp | 0 .../components/androidtextinput/AndroidTextInputShadowNode.h | 0 .../components/androidtextinput/AndroidTextInputState.cpp | 0 .../components/androidtextinput/AndroidTextInputState.h | 0 .../components/iostextinput/TextInputComponentDescriptor.h | 0 .../components/iostextinput/TextInputEventEmitter.cpp | 0 .../renderer/components/iostextinput/TextInputEventEmitter.h | 0 .../renderer/components/iostextinput/TextInputProps.cpp | 0 .../react/renderer/components/iostextinput/TextInputProps.h | 0 .../renderer/components/iostextinput/TextInputShadowNode.cpp | 0 .../renderer/components/iostextinput/TextInputShadowNode.h | 0 .../renderer/components/iostextinput/TextInputState.cpp | 0 .../react/renderer/components/iostextinput/TextInputState.h | 0 .../react/renderer/components/iostextinput/conversions.h | 0 .../ios}/react/renderer/components/iostextinput/primitives.h | 0 .../renderer/components/iostextinput/propsConversions.h | 0 24 files changed, 6 insertions(+), 7 deletions(-) rename packages/react-native/ReactCommon/react/renderer/components/textinput/{androidtextinput => platform/android}/react/renderer/components/androidtextinput/AndroidTextInputComponentDescriptor.h (100%) rename packages/react-native/ReactCommon/react/renderer/components/textinput/{androidtextinput => platform/android}/react/renderer/components/androidtextinput/AndroidTextInputEventEmitter.h (100%) rename packages/react-native/ReactCommon/react/renderer/components/textinput/{androidtextinput => platform/android}/react/renderer/components/androidtextinput/AndroidTextInputProps.cpp (100%) rename packages/react-native/ReactCommon/react/renderer/components/textinput/{androidtextinput => platform/android}/react/renderer/components/androidtextinput/AndroidTextInputProps.h (100%) rename packages/react-native/ReactCommon/react/renderer/components/textinput/{androidtextinput => platform/android}/react/renderer/components/androidtextinput/AndroidTextInputShadowNode.cpp (100%) rename packages/react-native/ReactCommon/react/renderer/components/textinput/{androidtextinput => platform/android}/react/renderer/components/androidtextinput/AndroidTextInputShadowNode.h (100%) rename packages/react-native/ReactCommon/react/renderer/components/textinput/{androidtextinput => platform/android}/react/renderer/components/androidtextinput/AndroidTextInputState.cpp (100%) rename packages/react-native/ReactCommon/react/renderer/components/textinput/{androidtextinput => platform/android}/react/renderer/components/androidtextinput/AndroidTextInputState.h (100%) rename packages/react-native/ReactCommon/react/renderer/components/textinput/{iostextinput => platform/ios}/react/renderer/components/iostextinput/TextInputComponentDescriptor.h (100%) rename packages/react-native/ReactCommon/react/renderer/components/textinput/{iostextinput => platform/ios}/react/renderer/components/iostextinput/TextInputEventEmitter.cpp (100%) rename packages/react-native/ReactCommon/react/renderer/components/textinput/{iostextinput => platform/ios}/react/renderer/components/iostextinput/TextInputEventEmitter.h (100%) rename packages/react-native/ReactCommon/react/renderer/components/textinput/{iostextinput => platform/ios}/react/renderer/components/iostextinput/TextInputProps.cpp (100%) rename packages/react-native/ReactCommon/react/renderer/components/textinput/{iostextinput => platform/ios}/react/renderer/components/iostextinput/TextInputProps.h (100%) rename packages/react-native/ReactCommon/react/renderer/components/textinput/{iostextinput => platform/ios}/react/renderer/components/iostextinput/TextInputShadowNode.cpp (100%) rename packages/react-native/ReactCommon/react/renderer/components/textinput/{iostextinput => platform/ios}/react/renderer/components/iostextinput/TextInputShadowNode.h (100%) rename packages/react-native/ReactCommon/react/renderer/components/textinput/{iostextinput => platform/ios}/react/renderer/components/iostextinput/TextInputState.cpp (100%) rename packages/react-native/ReactCommon/react/renderer/components/textinput/{iostextinput => platform/ios}/react/renderer/components/iostextinput/TextInputState.h (100%) rename packages/react-native/ReactCommon/react/renderer/components/textinput/{iostextinput => platform/ios}/react/renderer/components/iostextinput/conversions.h (100%) rename packages/react-native/ReactCommon/react/renderer/components/textinput/{iostextinput => platform/ios}/react/renderer/components/iostextinput/primitives.h (100%) rename packages/react-native/ReactCommon/react/renderer/components/textinput/{iostextinput => platform/ios}/react/renderer/components/iostextinput/propsConversions.h (100%) diff --git a/packages/react-native/React/React-RCTFabric.podspec b/packages/react-native/React/React-RCTFabric.podspec index e6dbb8cb3d4db8..9e7b934711d76f 100644 --- a/packages/react-native/React/React-RCTFabric.podspec +++ b/packages/react-native/React/React-RCTFabric.podspec @@ -75,7 +75,7 @@ Pod::Spec.new do |s| add_dependency(s, "React-FabricImage") add_dependency(s, "React-Fabric", :additional_framework_paths => [ "react/renderer/textlayoutmanager/platform/ios", - "react/renderer/components/textinput/iostextinput", + "react/renderer/components/textinput/platform/ios", "react/renderer/components/view/platform/cxx", "react/renderer/imagemanager/platform/ios", ]) diff --git a/packages/react-native/ReactCommon/React-Fabric.podspec b/packages/react-native/ReactCommon/React-Fabric.podspec index eb47078b78c891..c9ee015fddcd13 100644 --- a/packages/react-native/ReactCommon/React-Fabric.podspec +++ b/packages/react-native/ReactCommon/React-Fabric.podspec @@ -97,7 +97,7 @@ Pod::Spec.new do |s| if ENV['USE_FRAMEWORKS'] header_search_path = header_search_path + [ "\"$(PODS_TARGET_SRCROOT)/react/renderer/textlayoutmanager/platform/ios\"", - "\"$(PODS_TARGET_SRCROOT)/react/renderer/components/textinput/iostextinput\"", + "\"$(PODS_TARGET_SRCROOT)/react/renderer/components/textinput/platform/ios\"", "\"$(PODS_TARGET_SRCROOT)/react/renderer/components/view/platform/cxx\"", ] end @@ -198,8 +198,7 @@ Pod::Spec.new do |s| ss.subspec "textinput" do |sss| sss.dependency folly_dep_name, folly_version sss.compiler_flags = folly_compiler_flags - sss.source_files = "react/renderer/components/textinput/iostextinput/**/*.{m,mm,cpp,h}" - sss.exclude_files = "react/renderer/components/textinput/iostextinput/tests" + sss.source_files = "react/renderer/components/textinput/platform/ios/**/*.{m,mm,cpp,h}" sss.header_dir = "react/renderer/components/iostextinput" end diff --git a/packages/react-native/ReactCommon/React-FabricImage.podspec b/packages/react-native/ReactCommon/React-FabricImage.podspec index 8d645c329fcb26..a32f07c8b9207a 100644 --- a/packages/react-native/ReactCommon/React-FabricImage.podspec +++ b/packages/react-native/ReactCommon/React-FabricImage.podspec @@ -35,7 +35,7 @@ if ENV['USE_FRAMEWORKS'] header_search_path = header_search_path + [ "\"$(PODS_TARGET_SRCROOT)\"", "\"$(PODS_TARGET_SRCROOT)/react/renderer/textlayoutmanager/platform/ios\"", - "\"$(PODS_TARGET_SRCROOT)/react/renderer/components/textinput/iostextinput\"", + "\"$(PODS_TARGET_SRCROOT)/react/renderer/components/textinput/platform/ios\"", # "\"$(PODS_CONFIGURATION_BUILD_DIR)/React-Codegen/React_Codegen.framework/Headers\"", ] end diff --git a/packages/react-native/ReactCommon/react/renderer/components/textinput/CMakeLists.txt b/packages/react-native/ReactCommon/react/renderer/components/textinput/CMakeLists.txt index 39e2a428bb64e6..3f780470383581 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/textinput/CMakeLists.txt +++ b/packages/react-native/ReactCommon/react/renderer/components/textinput/CMakeLists.txt @@ -15,12 +15,12 @@ add_compile_options( -Wno-gnu-zero-variadic-macro-arguments -DLOG_TAG=\"Fabric\") -file(GLOB rrc_textinput_SRC CONFIGURE_DEPENDS androidtextinput/react/renderer/components/androidtextinput/*.cpp) +file(GLOB rrc_textinput_SRC CONFIGURE_DEPENDS platform/android/react/renderer/components/androidtextinput/*.cpp) add_library(rrc_textinput SHARED ${rrc_textinput_SRC}) target_include_directories(rrc_textinput PUBLIC - ${CMAKE_CURRENT_SOURCE_DIR}/androidtextinput/ + ${CMAKE_CURRENT_SOURCE_DIR}/platform/android/ ) target_link_libraries(rrc_textinput diff --git a/packages/react-native/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputComponentDescriptor.h b/packages/react-native/ReactCommon/react/renderer/components/textinput/platform/android/react/renderer/components/androidtextinput/AndroidTextInputComponentDescriptor.h similarity index 100% rename from packages/react-native/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputComponentDescriptor.h rename to packages/react-native/ReactCommon/react/renderer/components/textinput/platform/android/react/renderer/components/androidtextinput/AndroidTextInputComponentDescriptor.h diff --git a/packages/react-native/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputEventEmitter.h b/packages/react-native/ReactCommon/react/renderer/components/textinput/platform/android/react/renderer/components/androidtextinput/AndroidTextInputEventEmitter.h similarity index 100% rename from packages/react-native/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputEventEmitter.h rename to packages/react-native/ReactCommon/react/renderer/components/textinput/platform/android/react/renderer/components/androidtextinput/AndroidTextInputEventEmitter.h diff --git a/packages/react-native/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputProps.cpp b/packages/react-native/ReactCommon/react/renderer/components/textinput/platform/android/react/renderer/components/androidtextinput/AndroidTextInputProps.cpp similarity index 100% rename from packages/react-native/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputProps.cpp rename to packages/react-native/ReactCommon/react/renderer/components/textinput/platform/android/react/renderer/components/androidtextinput/AndroidTextInputProps.cpp diff --git a/packages/react-native/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputProps.h b/packages/react-native/ReactCommon/react/renderer/components/textinput/platform/android/react/renderer/components/androidtextinput/AndroidTextInputProps.h similarity index 100% rename from packages/react-native/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputProps.h rename to packages/react-native/ReactCommon/react/renderer/components/textinput/platform/android/react/renderer/components/androidtextinput/AndroidTextInputProps.h diff --git a/packages/react-native/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputShadowNode.cpp b/packages/react-native/ReactCommon/react/renderer/components/textinput/platform/android/react/renderer/components/androidtextinput/AndroidTextInputShadowNode.cpp similarity index 100% rename from packages/react-native/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputShadowNode.cpp rename to packages/react-native/ReactCommon/react/renderer/components/textinput/platform/android/react/renderer/components/androidtextinput/AndroidTextInputShadowNode.cpp diff --git a/packages/react-native/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputShadowNode.h b/packages/react-native/ReactCommon/react/renderer/components/textinput/platform/android/react/renderer/components/androidtextinput/AndroidTextInputShadowNode.h similarity index 100% rename from packages/react-native/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputShadowNode.h rename to packages/react-native/ReactCommon/react/renderer/components/textinput/platform/android/react/renderer/components/androidtextinput/AndroidTextInputShadowNode.h diff --git a/packages/react-native/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputState.cpp b/packages/react-native/ReactCommon/react/renderer/components/textinput/platform/android/react/renderer/components/androidtextinput/AndroidTextInputState.cpp similarity index 100% rename from packages/react-native/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputState.cpp rename to packages/react-native/ReactCommon/react/renderer/components/textinput/platform/android/react/renderer/components/androidtextinput/AndroidTextInputState.cpp diff --git a/packages/react-native/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputState.h b/packages/react-native/ReactCommon/react/renderer/components/textinput/platform/android/react/renderer/components/androidtextinput/AndroidTextInputState.h similarity index 100% rename from packages/react-native/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputState.h rename to packages/react-native/ReactCommon/react/renderer/components/textinput/platform/android/react/renderer/components/androidtextinput/AndroidTextInputState.h diff --git a/packages/react-native/ReactCommon/react/renderer/components/textinput/iostextinput/react/renderer/components/iostextinput/TextInputComponentDescriptor.h b/packages/react-native/ReactCommon/react/renderer/components/textinput/platform/ios/react/renderer/components/iostextinput/TextInputComponentDescriptor.h similarity index 100% rename from packages/react-native/ReactCommon/react/renderer/components/textinput/iostextinput/react/renderer/components/iostextinput/TextInputComponentDescriptor.h rename to packages/react-native/ReactCommon/react/renderer/components/textinput/platform/ios/react/renderer/components/iostextinput/TextInputComponentDescriptor.h diff --git a/packages/react-native/ReactCommon/react/renderer/components/textinput/iostextinput/react/renderer/components/iostextinput/TextInputEventEmitter.cpp b/packages/react-native/ReactCommon/react/renderer/components/textinput/platform/ios/react/renderer/components/iostextinput/TextInputEventEmitter.cpp similarity index 100% rename from packages/react-native/ReactCommon/react/renderer/components/textinput/iostextinput/react/renderer/components/iostextinput/TextInputEventEmitter.cpp rename to packages/react-native/ReactCommon/react/renderer/components/textinput/platform/ios/react/renderer/components/iostextinput/TextInputEventEmitter.cpp diff --git a/packages/react-native/ReactCommon/react/renderer/components/textinput/iostextinput/react/renderer/components/iostextinput/TextInputEventEmitter.h b/packages/react-native/ReactCommon/react/renderer/components/textinput/platform/ios/react/renderer/components/iostextinput/TextInputEventEmitter.h similarity index 100% rename from packages/react-native/ReactCommon/react/renderer/components/textinput/iostextinput/react/renderer/components/iostextinput/TextInputEventEmitter.h rename to packages/react-native/ReactCommon/react/renderer/components/textinput/platform/ios/react/renderer/components/iostextinput/TextInputEventEmitter.h diff --git a/packages/react-native/ReactCommon/react/renderer/components/textinput/iostextinput/react/renderer/components/iostextinput/TextInputProps.cpp b/packages/react-native/ReactCommon/react/renderer/components/textinput/platform/ios/react/renderer/components/iostextinput/TextInputProps.cpp similarity index 100% rename from packages/react-native/ReactCommon/react/renderer/components/textinput/iostextinput/react/renderer/components/iostextinput/TextInputProps.cpp rename to packages/react-native/ReactCommon/react/renderer/components/textinput/platform/ios/react/renderer/components/iostextinput/TextInputProps.cpp diff --git a/packages/react-native/ReactCommon/react/renderer/components/textinput/iostextinput/react/renderer/components/iostextinput/TextInputProps.h b/packages/react-native/ReactCommon/react/renderer/components/textinput/platform/ios/react/renderer/components/iostextinput/TextInputProps.h similarity index 100% rename from packages/react-native/ReactCommon/react/renderer/components/textinput/iostextinput/react/renderer/components/iostextinput/TextInputProps.h rename to packages/react-native/ReactCommon/react/renderer/components/textinput/platform/ios/react/renderer/components/iostextinput/TextInputProps.h diff --git a/packages/react-native/ReactCommon/react/renderer/components/textinput/iostextinput/react/renderer/components/iostextinput/TextInputShadowNode.cpp b/packages/react-native/ReactCommon/react/renderer/components/textinput/platform/ios/react/renderer/components/iostextinput/TextInputShadowNode.cpp similarity index 100% rename from packages/react-native/ReactCommon/react/renderer/components/textinput/iostextinput/react/renderer/components/iostextinput/TextInputShadowNode.cpp rename to packages/react-native/ReactCommon/react/renderer/components/textinput/platform/ios/react/renderer/components/iostextinput/TextInputShadowNode.cpp diff --git a/packages/react-native/ReactCommon/react/renderer/components/textinput/iostextinput/react/renderer/components/iostextinput/TextInputShadowNode.h b/packages/react-native/ReactCommon/react/renderer/components/textinput/platform/ios/react/renderer/components/iostextinput/TextInputShadowNode.h similarity index 100% rename from packages/react-native/ReactCommon/react/renderer/components/textinput/iostextinput/react/renderer/components/iostextinput/TextInputShadowNode.h rename to packages/react-native/ReactCommon/react/renderer/components/textinput/platform/ios/react/renderer/components/iostextinput/TextInputShadowNode.h diff --git a/packages/react-native/ReactCommon/react/renderer/components/textinput/iostextinput/react/renderer/components/iostextinput/TextInputState.cpp b/packages/react-native/ReactCommon/react/renderer/components/textinput/platform/ios/react/renderer/components/iostextinput/TextInputState.cpp similarity index 100% rename from packages/react-native/ReactCommon/react/renderer/components/textinput/iostextinput/react/renderer/components/iostextinput/TextInputState.cpp rename to packages/react-native/ReactCommon/react/renderer/components/textinput/platform/ios/react/renderer/components/iostextinput/TextInputState.cpp diff --git a/packages/react-native/ReactCommon/react/renderer/components/textinput/iostextinput/react/renderer/components/iostextinput/TextInputState.h b/packages/react-native/ReactCommon/react/renderer/components/textinput/platform/ios/react/renderer/components/iostextinput/TextInputState.h similarity index 100% rename from packages/react-native/ReactCommon/react/renderer/components/textinput/iostextinput/react/renderer/components/iostextinput/TextInputState.h rename to packages/react-native/ReactCommon/react/renderer/components/textinput/platform/ios/react/renderer/components/iostextinput/TextInputState.h diff --git a/packages/react-native/ReactCommon/react/renderer/components/textinput/iostextinput/react/renderer/components/iostextinput/conversions.h b/packages/react-native/ReactCommon/react/renderer/components/textinput/platform/ios/react/renderer/components/iostextinput/conversions.h similarity index 100% rename from packages/react-native/ReactCommon/react/renderer/components/textinput/iostextinput/react/renderer/components/iostextinput/conversions.h rename to packages/react-native/ReactCommon/react/renderer/components/textinput/platform/ios/react/renderer/components/iostextinput/conversions.h diff --git a/packages/react-native/ReactCommon/react/renderer/components/textinput/iostextinput/react/renderer/components/iostextinput/primitives.h b/packages/react-native/ReactCommon/react/renderer/components/textinput/platform/ios/react/renderer/components/iostextinput/primitives.h similarity index 100% rename from packages/react-native/ReactCommon/react/renderer/components/textinput/iostextinput/react/renderer/components/iostextinput/primitives.h rename to packages/react-native/ReactCommon/react/renderer/components/textinput/platform/ios/react/renderer/components/iostextinput/primitives.h diff --git a/packages/react-native/ReactCommon/react/renderer/components/textinput/iostextinput/react/renderer/components/iostextinput/propsConversions.h b/packages/react-native/ReactCommon/react/renderer/components/textinput/platform/ios/react/renderer/components/iostextinput/propsConversions.h similarity index 100% rename from packages/react-native/ReactCommon/react/renderer/components/textinput/iostextinput/react/renderer/components/iostextinput/propsConversions.h rename to packages/react-native/ReactCommon/react/renderer/components/textinput/platform/ios/react/renderer/components/iostextinput/propsConversions.h From c30f2b6205a04bd948bd2bf8a243f82268bd7481 Mon Sep 17 00:00:00 2001 From: Arushi Kesarwani Date: Fri, 1 Dec 2023 12:19:07 -0800 Subject: [PATCH 162/162] Refactor DefaultReactNativeHost to use the new way of Fabric initialization (#41739) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41739 Refactoring `DefaultReactNativeHost` to use the new way of Fabric initialization through `FabricUIManagerProviderImpl` Reviewed By: philIip Differential Revision: D51719555 fbshipit-source-id: bad471a8a273accecb0641ccaa77223534cd45fd --- .../react/defaults/DefaultReactNativeHost.kt | 36 ++++++------------- 1 file changed, 11 insertions(+), 25 deletions(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultReactNativeHost.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultReactNativeHost.kt index 60c1e791912b42..e5683059a68bdb 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultReactNativeHost.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultReactNativeHost.kt @@ -14,12 +14,8 @@ import com.facebook.react.ReactHost import com.facebook.react.ReactInstanceManager import com.facebook.react.ReactNativeHost import com.facebook.react.ReactPackageTurboModuleManagerDelegate -import com.facebook.react.bridge.JSIModulePackage -import com.facebook.react.bridge.JSIModuleProvider -import com.facebook.react.bridge.JSIModuleSpec -import com.facebook.react.bridge.JSIModuleType import com.facebook.react.bridge.ReactApplicationContext -import com.facebook.react.bridge.UIManager +import com.facebook.react.bridge.UIManagerProvider import com.facebook.react.fabric.ComponentFactory import com.facebook.react.fabric.FabricUIManagerProviderImpl import com.facebook.react.fabric.ReactNativeConfig @@ -46,30 +42,20 @@ protected constructor( null } - override fun getJSIModulePackage(): JSIModulePackage? = + override fun getUIManagerProvider(): UIManagerProvider? = if (isNewArchEnabled) { - JSIModulePackage { reactApplicationContext: ReactApplicationContext, _ -> - listOf( - object : JSIModuleSpec { - override fun getJSIModuleType(): JSIModuleType = JSIModuleType.UIManager + UIManagerProvider { reactApplicationContext: ReactApplicationContext -> + val componentFactory = ComponentFactory() - override fun getJSIModuleProvider(): JSIModuleProvider { - val componentFactory = ComponentFactory() + DefaultComponentsRegistry.register(componentFactory) - DefaultComponentsRegistry.register(componentFactory) + val reactInstanceManager: ReactInstanceManager = getReactInstanceManager() - val reactInstanceManager: ReactInstanceManager = getReactInstanceManager() - - val viewManagers = - reactInstanceManager.getOrCreateViewManagers(reactApplicationContext) - val viewManagerRegistry = ViewManagerRegistry(viewManagers) - return FabricUIManagerProviderImpl( - reactApplicationContext, - componentFactory, - ReactNativeConfig.DEFAULT_CONFIG, - viewManagerRegistry) - } - }) + val viewManagers = reactInstanceManager.getOrCreateViewManagers(reactApplicationContext) + val viewManagerRegistry = ViewManagerRegistry(viewManagers) + FabricUIManagerProviderImpl( + componentFactory, ReactNativeConfig.DEFAULT_CONFIG, viewManagerRegistry) + .createUIManager(reactApplicationContext) } } else { null