diff --git a/packages/react-native/Libraries/WebPerformance/PerformanceEntryReporter.cpp b/packages/react-native/Libraries/WebPerformance/PerformanceEntryReporter.cpp index 6c0ec3d77df..ff7389eeb17 100644 --- a/packages/react-native/Libraries/WebPerformance/PerformanceEntryReporter.cpp +++ b/packages/react-native/Libraries/WebPerformance/PerformanceEntryReporter.cpp @@ -10,6 +10,7 @@ #include #include "NativePerformanceObserver.h" +#include #include namespace facebook::react { @@ -298,8 +299,7 @@ void PerformanceEntryReporter::scheduleFlushBuffer() { struct StrKey { uint32_t key; - StrKey(std::string_view s) - : key(folly::hash::fnv32_buf(s.data(), s.length())) {} + StrKey(std::string_view s) : key(std::hash{}(s)) {} bool operator==(const StrKey& rhs) const { return key == rhs.key; diff --git a/packages/react-native/ReactCommon/react/renderer/core/PropsMacros.h b/packages/react-native/ReactCommon/react/renderer/core/PropsMacros.h index a3d07018fb9..4190b17a135 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/PropsMacros.h +++ b/packages/react-native/ReactCommon/react/renderer/core/PropsMacros.h @@ -8,6 +8,8 @@ #pragma once #include +#include +#include // We need to use clang pragmas inside of a macro below, // so we need to pull out the "if" statement here. @@ -22,11 +24,11 @@ ([]() constexpr->RawPropsPropNameHash { \ CLANG_PRAGMA("clang diagnostic push") \ CLANG_PRAGMA("clang diagnostic ignored \"-Wshadow\"") \ - return folly::hash::fnv32_buf(s, sizeof(s) - 1); \ + return RAW_PROPS_KEY_HASH(s); \ CLANG_PRAGMA("clang diagnostic pop") \ }()) -#define RAW_PROPS_KEY_HASH(s) folly::hash::fnv32_buf(s, std::strlen(s)) +#define RAW_PROPS_KEY_HASH(s) facebook::react::fnv1a(s) // Convenience for building setProps switch statements. // This injects `fromRawValue` into source; each file that uses diff --git a/packages/react-native/ReactCommon/react/renderer/core/RawPropsParser.cpp b/packages/react-native/ReactCommon/react/renderer/core/RawPropsParser.cpp index 3ac97018d5c..620685d713d 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/RawPropsParser.cpp +++ b/packages/react-native/ReactCommon/react/renderer/core/RawPropsParser.cpp @@ -198,7 +198,7 @@ void RawPropsParser::iterateOverValues( auto name = nameValue.utf8(runtime); - auto nameHash = RAW_PROPS_KEY_HASH(name.c_str()); + auto nameHash = RAW_PROPS_KEY_HASH(name); auto rawValue = RawValue(jsi::dynamicFromValue(runtime, value)); visit(nameHash, name.c_str(), rawValue); @@ -213,7 +213,7 @@ void RawPropsParser::iterateOverValues( for (const auto& pair : dynamic.items()) { auto name = pair.first.getString(); - auto nameHash = RAW_PROPS_KEY_HASH(name.c_str()); + auto nameHash = RAW_PROPS_KEY_HASH(name); auto rawValue = RawValue{pair.second}; visit(nameHash, name.c_str(), rawValue); } diff --git a/packages/react-native/ReactCommon/react/utils/fnv1a.h b/packages/react-native/ReactCommon/react/utils/fnv1a.h new file mode 100644 index 00000000000..fe2721d4bc0 --- /dev/null +++ b/packages/react-native/ReactCommon/react/utils/fnv1a.h @@ -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. + */ + +#pragma once + +namespace facebook::react { + +/** + * FNV-1a hash function implementation. + * Implemented as described in http://www.isthe.com/chongo/tech/comp/fnv/. + * + * Please use std::hash if possible. `fnv1a` should only be used in cases + * when std::hash does not provide the needed functionality. For example, + * constexpr. + */ +constexpr uint32_t fnv1a(std::string_view string) noexcept { + constexpr uint32_t offset_basis = 2166136261; + + uint32_t hash = offset_basis; + + for (auto const& c : string) { + hash ^= static_cast(c); + // Using shifts and adds instead of multiplication with a prime number. + // This is faster when compiled with optimizations. + hash += + (hash << 1) + (hash << 4) + (hash << 7) + (hash << 8) + (hash << 24); + } + + return hash; +} + +} // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/utils/tests/fnv1aTests.cpp b/packages/react-native/ReactCommon/react/utils/tests/fnv1aTests.cpp new file mode 100644 index 00000000000..5c7b76d099a --- /dev/null +++ b/packages/react-native/ReactCommon/react/utils/tests/fnv1aTests.cpp @@ -0,0 +1,24 @@ +/* + * 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 + +namespace facebook::react { + +TEST(fnv1aTests, testBasicHashing) { + EXPECT_EQ(fnv1a("react"), fnv1a("react")); + + EXPECT_NE(fnv1a("react"), fnv1a("tceat")); + + auto string1 = "case 1"; + auto string2 = "different string"; + EXPECT_EQ(fnv1a(string1), fnv1a(string1)); + EXPECT_NE(fnv1a(string1), fnv1a(string2)); +} + +} // namespace facebook::react