feat(smart-app): implement complete mobile app MVP

- App.tsx: full navigation (Auth stack + Main tabs with 5 screens)
- Auth: LoginScreen, RegisterScreen, ForgotPasswordScreen
- HomeScreen: dashboard with IoT metrics, weather widget, alerts, quick actions, sensors
- MapScreen: interactive map with layer toggles (6 layers)
- MarketplaceScreen: categories (6), products (5), search
- ChatScreen: AI chat with quick prompts (4), bot responses
- ProfileScreen: user info, stats, menu (9 items), logout
- AlertsScreen: alert list with severity, acknowledge
- SensorsScreen: sensor list with type filters (6 types), search
- ZonesScreen: zone cards with stats
- SettingsScreen: language picker (FR/EN/ES/DE), privacy, about
- Stores: iotStore (sensors, zones, alerts), notificationStore, uiStore + i18n
- Hooks: useSensors, useAlerts, useNotifications, useLocation
- Components: Card, Button, LoadingSpinner, ErrorBoundary, Header
- Services: iotService, notificationService (with axios API client)
- Utils: formatters (temp, AQI, noise, dates), validators (email, password, IBAN)
- Theme: colors.ts with full design system (Blue Ocean palette)
- Ditto: fixed MongoDB connection, new JWT secrets, official gateway image
This commit is contained in:
Eric FELIXINE
2026-06-01 18:00:35 -04:00
parent 08ca495bde
commit e30ae8ed09
35578 changed files with 3703534 additions and 43 deletions

View File

@@ -0,0 +1,6 @@
---
Checks: '>
clang-diagnostic-*,
'
InheritParentConfig: true
...

View File

@@ -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.
cmake_minimum_required(VERSION 3.13)
set(CMAKE_VERBOSE_MAKEFILE on)
add_compile_options(
-fexceptions
-frtti
-std=c++20
-Wall
-Wpedantic
-DLOG_TAG=\"Fabric\")
file(GLOB react_utils_SRC CONFIGURE_DEPENDS *.cpp *.mm)
add_library(react_utils SHARED ${react_utils_SRC})
target_include_directories(react_utils PUBLIC ${REACT_COMMON_DIR})
target_link_libraries(react_utils
glog
glog_init
jsireact
react_debug)

View File

@@ -0,0 +1,110 @@
/*
* 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 <memory>
#include <mutex>
#include <optional>
#include <shared_mutex>
#include <string>
#include <unordered_map>
#include <react/debug/flags.h>
#include <react/debug/react_native_assert.h>
namespace facebook::react {
/*
* General purpose dependency injection container.
* Instance types must be copyable.
*/
class ContextContainer final {
public:
using Shared = std::shared_ptr<const ContextContainer>;
/*
* Registers an instance of the particular type `T` in the container
* using the provided `key`. Only one instance can be registered per key.
* The method does nothing if given `key` already exists in the container.
*
* Convention is to use the plain base class name for the key, so for
* example if the type `T` is `std::shared_ptr<const ReactNativeConfig>`,
* then one would use `"ReactNativeConfig"` for the `key`, even if the
* instance is actually a `shared_ptr` of derived class
*`ReactNativeConfig`.
*/
template <typename T>
void insert(const std::string& key, T const& instance) const {
std::unique_lock lock(mutex_);
instances_.insert({key, std::make_shared<T>(instance)});
}
/*
* Removes an instance stored for a given `key`.
* Does nothing if the instance was not found.
*/
void erase(const std::string& key) const {
std::unique_lock lock(mutex_);
instances_.erase(key);
}
/*
* Updates the container with values from a given container.
* Values with keys that already exist in the container will be replaced with
* values from the given container.
*/
void update(const ContextContainer& contextContainer) const {
std::unique_lock lock(mutex_);
for (const auto& pair : contextContainer.instances_) {
instances_.erase(pair.first);
instances_.insert(pair);
}
}
/*
* Returns a previously registered instance of the particular type `T`
* for `key`.
* Throws an exception if the instance could not be found.
*/
template <typename T>
T at(const std::string& key) const {
std::shared_lock lock(mutex_);
react_native_assert(
instances_.find(key) != instances_.end() &&
"ContextContainer doesn't have an instance for given key.");
return *static_cast<T*>(instances_.at(key).get());
}
/*
* Returns a (wrapped in an optional) previously registered instance of
* the particular type `T` for given `key`.
* Returns an empty optional if the instance could not be found.
*/
template <typename T>
std::optional<T> find(const std::string& key) const {
std::shared_lock lock(mutex_);
auto iterator = instances_.find(key);
if (iterator == instances_.end()) {
return {};
}
return *static_cast<T*>(iterator->second.get());
}
private:
mutable std::shared_mutex mutex_;
// Protected by mutex_`.
mutable std::unordered_map<std::string, std::shared_ptr<void>> instances_;
};
} // namespace facebook::react

View File

@@ -0,0 +1,21 @@
/*
* 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 "CoreFeatures.h"
namespace facebook::react {
bool CoreFeatures::enablePropIteratorSetter = false;
bool CoreFeatures::cacheLastTextMeasurement = false;
bool CoreFeatures::enableGranularScrollViewStateUpdatesIOS = false;
bool CoreFeatures::enableMountHooks = false;
bool CoreFeatures::enableGranularShadowTreeStateReconciliation = false;
bool CoreFeatures::enableClonelessStateProgression = false;
bool CoreFeatures::excludeYogaFromRawProps = false;
bool CoreFeatures::enableReportEventPaintTime = false;
} // namespace facebook::react

View File

@@ -0,0 +1,50 @@
/*
* 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 {
/*
* Contains the set of feature flags for the renderer core.
* Some of them are temporary and may be eventually phased out
* as soon as the feature is fully implemented.
*/
class CoreFeatures {
public:
// Specifies whether the iterator-style prop parsing is enabled.
static bool enablePropIteratorSetter;
// Yoga might measure multiple times the same Text with the same constraints
// This flag enables a caching mechanism to avoid subsequents measurements
// of the same Text with the same constrainst.
// On iOS, we also cache NSTextStorage.
static bool cacheLastTextMeasurement;
// When enabled, RCTScrollViewComponentView will trigger ShadowTree state
// updates for all changes in scroll position.
static bool enableGranularScrollViewStateUpdatesIOS;
// Report mount operations from the host platform to notify mount hooks.
static bool enableMountHooks;
// 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;
// When enabled, Fabric will avoid cloning notes to perform state progression.
static bool enableClonelessStateProgression;
// When enabled, rawProps in Props will not include Yoga specific props.
static bool excludeYogaFromRawProps;
// Report paint time inside the Event Timing API implementation
// (PerformanceObserver).
static bool enableReportEventPaintTime;
};
} // namespace facebook::react

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.
*/
#pragma once
namespace facebook::react {
inline bool floatEquality(float a, float b, float epsilon = 0.005f) {
return (std::isnan(a) && std::isnan(b)) ||
(!std::isnan(a) && !std::isnan(b) && fabs(a - b) < epsilon);
}
} // namespace facebook::react

View File

@@ -0,0 +1,80 @@
/*
* 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/react_native_assert.h>
#if defined(__APPLE__)
#include <TargetConditionals.h>
#endif
#if defined(__OBJC__) && defined(__cplusplus)
#if TARGET_OS_MAC
#include <memory>
#import <Foundation/Foundation.h>
@interface RCTInternalGenericWeakWrapper : NSObject
@property (nonatomic, weak) id object;
@end
namespace facebook::react {
namespace detail {
/*
* A custom deleter used for the deallocation of Objective-C managed objects.
* To be used only by `wrapManagedObject`.
*/
void wrappedManagedObjectDeleter(void *cfPointer) noexcept;
}
/*
* `wrapManagedObject` and `unwrapManagedObject` are wrapper functions that
* convert ARC-managed objects into `std::shared_ptr<void>` and vice-versa. It's
* a very useful mechanism when we need to pass Objective-C objects through pure
* C++ code, pass blocks into C++ lambdas, and so on.
*
* The idea behind this mechanism is quite simple but tricky: When we
* instantiate a C++ shared pointer for a managed object, we practically call
* `CFRetain` for it once and then we represent this single retaining operation
* as a counter inside the shared pointer; when the counter became zero, we call
* `CFRelease` on the object. In this model, one bump of ARC-managed counter is
* represented as multiple bumps of C++ counter, so we can have multiple
* counters for the same object that form some kind of counters tree.
*/
inline std::shared_ptr<void> wrapManagedObject(id object) noexcept
{
return std::shared_ptr<void>((__bridge_retained void *)object, detail::wrappedManagedObjectDeleter);
}
inline id unwrapManagedObject(const std::shared_ptr<void> &object) noexcept
{
return (__bridge id)object.get();
}
inline std::shared_ptr<void> wrapManagedObjectWeakly(id object) noexcept
{
RCTInternalGenericWeakWrapper *weakWrapper = [RCTInternalGenericWeakWrapper new];
weakWrapper.object = object;
return wrapManagedObject(weakWrapper);
}
inline id unwrapManagedObjectWeakly(const std::shared_ptr<void> &object) noexcept
{
RCTInternalGenericWeakWrapper *weakWrapper = (RCTInternalGenericWeakWrapper *)unwrapManagedObject(object);
react_native_assert(weakWrapper && "`RCTInternalGenericWeakWrapper` instance must not be `nil`.");
return weakWrapper.object;
}
} // namespace facebook::react
#endif
#endif

View File

@@ -0,0 +1,34 @@
/*
* 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 "ManagedObjectWrapper.h"
#if TARGET_OS_MAC
namespace facebook::react {
namespace detail {
void wrappedManagedObjectDeleter(void *cfPointer) noexcept
{
// A shared pointer does call custom deleter on `nullptr`s.
// This is somewhat counter-intuitively but makes sense considering the type-erasured nature of shared pointer and an
// aliasing constructor feature. `CFRelease` crashes on null pointer though. Therefore we must check for this case
// explicitly.
if (cfPointer == NULL) {
return;
}
CFRelease(cfPointer);
}
} // namespace detail
} // namespace facebook::react
@implementation RCTInternalGenericWeakWrapper
@end
#endif

View File

@@ -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 <algorithm>
#include <cstdint>
#include <type_traits>
namespace facebook::react::traits {
template <typename ExpectedT>
static constexpr bool containsType() {
return false;
}
template <typename ExpectedT, typename FirstT, typename... RestT>
static constexpr bool containsType() {
if constexpr (sizeof...(RestT) > 0) {
return std::is_same_v<ExpectedT, FirstT> ||
containsType<ExpectedT, RestT...>();
} else {
return std::is_same_v<ExpectedT, FirstT>;
}
}
} // namespace facebook::react::traits

View File

@@ -0,0 +1,62 @@
# 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
folly_config = get_folly_config()
folly_compiler_flags = folly_config[:compiler_flags]
folly_version = folly_config[:version]
header_search_paths = [
"\"$(PODS_ROOT)/RCT-Folly\"",
"\"$(PODS_TARGET_SRCROOT)\"",
"\"$(PODS_TARGET_SRCROOT)/ReactCommon\"",
]
Pod::Spec.new do |s|
s.name = "React-utils"
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.source = source
s.source_files = "**/*.{cpp,h,mm}"
s.compiler_flags = folly_compiler_flags
s.header_dir = "react/utils"
s.exclude_files = "tests"
s.pod_target_xcconfig = { "CLANG_CXX_LANGUAGE_STANDARD" => "c++20",
"HEADER_SEARCH_PATHS" => header_search_paths.join(' '),
"DEFINES_MODULE" => "YES" }
if ENV['USE_FRAMEWORKS']
s.module_name = "React_utils"
s.header_mappings_dir = "../.."
end
s.dependency "RCT-Folly", folly_version
s.dependency "React-jsi", version
s.dependency "glog"
if ENV["USE_HERMES"] == nil || ENV["USE_HERMES"] == "1"
s.dependency "hermes-engine"
else
s.dependency "React-jsc"
end
add_dependency(s, "React-debug")
end

View File

@@ -0,0 +1,61 @@
/*
* 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 "RunLoopObserver.h"
#include <react/debug/react_native_assert.h>
namespace facebook::react {
RunLoopObserver::RunLoopObserver(
Activity activities,
const WeakOwner& owner) noexcept
: activities_(activities), owner_(owner) {}
void RunLoopObserver::setDelegate(const Delegate* delegate) const noexcept {
// We need these constraints to ensure basic thread-safety.
react_native_assert(delegate && "A delegate must not be `nullptr`.");
react_native_assert(
!delegate_ && "`RunLoopObserver::setDelegate` must be called once.");
delegate_ = delegate;
}
void RunLoopObserver::enable() const noexcept {
if (enabled_) {
return;
}
enabled_ = true;
startObserving();
}
void RunLoopObserver::disable() const noexcept {
if (!enabled_) {
return;
}
enabled_ = false;
stopObserving();
}
void RunLoopObserver::activityDidChange(Activity activity) const noexcept {
if (!enabled_) {
return;
}
react_native_assert(
!owner_.expired() &&
"`owner_` is null. The caller must `lock` the owner and check it for being not null.");
delegate_->activityDidChange(delegate_, activity);
}
RunLoopObserver::WeakOwner RunLoopObserver::getOwner() const noexcept {
return owner_;
}
} // namespace facebook::react

View File

@@ -0,0 +1,127 @@
/*
* 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 <atomic>
#include <functional>
#include <memory>
namespace facebook::react {
/*
* A cross-platform abstraction for observing a run loop life cycle.
*/
class RunLoopObserver {
public:
using Unique = std::unique_ptr<const RunLoopObserver>;
/*
* The concept of an owner.
* A run loop observer normally observes a run loop running on a different
* thread. That implies that this other thread (the run loop thread) will call
* methods of this class owned by some other thread. To make it safe, we need
* to ensure that at the moment of the calling the observer still exists. To
* do so, we use an owner object (a weak pointer) that must retain (possibly
* indirectly) the observer. The platform-specific code should convert the
* weak pointer (owner) to a strong one right before calling the observer,
* ensuring the safety of calling; right after the call, the strong pointer
* should be safely released.
*
* Note, in the case when the pointer to the actual owner will be available
* later, only after calling the constructor of the class, the caller can
* create a dummy pointer beforehand and then merge it (using
* `shared_ptr<X>(shared_ptr<Y> const &, X *)`) with the actual one (sharing
* the control block).
*/
using Owner = std::shared_ptr<const void>;
using WeakOwner = std::weak_ptr<const void>;
/*
* Run loop activity stages which run loop observers can be observe.
*/
enum Activity : int32_t {
None = 0,
BeforeWaiting = 1 << 0,
AfterWaiting = 1 << 1,
};
/*
* A delegate interface.
*/
class Delegate {
public:
/*
* Called on every run loop tick at moments corresponding to requested
* activities.
*
* A platform-specific implementation guarantees that the owner pointer
* is retained during this call.
* Will be called on the thread associated with the run loop.
*/
virtual void activityDidChange(const Delegate* delegate, Activity activity)
const noexcept = 0;
virtual ~Delegate() noexcept = default;
};
using Factory = std::function<std::unique_ptr<RunLoopObserver>(
Activity activities,
const WeakOwner& owner)>;
/*
* Constructs a run loop observer.
*/
RunLoopObserver(Activity activities, const WeakOwner& owner) noexcept;
virtual ~RunLoopObserver() noexcept = default;
/*
* Sets the delegate.
* Must be called just once.
*/
void setDelegate(const Delegate* delegate) const noexcept;
/*
* Enables or disables run loop observing.
* It can be used to save CPU cycles during periods of time when observing
* is not required.
* A newly constructed run time observer is initially disabled.
*/
void enable() const noexcept;
void disable() const noexcept;
/*
* Returns true if called on a thread associated with the run loop.
* Must be implemented in subclasses.
*/
virtual bool isOnRunLoopThread() const noexcept = 0;
/*
* Returns an owner associated with the observer.
* It might be useful to ensure the safety of consequent asynchronous calls.
*/
WeakOwner getOwner() const noexcept;
protected:
/*
* Must be implemented in subclasses.
*/
virtual void startObserving() const noexcept = 0;
virtual void stopObserving() const noexcept = 0;
/*
* Called by subclasses to generate a call on a delegate.
*/
void activityDidChange(Activity activity) const noexcept;
const Activity activities_{};
const WeakOwner owner_;
mutable const Delegate* delegate_{nullptr};
mutable std::atomic<bool> enabled_{false};
};
} // namespace facebook::react

View File

@@ -0,0 +1,62 @@
/*
* 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 <functional>
#include <memory>
#include <shared_mutex>
namespace facebook::react {
/*
* `SharedFunction` implements a pattern of a shared callable object that
* contains the same executable inside. It's similar to `std::function` with
* one important difference: when the object is copied, the stored function (and
* captured values) are shared between instances (not copied). `SharedFunction`
* can be stored inside `std::function` because it's callable. It useful in some
* scenarios, such as:
* - When captured by `std::function` arguments are not copyable;
* - When we need to replace the content of the callable later on the go.
*/
template <typename... ArgumentT>
class SharedFunction {
using T = void(ArgumentT...);
struct Pair {
Pair(std::function<T>&& function) : function(std::move(function)) {}
std::function<T> function;
std::shared_mutex mutex{};
};
public:
SharedFunction(std::function<T>&& function = nullptr)
: pair_(std::make_shared<Pair>(std::move(function))) {}
SharedFunction(const SharedFunction& other) = default;
SharedFunction(SharedFunction&& other) noexcept = default;
SharedFunction& operator=(const SharedFunction& other) = default;
SharedFunction& operator=(SharedFunction&& other) noexcept = default;
void assign(std::function<T> function) const {
std::unique_lock lock(pair_->mutex);
pair_->function = function;
}
void operator()(ArgumentT... args) const {
std::shared_lock lock(pair_->mutex);
if (pair_->function) {
pair_->function(args...);
}
}
private:
std::shared_ptr<Pair> pair_;
};
} // namespace facebook::react

View File

@@ -0,0 +1,74 @@
/*
* 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 <functional>
#include <memory>
#include <mutex>
#include <optional>
#include <folly/container/EvictingCacheMap.h>
namespace facebook::react {
/*
* Simple thread-safe LRU cache.
*/
template <typename KeyT, typename ValueT, int maxSize>
class SimpleThreadSafeCache {
public:
SimpleThreadSafeCache() : map_{maxSize} {}
SimpleThreadSafeCache(unsigned long size) : map_{size} {}
/*
* Returns a value from the map with a given key.
* If the value wasn't found in the cache, constructs the value using given
* generator function, stores it inside a cache and returns it.
* Can be called from any thread.
*/
ValueT get(const KeyT& key, std::function<ValueT(const KeyT& key)> generator)
const {
std::lock_guard<std::mutex> lock(mutex_);
auto iterator = map_.find(key);
if (iterator == map_.end()) {
auto value = generator(key);
map_.set(key, value);
return value;
}
return iterator->second;
}
/*
* Returns a value from the map with a given key.
* If the value wasn't found in the cache, returns empty optional.
* Can be called from any thread.
*/
std::optional<ValueT> get(const KeyT& key) const {
std::lock_guard<std::mutex> lock(mutex_);
auto iterator = map_.find(key);
if (iterator == map_.end()) {
return {};
}
return iterator->second;
}
/*
* Sets a key-value pair in the LRU cache.
* Can be called from any thread.
*/
void set(const KeyT& key, const ValueT& value) const {
std::lock_guard<std::mutex> lock(mutex_);
map_.set(std::move(key), std::move(value));
}
private:
mutable folly::EvictingCacheMap<KeyT, ValueT> map_;
mutable std::mutex mutex_;
};
} // namespace facebook::react

View File

@@ -0,0 +1,113 @@
/*
* 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 <chrono>
#include <type_traits>
namespace facebook::react {
/*
* Represents a monotonic clock suitable for measuring intervals.
*/
using TelemetryClock = std::chrono::steady_clock;
/*
* Represents a point in time satisfied the requirements of TelemetryClock.
*/
using TelemetryTimePoint = TelemetryClock::time_point;
/*
* Represents a time interval satisfied the requirements of TelemetryClock.
*/
using TelemetryDuration = std::chrono::nanoseconds;
/*
* Represents a time point which never happens.
*/
static const TelemetryTimePoint kTelemetryUndefinedTimePoint =
TelemetryTimePoint::max();
/*
* Returns a time point representing the current point in time.
*/
static inline TelemetryTimePoint telemetryTimePointNow() {
return TelemetryClock::now();
}
/*
* Returns a number of milliseconds that passed from some epoch starting time
* point to a given time point. The epoch starting time point is not specified
* but stays the same for an application run.
*/
static inline int64_t telemetryTimePointToMilliseconds(
TelemetryTimePoint timePoint) {
return std::chrono::duration_cast<std::chrono::milliseconds>(
timePoint - TelemetryTimePoint{})
.count();
}
/*
* Returns a number of seconds that passed from "Steady Clock" epoch starting
* time point to a given time point.
*/
static inline double telemetryTimePointToSteadyClockSeconds(
TelemetryTimePoint timePoint) {
static_assert(
std::is_same<decltype(timePoint), std::chrono::steady_clock::time_point>::
value,
"`TelemetryClock` must be `std::chrono::steady_clock` to make the "
"following implementation work correctly.");
auto nanoseconds = std::chrono::duration_cast<std::chrono::nanoseconds>(
timePoint.time_since_epoch())
.count();
return (double)nanoseconds / 1.0e9;
}
/*
* Converts a time point on one clock to a time point on a different clock.
*/
template <
typename DestinationTimePointT,
typename SourceTimePointT,
typename DestnationClockT = typename DestinationTimePointT::clock,
typename SourceClockT = typename SourceTimePointT::clock>
DestinationTimePointT clockCast(SourceTimePointT timePoint) {
auto sourseClockNow = SourceClockT::now();
auto destinationClockNow = DestnationClockT::now();
return std::chrono::time_point_cast<typename DestnationClockT::duration>(
timePoint - sourseClockNow + destinationClockNow);
}
/*
* Returns a number of seconds that passed from the UNIX Epoch starting time
* point to a given time point.
* Also known as POSIX time or UNIX Timestamp.
*/
static inline double telemetryTimePointToSecondsSinceEpoch(
TelemetryTimePoint timePoint) {
auto systemClockTimePoint =
clockCast<std::chrono::system_clock::time_point, TelemetryTimePoint>(
timePoint);
return (double)std::chrono::duration_cast<std::chrono::microseconds>(
systemClockTimePoint.time_since_epoch())
.count() /
1000000.0;
}
/*
* Returns a number of milliseconds that represents the given duration object.
*/
static inline int64_t telemetryDurationToMilliseconds(
TelemetryDuration duration) {
return std::chrono::duration_cast<std::chrono::milliseconds>(duration)
.count();
}
} // namespace facebook::react

View File

@@ -0,0 +1,41 @@
/*
* 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 <cstdint>
#include <functional>
#include <string_view>
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.
*/
template <typename CharTransformT = std::identity>
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<int8_t>(CharTransformT{}(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

View File

@@ -0,0 +1,33 @@
/*
* 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 <functional>
#include <type_traits>
namespace facebook::react {
template <typename T>
concept Hashable = !std::is_same_v<T, const char*> && (requires(T a) {
{ std::hash<T>{}(a) } -> std::convertible_to<std::size_t>;
});
template <Hashable T, Hashable... Rest>
void hash_combine(std::size_t& seed, const T& v, const Rest&... rest) {
seed ^= std::hash<T>{}(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
(hash_combine(seed, rest), ...);
}
template <Hashable T, Hashable... Args>
std::size_t hash_combine(const T& v, const Args&... args) {
std::size_t seed = 0;
hash_combine<T, Args...>(seed, v, args...);
return seed;
}
} // namespace facebook::react

View File

@@ -0,0 +1,39 @@
/*
* 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 "jsi.h"
namespace facebook::react {
void defineReadOnlyGlobal(
jsi::Runtime& runtime,
const std::string& propName,
jsi::Value&& value) {
auto global = runtime.global();
if (global.hasProperty(runtime, propName.c_str())) {
throw jsi::JSError(
runtime,
"Tried to redefine read-only global \"" + propName +
"\", but read-only globals can only be defined once.");
}
jsi::Object jsObject =
global.getProperty(runtime, "Object").asObject(runtime);
jsi::Function defineProperty = jsObject.getProperty(runtime, "defineProperty")
.asObject(runtime)
.asFunction(runtime);
jsi::Object descriptor = jsi::Object(runtime);
descriptor.setProperty(runtime, "value", std::move(value));
defineProperty.callWithThis(
runtime,
jsObject,
global,
jsi::String::createFromUtf8(runtime, propName),
descriptor);
}
} // namespace facebook::react

View File

@@ -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 <jsi/jsi.h>
#include <string>
namespace facebook::react {
/**
* Defines a property on the global object that is neither enumerable, nor
* configurable, nor writable. This ensures that the private globals exposed by
* ReactInstance cannot overwritten by third-party JavaScript code. It also
* ensures that third-party JavaScript code unaware of these globals isn't able
* to accidentally access them. In JavaScript, equivalent to:
*
* Object.defineProperty(global, propName, {
* value: value
* })
*/
void defineReadOnlyGlobal(
jsi::Runtime& runtime,
const std::string& propName,
jsi::Value&& value);
} // namespace facebook::react

View File

@@ -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 <gtest/gtest.h>
#include <react/utils/fnv1a.h>
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

View File

@@ -0,0 +1,82 @@
/*
* 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 <react/utils/hash_combine.h>
struct Person {
std::string firstName;
std::string lastName;
};
namespace std {
template <>
struct hash<Person> {
size_t operator()(const Person& person) const {
return facebook::react::hash_combine(person.firstName, person.lastName);
}
};
} // namespace std
namespace facebook::react {
TEST(hash_combineTests, testIntegerTemplating) {
std::size_t seed = 0;
hash_combine(seed, 1);
auto hashedValue = hash_combine(1);
EXPECT_EQ(hashedValue, seed);
EXPECT_NE(hash_combine(1), hash_combine(2));
}
TEST(hash_combineTests, testIntegerCombinationsHashing) {
std::size_t seed = 0;
hash_combine(seed, 1, 2);
auto hashedValue = hash_combine(1, 2);
EXPECT_EQ(hashedValue, seed);
EXPECT_NE(hash_combine(1, 2), hash_combine(2, 1));
}
TEST(hash_combineTests, testContiniousIntegerHashing) {
std::size_t seed = 0;
for (int i = 1; i <= 200; ++i) {
auto previousSeed = seed;
hash_combine(seed, i);
EXPECT_NE(seed, previousSeed);
}
}
TEST(hash_combineTests, testStrings) {
std::size_t seed = 0;
hash_combine<std::string>(seed, "react");
auto hashedValue = hash_combine<std::string>("react");
EXPECT_EQ(hashedValue, seed);
EXPECT_NE(
hash_combine<std::string>("react"),
hash_combine<std::string>("react native"));
}
TEST(hash_combineTests, testCustomTypes) {
auto person1 = Person{"John", "Doe"};
auto person2 = Person{"Jane", "Doe"};
std::size_t seed = 0;
hash_combine(seed, person1);
auto hashedValue = hash_combine(person1);
EXPECT_EQ(hashedValue, seed);
EXPECT_NE(hash_combine(person1), hash_combine(person2));
}
} // namespace facebook::react

View File

@@ -0,0 +1,22 @@
/*
* 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 <type_traits>
namespace facebook::react {
/**
* 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<std::underlying_type_t<decltype(e)>>(e);
}
} // namespace facebook::react