react-native-nitro-modules 0.31.9 → 0.32.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/NitroModules.podspec +1 -0
  2. package/android/build.gradle +1 -1
  3. package/android/src/main/cpp/core/JAnyMap.cpp +120 -0
  4. package/android/src/main/cpp/core/JAnyMap.hpp +20 -56
  5. package/android/src/main/cpp/platform/NitroLogger.cpp +3 -1
  6. package/android/src/main/java/com/margelo/nitro/core/AnyMap.kt +16 -7
  7. package/cpp/core/AnyMap.hpp +2 -2
  8. package/cpp/core/HybridObject.cpp +10 -10
  9. package/cpp/entrypoint/InstallNitro.cpp +2 -2
  10. package/cpp/jsi/JSICache.cpp +10 -5
  11. package/cpp/jsi/JSICache.hpp +6 -0
  12. package/cpp/jsi/JSIConverter+AnyMap.hpp +4 -3
  13. package/cpp/jsi/JSIConverter+Date.hpp +8 -10
  14. package/cpp/jsi/JSIConverter+Exception.hpp +5 -5
  15. package/cpp/jsi/JSIConverter+Function.hpp +4 -1
  16. package/cpp/jsi/JSIConverter+Promise.hpp +8 -14
  17. package/cpp/jsi/JSIConverter+UnorderedMap.hpp +2 -1
  18. package/cpp/jsi/JSIHelpers.hpp +1 -1
  19. package/cpp/platform/NitroLogger.hpp +3 -1
  20. package/cpp/prototype/HybridObjectPrototype.cpp +28 -28
  21. package/cpp/threading/Dispatcher.cpp +5 -5
  22. package/cpp/utils/BorrowingReference.hpp +6 -6
  23. package/cpp/utils/CommonGlobals.cpp +215 -0
  24. package/cpp/utils/CommonGlobals.hpp +158 -0
  25. package/cpp/utils/NitroDefines.hpp +1 -1
  26. package/cpp/utils/PropNameIDCache.cpp +38 -0
  27. package/cpp/utils/PropNameIDCache.hpp +44 -0
  28. package/cpp/utils/{WeakReference+Owning.hpp → WeakReference+Borrowing.hpp} +1 -1
  29. package/cpp/utils/WeakReference.hpp +1 -1
  30. package/ios/platform/NitroLogger.cpp +37 -0
  31. package/ios/platform/ThreadUtils.cpp +43 -0
  32. package/package.json +1 -2
  33. package/cpp/utils/ObjectUtils.cpp +0 -172
  34. package/cpp/utils/ObjectUtils.hpp +0 -94
  35. package/ios/platform/NitroLogger.mm +0 -36
  36. package/ios/platform/ThreadUtils.mm +0 -46
@@ -22,7 +22,9 @@ private:
22
22
 
23
23
  public:
24
24
  template <typename... Args>
25
- static void log([[maybe_unused]] LogLevel level, [[maybe_unused]] const char* NON_NULL tag, [[maybe_unused]] const char* NON_NULL format,
25
+ static void log([[maybe_unused]] LogLevel level, //
26
+ [[maybe_unused]] const char* NON_NULL tag, //
27
+ [[maybe_unused]] const char* NON_NULL format, //
26
28
  [[maybe_unused]] Args... args) {
27
29
  #ifdef NITRO_DEBUG
28
30
  // 1. Make sure args can be passed to sprintf(..)
@@ -6,10 +6,10 @@
6
6
  //
7
7
 
8
8
  #include "HybridObjectPrototype.hpp"
9
+ #include "CommonGlobals.hpp"
9
10
  #include "NitroDefines.hpp"
10
11
  #include "NitroLogger.hpp"
11
12
  #include "NitroTypeInfo.hpp"
12
- #include "ObjectUtils.hpp"
13
13
 
14
14
  namespace margelo::nitro {
15
15
 
@@ -39,19 +39,19 @@ jsi::Value HybridObjectPrototype::createPrototype(jsi::Runtime& runtime, const s
39
39
  std::string typeName = TypeInfo::getFriendlyTypename(prototype->getNativeInstanceId(), true);
40
40
  Logger::log(LogLevel::Info, TAG, "Creating new JS prototype for C++ instance type \"%s\"...", typeName.c_str());
41
41
  jsi::Value basePrototype = createPrototype(runtime, prototype->getBase());
42
- jsi::Object object = ObjectUtils::create(runtime, basePrototype);
42
+ jsi::Object object = CommonGlobals::Object::create(runtime, basePrototype);
43
43
 
44
44
  // 4. Add all Hybrid Methods to it
45
45
  for (const auto& method : prototype->getMethods()) {
46
46
  // method()
47
47
  const std::string& name = method.first;
48
- ObjectUtils::defineProperty(runtime, object, name.c_str(),
49
- PlainPropertyDescriptor{
50
- .configurable = false,
51
- .enumerable = true,
52
- .value = method.second.toJSFunction(runtime),
53
- .writable = false,
54
- });
48
+ CommonGlobals::Object::defineProperty(runtime, object, name.c_str(),
49
+ PlainPropertyDescriptor{
50
+ .configurable = false,
51
+ .enumerable = true,
52
+ .value = method.second.toJSFunction(runtime),
53
+ .writable = false,
54
+ });
55
55
  }
56
56
 
57
57
  // 5. Add all properties (getter + setter) to it using defineProperty
@@ -61,37 +61,37 @@ jsi::Value HybridObjectPrototype::createPrototype(jsi::Runtime& runtime, const s
61
61
  const std::string& name = getter.first;
62
62
  if (isReadonly) {
63
63
  // get
64
- ObjectUtils::defineProperty(runtime, object, name.c_str(),
65
- ComputedReadonlyPropertyDescriptor{// readonly
66
- .configurable = false,
67
- .enumerable = true,
68
- .get = getter.second.toJSFunction(runtime)});
64
+ CommonGlobals::Object::defineProperty(runtime, object, name.c_str(),
65
+ ComputedReadonlyPropertyDescriptor{// readonly
66
+ .configurable = false,
67
+ .enumerable = true,
68
+ .get = getter.second.toJSFunction(runtime)});
69
69
  } else {
70
70
  // get + set
71
- ObjectUtils::defineProperty(runtime, object, name.c_str(),
72
- ComputedPropertyDescriptor{// readonly with setter
73
- .configurable = false,
74
- .enumerable = false,
75
- .get = getter.second.toJSFunction(runtime),
76
- .set = setter->second.toJSFunction(runtime)});
71
+ CommonGlobals::Object::defineProperty(runtime, object, name.c_str(),
72
+ ComputedPropertyDescriptor{// readonly with setter
73
+ .configurable = false,
74
+ .enumerable = false,
75
+ .get = getter.second.toJSFunction(runtime),
76
+ .set = setter->second.toJSFunction(runtime)});
77
77
  }
78
78
  }
79
79
 
80
80
  // 6. In DEBUG, add a __type info to the prototype object.
81
81
  #ifdef NITRO_DEBUG
82
82
  std::string prototypeName = "Prototype<" + typeName + ">";
83
- ObjectUtils::defineProperty(runtime, object, "__type",
84
- PlainPropertyDescriptor{
85
- .configurable = false,
86
- .enumerable = true,
87
- .value = jsi::String::createFromUtf8(runtime, prototypeName),
88
- .writable = false,
89
- });
83
+ CommonGlobals::Object::defineProperty(runtime, object, "__type",
84
+ PlainPropertyDescriptor{
85
+ .configurable = false,
86
+ .enumerable = true,
87
+ .value = jsi::String::createFromUtf8(runtime, prototypeName),
88
+ .writable = false,
89
+ });
90
90
  #endif
91
91
 
92
92
  // 7. In DEBUG, freeze the prototype.
93
93
  #ifdef NITRO_DEBUG
94
- ObjectUtils::freeze(runtime, object);
94
+ CommonGlobals::Object::freeze(runtime, object);
95
95
  #endif
96
96
 
97
97
  // 8. Throw it into our cache so the next lookup can be cached and therefore faster
@@ -6,11 +6,11 @@
6
6
  //
7
7
 
8
8
  #include "Dispatcher.hpp"
9
+ #include "CommonGlobals.hpp"
9
10
  #include "JSIConverter.hpp"
10
11
  #include "JSIHelpers.hpp"
11
12
  #include "NitroDefines.hpp"
12
13
  #include "NitroLogger.hpp"
13
- #include "ObjectUtils.hpp"
14
14
 
15
15
  namespace margelo::nitro {
16
16
 
@@ -30,7 +30,7 @@ void Dispatcher::installRuntimeGlobalDispatcher(jsi::Runtime& runtime, std::shar
30
30
 
31
31
  // Inject the dispatcher into Runtime global (runtime will hold a strong reference)
32
32
  jsi::Value dispatcherHolder = JSIConverter<std::shared_ptr<Dispatcher>>::toJSI(runtime, dispatcher);
33
- ObjectUtils::defineGlobal(runtime, KnownGlobalPropertyName::DISPATCHER, std::move(dispatcherHolder));
33
+ CommonGlobals::defineGlobal(runtime, KnownGlobalPropertyName::DISPATCHER, std::move(dispatcherHolder));
34
34
  }
35
35
 
36
36
  std::shared_ptr<Dispatcher> Dispatcher::getRuntimeGlobalDispatcher(jsi::Runtime& runtime) {
@@ -57,15 +57,15 @@ std::shared_ptr<Dispatcher> Dispatcher::getRuntimeGlobalDispatcher(jsi::Runtime&
57
57
  }
58
58
 
59
59
  jsi::Value Dispatcher::getRuntimeGlobalDispatcherHolder(jsi::Runtime& runtime) {
60
- const char* dispatcherHolderName = ObjectUtils::getKnownGlobalPropertyNameString(KnownGlobalPropertyName::DISPATCHER);
61
- if (!runtime.global().hasProperty(runtime, dispatcherHolderName)) [[unlikely]] {
60
+ const jsi::PropNameID& dispatcherHolderPropName = CommonGlobals::getKnownGlobalPropertyName(runtime, KnownGlobalPropertyName::DISPATCHER);
61
+ if (!runtime.global().hasProperty(runtime, dispatcherHolderPropName)) [[unlikely]] {
62
62
  throw std::runtime_error("The `jsi::Runtime` \"" + getRuntimeId(runtime) +
63
63
  "\" does not support Callbacks or Promises because it does not have a `Dispatcher` installed!\n"
64
64
  "To use Callbacks and Promises follow these steps;\n"
65
65
  "1. Subclass `Dispatcher` with your implementation of `runAsync`/`runSync` for your Thread.\n"
66
66
  "2. Call `Dispatcher::installRuntimeGlobalDispatcher(...)` with your `Runtime` and your `Dispatcher`.");
67
67
  }
68
- return runtime.global().getProperty(runtime, dispatcherHolderName);
68
+ return runtime.global().getProperty(runtime, dispatcherHolderPropName);
69
69
  }
70
70
 
71
71
  } // namespace margelo::nitro
@@ -18,15 +18,15 @@
18
18
  namespace margelo::nitro {
19
19
 
20
20
  /**
21
- * An `BorrowingReference<T>` is a smart-pointer that holds a strong reference to a pointer.
21
+ * A `BorrowingReference<T>` is a smart-pointer that holds a strong reference to a pointer.
22
22
  * You can have multiple `BorrowingReference<T>` instances point to the same pointer, as they internally keep a ref-count.
23
- * As opposed to a `shared_ptr<T>`, an `BorrowingReference<T>` can also be imperatively manually deleted, even if there
23
+ * As opposed to a `shared_ptr<T>`, a `BorrowingReference<T>` can also be imperatively manually deleted, even if there
24
24
  * are multiple strong references still holding onto the pointer.
25
25
  * This is useful in cases where the `BorrowingReference` might keep a reference alive, but an external value holder
26
26
  * is actually responsible for truly deleting the underlying value - like a `jsi::Runtime` for a `jsi::Value`.
27
27
  *
28
- * An `BorrowingReference<T>` can be weakified, which gives the user a `WeakReference<T>`.
29
- * A `WeakReference<T>` can be locked to get an `BorrowingReference<T>` again, assuming it has not been deleted yet.
28
+ * A `BorrowingReference<T>` can be weakified, which gives the user a `WeakReference<T>`.
29
+ * A `WeakReference<T>` can be locked to get a `BorrowingReference<T>` again, assuming it has not been deleted yet.
30
30
  */
31
31
  template <typename T>
32
32
  class BorrowingReference final {
@@ -120,7 +120,7 @@ public:
120
120
  }
121
121
 
122
122
  /**
123
- * Get a borrowing (or "weak") reference to this owning reference
123
+ * Get a weak reference to this borrowing reference.
124
124
  */
125
125
  [[nodiscard]]
126
126
  WeakReference<T> weak() const {
@@ -220,4 +220,4 @@ private:
220
220
 
221
221
  } // namespace margelo::nitro
222
222
 
223
- #include "WeakReference+Owning.hpp"
223
+ #include "WeakReference+Borrowing.hpp"
@@ -0,0 +1,215 @@
1
+ //
2
+ // CommonGlobals.cpp
3
+ // react-native-nitro
4
+ //
5
+ // Created by Marc Rousavy on 17.10.25.
6
+ //
7
+
8
+ #include "CommonGlobals.hpp"
9
+ #include "JSICache.hpp"
10
+ #include "JSIHelpers.hpp"
11
+ #include "NitroDefines.hpp"
12
+ #include "PropNameIDCache.hpp"
13
+
14
+ #if __has_include(<cxxreact/ReactNativeVersion.h>)
15
+ #include <cxxreact/ReactNativeVersion.h>
16
+ #if REACT_NATIVE_VERSION_MINOR >= 78
17
+ #define ENABLE_NATIVE_OBJECT_CREATE
18
+ #endif
19
+ #endif
20
+
21
+ namespace margelo::nitro {
22
+
23
+ using namespace facebook;
24
+
25
+ std::unordered_map<jsi::Runtime*, CommonGlobals::FunctionCache> CommonGlobals::_cache;
26
+
27
+ // pragma MARK: Object
28
+
29
+ jsi::Object CommonGlobals::Object::create(jsi::Runtime& runtime, const jsi::Value& prototype) {
30
+ #ifdef ENABLE_NATIVE_OBJECT_CREATE
31
+ return jsi::Object::create(runtime, prototype);
32
+ #else
33
+ const jsi::Function& createFn = getGlobalFunction(runtime, "Object.create", [](jsi::Runtime& runtime) {
34
+ return runtime.global().getPropertyAsObject(runtime, "Object").getPropertyAsFunction(runtime, "create");
35
+ });
36
+ return createFn.call(runtime, prototype).getObject(runtime);
37
+ #endif
38
+ }
39
+
40
+ void CommonGlobals::Object::defineProperty(jsi::Runtime& runtime, const jsi::Object& object, const char* propertyName,
41
+ PlainPropertyDescriptor&& descriptor) {
42
+ const jsi::Function& definePropertyFn = getGlobalFunction(runtime, "Object.defineProperty", [](jsi::Runtime& runtime) {
43
+ return runtime.global().getPropertyAsObject(runtime, "Object").getPropertyAsFunction(runtime, "defineProperty");
44
+ });
45
+
46
+ jsi::String nameJs = jsi::String::createFromAscii(runtime, propertyName);
47
+
48
+ jsi::Object descriptorJs(runtime);
49
+ descriptorJs.setProperty(runtime, PropNameIDCache::get(runtime, "configurable"), jsi::Value(descriptor.configurable));
50
+ descriptorJs.setProperty(runtime, PropNameIDCache::get(runtime, "enumerable"), jsi::Value(descriptor.enumerable));
51
+ descriptorJs.setProperty(runtime, PropNameIDCache::get(runtime, "value"), std::move(descriptor.value));
52
+ descriptorJs.setProperty(runtime, PropNameIDCache::get(runtime, "writable"), jsi::Value(descriptor.writable));
53
+
54
+ definePropertyFn.call(runtime, object, std::move(nameJs), std::move(descriptorJs));
55
+ }
56
+
57
+ void CommonGlobals::Object::defineProperty(jsi::Runtime& runtime, const jsi::Object& object, const char* propertyName,
58
+ ComputedReadonlyPropertyDescriptor&& descriptor) {
59
+ const jsi::Function& definePropertyFn = getGlobalFunction(runtime, "Object.defineProperty", [](jsi::Runtime& runtime) {
60
+ return runtime.global().getPropertyAsObject(runtime, "Object").getPropertyAsFunction(runtime, "defineProperty");
61
+ });
62
+
63
+ jsi::String nameJs = jsi::String::createFromAscii(runtime, propertyName);
64
+
65
+ jsi::Object descriptorJs(runtime);
66
+ descriptorJs.setProperty(runtime, PropNameIDCache::get(runtime, "configurable"), jsi::Value(descriptor.configurable));
67
+ descriptorJs.setProperty(runtime, PropNameIDCache::get(runtime, "enumerable"), jsi::Value(descriptor.enumerable));
68
+ descriptorJs.setProperty(runtime, PropNameIDCache::get(runtime, "get"), std::move(descriptor.get));
69
+
70
+ definePropertyFn.call(runtime, object, std::move(nameJs), std::move(descriptorJs));
71
+ }
72
+
73
+ void CommonGlobals::Object::defineProperty(jsi::Runtime& runtime, const jsi::Object& object, const char* propertyName,
74
+ ComputedPropertyDescriptor&& descriptor) {
75
+ const jsi::Function& definePropertyFn = getGlobalFunction(runtime, "Object.defineProperty", [](jsi::Runtime& runtime) {
76
+ return runtime.global().getPropertyAsObject(runtime, "Object").getPropertyAsFunction(runtime, "defineProperty");
77
+ });
78
+
79
+ jsi::String nameJs = jsi::String::createFromAscii(runtime, propertyName);
80
+
81
+ jsi::Object descriptorJs(runtime);
82
+ descriptorJs.setProperty(runtime, PropNameIDCache::get(runtime, "configurable"), jsi::Value(descriptor.configurable));
83
+ descriptorJs.setProperty(runtime, PropNameIDCache::get(runtime, "enumerable"), jsi::Value(descriptor.enumerable));
84
+ descriptorJs.setProperty(runtime, PropNameIDCache::get(runtime, "get"), std::move(descriptor.get));
85
+ descriptorJs.setProperty(runtime, PropNameIDCache::get(runtime, "set"), std::move(descriptor.set));
86
+
87
+ definePropertyFn.call(runtime, object, std::move(nameJs), std::move(descriptorJs));
88
+ }
89
+
90
+ void CommonGlobals::Object::freeze(jsi::Runtime& runtime, const jsi::Object& object) {
91
+ const jsi::Function& freezeFn = getGlobalFunction(runtime, "Object.freeze", [](jsi::Runtime& runtime) {
92
+ return runtime.global().getPropertyAsObject(runtime, "Object").getPropertyAsFunction(runtime, "freeze");
93
+ });
94
+
95
+ freezeFn.call(runtime, object);
96
+ }
97
+
98
+ // pragma MARK: Promise
99
+
100
+ jsi::Value CommonGlobals::Promise::resolved(jsi::Runtime& runtime) {
101
+ const jsi::Function& resolvedFunc = getGlobalFunction(runtime, "Promise.resolve", [](jsi::Runtime& runtime) {
102
+ return runtime.global().getPropertyAsObject(runtime, "Promise").getPropertyAsFunction(runtime, "resolve");
103
+ });
104
+ return resolvedFunc.call(runtime);
105
+ }
106
+ jsi::Value CommonGlobals::Promise::resolved(jsi::Runtime& runtime, jsi::Value&& value) {
107
+ const jsi::Function& resolvedFunc = getGlobalFunction(runtime, "Promise.resolve", [](jsi::Runtime& runtime) {
108
+ return runtime.global().getPropertyAsObject(runtime, "Promise").getPropertyAsFunction(runtime, "resolve");
109
+ });
110
+ return resolvedFunc.call(runtime, {std::move(value)});
111
+ }
112
+ jsi::Value CommonGlobals::Promise::rejected(jsi::Runtime& runtime, jsi::Value&& error) {
113
+ const jsi::Function& rejectedFunc = getGlobalFunction(runtime, "Promise.reject", [](jsi::Runtime& runtime) {
114
+ return runtime.global().getPropertyAsObject(runtime, "Promise").getPropertyAsFunction(runtime, "reject");
115
+ });
116
+ return rejectedFunc.call(runtime, {std::move(error)});
117
+ }
118
+
119
+ jsi::Value CommonGlobals::Promise::callConstructor(jsi::Runtime& runtime, jsi::HostFunctionType&& executor) {
120
+ const jsi::Function& promiseCtor = getGlobalFunction(
121
+ runtime, "Promise", [](jsi::Runtime& runtime) { return runtime.global().getPropertyAsFunction(runtime, "Promise"); });
122
+ jsi::Function executorFunc =
123
+ jsi::Function::createFromHostFunction(runtime, jsi::PropNameID::forAscii(runtime, "executor"), 2, std::move(executor));
124
+ return promiseCtor.callAsConstructor(runtime, std::move(executorFunc));
125
+ }
126
+ bool CommonGlobals::Promise::isInstanceOf(jsi::Runtime& runtime, const jsi::Object& object) {
127
+ const jsi::Function& promiseCtor = getGlobalFunction(
128
+ runtime, "Promise", [](jsi::Runtime& runtime) { return runtime.global().getPropertyAsFunction(runtime, "Promise"); });
129
+ return object.instanceOf(runtime, promiseCtor);
130
+ }
131
+
132
+ // pragma MARK: Date
133
+
134
+ jsi::Value CommonGlobals::Date::callConstructor(jsi::Runtime& runtime, double msSinceEpoch) {
135
+ const jsi::Function& dateCtor =
136
+ getGlobalFunction(runtime, "Date", [](jsi::Runtime& runtime) { return runtime.global().getPropertyAsFunction(runtime, "Date"); });
137
+ return dateCtor.callAsConstructor(runtime, {jsi::Value(msSinceEpoch)});
138
+ }
139
+ bool CommonGlobals::Date::isInstanceOf(jsi::Runtime& runtime, const jsi::Object& object) {
140
+ const jsi::Function& dateCtor =
141
+ getGlobalFunction(runtime, "Date", [](jsi::Runtime& runtime) { return runtime.global().getPropertyAsFunction(runtime, "Date"); });
142
+ return object.instanceOf(runtime, dateCtor);
143
+ }
144
+
145
+ // pragma MARK: Error
146
+
147
+ bool CommonGlobals::Error::isInstanceOf(jsi::Runtime& runtime, const jsi::Object& object) {
148
+ const jsi::Function& errorCtor =
149
+ getGlobalFunction(runtime, "Error", [](jsi::Runtime& runtime) { return runtime.global().getPropertyAsFunction(runtime, "Error"); });
150
+ return object.instanceOf(runtime, errorCtor);
151
+ }
152
+
153
+ // pragma MARK: CommonGlobals
154
+
155
+ void CommonGlobals::defineGlobal(jsi::Runtime& runtime, KnownGlobalPropertyName name, jsi::Value&& value) {
156
+ const char* nameString = getKnownGlobalPropertyNameString(name);
157
+
158
+ #ifdef NITRO_DEBUG
159
+ // In debug, let's perform additional safety checks.
160
+ if (runtime.global().hasProperty(runtime, nameString)) [[unlikely]] {
161
+ throw std::runtime_error("Failed to set `global." + std::string(nameString) + "` - it already exists for Runtime \"" +
162
+ getRuntimeId(runtime) + "\"! Did you call `defineGlobal(\"" + std::string(nameString) +
163
+ "\")` twice? Did you link Nitro Modules twice?");
164
+ }
165
+ Object::defineProperty(runtime, runtime.global(), nameString,
166
+ PlainPropertyDescriptor{.configurable = false, .enumerable = true, .value = std::move(value), .writable = false});
167
+ #else
168
+ // In release, just set the property.
169
+ runtime.global().setProperty(runtime, nameString, std::move(value));
170
+ #endif
171
+ }
172
+
173
+ const char* CommonGlobals::getKnownGlobalPropertyNameString(KnownGlobalPropertyName name) {
174
+ switch (name) {
175
+ case KnownGlobalPropertyName::DISPATCHER:
176
+ return "__nitroDispatcher";
177
+ case KnownGlobalPropertyName::JSI_CACHE:
178
+ return "__nitroJsiCache";
179
+ case KnownGlobalPropertyName::NITRO_MODULES_PROXY:
180
+ return "NitroModulesProxy";
181
+ }
182
+ }
183
+
184
+ const jsi::PropNameID& CommonGlobals::getKnownGlobalPropertyName(jsi::Runtime& runtime, KnownGlobalPropertyName name) {
185
+ return PropNameIDCache::get(runtime, getKnownGlobalPropertyNameString(name));
186
+ }
187
+
188
+ const jsi::Function& CommonGlobals::getGlobalFunction(jsi::Runtime& runtime, const char* key,
189
+ std::function<jsi::Function(jsi::Runtime&)> getFunction) {
190
+ // Let's try to find the function in cache
191
+ FunctionCache& functionCache = _cache[&runtime];
192
+ std::string stringKey = key;
193
+ auto iterator = functionCache.find(stringKey);
194
+ if (iterator != functionCache.end()) {
195
+ // We found it! Let's check if the reference is still valid...
196
+ BorrowingReference<jsi::Function> function = iterator->second;
197
+ if (function != nullptr) [[likely]] {
198
+ // It's still alive - let's use it from cache!
199
+ return *function;
200
+ }
201
+ }
202
+
203
+ // We haven't found the function with the given key in cache - so let's get it:
204
+ jsi::Function function = getFunction(runtime);
205
+
206
+ // Let's throw it in cache!
207
+ JSICacheReference jsiCache = JSICache::getOrCreateCache(runtime);
208
+ BorrowingReference<jsi::Function> sharedFunction = jsiCache.makeShared(std::move(function));
209
+ functionCache[stringKey] = sharedFunction;
210
+
211
+ // And now return:
212
+ return *sharedFunction;
213
+ }
214
+
215
+ } // namespace margelo::nitro
@@ -0,0 +1,158 @@
1
+ //
2
+ // CommonGlobals.hpp
3
+ // react-native-nitro
4
+ //
5
+ // Created by Marc Rousavy on 17.10.25.
6
+ //
7
+
8
+ #pragma once
9
+
10
+ #include "BorrowingReference.hpp"
11
+ #include <jsi/jsi.h>
12
+ #include <unordered_map>
13
+
14
+ namespace margelo::nitro {
15
+
16
+ using namespace facebook;
17
+
18
+ struct PlainPropertyDescriptor {
19
+ bool configurable;
20
+ bool enumerable;
21
+ jsi::Value value;
22
+ bool writable;
23
+ };
24
+ struct ComputedReadonlyPropertyDescriptor {
25
+ bool configurable;
26
+ bool enumerable;
27
+ jsi::Function get;
28
+ };
29
+ struct ComputedPropertyDescriptor {
30
+ bool configurable;
31
+ bool enumerable;
32
+ jsi::Function get;
33
+ jsi::Function set;
34
+ };
35
+
36
+ enum class KnownGlobalPropertyName { DISPATCHER, JSI_CACHE, NITRO_MODULES_PROXY };
37
+
38
+ class CommonGlobals final {
39
+ public:
40
+ CommonGlobals() = delete;
41
+ ~CommonGlobals() = delete;
42
+
43
+ public:
44
+ /**
45
+ * Define a global value for the given Runtime.
46
+ * In debug, this performs additional safety checks such as freezing the property.
47
+ */
48
+ static void defineGlobal(jsi::Runtime& runtime, KnownGlobalPropertyName name, jsi::Value&& value);
49
+ /**
50
+ * Get a string name for a known global property name.
51
+ */
52
+ static const char* getKnownGlobalPropertyNameString(KnownGlobalPropertyName name);
53
+ /**
54
+ * Get a `jsi::PropNameID` for a known global property name.
55
+ */
56
+ static const jsi::PropNameID& getKnownGlobalPropertyName(jsi::Runtime& runtime, KnownGlobalPropertyName name);
57
+
58
+ /**
59
+ * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object
60
+ */
61
+ class Object final {
62
+ public:
63
+ Object() = delete;
64
+ ~Object() = delete;
65
+
66
+ /**
67
+ * Create a new `jsi::Object` with the given `prototype`.
68
+ * Uses a native implementation if possible.
69
+ */
70
+ static jsi::Object create(jsi::Runtime& runtime, const jsi::Value& prototype);
71
+
72
+ /**
73
+ * Define a plain property on the given `object` with the given `propertyName`.
74
+ * The `descriptor` defines the attributes of this property.
75
+ */
76
+ static void defineProperty(jsi::Runtime& runtime, const jsi::Object& object, const char* propertyName,
77
+ PlainPropertyDescriptor&& descriptor);
78
+ /**
79
+ * Define a plain property on the given `object` with the given `propertyName`.
80
+ * The `descriptor` defines the attributes of this property.
81
+ */
82
+ static void defineProperty(jsi::Runtime& runtime, const jsi::Object& object, const char* propertyName,
83
+ ComputedReadonlyPropertyDescriptor&& descriptor);
84
+ /**
85
+ * Define a plain property on the given `object` with the given `propertyName`.
86
+ * The `descriptor` defines the attributes of this property.
87
+ */
88
+ static void defineProperty(jsi::Runtime& runtime, const jsi::Object& object, const char* propertyName,
89
+ ComputedPropertyDescriptor&& descriptor);
90
+
91
+ /**
92
+ * Freezes all values of the given `object`.
93
+ */
94
+ static void freeze(jsi::Runtime& runtime, const jsi::Object& object);
95
+ };
96
+
97
+ /**
98
+ * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
99
+ */
100
+ class Promise final {
101
+ public:
102
+ Promise() = delete;
103
+ ~Promise() = delete;
104
+
105
+ static jsi::Value resolved(jsi::Runtime& runtime);
106
+ static jsi::Value resolved(jsi::Runtime& runtime, jsi::Value&& value);
107
+ static jsi::Value rejected(jsi::Runtime& runtime, jsi::Value&& error);
108
+
109
+ static jsi::Value callConstructor(jsi::Runtime& runtime, jsi::HostFunctionType&& executor);
110
+ static bool isInstanceOf(jsi::Runtime& runtime, const jsi::Object& object);
111
+ };
112
+
113
+ /**
114
+ * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date
115
+ */
116
+ class Date final {
117
+ public:
118
+ Date() = delete;
119
+ ~Date() = delete;
120
+
121
+ static jsi::Value callConstructor(jsi::Runtime& runtime, double msSinceEpoch);
122
+ static bool isInstanceOf(jsi::Runtime& runtime, const jsi::Object& object);
123
+ };
124
+
125
+ /**
126
+ * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error
127
+ */
128
+ class Error final {
129
+ public:
130
+ Error() = delete;
131
+ ~Error() = delete;
132
+
133
+ static bool isInstanceOf(jsi::Runtime& runtime, const jsi::Object& object);
134
+ };
135
+
136
+ private:
137
+ friend Object;
138
+ friend Promise;
139
+ friend Date;
140
+ friend Error;
141
+
142
+ private:
143
+ /**
144
+ * Get a global Function, and optionally cache it in the Runtime via the `key`.
145
+ *
146
+ * The returned const-ref to a `jsi::Function` should only be used within the callee's
147
+ * synchronous scope.
148
+ * It may no longer be active after the scope ends (function return).
149
+ */
150
+ static const jsi::Function& getGlobalFunction(jsi::Runtime& runtime, const char* key,
151
+ std::function<jsi::Function(jsi::Runtime&)> getFunction);
152
+
153
+ private:
154
+ using FunctionCache = std::unordered_map<std::string, BorrowingReference<jsi::Function>>;
155
+ static std::unordered_map<jsi::Runtime*, FunctionCache> _cache;
156
+ };
157
+
158
+ } // namespace margelo::nitro
@@ -9,7 +9,7 @@
9
9
  #define NitroDefines_h
10
10
 
11
11
  // Sets the version of the native Nitro core library
12
- #define NITRO_VERSION "0.31.9"
12
+ #define NITRO_VERSION "0.32.0-beta.0"
13
13
 
14
14
  // Sets whether to use debug or optimized production build flags
15
15
  #ifdef DEBUG
@@ -0,0 +1,38 @@
1
+ //
2
+ // PropNameIDCache.cpp
3
+ // react-native-nitro
4
+ //
5
+ // Created by Marc Rousavy on 17.10.25.
6
+ //
7
+
8
+ #include "PropNameIDCache.hpp"
9
+ #include "JSICache.hpp"
10
+
11
+ namespace margelo::nitro {
12
+
13
+ using namespace facebook;
14
+
15
+ std::unordered_map<jsi::Runtime*, PropNameIDCache::CacheMap> PropNameIDCache::_cache;
16
+
17
+ const jsi::PropNameID& PropNameIDCache::get(jsi::Runtime& runtime, std::string value) {
18
+ CacheMap& cache = _cache[&runtime];
19
+ const auto& cachedName = cache.find(value);
20
+ if (cachedName != cache.end()) {
21
+ // cache warm!
22
+ const BorrowingReference<jsi::PropNameID>& value = cachedName->second;
23
+ return *value;
24
+ }
25
+
26
+ // not cached - create the jsi::PropNameID...
27
+ auto propName = jsi::PropNameID::forAscii(runtime, value);
28
+ auto jsiCache = JSICache::getOrCreateCache(runtime);
29
+ auto sharedPropName = jsiCache.makeShared(std::move(propName));
30
+
31
+ // store it in cache...
32
+ cache.emplace(value, sharedPropName);
33
+
34
+ // return it!
35
+ return *sharedPropName;
36
+ }
37
+
38
+ } // namespace margelo::nitro
@@ -0,0 +1,44 @@
1
+ //
2
+ // PropNameIDCache.hpp
3
+ // react-native-nitro
4
+ //
5
+ // Created by Marc Rousavy on 17.10.25.
6
+ //
7
+
8
+ #pragma once
9
+
10
+ #include "BorrowingReference.hpp"
11
+ #include <jsi/jsi.h>
12
+ #include <unordered_map>
13
+
14
+ namespace margelo::nitro {
15
+
16
+ using namespace facebook;
17
+
18
+ /**
19
+ * Allows caching `jsi::PropNameID`s via `std::string`s.
20
+ * The returned `jsi::PropNameID` can be used for JSI operations like
21
+ * - `jsi::Object::getProperty(...)`
22
+ * - `jsi::Object::setProperty(...)`
23
+ * - `jsi::Object::hasProperty(...)`
24
+ * And is more efficient than the string equivalent overloads of those
25
+ * functions due to caching.
26
+ */
27
+ class PropNameIDCache final {
28
+ public:
29
+ PropNameIDCache() = delete;
30
+ ~PropNameIDCache() = delete;
31
+
32
+ /**
33
+ * Get a `jsi::PropNameID` for the given `std::string` value.
34
+ * The `jsi::PropNameID` is only valid within the callee's current
35
+ * synchronous scope, and must be non-escaping.
36
+ */
37
+ static const jsi::PropNameID& get(jsi::Runtime& runtime, std::string value);
38
+
39
+ private:
40
+ using CacheMap = std::unordered_map<std::string, BorrowingReference<jsi::PropNameID>>;
41
+ static std::unordered_map<jsi::Runtime*, CacheMap> _cache;
42
+ };
43
+
44
+ } // namespace margelo::nitro
@@ -1,5 +1,5 @@
1
1
  //
2
- // WeakReference+Owning.hpp
2
+ // WeakReference+Borrowing.hpp
3
3
  // react-native-nitro
4
4
  //
5
5
  // Created by Marc Rousavy on 23.06.24.
@@ -72,7 +72,7 @@ public:
72
72
  }
73
73
 
74
74
  /**
75
- Try to lock the borrowing reference to an owning reference, or `nullptr` if it has already been deleted.
75
+ * Try to lock the weak reference to a borrowing reference, or `nullptr` if it has already been deleted.
76
76
  */
77
77
  [[nodiscard]]
78
78
  BorrowingReference<T> lock() const;