1 // Copyright © 2021-present 650 Industries, Inc. (aka Expo)
2 
3 #pragma once
4 
5 #include "JavaReferencesCache.h"
6 #include "Exceptions.h"
7 #include "JavaScriptObject.h"
8 #include "JavaScriptRuntime.h"
9 #include "JSIObjectWrapper.h"
10 #include "WeakRuntimeHolder.h"
11 
12 #include <jsi/jsi.h>
13 #include <memory>
14 #include <unordered_map>
15 
16 namespace expo {
17 /**
18  * Registry used to store references to often used JS objects like Promise.
19  * The object lifetime should be bound with the JS runtime.
20  */
21 class JSReferencesCache {
22 public:
23   enum class JSKeys {
24     PROMISE,
25     CODED_ERROR
26   };
27 
28   JSReferencesCache() = delete;
29 
30   JSReferencesCache(jsi::Runtime &runtime);
31 
32   /**
33    * Gets a cached object.
34    */
35   template<class T, typename std::enable_if_t<std::is_base_of_v<jsi::Object, T>, int> = 0>
36   T &getObject(JSKeys key) {
37     return static_cast<T &>(*jsObjectRegistry.at(key));
38   }
39 
40   /**
41    * Gets a cached object if present. Otherwise, returns nullptr.
42    */
43   template<class T, typename std::enable_if_t<std::is_base_of_v<jsi::Object, T>, int> = 0>
44   T *getOptionalObject(JSKeys key) {
45     auto result = jsObjectRegistry.find(key);
46 
47     if (result == jsObjectRegistry.end()) {
48       return nullptr;
49     }
50     jsi::Object &object = *result->second;
51     return &static_cast<T &>(object);
52   }
53 
54   /**
55    * Gets a cached jsi::PropNameID or creates a new one for the provided string.
56    */
57   jsi::PropNameID &getPropNameID(jsi::Runtime &runtime, const std::string &name);
58 
59 private:
60   std::unordered_map<JSKeys, std::unique_ptr<jsi::Object>> jsObjectRegistry;
61 
62   std::unordered_map<std::string, std::unique_ptr<jsi::PropNameID>> propNameIDRegistry;
63 };
64 } // namespace expo
65