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