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