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