/* * 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 "JSINativeModules.h" #include #include #include #include #include #include #include namespace facebook { namespace react { // A JSIScopedTimeoutInvoker is a trampoline-type function for introducing // timeouts. Call the TimeoutInvoker with a function to execute, the invokee. // The TimeoutInvoker will immediately invoke it, synchronously on the same // thread. If the invokee fails to return after some timeout (private to the // TimeoutInvoker), a soft error may be reported. // // If a soft error is reported, the second parameter errorMessageProducer will // be invoked to produce an error message, which will be included in the soft // error report. Note that the errorMessageProducer will be invoked // asynchronously on a different thread. // // The timeout behavior does NOT cause the invokee to aborted. If the invokee // blocks forever, so will the ScopedTimeoutInvoker (but the soft error may // still be reported). // // The invokee is passed by const ref because it is executed synchronously, but // the errorMessageProducer is passed by value because it must be copied or // moved for async execution. // // Example usage: // // int param = ...; // timeoutInvoker( // [&]{ someBigWork(param); }, // [=] -> std::string { // return "someBigWork, param " + std::to_string(param); // }) // using JSIScopedTimeoutInvoker = std::function &invokee, std::function errorMessageProducer)>; class BigStringBuffer : public jsi::Buffer { public: BigStringBuffer(std::unique_ptr script) : script_(std::move(script)) {} size_t size() const override { return script_->size(); } const uint8_t *data() const override { return reinterpret_cast(script_->c_str()); } private: std::unique_ptr script_; }; class JSIExecutor : public JSExecutor { public: using RuntimeInstaller = std::function; JSIExecutor( std::shared_ptr runtime, std::shared_ptr delegate, const JSIScopedTimeoutInvoker &timeoutInvoker, RuntimeInstaller runtimeInstaller); void initializeRuntime() override; void loadBundle( std::unique_ptr script, std::string sourceURL) override; void setBundleRegistry(std::unique_ptr) override; void registerBundle(uint32_t bundleId, const std::string &bundlePath) override; void callFunction( const std::string &moduleId, const std::string &methodId, const folly::dynamic &arguments) override; void invokeCallback(const double callbackId, const folly::dynamic &arguments) override; void setGlobalVariable( std::string propName, std::unique_ptr jsonValue) override; std::string getDescription() override; void *getJavaScriptContext() override; bool isInspectable() override; void handleMemoryPressure(int pressureLevel) override; // An implementation of JSIScopedTimeoutInvoker that simply runs the // invokee, with no timeout. static void defaultTimeoutInvoker( const std::function &invokee, std::function errorMessageProducer) { (void)errorMessageProducer; invokee(); } void flush() override; private: class NativeModuleProxy; void bindBridge(); void callNativeModules(const jsi::Value &queue, bool isEndOfBatch); jsi::Value nativeCallSyncHook(const jsi::Value *args, size_t count); jsi::Value nativeRequire(const jsi::Value *args, size_t count); jsi::Value globalEvalWithSourceUrl(const jsi::Value *args, size_t count); std::shared_ptr runtime_; std::shared_ptr delegate_; std::shared_ptr nativeModules_; std::shared_ptr moduleRegistry_; std::once_flag bindFlag_; std::unique_ptr bundleRegistry_; JSIScopedTimeoutInvoker scopedTimeoutInvoker_; RuntimeInstaller runtimeInstaller_; std::optional callFunctionReturnFlushedQueue_; std::optional invokeCallbackAndReturnFlushedQueue_; std::optional flushedQueue_; }; using Logger = std::function; void bindNativeLogger(jsi::Runtime &runtime, Logger logger); void bindNativePerformanceNow(jsi::Runtime &runtime); double performanceNow(); } // namespace react } // namespace facebook