1 // Copyright © 2021-present 650 Industries, Inc. (aka Expo) 2 3 #pragma once 4 5 #include "JNIDeallocator.h" 6 7 #include <jsi/jsi.h> 8 #include <fbjni/fbjni.h> 9 #include <ReactCommon/CallInvoker.h> 10 11 namespace jsi = facebook::jsi; 12 namespace jni = facebook::jni; 13 namespace react = facebook::react; 14 15 namespace expo { 16 17 class JavaScriptValue; 18 class JavaScriptObject; 19 class JSIInteropModuleRegistry; 20 21 #if REACT_NATIVE_TARGET_VERSION >= 73 22 using NativeMethodCallInvokerCompatible = react::NativeMethodCallInvoker; 23 #else 24 using NativeMethodCallInvokerCompatible = react::CallInvoker; 25 #endif 26 27 /** 28 * A wrapper for the jsi::Runtime. 29 * This class is used as a bridge between CPP and Kotlin and to encapsulate common runtime helper functions. 30 * 31 * Instances of this class should be managed using a shared smart pointer. 32 * To pass runtime information to all of `JavaScriptValue` and `JavaScriptObject` we use `weak_from_this()` 33 * that requires that the object is held via a smart pointer. Otherwise, `weak_from_this()` returns `nullptr`. 34 */ 35 class JavaScriptRuntime : public std::enable_shared_from_this<JavaScriptRuntime> { 36 public: 37 /** 38 * Initializes a runtime that is independent from React Native and its runtime initialization. 39 * This flow is mostly intended for tests. The JS call invoker is set to `SyncCallInvoker`. 40 * See **JavaScriptRuntime.cpp** for the `SyncCallInvoker` implementation. 41 */ 42 JavaScriptRuntime( 43 JSIInteropModuleRegistry *jsiInteropModuleRegistry 44 ); 45 46 JavaScriptRuntime( 47 JSIInteropModuleRegistry *jsiInteropModuleRegistry, 48 jsi::Runtime *runtime, 49 std::shared_ptr<react::CallInvoker> jsInvoker, 50 std::shared_ptr<NativeMethodCallInvokerCompatible> nativeInvoker 51 ); 52 53 /** 54 * Returns the underlying runtime object. 55 */ 56 jsi::Runtime &get() const; 57 58 /** 59 * Evaluates given JavaScript source code. 60 * @throws if the input format is unknown, or evaluation causes an error, 61 * a jni::JniException<JavaScriptEvaluateException> will be thrown. 62 */ 63 jni::local_ref<jni::HybridClass<JavaScriptValue, Destructible>::javaobject> evaluateScript( 64 const std::string &script 65 ); 66 67 /** 68 * Returns the runtime global object for use in Kotlin. 69 */ 70 jni::local_ref<jni::HybridClass<JavaScriptObject, Destructible>::javaobject> global(); 71 72 /** 73 * Creates a new object for use in Kotlin. 74 */ 75 jni::local_ref<jni::HybridClass<JavaScriptObject, Destructible>::javaobject> createObject(); 76 77 /** 78 * Drains the JavaScript VM internal Microtask (a.k.a. event loop) queue. 79 */ 80 void drainJSEventLoop(); 81 82 std::shared_ptr<react::CallInvoker> jsInvoker; 83 std::shared_ptr<NativeMethodCallInvokerCompatible> nativeInvoker; 84 85 std::shared_ptr<jsi::Object> getMainObject(); 86 87 JSIInteropModuleRegistry *getModuleRegistry(); 88 private: 89 std::shared_ptr<jsi::Runtime> runtime; 90 std::shared_ptr<jsi::Object> mainObject; 91 JSIInteropModuleRegistry *jsiInteropModuleRegistry; 92 93 void installMainObject(); 94 }; 95 } // namespace expo 96