1 // Copyright © 2021-present 650 Industries, Inc. (aka Expo) 2 3 #include "JavaScriptRuntime.h" 4 #include "JavaScriptValue.h" 5 #include "JavaScriptObject.h" 6 #include "Exceptions.h" 7 8 #if FOR_HERMES 9 10 #include <hermes/hermes.h> 11 12 #include <utility> 13 14 #else 15 16 #include <jsi/JSCRuntime.h> 17 18 #endif 19 20 namespace jsi = facebook::jsi; 21 22 namespace expo { 23 24 25 JavaScriptRuntime::JavaScriptRuntime() { 26 #if FOR_HERMES 27 auto config = ::hermes::vm::RuntimeConfig::Builder().withEnableSampleProfiling(false); 28 runtime = facebook::hermes::makeHermesRuntime(config.build()); 29 #else 30 runtime = facebook::jsc::makeJSCRuntime(); 31 #endif 32 } 33 34 JavaScriptRuntime::JavaScriptRuntime( 35 jsi::Runtime *runtime, 36 std::shared_ptr<react::CallInvoker> jsInvoker, 37 std::shared_ptr<react::CallInvoker> nativeInvoker 38 ) : jsInvoker(std::move(jsInvoker)), nativeInvoker(std::move(nativeInvoker)) { 39 // Creating a shared pointer that points to the runtime but doesn't own it, thus doesn't release it. 40 // In this code flow, the runtime should be owned by something else like the CatalystInstance. 41 // See explanation for constructor (8): https://en.cppreference.com/w/cpp/memory/shared_ptr/shared_ptr 42 this->runtime = std::shared_ptr<jsi::Runtime>(std::shared_ptr<jsi::Runtime>(), runtime); 43 } 44 45 jsi::Runtime *JavaScriptRuntime::get() { 46 return runtime.get(); 47 } 48 49 jni::local_ref<JavaScriptValue::javaobject> 50 JavaScriptRuntime::evaluateScript(const std::string &script) { 51 auto scriptBuffer = std::make_shared<jsi::StringBuffer>(script); 52 std::shared_ptr<jsi::Value> result; 53 try { 54 result = std::make_shared<jsi::Value>( 55 runtime->evaluateJavaScript(scriptBuffer, "<<evaluated>>") 56 ); 57 } catch (const jsi::JSError &error) { 58 jni::throwNewJavaException( 59 JavaScriptEvaluateException::create( 60 error.getMessage(), 61 error.getStack() 62 ).get() 63 ); 64 } catch (const jsi::JSIException &error) { 65 jni::throwNewJavaException( 66 JavaScriptEvaluateException::create( 67 error.what(), 68 "" 69 ).get() 70 ); 71 } 72 73 return JavaScriptValue::newObjectCxxArgs(weak_from_this(), result); 74 } 75 76 jni::local_ref<JavaScriptObject::javaobject> JavaScriptRuntime::global() { 77 auto global = std::make_shared<jsi::Object>(runtime->global()); 78 return JavaScriptObject::newObjectCxxArgs(weak_from_this(), global); 79 } 80 81 jni::local_ref<JavaScriptObject::javaobject> JavaScriptRuntime::createObject() { 82 auto newObject = std::make_shared<jsi::Object>(*runtime); 83 return JavaScriptObject::newObjectCxxArgs(weak_from_this(), newObject); 84 } 85 86 void JavaScriptRuntime::drainJSEventLoop() { 87 while (!runtime->drainMicrotasks()) {} 88 } 89 } // namespace expo 90