first commit

This commit is contained in:
2026-03-10 16:18:05 +00:00
commit 11f9c069b5
31635 changed files with 3187747 additions and 0 deletions

View File

@@ -0,0 +1,17 @@
# 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)
include(${REACT_COMMON_DIR}/cmake-utils/react-native-flags.cmake)
add_library(react_timing INTERFACE)
target_include_directories(react_timing INTERFACE ${REACT_COMMON_DIR})
target_link_libraries(react_timing INTERFACE
react_debug)
target_compile_reactnative_options(react_timing INTERFACE)
target_compile_options(react_timing INTERFACE -Wpedantic)

View File

@@ -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.
require "json"
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 were 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
header_search_paths = []
if ENV['USE_FRAMEWORKS']
header_search_paths << "\"$(PODS_TARGET_SRCROOT)/../..\"" # this is needed to allow the target access its own files
end
Pod::Spec.new do |s|
s.name = "React-timing"
s.version = version
s.summary = "React Native timing primitives"
s.homepage = "https://reactnative.dev/"
s.license = package["license"]
s.author = "Meta Platforms, Inc. and its affiliates"
s.platforms = min_supported_versions
s.source = source
s.source_files = podspec_sources("*.{cpp,h}", "**/*.h")
s.header_dir = "react/timing"
s.pod_target_xcconfig = { "CLANG_CXX_LANGUAGE_STANDARD" => rct_cxx_language_standard(),
"HEADER_SEARCH_PATHS" => header_search_paths.join(' '),
"DEFINES_MODULE" => "YES" }
resolve_use_frameworks(s, header_mappings_dir: "./", module_name: "React_timing")
add_dependency(s, "React-debug")
end

View File

@@ -0,0 +1,350 @@
/*
* 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 <react/debug/flags.h>
#include <chrono>
#include <functional>
namespace facebook::react {
class HighResDuration;
class HighResTimeStamp;
/*
* A class representing a duration of time with high precision.
*
* @see __docs__/README.md for more information.
*/
class HighResDuration {
friend class HighResTimeStamp;
friend constexpr HighResDuration operator-(const HighResTimeStamp &lhs, const HighResTimeStamp &rhs);
friend constexpr HighResTimeStamp operator+(const HighResTimeStamp &lhs, const HighResDuration &rhs);
friend constexpr HighResTimeStamp operator-(const HighResTimeStamp &lhs, const HighResDuration &rhs);
public:
constexpr HighResDuration() : chronoDuration_(std::chrono::steady_clock::duration()) {}
static constexpr HighResDuration zero()
{
return HighResDuration(std::chrono::steady_clock::duration::zero());
}
static constexpr HighResDuration fromChrono(std::chrono::steady_clock::duration chronoDuration)
{
return HighResDuration(chronoDuration);
}
static constexpr HighResDuration fromNanoseconds(int64_t units)
{
return HighResDuration(std::chrono::nanoseconds(units));
}
static constexpr HighResDuration fromMilliseconds(int64_t units)
{
return HighResDuration(std::chrono::milliseconds(units));
}
constexpr int64_t toNanoseconds() const
{
return std::chrono::duration_cast<std::chrono::nanoseconds>(chronoDuration_).count();
}
// @see https://developer.mozilla.org/en-US/docs/Web/API/DOMHighResTimeStamp
static constexpr HighResDuration fromDOMHighResTimeStamp(double units)
{
auto nanoseconds = static_cast<int64_t>(units * 1e6);
return fromNanoseconds(nanoseconds);
}
// @see https://developer.mozilla.org/en-US/docs/Web/API/DOMHighResTimeStamp
constexpr double toDOMHighResTimeStamp() const
{
return static_cast<std::chrono::duration<double, std::milli>>(chronoDuration_).count();
}
constexpr HighResDuration operator+(const HighResDuration &rhs) const
{
return HighResDuration(chronoDuration_ + rhs.chronoDuration_);
}
constexpr HighResDuration operator+(const std::chrono::steady_clock::duration &rhs) const
{
return HighResDuration(chronoDuration_ + rhs);
}
constexpr HighResDuration operator-(const HighResDuration &rhs) const
{
return HighResDuration(chronoDuration_ - rhs.chronoDuration_);
}
constexpr HighResDuration operator-(const std::chrono::steady_clock::duration &rhs) const
{
return HighResDuration(chronoDuration_ - rhs);
}
constexpr HighResDuration &operator+=(const HighResDuration &rhs)
{
chronoDuration_ += rhs.chronoDuration_;
return *this;
}
constexpr HighResDuration &operator+=(const std::chrono::steady_clock::duration &rhs)
{
chronoDuration_ += rhs;
return *this;
}
constexpr HighResDuration &operator-=(const HighResDuration &rhs)
{
chronoDuration_ -= rhs.chronoDuration_;
return *this;
}
constexpr HighResDuration &operator-=(const std::chrono::steady_clock::duration &rhs)
{
chronoDuration_ -= rhs;
return *this;
}
constexpr bool operator==(const HighResDuration &rhs) const
{
return chronoDuration_ == rhs.chronoDuration_;
}
constexpr bool operator==(const std::chrono::steady_clock::duration &rhs) const
{
return chronoDuration_ == rhs;
}
constexpr bool operator!=(const HighResDuration &rhs) const
{
return chronoDuration_ != rhs.chronoDuration_;
}
constexpr bool operator!=(const std::chrono::steady_clock::duration &rhs) const
{
return chronoDuration_ != rhs;
}
constexpr bool operator<(const HighResDuration &rhs) const
{
return chronoDuration_ < rhs.chronoDuration_;
}
constexpr bool operator<(const std::chrono::steady_clock::duration &rhs) const
{
return chronoDuration_ < rhs;
}
constexpr bool operator<=(const HighResDuration &rhs) const
{
return chronoDuration_ <= rhs.chronoDuration_;
}
constexpr bool operator<=(const std::chrono::steady_clock::duration &rhs) const
{
return chronoDuration_ <= rhs;
}
constexpr bool operator>(const HighResDuration &rhs) const
{
return chronoDuration_ > rhs.chronoDuration_;
}
constexpr bool operator>(const std::chrono::steady_clock::duration &rhs) const
{
return chronoDuration_ > rhs;
}
constexpr bool operator>=(const HighResDuration &rhs) const
{
return chronoDuration_ >= rhs.chronoDuration_;
}
constexpr bool operator>=(const std::chrono::steady_clock::duration &rhs) const
{
return chronoDuration_ >= rhs;
}
constexpr operator std::chrono::steady_clock::duration() const
{
return chronoDuration_;
}
private:
explicit constexpr HighResDuration(std::chrono::steady_clock::duration chronoDuration)
: chronoDuration_(chronoDuration)
{
}
std::chrono::steady_clock::duration chronoDuration_;
};
/*
* A class representing a specific point in time with high precision.
*
* @see __docs__/README.md for more information.
*/
class HighResTimeStamp {
friend constexpr HighResDuration operator-(const HighResTimeStamp &lhs, const HighResTimeStamp &rhs);
friend constexpr HighResTimeStamp operator+(const HighResTimeStamp &lhs, const HighResDuration &rhs);
friend constexpr HighResTimeStamp operator-(const HighResTimeStamp &lhs, const HighResDuration &rhs);
public:
HighResTimeStamp() noexcept : chronoTimePoint_(chronoNow()) {}
static HighResTimeStamp now() noexcept
{
return HighResTimeStamp(chronoNow());
}
static HighResDuration unsafeOriginFromUnixTimeStamp() noexcept
{
static auto origin = computeUnsafeOriginFromUnixTimeStamp();
return origin;
}
static constexpr HighResTimeStamp min() noexcept
{
return HighResTimeStamp(std::chrono::steady_clock::time_point::min());
}
static constexpr HighResTimeStamp max() noexcept
{
return HighResTimeStamp(std::chrono::steady_clock::time_point::max());
}
// @see https://developer.mozilla.org/en-US/docs/Web/API/DOMHighResTimeStamp
static constexpr HighResTimeStamp fromDOMHighResTimeStamp(double units)
{
auto nanoseconds = static_cast<int64_t>(units * 1e6);
return HighResTimeStamp(std::chrono::steady_clock::time_point(std::chrono::nanoseconds(nanoseconds)));
}
// @see https://developer.mozilla.org/en-US/docs/Web/API/DOMHighResTimeStamp
constexpr double toDOMHighResTimeStamp() const
{
return HighResDuration(chronoTimePoint_.time_since_epoch()).toDOMHighResTimeStamp();
}
// This method is expected to be used only when converting time stamps from
// external systems.
static constexpr HighResTimeStamp fromChronoSteadyClockTimePoint(
std::chrono::steady_clock::time_point chronoTimePoint)
{
return HighResTimeStamp(chronoTimePoint);
}
#ifdef REACT_NATIVE_DEBUG
static void setTimeStampProviderForTesting(std::function<std::chrono::steady_clock::time_point()> &&timeStampProvider)
{
getTimeStampProvider() = std::move(timeStampProvider);
}
#endif
// This method is provided for convenience, if you need to convert
// HighResTimeStamp to some common epoch with time stamps from other sources.
constexpr std::chrono::steady_clock::time_point toChronoSteadyClockTimePoint() const
{
return chronoTimePoint_;
}
constexpr bool operator==(const HighResTimeStamp &rhs) const
{
return chronoTimePoint_ == rhs.chronoTimePoint_;
}
constexpr bool operator!=(const HighResTimeStamp &rhs) const
{
return chronoTimePoint_ != rhs.chronoTimePoint_;
}
constexpr bool operator<(const HighResTimeStamp &rhs) const
{
return chronoTimePoint_ < rhs.chronoTimePoint_;
}
constexpr bool operator<=(const HighResTimeStamp &rhs) const
{
return chronoTimePoint_ <= rhs.chronoTimePoint_;
}
constexpr bool operator>(const HighResTimeStamp &rhs) const
{
return chronoTimePoint_ > rhs.chronoTimePoint_;
}
constexpr bool operator>=(const HighResTimeStamp &rhs) const
{
return chronoTimePoint_ >= rhs.chronoTimePoint_;
}
constexpr HighResTimeStamp &operator+=(const HighResDuration &rhs)
{
chronoTimePoint_ += rhs.chronoDuration_;
return *this;
}
constexpr HighResTimeStamp &operator-=(const HighResDuration &rhs)
{
chronoTimePoint_ -= rhs.chronoDuration_;
return *this;
}
private:
explicit constexpr HighResTimeStamp(std::chrono::steady_clock::time_point chronoTimePoint)
: chronoTimePoint_(chronoTimePoint)
{
}
std::chrono::steady_clock::time_point chronoTimePoint_;
static HighResDuration computeUnsafeOriginFromUnixTimeStamp() noexcept
{
auto systemNow = std::chrono::system_clock::now();
auto steadyNow = std::chrono::steady_clock::now();
return HighResDuration(systemNow.time_since_epoch() - steadyNow.time_since_epoch());
}
#ifdef REACT_NATIVE_DEBUG
static std::function<std::chrono::steady_clock::time_point()> &getTimeStampProvider()
{
static std::function<std::chrono::steady_clock::time_point()> timeStampProvider = nullptr;
return timeStampProvider;
}
static std::chrono::steady_clock::time_point chronoNow()
{
auto &timeStampProvider = getTimeStampProvider();
return timeStampProvider != nullptr ? timeStampProvider() : std::chrono::steady_clock::now();
}
#else
inline static std::chrono::steady_clock::time_point chronoNow()
{
return std::chrono::steady_clock::now();
}
#endif
};
inline constexpr HighResDuration operator-(const HighResTimeStamp &lhs, const HighResTimeStamp &rhs)
{
return HighResDuration(lhs.chronoTimePoint_ - rhs.chronoTimePoint_);
}
inline constexpr HighResTimeStamp operator+(const HighResTimeStamp &lhs, const HighResDuration &rhs)
{
return HighResTimeStamp(lhs.chronoTimePoint_ + rhs.chronoDuration_);
}
inline constexpr HighResTimeStamp operator-(const HighResTimeStamp &lhs, const HighResDuration &rhs)
{
return HighResTimeStamp(lhs.chronoTimePoint_ - rhs.chronoDuration_);
}
} // namespace facebook::react

View File

@@ -0,0 +1,105 @@
/*
* 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 <gtest/gtest.h>
#include "../primitives.h"
namespace facebook::react {
TEST(HighResDuration, CorrectlyConvertsToDOMHighResTimeStamp) {
EXPECT_EQ(
HighResDuration::fromNanoseconds(10).toDOMHighResTimeStamp(), 0.00001);
EXPECT_EQ(
HighResDuration::fromNanoseconds(10 * 1e3).toDOMHighResTimeStamp(), 0.01);
EXPECT_EQ(
HighResDuration::fromNanoseconds(10 * 1e6).toDOMHighResTimeStamp(), 10.0);
EXPECT_EQ(
HighResDuration::fromNanoseconds(10 * 1e9).toDOMHighResTimeStamp(),
10000.0);
EXPECT_EQ(
HighResDuration::fromNanoseconds(1e9 + 20).toDOMHighResTimeStamp(),
1000.000020);
EXPECT_EQ(HighResDuration::fromMilliseconds(0).toDOMHighResTimeStamp(), 0);
EXPECT_EQ(
HighResDuration::fromMilliseconds(10).toDOMHighResTimeStamp(), 10.0);
}
TEST(HighResDuration, ComparisonOperators) {
auto duration1 = HighResDuration::fromNanoseconds(10);
auto duration2 = HighResDuration::fromNanoseconds(20);
auto duration3 = HighResDuration::fromNanoseconds(10);
EXPECT_TRUE(duration1 == duration3);
EXPECT_FALSE(duration1 == duration2);
EXPECT_TRUE(duration1 != duration2);
EXPECT_FALSE(duration1 != duration3);
EXPECT_TRUE(duration1 < duration2);
EXPECT_FALSE(duration2 < duration1);
EXPECT_FALSE(duration1 < duration3);
EXPECT_TRUE(duration1 <= duration2);
EXPECT_TRUE(duration1 <= duration3);
EXPECT_FALSE(duration2 <= duration1);
EXPECT_TRUE(duration2 > duration1);
EXPECT_FALSE(duration1 > duration2);
EXPECT_FALSE(duration1 > duration3);
EXPECT_TRUE(duration2 >= duration1);
EXPECT_TRUE(duration1 >= duration3);
EXPECT_FALSE(duration1 >= duration2);
}
TEST(HighResDuration, ArithmeticOperators) {
auto duration1 = HighResDuration::fromChrono(std::chrono::nanoseconds(100));
auto duration2 = HighResDuration::fromChrono(std::chrono::nanoseconds(50));
EXPECT_EQ(duration1 + duration2, std::chrono::nanoseconds(150));
EXPECT_EQ(duration1 - duration2, std::chrono::nanoseconds(50));
EXPECT_EQ(duration2 - duration1, std::chrono::nanoseconds(-50));
}
TEST(HighResTimeStamp, ComparisonOperators) {
auto now = HighResTimeStamp::now();
auto later = now + HighResDuration::fromNanoseconds(1);
auto nowCopy = now;
EXPECT_TRUE(now == nowCopy);
EXPECT_FALSE(now == later);
EXPECT_TRUE(now != later);
EXPECT_FALSE(now != nowCopy);
EXPECT_TRUE(now < later);
EXPECT_FALSE(later < now);
EXPECT_FALSE(now < nowCopy);
EXPECT_TRUE(now <= later);
EXPECT_TRUE(now <= nowCopy);
EXPECT_FALSE(later <= now);
EXPECT_TRUE(later > now);
EXPECT_FALSE(now > later);
EXPECT_FALSE(now > nowCopy);
EXPECT_TRUE(later >= now);
EXPECT_TRUE(now >= nowCopy);
EXPECT_FALSE(now >= later);
}
TEST(HighResTimeStamp, SteadyClockTimePointConversion) {
[[maybe_unused]] auto timestamp =
HighResTimeStamp::now().toChronoSteadyClockTimePoint();
EXPECT_TRUE(decltype(timestamp)::clock::is_steady);
}
} // namespace facebook::react