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,95 @@
/*
* 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 <pthread.h>
#include <sched.h>
#include <condition_variable>
#include <mutex>
#include <queue>
#include <thread>
#include <utility>
namespace facebook::react::LowPriorityExecutor {
struct LowPriorityExecutorThread {
LowPriorityExecutorThread() : thread_{std::thread([this] { run(); })} {
pthread_t hThread = thread_.native_handle();
struct sched_param param{};
param.sched_priority = 19; // Higher value means lower priority
pthread_setschedparam(hThread, SCHED_OTHER, &param);
}
// Deleted constructors
LowPriorityExecutorThread(const LowPriorityExecutorThread& other) = delete;
LowPriorityExecutorThread(LowPriorityExecutorThread&& other) = delete;
LowPriorityExecutorThread& operator=(const LowPriorityExecutorThread& other) =
delete;
LowPriorityExecutorThread& operator=(LowPriorityExecutorThread&& other) =
delete;
~LowPriorityExecutorThread() {
// Stop the thread
{
std::lock_guard<std::mutex> lock(mutex_);
running_ = false;
}
// Unblock the thread to check the running_ flag and terminate.
cv_.notify_one();
// Wait for thread completion to avoid use-after-free on background thread.
thread_.join();
}
void post(std::function<void()>&& workItem) {
// Move the object to the queue.
{
std::lock_guard<std::mutex> lock(mutex_);
queue_.emplace(std::move(workItem));
}
// Notify the background thread.
cv_.notify_one();
}
private:
void run() {
pthread_setname_np(pthread_self(), "LowPriorityExecutorThread");
while (true) {
std::unique_lock<std::mutex> lock(mutex_);
// Wait until an object is in the queue or the thread is stopped.
cv_.wait(lock, [this] { return !queue_.empty() || !running_; });
// Empty the queue.
while (!queue_.empty()) {
queue_.front()();
queue_.pop();
}
// Check if the thread is stopping.
if (!running_) {
break;
}
}
}
std::string threadName_;
std::thread thread_;
std::queue<std::function<void()>> queue_;
std::mutex mutex_;
std::condition_variable cv_;
bool running_{true};
};
void execute(std::function<void()>&& workItem) {
static LowPriorityExecutorThread thread{};
thread.post(std::move(workItem));
}
} // namespace facebook::react::LowPriorityExecutor

View File

@@ -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.
*/
#pragma once
namespace facebook::react::LowPriorityExecutor {
void execute(std::function<void()> &&workItem);
} // namespace facebook::react::LowPriorityExecutor

View File

@@ -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.
*/
#pragma once
#include <functional>
namespace facebook::react::LowPriorityExecutor {
inline void execute(std::function<void()> &&workItem)
{
workItem();
}
} // namespace facebook::react::LowPriorityExecutor

View File

@@ -0,0 +1,18 @@
/*
* 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 <Foundation/Foundation.h>
#include <folly/dynamic.h>
namespace facebook::react {
folly::dynamic convertIdToFollyDynamic(id json);
id convertFollyDynamicToId(const folly::dynamic &dyn);
NSArray<NSString *> *extractKeysFromFollyDynamic(const folly::dynamic &dyn);
} // namespace facebook::react

View File

@@ -0,0 +1,132 @@
/*
* 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 "FollyConvert.h"
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
namespace facebook::react {
id convertFollyDynamicToId(const folly::dynamic &dyn)
{
// I could imagine an implementation which avoids copies by wrapping the
// dynamic in a derived class of NSDictionary. We can do that if profiling
// implies it will help.
switch (dyn.type()) {
case folly::dynamic::NULLT:
return (id)kCFNull;
case folly::dynamic::BOOL:
return dyn.getBool() ? @YES : @NO;
case folly::dynamic::INT64:
return @(dyn.getInt());
case folly::dynamic::DOUBLE:
return @(dyn.getDouble());
case folly::dynamic::STRING:
return [[NSString alloc] initWithBytes:dyn.c_str() length:dyn.size() encoding:NSUTF8StringEncoding];
case folly::dynamic::ARRAY: {
NSMutableArray *array = [[NSMutableArray alloc] initWithCapacity:dyn.size()];
for (const auto &elem : dyn) {
id value = convertFollyDynamicToId(elem);
if (value != nullptr) {
[array addObject:value];
}
}
return array;
}
case folly::dynamic::OBJECT: {
NSMutableDictionary *dict = [[NSMutableDictionary alloc] initWithCapacity:dyn.size()];
for (const auto &elem : dyn.items()) {
id key = convertFollyDynamicToId(elem.first);
id value = convertFollyDynamicToId(elem.second);
if ((key != nullptr) && (value != nullptr)) {
dict[key] = value;
}
}
return dict;
}
}
}
folly::dynamic convertIdToFollyDynamic(id json)
{
if (json == nil || json == (id)kCFNull) {
return nullptr;
} else if ([json isKindOfClass:[NSNumber class]]) {
const char *objCType = [json objCType];
switch (objCType[0]) {
// This is a c++ bool or C99 _Bool. On some platforms, BOOL is a bool.
case _C_BOOL:
return (bool)[json boolValue];
case _C_CHR:
// On some platforms, objc BOOL is a signed char, but it
// might also be a small number. Use the same hack JSC uses
// to distinguish them:
// https://phabricator.intern.facebook.com/diffusion/FBS/browse/master/fbobjc/xplat/third-party/jsc/safari-600-1-4-17/JavaScriptCore/API/JSValue.mm;b8ee03916489f8b12143cd5c0bca546da5014fc9$901
if ([json isKindOfClass:[@YES class]]) {
return (bool)[json boolValue];
} else {
return [json longLongValue];
}
case _C_UCHR:
case _C_SHT:
case _C_USHT:
case _C_INT:
case _C_UINT:
case _C_LNG:
case _C_ULNG:
case _C_LNG_LNG:
case _C_ULNG_LNG:
return [json longLongValue];
case _C_FLT:
case _C_DBL:
return [json doubleValue];
// default:
// fall through
}
} else if ([json isKindOfClass:[NSString class]]) {
NSData *data = [json dataUsingEncoding:NSUTF8StringEncoding];
return std::string(reinterpret_cast<const char *>(data.bytes), data.length);
} else if ([json isKindOfClass:[NSArray class]]) {
folly::dynamic array = folly::dynamic::array;
for (id element in json) {
array.push_back(convertIdToFollyDynamic(element));
}
return array;
} else if ([json isKindOfClass:[NSDictionary class]]) {
__block folly::dynamic object = folly::dynamic::object();
[json enumerateKeysAndObjectsUsingBlock:^(NSString *key, NSString *value, __unused BOOL *stop) {
object.insert(convertIdToFollyDynamic(key), convertIdToFollyDynamic(value));
}];
return object;
}
return nil;
}
NSArray<NSString *> *extractKeysFromFollyDynamic(const folly::dynamic &dyn)
{
if (dyn.type() == folly::dynamic::OBJECT) {
NSMutableArray<NSString *> *result = [NSMutableArray arrayWithCapacity:dyn.size()];
for (const auto &elem : dyn.items()) {
NSString *key = [[NSString alloc] initWithBytes:elem.first.c_str()
length:elem.first.size()
encoding:NSUTF8StringEncoding];
[result addObject:key];
}
return result;
}
return @[];
}
} // namespace facebook::react

View File

@@ -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.
*/
#pragma once
#include <functional>
namespace facebook::react::LowPriorityExecutor {
void execute(std::function<void()> &&workItem);
} // namespace facebook::react::LowPriorityExecutor

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.
*/
#import "LowPriorityExecutor.h"
#import <Foundation/Foundation.h>
namespace facebook::react::LowPriorityExecutor {
void execute(std::function<void()> &&workItem)
{
std::function<void()> localWorkItem = std::move(workItem);
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
localWorkItem();
});
}
} // namespace facebook::react::LowPriorityExecutor