This commit is contained in:
Yamozha
2021-04-02 02:24:13 +03:00
parent c23950b545
commit 7256d79e2c
31493 changed files with 3036630 additions and 0 deletions

View File

@ -0,0 +1,29 @@
/*
* 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 <jsireact/JSIExecutor.h>
namespace facebook {
namespace react {
class JSCExecutorFactory : public JSExecutorFactory {
public:
explicit JSCExecutorFactory(JSIExecutor::RuntimeInstaller runtimeInstaller)
: runtimeInstaller_(std::move(runtimeInstaller)) {}
std::unique_ptr<JSExecutor> createJSExecutor(
std::shared_ptr<ExecutorDelegate> delegate,
std::shared_ptr<MessageQueueThread> jsQueue) override;
private:
JSIExecutor::RuntimeInstaller runtimeInstaller_;
};
} // namespace react
} // namespace facebook

View File

@ -0,0 +1,44 @@
/*
* 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.
*/
#include "JSCExecutorFactory.h"
#import <React/RCTLog.h>
#import <jsi/JSCRuntime.h>
#import <memory>
namespace facebook {
namespace react {
std::unique_ptr<JSExecutor> JSCExecutorFactory::createJSExecutor(
std::shared_ptr<ExecutorDelegate> delegate,
std::shared_ptr<MessageQueueThread> __unused jsQueue)
{
auto installBindings = [runtimeInstaller = runtimeInstaller_](jsi::Runtime &runtime) {
react::Logger iosLoggingBinder = [](const std::string &message, unsigned int logLevel) {
_RCTLogJavaScriptInternal(static_cast<RCTLogLevel>(logLevel), [NSString stringWithUTF8String:message.c_str()]);
};
react::bindNativeLogger(runtime, iosLoggingBinder);
react::PerformanceNow iosPerformanceNowBinder = []() {
// CACurrentMediaTime() returns the current absolute time, in seconds
return CACurrentMediaTime() * 1000;
};
react::bindNativePerformanceNow(runtime, iosPerformanceNowBinder);
// Wrap over the original runtimeInstaller
if (runtimeInstaller) {
runtimeInstaller(runtime);
}
};
return std::make_unique<JSIExecutor>(
facebook::jsc::makeJSCRuntime(), delegate, JSIExecutor::defaultTimeoutInvoker, std::move(installBindings));
}
} // namespace react
} // namespace facebook

View File

@ -0,0 +1,42 @@
/*
* 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.
*/
#import <Foundation/Foundation.h>
#include <cxxreact/JSBigString.h>
namespace facebook {
namespace react {
class NSDataBigString : public JSBigString {
public:
// The NSData passed in must be be null-terminated.
NSDataBigString(NSData *data);
// The ASCII optimization is not enabled on iOS
bool isAscii() const override
{
return false;
}
const char *c_str() const override
{
return (const char *)[m_data bytes];
}
size_t size() const override
{
return m_length;
}
private:
NSData *m_data;
size_t m_length;
};
}
}

View File

@ -0,0 +1,43 @@
/*
* 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.
*/
#import "NSDataBigString.h"
namespace facebook {
namespace react {
static NSData *ensureNullTerminated(NSData *source)
{
if (!source || source.length == 0) {
return nil;
}
NSUInteger sourceLength = source.length;
unsigned char lastByte;
[source getBytes:&lastByte range:NSMakeRange(sourceLength - 1, 1)];
// TODO: bundles from the packager should always include a NULL byte
// or we should we relax this requirement and only read as much from the
// buffer as length indicates
if (lastByte == '\0') {
return source;
} else {
NSMutableData *data = [source mutableCopy];
unsigned char nullByte = '\0';
[data appendBytes:&nullByte length:1];
return data;
}
}
NSDataBigString::NSDataBigString(NSData *data)
{
m_length = [data length];
m_data = ensureNullTerminated(data);
}
}
}

1460
node_modules/react-native/React/CxxBridge/RCTCxxBridge.mm generated vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,33 @@
/*
* 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.
*/
#include <memory>
#import <React/RCTBridgeDelegate.h>
namespace facebook {
namespace react {
class JSExecutorFactory;
}
}
// This is a separate class so non-C++ implementations don't need to
// take a C++ dependency.
@protocol RCTCxxBridgeDelegate <RCTBridgeDelegate>
/**
* In the RCTCxxBridge, if this method is implemented, return a
* ExecutorFactory instance which can be used to create the executor.
* If not implemented, or returns an empty pointer, JSIExecutorFactory
* will be used with a JSCRuntime.
*/
- (std::unique_ptr<facebook::react::JSExecutorFactory>)jsExecutorFactoryForBridge:(RCTBridge *)bridge;
@end

View File

@ -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.
*/
#import <string>
#import <Foundation/Foundation.h>
#import <React/RCTJavaScriptExecutor.h>
#import <cxxreact/MessageQueueThread.h>
namespace facebook {
namespace react {
class RCTMessageThread : public MessageQueueThread {
public:
RCTMessageThread(NSRunLoop *runLoop, RCTJavaScriptCompleteBlock errorBlock);
~RCTMessageThread() override;
void runOnQueue(std::function<void()> &&) override;
void runOnQueueSync(std::function<void()> &&) override;
void quitSynchronous() override;
void setRunLoop(NSRunLoop *runLoop);
private:
void tryFunc(const std::function<void()> &func);
void runAsync(std::function<void()> func);
void runSync(std::function<void()> func);
CFRunLoopRef m_cfRunLoop;
RCTJavaScriptCompleteBlock m_errorBlock;
std::atomic_bool m_shutdown;
};
} // namespace react
} // namespace facebook

View File

@ -0,0 +1,114 @@
/*
* 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.
*/
#include "RCTMessageThread.h"
#include <condition_variable>
#include <mutex>
#import <React/RCTCxxUtils.h>
#import <React/RCTUtils.h>
// A note about the implementation: This class is not used
// generically. It's a thin wrapper around a run loop which
// implements a C++ interface, for use by the C++ xplat bridge code.
// This means it can make certain non-generic assumptions. In
// particular, the sync functions are only used for bridge setup and
// teardown, and quitSynchronous is guaranteed to be called.
namespace facebook {
namespace react {
RCTMessageThread::RCTMessageThread(NSRunLoop *runLoop, RCTJavaScriptCompleteBlock errorBlock)
: m_cfRunLoop([runLoop getCFRunLoop]), m_errorBlock(errorBlock), m_shutdown(false)
{
CFRetain(m_cfRunLoop);
}
RCTMessageThread::~RCTMessageThread()
{
CFRelease(m_cfRunLoop);
}
// This is analogous to dispatch_async
void RCTMessageThread::runAsync(std::function<void()> func)
{
CFRunLoopPerformBlock(m_cfRunLoop, kCFRunLoopCommonModes, ^{
// Create an autorelease pool each run loop to prevent memory footprint from growing too large, which can lead to
// performance problems.
@autoreleasepool {
func();
}
});
CFRunLoopWakeUp(m_cfRunLoop);
}
// This is analogous to dispatch_sync
void RCTMessageThread::runSync(std::function<void()> func)
{
if (m_cfRunLoop == CFRunLoopGetCurrent()) {
func();
return;
}
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
runAsync([func = std::make_shared<std::function<void()>>(std::move(func)), &sema] {
(*func)();
dispatch_semaphore_signal(sema);
});
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
}
void RCTMessageThread::tryFunc(const std::function<void()> &func)
{
NSError *error = tryAndReturnError(func);
if (error) {
m_errorBlock(error);
}
}
void RCTMessageThread::runOnQueue(std::function<void()> &&func)
{
if (m_shutdown) {
return;
}
runAsync([this, func = std::make_shared<std::function<void()>>(std::move(func))] {
if (!m_shutdown) {
tryFunc(*func);
}
});
}
void RCTMessageThread::runOnQueueSync(std::function<void()> &&func)
{
if (m_shutdown) {
return;
}
runSync([this, func = std::move(func)] {
if (!m_shutdown) {
tryFunc(func);
}
});
}
void RCTMessageThread::quitSynchronous()
{
m_shutdown = true;
runSync([] {});
CFRunLoopStop(m_cfRunLoop);
}
void RCTMessageThread::setRunLoop(NSRunLoop *runLoop)
{
CFRelease(m_cfRunLoop);
m_cfRunLoop = [runLoop getCFRunLoop];
CFRetain(m_cfRunLoop);
}
}
}

View File

@ -0,0 +1,33 @@
/*
* 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.
*/
#include <functional>
#include <memory>
#import <React/RCTDefines.h>
#import <React/RCTJavaScriptExecutor.h>
#import <cxxreact/JSExecutor.h>
namespace facebook {
namespace react {
class RCTObjcExecutorFactory : public JSExecutorFactory {
public:
RCTObjcExecutorFactory(
id<RCTJavaScriptExecutor> jse,
RCTJavaScriptCompleteBlock errorBlock);
std::unique_ptr<JSExecutor> createJSExecutor(
std::shared_ptr<ExecutorDelegate> delegate,
std::shared_ptr<MessageQueueThread> jsQueue) override;
private:
id<RCTJavaScriptExecutor> m_jse;
RCTJavaScriptCompleteBlock m_errorBlock;
};
} // namespace react
} // namespace facebook

View File

@ -0,0 +1,148 @@
/*
* 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.
*/
#import "RCTObjcExecutor.h"
#import <React/RCTCxxUtils.h>
#import <React/RCTFollyConvert.h>
#import <React/RCTJavaScriptExecutor.h>
#import <React/RCTLog.h>
#import <React/RCTProfile.h>
#import <React/RCTUtils.h>
#import <cxxreact/JSBigString.h>
#import <cxxreact/JSExecutor.h>
#import <cxxreact/MessageQueueThread.h>
#import <cxxreact/ModuleRegistry.h>
#import <cxxreact/RAMBundleRegistry.h>
#import <folly/json.h>
namespace facebook {
namespace react {
namespace {
class JSEException : public std::runtime_error {
public:
JSEException(NSError *error) : runtime_error([[error description] UTF8String]) {}
};
class RCTObjcExecutor : public JSExecutor {
public:
RCTObjcExecutor(
id<RCTJavaScriptExecutor> jse,
RCTJavaScriptCompleteBlock errorBlock,
std::shared_ptr<MessageQueueThread> jsThread,
std::shared_ptr<ExecutorDelegate> delegate)
: m_jse(jse), m_errorBlock(errorBlock), m_delegate(std::move(delegate)), m_jsThread(std::move(jsThread))
{
m_jsCallback = ^(id json, NSError *error) {
if (error) {
// Do not use "m_errorBlock" here as the bridge might be in the middle
// of invalidation as a result of error handling and "this" can be
// already deallocated.
errorBlock(error);
return;
}
m_jsThread->runOnQueue(
[this, json] { m_delegate->callNativeModules(*this, convertIdToFollyDynamic(json), true); });
};
// Synchronously initialize the executor
[jse setUp];
folly::dynamic nativeModuleConfig = folly::dynamic::array;
auto moduleRegistry = m_delegate->getModuleRegistry();
for (const auto &name : moduleRegistry->moduleNames()) {
auto config = moduleRegistry->getConfig(name);
nativeModuleConfig.push_back(config ? config->config : nullptr);
}
folly::dynamic config = folly::dynamic::object("remoteModuleConfig", std::move(nativeModuleConfig));
setGlobalVariable("__fbBatchedBridgeConfig", std::make_unique<JSBigStdString>(folly::toJson(config)));
}
void initializeRuntime() override
{
// We do nothing here since initialization is done in the constructor
}
void loadBundle(std::unique_ptr<const JSBigString> script, std::string sourceURL) override
{
RCTProfileBeginFlowEvent();
[m_jse executeApplicationScript:[NSData dataWithBytes:script->c_str() length:script->size()]
sourceURL:[[NSURL alloc] initWithString:@(sourceURL.c_str())]
onComplete:^(NSError *error) {
RCTProfileEndFlowEvent();
if (error) {
m_errorBlock(error);
return;
}
[m_jse flushedQueue:m_jsCallback];
}];
}
void setBundleRegistry(std::unique_ptr<RAMBundleRegistry>) override
{
RCTAssert(NO, @"RAM bundles are not supported in RCTObjcExecutor");
}
void registerBundle(uint32_t __unused bundleId, const std::string __unused &bundlePath) override
{
RCTAssert(NO, @"RAM bundles are not supported in RCTObjcExecutor");
}
void callFunction(const std::string &module, const std::string &method, const folly::dynamic &arguments) override
{
[m_jse callFunctionOnModule:@(module.c_str())
method:@(method.c_str())
arguments:convertFollyDynamicToId(arguments)
callback:m_jsCallback];
}
void invokeCallback(double callbackId, const folly::dynamic &arguments) override
{
[m_jse invokeCallbackID:@(callbackId) arguments:convertFollyDynamicToId(arguments) callback:m_jsCallback];
}
virtual void setGlobalVariable(std::string propName, std::unique_ptr<const JSBigString> jsonValue) override
{
[m_jse injectJSONText:@(jsonValue->c_str()) asGlobalObjectNamed:@(propName.c_str()) callback:m_errorBlock];
}
virtual std::string getDescription() override
{
return [NSStringFromClass([m_jse class]) UTF8String];
}
private:
id<RCTJavaScriptExecutor> m_jse;
RCTJavaScriptCompleteBlock m_errorBlock;
std::shared_ptr<ExecutorDelegate> m_delegate;
std::shared_ptr<MessageQueueThread> m_jsThread;
RCTJavaScriptCallback m_jsCallback;
};
}
RCTObjcExecutorFactory::RCTObjcExecutorFactory(id<RCTJavaScriptExecutor> jse, RCTJavaScriptCompleteBlock errorBlock)
: m_jse(jse), m_errorBlock(errorBlock)
{
}
std::unique_ptr<JSExecutor> RCTObjcExecutorFactory::createJSExecutor(
std::shared_ptr<ExecutorDelegate> delegate,
std::shared_ptr<MessageQueueThread> jsQueue)
{
return std::unique_ptr<JSExecutor>(new RCTObjcExecutor(m_jse, m_errorBlock, jsQueue, delegate));
}
}
}