diff --git a/ReactCommon/better/BUCK b/ReactCommon/better/BUCK new file mode 100644 index 000000000..65995e06e --- /dev/null +++ b/ReactCommon/better/BUCK @@ -0,0 +1,55 @@ +load("@fbsource//tools/build_defs/apple:flag_defs.bzl", "get_debug_preprocessor_flags") +load( + "//tools/build_defs/oss:rn_defs.bzl", + "ANDROID", + "APPLE", + "get_apple_compiler_flags", + "get_apple_inspector_flags", + "rn_xplat_cxx_library", + "subdir_glob", +) + +APPLE_COMPILER_FLAGS = get_apple_compiler_flags() + +rn_xplat_cxx_library( + name = "better", + srcs = glob( + ["**/*.cpp"], + exclude = glob(["tests/**/*.cpp"]), + ), + headers = glob( + ["**/*.h"], + exclude = glob(["tests/**/*.h"]), + ), + header_namespace = "", + exported_headers = subdir_glob( + [ + ("", "*.h"), + ], + prefix = "better", + ), + compiler_flags = [ + "-fexceptions", + "-frtti", + "-std=c++14", + "-Wall", + ], + fbobjc_compiler_flags = APPLE_COMPILER_FLAGS, + fbobjc_preprocessor_flags = get_debug_preprocessor_flags() + get_apple_inspector_flags(), + force_static = True, + macosx_tests_override = [], + platforms = (ANDROID, APPLE), + preprocessor_flags = [ + "-DLOG_TAG=\"ReactNative\"", + "-DWITH_FBSYSTRACE=1", + ], + tests = [], + visibility = ["PUBLIC"], + deps = [ + "xplat//fbsystrace:fbsystrace", + "xplat//folly:headers_only", + "xplat//folly:memory", + "xplat//folly:molly", + "xplat//third-party/glog:glog", + ], +) diff --git a/ReactCommon/better/better.h b/ReactCommon/better/better.h new file mode 100644 index 000000000..b2f3f61f5 --- /dev/null +++ b/ReactCommon/better/better.h @@ -0,0 +1,57 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#pragma once + +namespace facebook { +namespace better { + +/* + * `Better` is a trivial collection of basic tools borrowed from other low-level + * general purpose libraries (like Folly, Abseil or Boost). The main goals of + * Better: + * - Make the codebase more portable; + * - Make the dependency list explicit (by decoupling it as a dependency list of + * Better); + * - Make relying on modern C++ patterns and tools in code simple and easy. + * - Make executing experiments with different dependencies easier. + * + * What should be part of Better and what should not? Should I add some piece of + * functionality in the Better? Here is a quick checklist. + * + * If one of the following is true, yes, go for it: + * - If some feature is already in some future C++ standard (possibly in draft + * stage) and it's already implemented in some 3rd party library. + * - If some standardized feature of C++ is implemented in the standard not in + * the most efficient way (because the standard enforces some tricky constraints + * (like always-valid iterators) which nobody uses and should use), but you have + * a library that does it right providing exact same interface. + * + * If one of the following is true, please do *NOT* do it (at least as part of + * the library): + * - You want to use some very fancy pattern that your favorite library (but + * nothing else) provides, and You want to make this pattern very command in the + * code base. Your hope is that this pattern will conquer the world and be + * a part of the C++ standard eventually. + * - You favorite library provides some general purpose container that 10x times + * faster than the standard one, so You want to use that in the code base. That + * container does not have compatible API though (because it's a clear trade-off + * with efficiency, of course). + */ + +/* + * Configuration + */ + +/* + * Enables using Folly containers instead of standard ones (such as map, vector, + * string, optional and etc.) + */ +#define BETTER_USE_FOLLY_CONTAINERS + +} // namespace better +} // namespace facebook diff --git a/ReactCommon/better/map.h b/ReactCommon/better/map.h new file mode 100644 index 000000000..4b190195d --- /dev/null +++ b/ReactCommon/better/map.h @@ -0,0 +1,45 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#pragma once + +#include + +#ifdef BETTER_USE_FOLLY_CONTAINERS + +#include + +#else + +#include + +#endif + +namespace facebook { +namespace better { + +/* + * Note: In Better, `map` aliases to `unorderd_map` because everyone agrees that + * an *ordered* map is nonsense and was a huge mistake for standardization. If + * you need an *ordered* map, feel free to introduce that as + * `better::ordered_map`. + */ + +#ifdef BETTER_USE_FOLLY_CONTAINERS + +template +using map = folly::F14FastMap; + +#else + +template +using map = std::unordered_map; + +#endif + +} // namespace better +} // namespace facebook diff --git a/ReactCommon/better/mutex.h b/ReactCommon/better/mutex.h new file mode 100644 index 000000000..327d2f14b --- /dev/null +++ b/ReactCommon/better/mutex.h @@ -0,0 +1,24 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#pragma once + +#include +#include +#include + +namespace facebook { +namespace better { + +template +using shared_lock = std::shared_lock; + +template +using shared_mutex = folly::SharedMutex; + +} // namespace better +} // namespace facebook diff --git a/ReactCommon/better/optional.h b/ReactCommon/better/optional.h new file mode 100644 index 000000000..7ed99e27e --- /dev/null +++ b/ReactCommon/better/optional.h @@ -0,0 +1,38 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#pragma once + +#include + +#ifdef BETTER_USE_FOLLY_CONTAINERS + +#include + +#else + +#include + +#endif + +namespace facebook { +namespace better { + +#ifdef BETTER_USE_FOLLY_CONTAINERS + +template +using optional = folly::Optional; + +#else + +template +using optional = std::optional; + +#endif + +} // namespace better +} // namespace facebook diff --git a/ReactCommon/better/set.h b/ReactCommon/better/set.h new file mode 100644 index 000000000..fd25392b0 --- /dev/null +++ b/ReactCommon/better/set.h @@ -0,0 +1,38 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#pragma once + +#include + +#ifdef BETTER_USE_FOLLY_CONTAINERS + +#include + +#else + +#include + +#endif + +namespace facebook { +namespace better { + +#ifdef BETTER_USE_FOLLY_CONTAINERS + +template +using set = folly::F14FastSet; + +#else + +template +using set = std::unordered_set; + +#endif + +} // namespace better +} // namespace facebook diff --git a/ReactCommon/better/string.h b/ReactCommon/better/string.h new file mode 100644 index 000000000..1b8add7ef --- /dev/null +++ b/ReactCommon/better/string.h @@ -0,0 +1,36 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#pragma once + +#include + +#ifdef BETTER_USE_FOLLY_CONTAINERS + +#include + +#else + +#include + +#endif + +namespace facebook { +namespace better { + +#ifdef BETTER_USE_FOLLY_CONTAINERS + +using string = folly::fbstring; + +#else + +using string = std::string; + +#endif + +} // namespace better +} // namespace facebook diff --git a/ReactCommon/better/vector.h b/ReactCommon/better/vector.h new file mode 100644 index 000000000..f5f13058f --- /dev/null +++ b/ReactCommon/better/vector.h @@ -0,0 +1,38 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#pragma once + +#include + +#ifdef BETTER_USE_FOLLY_CONTAINERS + +#include + +#else + +#include + +#endif + +namespace facebook { +namespace better { + +#ifdef BETTER_USE_FOLLY_CONTAINERS + +template +using vector = folly::fbvector; + +#else + +template +using vector = std::vector; + +#endif + +} // namespace better +} // namespace facebook diff --git a/ReactCommon/fabric/mounting/BUCK b/ReactCommon/fabric/mounting/BUCK index 082b1fb2e..21a1ab112 100644 --- a/ReactCommon/fabric/mounting/BUCK +++ b/ReactCommon/fabric/mounting/BUCK @@ -56,6 +56,7 @@ rn_xplat_cxx_library( "xplat//folly:memory", "xplat//folly:molly", "xplat//third-party/glog:glog", + react_native_xplat_target("better:better"), react_native_xplat_target("fabric/core:core"), react_native_xplat_target("fabric/debug:debug"), react_native_xplat_target("fabric/events:events"), diff --git a/ReactCommon/fabric/mounting/Differentiator.cpp b/ReactCommon/fabric/mounting/Differentiator.cpp index 9bac22008..f260937f7 100644 --- a/ReactCommon/fabric/mounting/Differentiator.cpp +++ b/ReactCommon/fabric/mounting/Differentiator.cpp @@ -5,6 +5,7 @@ #include "Differentiator.h" +#include #include #include "ShadowView.h" @@ -65,7 +66,7 @@ static void calculateShadowViewMutations( return; } - std::unordered_map insertedPaires; + better::map insertedPairs; int index = 0; ShadowViewMutationList createMutations = {}; @@ -116,7 +117,7 @@ static void calculateShadowViewMutations( insertMutations.push_back(ShadowViewMutation::InsertMutation( parentShadowView, newChildPair.shadowView, index)); - insertedPaires.insert({newChildPair.shadowView.tag, newChildPair}); + insertedPairs.insert({newChildPair.shadowView.tag, newChildPair}); } // Stage 3: Collecting `Delete` and `Remove` mutations @@ -129,9 +130,9 @@ static void calculateShadowViewMutations( removeMutations.push_back(ShadowViewMutation::RemoveMutation( parentShadowView, oldChildPair.shadowView, index)); - const auto &it = insertedPaires.find(oldChildPair.shadowView.tag); + const auto &it = insertedPairs.find(oldChildPair.shadowView.tag); - if (it == insertedPaires.end()) { + if (it == insertedPairs.end()) { // The old view was *not* (re)inserted. // We have to generate `delete` mutation and apply the algorithm // recursively. @@ -163,11 +164,11 @@ static void calculateShadowViewMutations( newGrandChildPairs); } - // In any case we have to remove the view from `insertedPaires` as + // In any case we have to remove the view from `insertedPairs` as // indication that the view was actually removed (which means that // the view existed before), hence we don't have to generate // `create` mutation. - insertedPaires.erase(it); + insertedPairs.erase(it); } } @@ -176,8 +177,8 @@ static void calculateShadowViewMutations( index++) { const auto &newChildPair = newChildPairs[index]; - if (insertedPaires.find(newChildPair.shadowView.tag) == - insertedPaires.end()) { + if (insertedPairs.find(newChildPair.shadowView.tag) == + insertedPairs.end()) { // The new view was (re)inserted, so there is no need to create it. continue; }