react-native-nitro-modules 0.32.0 → 0.32.1

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.
@@ -6,6 +6,7 @@
6
6
  //
7
7
 
8
8
  #include "BoxedHybridObject.hpp"
9
+ #include "PropNameIDCache.hpp"
9
10
 
10
11
  namespace margelo::nitro {
11
12
 
@@ -18,7 +19,7 @@ jsi::Value BoxedHybridObject::get(jsi::Runtime& runtime, const jsi::PropNameID&
18
19
 
19
20
  if (name == "unbox") {
20
21
  return jsi::Function::createFromHostFunction(
21
- runtime, jsi::PropNameID::forUtf8(runtime, "unbox"), 0,
22
+ runtime, PropNameIDCache::get(runtime, "unbox"), 0,
22
23
  [hybridObject = _hybridObject](jsi::Runtime& runtime, const jsi::Value&, const jsi::Value*, size_t) -> jsi::Value {
23
24
  return hybridObject->toObject(runtime);
24
25
  });
@@ -17,6 +17,7 @@ struct JSIConverter;
17
17
  #include "JSIConverter.hpp"
18
18
  #include "NitroDefines.hpp"
19
19
  #include "NitroTypeInfo.hpp"
20
+ #include "PropNameIDCache.hpp"
20
21
  #include <exception>
21
22
  #include <functional>
22
23
  #include <jsi/jsi.h>
@@ -67,7 +68,7 @@ public:
67
68
  public:
68
69
  // functions
69
70
  inline jsi::Function toJSFunction(jsi::Runtime& runtime) const {
70
- return jsi::Function::createFromHostFunction(runtime, jsi::PropNameID::forUtf8(runtime, _name), static_cast<unsigned int>(_paramCount),
71
+ return jsi::Function::createFromHostFunction(runtime, PropNameIDCache::get(runtime, _name), static_cast<unsigned int>(_paramCount),
71
72
  _function);
72
73
  }
73
74
 
@@ -91,7 +91,7 @@ jsi::Value HybridObject::toObject(jsi::Runtime& runtime) {
91
91
  // .configurable has to be true because this property is non-frozen
92
92
  .configurable = true,
93
93
  .enumerable = true,
94
- .value = jsi::String::createFromUtf8(runtime, typeName),
94
+ .value = jsi::String::createFromAscii(runtime, typeName),
95
95
  .writable = false,
96
96
  });
97
97
  #endif
@@ -90,7 +90,7 @@ public:
90
90
  * While two `jsi::Object`s of the same `HybridObject` might not be equal when compared with `==`,
91
91
  * they might still be the same `HybridObject` - in this case `equals(other)` will return true.
92
92
  */
93
- bool equals(const std::shared_ptr<HybridObject>& other);
93
+ virtual bool equals(const std::shared_ptr<HybridObject>& other);
94
94
  /**
95
95
  * Get a string representation of this `HybridObject` - useful for logging or debugging.
96
96
  */
@@ -55,25 +55,24 @@ jsi::Value HybridObjectPrototype::createPrototype(jsi::Runtime& runtime, const s
55
55
  }
56
56
 
57
57
  // 5. Add all properties (getter + setter) to it using defineProperty
58
- for (const auto& getter : prototype->getGetters()) {
59
- const auto& setter = prototype->getSetters().find(getter.first);
60
- bool isReadonly = setter == prototype->getSetters().end();
61
- const std::string& name = getter.first;
62
- if (isReadonly) {
58
+ for (const auto& [name, getter] : prototype->getGetters()) {
59
+ const auto& setterIterator = prototype->getSetters().find(name);
60
+ if (setterIterator != prototype->getSetters().end()) {
61
+ // get + set
62
+ const HybridFunction& setter = setterIterator->second;
63
+ CommonGlobals::Object::defineProperty(runtime, object, name.c_str(),
64
+ ComputedPropertyDescriptor{// getter + setter
65
+ .configurable = false,
66
+ .enumerable = true,
67
+ .get = getter.toJSFunction(runtime),
68
+ .set = setter.toJSFunction(runtime)});
69
+ } else {
63
70
  // get
64
71
  CommonGlobals::Object::defineProperty(runtime, object, name.c_str(),
65
- ComputedReadonlyPropertyDescriptor{// readonly
72
+ ComputedReadonlyPropertyDescriptor{// getter
66
73
  .configurable = false,
67
74
  .enumerable = true,
68
- .get = getter.second.toJSFunction(runtime)});
69
- } else {
70
- // get + set
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)});
75
+ .get = getter.toJSFunction(runtime)});
77
76
  }
78
77
  }
79
78
 
@@ -84,7 +83,7 @@ jsi::Value HybridObjectPrototype::createPrototype(jsi::Runtime& runtime, const s
84
83
  PlainPropertyDescriptor{
85
84
  .configurable = false,
86
85
  .enumerable = true,
87
- .value = jsi::String::createFromUtf8(runtime, prototypeName),
86
+ .value = jsi::String::createFromAscii(runtime, prototypeName),
88
87
  .writable = false,
89
88
  });
90
89
  #endif
@@ -97,13 +96,28 @@ jsi::Value HybridObjectPrototype::createPrototype(jsi::Runtime& runtime, const s
97
96
  // 8. Throw it into our cache so the next lookup can be cached and therefore faster
98
97
  JSICacheReference jsiCache = JSICache::getOrCreateCache(runtime);
99
98
  BorrowingReference<jsi::Object> sharedObject = jsiCache.makeShared(std::move(object));
100
- auto instanceId = prototype->getNativeInstanceId();
99
+ const NativeInstanceId& instanceId = prototype->getNativeInstanceId();
101
100
  prototypeCache[instanceId] = sharedObject;
102
101
 
103
102
  // 9. Return it!
104
103
  return jsi::Value(runtime, *sharedObject);
105
104
  }
106
105
 
106
+ void HybridObjectPrototype::ensureInitialized() {
107
+ if (!_didLoadMethods) {
108
+ // lock in case we try to create `HybridObject`s in parallel Runtimes
109
+ static std::mutex mutex;
110
+ std::unique_lock lock(mutex);
111
+ if (_didLoadMethods) [[unlikely]] {
112
+ // another call to `ensureInitialized()` has initialized in the meantime. abort.
113
+ return;
114
+ }
115
+ // lazy-load all exposed methods
116
+ loadHybridMethods();
117
+ _didLoadMethods = true;
118
+ }
119
+ }
120
+
107
121
  jsi::Value HybridObjectPrototype::getPrototype(jsi::Runtime& runtime) {
108
122
  ensureInitialized();
109
123
 
@@ -30,11 +30,6 @@ using namespace facebook;
30
30
  * as long as it has a valid NativeState (`this`).
31
31
  */
32
32
  class HybridObjectPrototype {
33
- private:
34
- PrototypeChain _prototypeChain;
35
- bool _didLoadMethods = false;
36
- static constexpr auto TAG = "HybridObjectPrototype";
37
-
38
33
  public:
39
34
  HybridObjectPrototype() {}
40
35
 
@@ -62,13 +57,12 @@ private:
62
57
  /**
63
58
  * Ensures that all Hybrid Methods, Getters and Setters are initialized by calling loadHybridMethods().
64
59
  */
65
- inline void ensureInitialized() {
66
- if (!_didLoadMethods) [[unlikely]] {
67
- // lazy-load all exposed methods
68
- loadHybridMethods();
69
- _didLoadMethods = true;
70
- }
71
- }
60
+ void ensureInitialized();
61
+
62
+ private:
63
+ PrototypeChain _prototypeChain;
64
+ volatile bool _didLoadMethods = false;
65
+ static constexpr auto TAG = "HybridObjectPrototype";
72
66
 
73
67
  protected:
74
68
  using RegisterFn = void (*NON_NULL)(Prototype&);
@@ -120,7 +120,7 @@ jsi::Value CommonGlobals::Promise::callConstructor(jsi::Runtime& runtime, jsi::H
120
120
  const jsi::Function& promiseCtor = getGlobalFunction(
121
121
  runtime, "Promise", [](jsi::Runtime& runtime) { return runtime.global().getPropertyAsFunction(runtime, "Promise"); });
122
122
  jsi::Function executorFunc =
123
- jsi::Function::createFromHostFunction(runtime, jsi::PropNameID::forAscii(runtime, "executor"), 2, std::move(executor));
123
+ jsi::Function::createFromHostFunction(runtime, PropNameIDCache::get(runtime, "executor"), 2, std::move(executor));
124
124
  return promiseCtor.callAsConstructor(runtime, std::move(executorFunc));
125
125
  }
126
126
  bool CommonGlobals::Promise::isInstanceOf(jsi::Runtime& runtime, const jsi::Object& object) {
@@ -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.32.0"
12
+ #define NITRO_VERSION "0.32.1"
13
13
 
14
14
  // Sets whether to use debug or optimized production build flags
15
15
  #ifdef DEBUG
@@ -14,7 +14,7 @@ using namespace facebook;
14
14
 
15
15
  std::unordered_map<jsi::Runtime*, PropNameIDCache::CacheMap> PropNameIDCache::_cache;
16
16
 
17
- const jsi::PropNameID& PropNameIDCache::get(jsi::Runtime& runtime, std::string value) {
17
+ const jsi::PropNameID& PropNameIDCache::get(jsi::Runtime& runtime, const std::string& value) {
18
18
  CacheMap& cache = _cache[&runtime];
19
19
  const auto& cachedName = cache.find(value);
20
20
  if (cachedName != cache.end()) {
@@ -31,10 +31,11 @@ public:
31
31
 
32
32
  /**
33
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.
34
+ * - The `std::string` must be an ASCII string.
35
+ * - The `jsi::PropNameID` is only valid within the callee's current
36
+ * synchronous scope, and must be non-escaping.
36
37
  */
37
- static const jsi::PropNameID& get(jsi::Runtime& runtime, std::string value);
38
+ static const jsi::PropNameID& get(jsi::Runtime& runtime, const std::string& value);
38
39
 
39
40
  private:
40
41
  using CacheMap = std::unordered_map<std::string, BorrowingReference<jsi::PropNameID>>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-nitro-modules",
3
- "version": "0.32.0",
3
+ "version": "0.32.1",
4
4
  "description": "Insanely fast native C++, Swift or Kotlin modules with a statically compiled binding layer to JSI.",
5
5
  "main": "lib/commonjs/index",
6
6
  "module": "lib/module/index",