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