react-native-nitro-modules 0.4.1 → 0.6.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 (109) hide show
  1. package/NitroModules.podspec +4 -1
  2. package/README.md +35 -16
  3. package/android/gradle.properties +5 -5
  4. package/android/src/main/cpp/JNIOnLoad.cpp +8 -0
  5. package/android/src/main/cpp/core/ByteBufferArrayBuffer.hpp +47 -0
  6. package/android/src/main/cpp/core/JAnyMap.hpp +193 -0
  7. package/android/src/main/cpp/core/JAnyValue.hpp +191 -0
  8. package/android/src/main/cpp/core/JArrayBuffer.hpp +119 -0
  9. package/android/src/main/cpp/core/JHybridObject.hpp +11 -4
  10. package/android/src/main/cpp/core/JPromise.hpp +88 -0
  11. package/android/src/main/cpp/platform/NitroLogger.cpp +36 -0
  12. package/android/src/main/cpp/registry/JHybridObjectInitializer.hpp +1 -1
  13. package/android/src/main/cpp/registry/JHybridObjectRegistry.cpp +1 -1
  14. package/android/src/main/cpp/registry/JHybridObjectRegistry.hpp +1 -1
  15. package/android/src/main/cpp/utils/{JNISharedPtr.h → JNISharedPtr.hpp} +13 -1
  16. package/android/src/main/java/com/margelo/nitro/JNIOnLoad.java +27 -0
  17. package/android/src/main/java/com/margelo/nitro/NitroModulesPackage.java +1 -9
  18. package/android/src/main/java/com/margelo/nitro/core/AnyMap.kt +61 -0
  19. package/android/src/main/java/com/margelo/nitro/core/AnyValue.kt +153 -0
  20. package/android/src/main/java/com/margelo/nitro/core/ArrayBuffer.kt +84 -0
  21. package/android/src/main/java/com/margelo/nitro/{HybridObject.kt → core/HybridObject.kt} +12 -15
  22. package/android/src/main/java/com/margelo/nitro/{HybridObjectInitializer.java → core/HybridObjectInitializer.java} +1 -1
  23. package/android/src/main/java/com/margelo/nitro/{HybridObjectRegistry.java → core/HybridObjectRegistry.java} +6 -4
  24. package/android/src/main/java/com/margelo/nitro/core/Promise.kt +115 -0
  25. package/cpp/core/AnyMap.hpp +2 -2
  26. package/cpp/core/ArrayBuffer.cpp +5 -5
  27. package/cpp/core/ArrayBuffer.hpp +12 -7
  28. package/cpp/core/HybridFunction.hpp +119 -45
  29. package/cpp/core/HybridObject.cpp +17 -6
  30. package/cpp/core/HybridObject.hpp +32 -8
  31. package/cpp/jsi/JSICache.cpp +5 -5
  32. package/cpp/jsi/JSICache.hpp +1 -3
  33. package/cpp/jsi/JSIConverter+AnyMap.hpp +2 -2
  34. package/cpp/jsi/JSIConverter+ArrayBuffer.hpp +2 -2
  35. package/cpp/jsi/JSIConverter+Function.hpp +7 -6
  36. package/cpp/jsi/JSIConverter+HybridObject.hpp +6 -5
  37. package/cpp/jsi/JSIConverter+Optional.hpp +1 -1
  38. package/cpp/jsi/JSIConverter+Promise.hpp +6 -4
  39. package/cpp/jsi/JSIConverter+Tuple.hpp +1 -1
  40. package/cpp/jsi/JSIConverter+UnorderedMap.hpp +1 -1
  41. package/cpp/jsi/JSIConverter+Variant.hpp +1 -3
  42. package/cpp/jsi/JSIConverter+Vector.hpp +1 -1
  43. package/cpp/jsi/JSIConverter.hpp +11 -11
  44. package/cpp/jsi/JSPromise.cpp +2 -2
  45. package/cpp/platform/NitroLogger.hpp +67 -0
  46. package/cpp/prototype/HybridObjectPrototype.cpp +2 -2
  47. package/cpp/prototype/Prototype.hpp +43 -22
  48. package/cpp/registry/HybridObjectRegistry.cpp +4 -4
  49. package/cpp/threading/Dispatcher.cpp +4 -3
  50. package/cpp/threading/ThreadPool.cpp +2 -2
  51. package/cpp/turbomodule/NativeNitroModules.cpp +26 -8
  52. package/cpp/turbomodule/NativeNitroModules.h +1 -0
  53. package/cpp/turbomodule/NativeNitroModules.hpp +2 -0
  54. package/cpp/utils/TypeInfo.hpp +14 -0
  55. package/ios/core/AnyMapHolder.hpp +91 -0
  56. package/ios/core/AnyMapHolder.swift +316 -0
  57. package/ios/core/ArrayBufferHolder.hpp +16 -5
  58. package/ios/core/{ArrayBuffer.swift → ArrayBufferHolder.swift} +15 -17
  59. package/ios/core/HybridContext.hpp +3 -3
  60. package/ios/core/Promise.swift +182 -0
  61. package/ios/core/PromiseHolder.hpp +86 -0
  62. package/ios/platform/NitroLogger.mm +36 -0
  63. package/ios/platform/ThreadUtils.cpp +1 -1
  64. package/ios/turbomodule/NitroModuleOnLoad.mm +6 -0
  65. package/ios/utils/SwiftClosure.hpp +63 -0
  66. package/ios/utils/SwiftClosure.swift +58 -0
  67. package/lib/AnyMap.d.ts +3 -0
  68. package/lib/HybridObject.d.ts +15 -0
  69. package/lib/NativeNitroModules.d.ts +2 -0
  70. package/lib/NitroModules.d.ts +18 -0
  71. package/lib/NitroModules.js +24 -0
  72. package/lib/commonjs/NativeNitroModules.js.map +1 -1
  73. package/lib/commonjs/NitroModules.js +24 -0
  74. package/lib/commonjs/NitroModules.js.map +1 -1
  75. package/lib/commonjs/package.json +1 -0
  76. package/lib/module/AnyMap.js +1 -1
  77. package/lib/module/HybridObject.js +1 -1
  78. package/lib/module/ModuleNotFoundError.js +2 -0
  79. package/lib/module/ModuleNotFoundError.js.map +1 -1
  80. package/lib/module/NativeNitroModules.js +2 -0
  81. package/lib/module/NativeNitroModules.js.map +1 -1
  82. package/lib/module/NativeNitroModules.web.js +2 -0
  83. package/lib/module/NativeNitroModules.web.js.map +1 -1
  84. package/lib/module/NitroModules.js +26 -0
  85. package/lib/module/NitroModules.js.map +1 -1
  86. package/lib/module/index.js +2 -0
  87. package/lib/module/index.js.map +1 -1
  88. package/lib/module/package.json +1 -0
  89. package/lib/tsconfig.tsbuildinfo +1 -1
  90. package/lib/typescript/AnyMap.d.ts +20 -0
  91. package/lib/typescript/AnyMap.d.ts.map +1 -1
  92. package/lib/typescript/HybridObject.d.ts +98 -0
  93. package/lib/typescript/HybridObject.d.ts.map +1 -1
  94. package/lib/typescript/NativeNitroModules.d.ts +2 -0
  95. package/lib/typescript/NativeNitroModules.d.ts.map +1 -1
  96. package/lib/typescript/NitroModules.d.ts +18 -0
  97. package/lib/typescript/NitroModules.d.ts.map +1 -1
  98. package/package.json +13 -12
  99. package/src/AnyMap.ts +3 -0
  100. package/src/HybridObject.ts +15 -0
  101. package/src/NativeNitroModules.ts +5 -0
  102. package/src/NitroModules.ts +24 -0
  103. package/android/src/main/cpp/core/JHybridObject.cpp +0 -8
  104. package/cpp/templates/IsInPack.hpp +0 -21
  105. package/cpp/utils/NitroLogger.hpp +0 -58
  106. package/ios/core/ClosureWrapper.swift +0 -25
  107. package/ios/core/HybridContext.cpp +0 -8
  108. package/ios/core/Promise.cpp +0 -10
  109. package/ios/core/Promise.hpp +0 -43
@@ -0,0 +1,119 @@
1
+ //
2
+ // JArrayBuffer.hpp
3
+ // react-native-nitro
4
+ //
5
+ // Created by Marc Rousavy on 14.07.24.
6
+ //
7
+
8
+ #pragma once
9
+
10
+ #include "ArrayBuffer.hpp"
11
+ #include "ByteBufferArrayBuffer.hpp"
12
+ #include <fbjni/ByteBuffer.h>
13
+ #include <fbjni/fbjni.h>
14
+ #include <functional>
15
+ #include <utility>
16
+
17
+ namespace margelo::nitro {
18
+
19
+ using namespace facebook;
20
+
21
+ /**
22
+ * Represents a `ArrayBuffer` that can either hold a `ByteBuffer` (owning),
23
+ * or unknown/foreign memory, potentially from JS (non-owning).
24
+ */
25
+ class JArrayBuffer final : public jni::HybridClass<JArrayBuffer> {
26
+ public:
27
+ static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/core/ArrayBuffer;";
28
+
29
+ public:
30
+ /**
31
+ * Create a new `JArrayBuffer` that wraps the given ArrayBuffer.
32
+ */
33
+ static jni::local_ref<JArrayBuffer::javaobject> wrap(const std::shared_ptr<ArrayBuffer>& arrayBuffer) {
34
+ return newObjectCxxArgs(arrayBuffer);
35
+ }
36
+
37
+ public:
38
+ /**
39
+ * Create a new `JArrayBuffer` that wraps the given `ByteBuffer` from Java.
40
+ */
41
+ static jni::local_ref<JArrayBuffer::jhybriddata> initHybrid(jni::alias_ref<jhybridobject> jThis,
42
+ jni::alias_ref<jni::JByteBuffer> buffer) {
43
+ return makeCxxInstance(buffer);
44
+ }
45
+
46
+ public:
47
+ /**
48
+ * Get whether the `ArrayBuffer` is holding data from a `ByteBuffer`.
49
+ */
50
+ bool getIsByteBuffer() {
51
+ auto byteBufferArrayBuffer = std::dynamic_pointer_cast<ByteBufferArrayBuffer>(_arrayBuffer);
52
+ return byteBufferArrayBuffer != nullptr;
53
+ }
54
+
55
+ /**
56
+ * Get whether the `ArrayBuffer` is owning the data and can safely hold onto it longer.
57
+ */
58
+ bool getIsOwner() {
59
+ return _arrayBuffer->isOwner();
60
+ }
61
+
62
+ /**
63
+ * Get the `ArrayBuffer`'s data as a `ByteBuffer`.
64
+ *
65
+ * - If the `ArrayBuffer` was created from a `ByteBuffer` (`isByteBuffer()`), this returns
66
+ * a reference to the original `ByteBuffer`, which is safe to be kept in memory for longer.
67
+ * - If the `ArrayBuffer` was created elsewhere (either in JS, or in C++), it does not have a
68
+ * `ByteBuffer`. In this case, `getBuffer()` will **copy** the data into a new `ByteBuffer` if
69
+ * `copyIfNeeded` is `true`, and **wrap** the data into a new `ByteBuffer` if `copyIfNeeded` is false.
70
+ */
71
+ jni::alias_ref<jni::JByteBuffer> getByteBuffer(bool copyIfNeeded) {
72
+ auto byteBufferArrayBuffer = std::dynamic_pointer_cast<ByteBufferArrayBuffer>(_arrayBuffer);
73
+ if (byteBufferArrayBuffer != nullptr) {
74
+ // It is a `ByteBufferArrayBuffer`, which has a `ByteBuffer` underneath!
75
+ return byteBufferArrayBuffer->getBuffer();
76
+ } else {
77
+ // It is a different kind of `ArrayBuffer`, we need to copy or wrap the data.
78
+ size_t size = _arrayBuffer->size();
79
+ if (copyIfNeeded) {
80
+ auto buffer = jni::JByteBuffer::allocateDirect(size);
81
+ buffer->order(jni::JByteOrder::bigEndian());
82
+ memcpy(buffer->getDirectAddress(), _arrayBuffer->data(), size);
83
+ return buffer;
84
+ } else {
85
+ auto buffer = jni::JByteBuffer::wrapBytes(_arrayBuffer->data(), size);
86
+ buffer->order(jni::JByteOrder::bigEndian());
87
+ return buffer;
88
+ }
89
+ }
90
+ }
91
+
92
+ public:
93
+ /**
94
+ * Get the underlying `ArrayBuffer`.
95
+ */
96
+ std::shared_ptr<ArrayBuffer> getArrayBuffer() const {
97
+ return _arrayBuffer;
98
+ }
99
+
100
+ private:
101
+ JArrayBuffer(const std::shared_ptr<ArrayBuffer>& arrayBuffer) : _arrayBuffer(arrayBuffer) {}
102
+ JArrayBuffer(jni::alias_ref<jni::JByteBuffer> byteBuffer) {
103
+ _arrayBuffer = std::make_shared<ByteBufferArrayBuffer>(byteBuffer);
104
+ }
105
+
106
+ private:
107
+ friend HybridBase;
108
+ using HybridBase::HybridBase;
109
+ std::shared_ptr<ArrayBuffer> _arrayBuffer;
110
+
111
+ public:
112
+ static void registerNatives() {
113
+ registerHybrid(
114
+ {makeNativeMethod("initHybrid", JArrayBuffer::initHybrid), makeNativeMethod("getByteBuffer", JArrayBuffer::getByteBuffer),
115
+ makeNativeMethod("getIsByteBuffer", JArrayBuffer::getIsByteBuffer), makeNativeMethod("getIsOwner", JArrayBuffer::getIsOwner)});
116
+ }
117
+ };
118
+
119
+ } // namespace margelo::nitro
@@ -14,12 +14,19 @@ namespace margelo::nitro {
14
14
 
15
15
  using namespace facebook;
16
16
 
17
- struct JHybridObject : public jni::HybridClass<JHybridObject>, public HybridObject {
17
+ /**
18
+ * Represents the Java `HybridObject` instance.
19
+ * HybridData is passed up from inherited members, so this acts like a base class
20
+ * and has to be inherited as "virtual" in C++ to properly avoid creating multiple `HybridObject` instances.
21
+ */
22
+ class JHybridObject : public jni::HybridClass<JHybridObject>, public virtual HybridObject {
18
23
  public:
19
- static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/HybridObject;";
24
+ static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/core/HybridObject;";
20
25
 
21
- public:
22
- static void registerNatives();
26
+ ~JHybridObject() override = default;
27
+
28
+ private:
29
+ friend HybridBase;
23
30
  };
24
31
 
25
32
  } // namespace margelo::nitro
@@ -0,0 +1,88 @@
1
+ //
2
+ // JPromise.hpp
3
+ // react-native-nitro
4
+ //
5
+ // Created by Marc Rousavy on 14.07.24.
6
+ //
7
+
8
+ #pragma once
9
+
10
+ #include <fbjni/fbjni.h>
11
+
12
+ namespace margelo::nitro {
13
+
14
+ using namespace facebook;
15
+
16
+ /**
17
+ * Represents a Promise implemented in Java.
18
+ */
19
+ class JPromise final : public jni::HybridClass<JPromise> {
20
+ public:
21
+ static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/core/Promise;";
22
+ using OnResolvedFunc = std::function<void(jni::alias_ref<jni::JObject>)>;
23
+ using OnRejectedFunc = std::function<void(jni::alias_ref<jni::JString>)>;
24
+
25
+ public:
26
+ /**
27
+ * Create a new, still unresolved `JPromise` from Java.
28
+ */
29
+ static jni::local_ref<JPromise::jhybriddata> initHybrid(jni::alias_ref<jhybridobject>) {
30
+ return makeCxxInstance();
31
+ }
32
+
33
+ public:
34
+ void resolve(jni::alias_ref<jni::JObject> result) {
35
+ _result = jni::make_global(result);
36
+ for (const auto& onResolved : _onResolvedListeners) {
37
+ onResolved(_result);
38
+ }
39
+ }
40
+ void reject(jni::alias_ref<jni::JString> error) {
41
+ _error = jni::make_global(error);
42
+ for (const auto& onRejected : _onRejectedListeners) {
43
+ onRejected(_error);
44
+ }
45
+ }
46
+
47
+ public:
48
+ void addOnResolvedListener(OnResolvedFunc&& onResolved) {
49
+ if (_result != nullptr) {
50
+ // Promise is already resolved! Call the callback immediately
51
+ onResolved(_result);
52
+ } else {
53
+ // Promise is not yet resolved, put the listener in our queue.
54
+ _onResolvedListeners.push_back(std::move(onResolved));
55
+ }
56
+ }
57
+ void addOnRejectedListener(OnRejectedFunc&& onRejected) {
58
+ if (_error != nullptr) {
59
+ // Promise is already rejected! Call the callback immediately
60
+ onRejected(_error);
61
+ } else {
62
+ // Promise is not yet rejected, put the listener in our queue.
63
+ _onRejectedListeners.push_back(std::move(onRejected));
64
+ }
65
+ }
66
+
67
+ private:
68
+ JPromise() {}
69
+
70
+ private:
71
+ friend HybridBase;
72
+ using HybridBase::HybridBase;
73
+ jni::global_ref<jni::JObject> _result;
74
+ jni::global_ref<jni::JString> _error;
75
+ std::vector<OnResolvedFunc> _onResolvedListeners;
76
+ std::vector<OnRejectedFunc> _onRejectedListeners;
77
+
78
+ public:
79
+ static void registerNatives() {
80
+ registerHybrid({
81
+ makeNativeMethod("initHybrid", JPromise::initHybrid),
82
+ makeNativeMethod("nativeResolve", JPromise::resolve),
83
+ makeNativeMethod("nativeReject", JPromise::reject),
84
+ });
85
+ }
86
+ };
87
+
88
+ } // namespace margelo::nitro
@@ -0,0 +1,36 @@
1
+ //
2
+ // NitroLogger.cpp
3
+ // react-native-nitro
4
+ //
5
+ // Created by Marc Rousavy on 14.07.24.
6
+ //
7
+
8
+ #include "NitroLogger.hpp"
9
+ #include <android/log.h>
10
+
11
+ namespace margelo::nitro {
12
+
13
+ int levelToAndroidLevel(LogLevel level) {
14
+ switch (level) {
15
+ case LogLevel::Debug:
16
+ return ANDROID_LOG_DEBUG;
17
+ case LogLevel::Info:
18
+ return ANDROID_LOG_INFO;
19
+ case LogLevel::Warning:
20
+ return ANDROID_LOG_WARN;
21
+ case LogLevel::Error:
22
+ return ANDROID_LOG_ERROR;
23
+ default:
24
+ throw std::runtime_error("Invalid LogLevel!");
25
+ }
26
+ }
27
+
28
+ void Logger::nativeLog(LogLevel level, const char* tag, const std::string& message) {
29
+ #ifndef NDEBUG
30
+ int logLevel = levelToAndroidLevel(level);
31
+ std::string combinedTag = "Nitro." + std::string(tag);
32
+ __android_log_print(logLevel, combinedTag.c_str(), "%s", message.c_str());
33
+ #endif
34
+ }
35
+
36
+ } // namespace margelo::nitro
@@ -23,7 +23,7 @@ public:
23
23
  }
24
24
 
25
25
  public:
26
- static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/HybridObjectInitializer;";
26
+ static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/core/HybridObjectInitializer;";
27
27
  };
28
28
 
29
29
  } // namespace margelo::nitro
@@ -7,7 +7,7 @@
7
7
 
8
8
  #include "JHybridObjectRegistry.hpp"
9
9
  #include "HybridObjectRegistry.hpp"
10
- #include "JNISharedPtr.h"
10
+ #include "JNISharedPtr.hpp"
11
11
 
12
12
  namespace margelo::nitro {
13
13
 
@@ -17,7 +17,7 @@ using namespace facebook;
17
17
 
18
18
  struct JHybridObjectRegistry : public jni::JavaClass<JHybridObjectRegistry> {
19
19
  public:
20
- static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/HybridObjectRegistry;";
20
+ static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/core/HybridObjectRegistry;";
21
21
 
22
22
  public:
23
23
  static void registerHybridObjectConstructor(jni::alias_ref<jni::JClass> clazz, std::string hybridObjectName,
@@ -26,8 +26,20 @@ private:
26
26
  };
27
27
 
28
28
  class JNISharedPtr {
29
+ private:
30
+ template <typename T, template <typename, typename...> class Base>
31
+ struct is_base_template_of {
32
+ template <typename U>
33
+ static std::true_type test(Base<U>*) {}
34
+
35
+ template <typename>
36
+ static std::false_type test(...) {}
37
+
38
+ static constexpr bool value = decltype(test<T>(nullptr))::value;
39
+ };
40
+
29
41
  public:
30
- template <typename T, typename std::enable_if<std::is_base_of<jni::HybridClass<T>, T>::value>::type* = nullptr>
42
+ template <typename T, typename std::enable_if<is_base_template_of<T, jni::HybridClass>::value, int>::type = 0>
31
43
  static std::shared_ptr<T> make_shared_from_jni(jni::global_ref<typename T::javaobject> ref) {
32
44
  return std::shared_ptr<T>(ref->cthis(), GlobalRefDeleter<T>{ref});
33
45
  }
@@ -0,0 +1,27 @@
1
+ package com.margelo.nitro;
2
+
3
+ import android.util.Log;
4
+
5
+ public class JNIOnLoad {
6
+ private static final String TAG = "NitroModules";
7
+ private static boolean isInitialized = false;
8
+
9
+ /**
10
+ * Initializes the C++ (JNI) part of Nitro Modules.
11
+ * This function should be called in a `static` block everytime the Java part
12
+ * interacts with the native C++ (JNI) part of Nitro Modules.
13
+ * If Native Nitro is already initialized, this function will do nothing.
14
+ */
15
+ public synchronized static void initializeNativeNitro() {
16
+ if (isInitialized) return;
17
+ try {
18
+ Log.i(TAG, "Loading NitroModules C++ library...");
19
+ System.loadLibrary("NitroModules");
20
+ Log.i(TAG, "Successfully loaded NitroModules C++ library!");
21
+ isInitialized = true;
22
+ } catch (Throwable e) {
23
+ Log.e(TAG, "Failed to load NitroModules C++ library! Is it properly installed and linked?", e);
24
+ throw e;
25
+ }
26
+ }
27
+ }
@@ -11,16 +11,8 @@ import com.facebook.react.TurboReactPackage;
11
11
  import java.util.HashMap;
12
12
 
13
13
  public class NitroModulesPackage extends TurboReactPackage {
14
- private static final String TAG = "NitroModules";
15
14
  static {
16
- try {
17
- Log.i(TAG, "Loading NitroModules C++ library...");
18
- System.loadLibrary("NitroModules");
19
- Log.i(TAG, "Successfully loaded NitroModules C++ library!");
20
- } catch (Throwable e) {
21
- Log.e(TAG, "Failed to load NitroModules C++ library! Is it properly installed and linked?", e);
22
- throw e;
23
- }
15
+ JNIOnLoad.initializeNativeNitro();
24
16
  }
25
17
 
26
18
  @Nullable
@@ -0,0 +1,61 @@
1
+ package com.margelo.nitro.core
2
+
3
+ import androidx.annotation.Keep
4
+ import com.facebook.jni.HybridData
5
+ import com.facebook.proguard.annotations.DoNotStrip
6
+
7
+ /**
8
+ * Represents an untyped map of string keys with associated values.
9
+ * This is like a JS [`object`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object).
10
+ */
11
+ @Suppress("KotlinJniMissingFunction")
12
+ @Keep
13
+ @DoNotStrip
14
+ class AnyMap {
15
+ private val mHybridData: HybridData
16
+
17
+ /**
18
+ * Create a new empty `AnyMap`.
19
+ */
20
+ constructor() {
21
+ mHybridData = initHybrid()
22
+ }
23
+
24
+ /**
25
+ * Create a new `AnyMap` from C++, which potentially already holds data.
26
+ */
27
+ @Suppress("unused")
28
+ private constructor(hybridData: HybridData) {
29
+ mHybridData = hybridData
30
+ }
31
+
32
+
33
+ external fun contains(key: String): Boolean
34
+ external fun remove(key: String)
35
+ external fun clear()
36
+
37
+ external fun isNull(key: String): Boolean
38
+ external fun isDouble(key: String): Boolean
39
+ external fun isBoolean(key: String): Boolean
40
+ external fun isBigInt(key: String): Boolean
41
+ external fun isString(key: String): Boolean
42
+ external fun isArray(key: String): Boolean
43
+ external fun isObject(key: String): Boolean
44
+
45
+ external fun getDouble(key: String): Double
46
+ external fun getBoolean(key: String): Boolean
47
+ external fun getBigInt(key: String): Long
48
+ external fun getString(key: String): String
49
+ external fun getAnyArray(key: String): AnyArray
50
+ external fun getAnyObject(key: String): AnyObject
51
+
52
+ external fun setNull(key: String)
53
+ external fun setDouble(key: String, value: Double)
54
+ external fun setBoolean(key: String, value: Boolean)
55
+ external fun setBigInt(key: String, value: Long)
56
+ external fun setString(key: String, value: String)
57
+ external fun setAnyArray(key: String, value: AnyArray)
58
+ external fun setAnyObject(key: String, value: AnyObject)
59
+
60
+ private external fun initHybrid(): HybridData
61
+ }
@@ -0,0 +1,153 @@
1
+ package com.margelo.nitro.core
2
+
3
+ import androidx.annotation.Keep
4
+ import com.facebook.jni.HybridData
5
+ import com.facebook.proguard.annotations.DoNotStrip
6
+
7
+ typealias AnyArray = Array<AnyValue>
8
+ typealias AnyObject = Map<String, AnyValue>
9
+
10
+ /**
11
+ * Represents a value that can be any of the following types:
12
+ * - `null`
13
+ * - [Double]
14
+ * - [Boolean]
15
+ * - [Long]
16
+ * - [String]
17
+ * - [AnyArray] ([Array]`<AnyValue>`)
18
+ * - [AnyObject] ([Map]`<String, AnyValue>`)
19
+ */
20
+ @Suppress("KotlinJniMissingFunction")
21
+ @Keep
22
+ @DoNotStrip
23
+ class AnyValue {
24
+ private val mHybridData: HybridData
25
+
26
+ /**
27
+ * Create a new [AnyValue] that holds `null`.
28
+ */
29
+ constructor() {
30
+ mHybridData = initHybrid()
31
+ }
32
+
33
+ /**
34
+ * Create a new [AnyValue] that holds the given [Double]
35
+ */
36
+ constructor(value: Double) {
37
+ mHybridData = initHybrid(value)
38
+ }
39
+
40
+ /**
41
+ * Create a new [AnyValue] that holds the given [Boolean]
42
+ */
43
+ constructor(value: Boolean) {
44
+ mHybridData = initHybrid(value)
45
+ }
46
+
47
+ /**
48
+ * Create a new [AnyValue] that holds the given [Long]
49
+ */
50
+ constructor(value: Long) {
51
+ mHybridData = initHybrid(value)
52
+ }
53
+
54
+ /**
55
+ * Create a new [AnyValue] that holds the given [String]
56
+ */
57
+ constructor(value: String) {
58
+ mHybridData = initHybrid(value)
59
+ }
60
+
61
+ /**
62
+ * Create a new [AnyValue] that holds the given [AnyArray]
63
+ */
64
+ constructor(value: AnyArray) {
65
+ mHybridData = initHybrid(value)
66
+ }
67
+
68
+ /**
69
+ * Create a new [AnyValue] that holds the given [AnyObject]
70
+ */
71
+ constructor(value: AnyObject) {
72
+ mHybridData = initHybrid(value)
73
+ }
74
+
75
+ /**
76
+ * Gets whether this [AnyValue] instance is holding a `null`.
77
+ */
78
+ external fun isNull(): Boolean
79
+
80
+ /**
81
+ * Gets whether this [AnyValue] instance is holding a [Double] value.
82
+ */
83
+ external fun isDouble(): Boolean
84
+
85
+ /**
86
+ * Gets whether this [AnyValue] instance is holding a [Boolean] value.
87
+ */
88
+ external fun isBoolean(): Boolean
89
+
90
+ /**
91
+ * Gets whether this [AnyValue] instance is holding a [Long] value.
92
+ */
93
+ external fun isBigInt(): Boolean
94
+
95
+ /**
96
+ * Gets whether this [AnyValue] instance is holding a [String] value.
97
+ */
98
+ external fun isString(): Boolean
99
+
100
+ /**
101
+ * Gets whether this [AnyValue] instance is holding an [AnyArray] value.
102
+ */
103
+ external fun isAnyArray(): Boolean
104
+
105
+ /**
106
+ * Gets whether this [AnyValue] instance is holding an [AnyObject] value.
107
+ */
108
+ external fun isAnyObject(): Boolean
109
+
110
+ /**
111
+ * Get the [Double] value this [AnyValue] is holding.
112
+ * @throws Error if this [AnyValue] is not holding a [Double] (see [isDouble]`()`)
113
+ */
114
+ external fun asDouble(): Double
115
+
116
+ /**
117
+ * Get the [Boolean] value this [AnyValue] is holding.
118
+ * @throws Error if this [AnyValue] is not holding a [Boolean] (see [isBoolean]`()`)
119
+ */
120
+ external fun asBoolean(): Boolean
121
+
122
+ /**
123
+ * Get the [Long] value this [AnyValue] is holding.
124
+ * @throws Error if this [AnyValue] is not holding a [Long] (see [isLong]`()`)
125
+ */
126
+ external fun asBigInt(): Long
127
+
128
+ /**
129
+ * Get the [String] value this [AnyValue] is holding.
130
+ * @throws Error if this [AnyValue] is not holding a [String] (see [isString]`()`)
131
+ */
132
+ external fun asString(): String
133
+
134
+ /**
135
+ * Get the [AnyArray] value this [AnyValue] is holding.
136
+ * @throws Error if this [AnyValue] is not holding an [AnyArray] (see [isAnyArray]`()`)
137
+ */
138
+ external fun asAnyArray(): AnyArray
139
+
140
+ /**
141
+ * Get the [AnyObject] value this [AnyValue] is holding.
142
+ * @throws Error if this [AnyValue] is not holding an [AnyObject] (see [isAnyObject]`()`)
143
+ */
144
+ external fun asAnyObject(): AnyObject
145
+
146
+ private external fun initHybrid(): HybridData
147
+ private external fun initHybrid(value: Double): HybridData
148
+ private external fun initHybrid(value: Boolean): HybridData
149
+ private external fun initHybrid(value: Long): HybridData
150
+ private external fun initHybrid(value: String): HybridData
151
+ private external fun initHybrid(value: AnyArray): HybridData
152
+ private external fun initHybrid(value: AnyObject): HybridData
153
+ }
@@ -0,0 +1,84 @@
1
+ package com.margelo.nitro.core
2
+
3
+ import androidx.annotation.Keep
4
+ import com.facebook.jni.HybridData
5
+ import com.facebook.proguard.annotations.DoNotStrip
6
+ import java.nio.ByteBuffer
7
+
8
+ /**
9
+ * An ArrayBuffer instance shared between native (Kotlin/C++) and JS.
10
+ *
11
+ * A `ByteBuffer` will be used as the underlying `ArrayBuffer`'s data,
12
+ * which has to remain valid for as long as the `ArrayBuffer` is alive.
13
+ */
14
+ @Suppress("KotlinJniMissingFunction")
15
+ @Keep
16
+ @DoNotStrip
17
+ class ArrayBuffer {
18
+ /**
19
+ * Holds the native C++ instance of the `ArrayBuffer`.
20
+ */
21
+ private val mHybridData: HybridData
22
+
23
+ /**
24
+ * Whether this `ArrayBuffer` is an **owning-**, or a **non-owning-** `ArrayBuffer`.
25
+ * - **Owning** ArrayBuffers can safely be held in memory for longer, and accessed at any point.
26
+ * - **Non-owning** ArrayBuffers can not be held in memory for longer, and can only be safely
27
+ * accessed within the synchronous function's scope (aka on the JS Thread). Once you switch Threads,
28
+ * data access is not safe anymore. If you need to access data longer, copy the data.
29
+ */
30
+ val isOwner: Boolean
31
+ get() = getIsOwner()
32
+
33
+ /**
34
+ * Whether this `ArrayBuffer` is holding a `ByteBuffer`, or not.
35
+ * - If the `ArrayBuffer` holds a `ByteBuffer`, `getBuffer(false)` can safely be called to
36
+ * get shared access to the underlying data, without performing any copies.
37
+ * - If the `ArrayBuffer` doesn't hold a `ByteBuffer`, it can still be accessed via `getBuffer(false)`,
38
+ * but the returned `ByteBuffer` is only valid as long as it's parent `ArrayBuffer` is alive.
39
+ */
40
+ val isByteBuffer: Boolean
41
+ get() = getIsByteBuffer()
42
+
43
+ /**
44
+ * Get a `ByteBuffer` that holds- or wraps- the underlying data.
45
+ * - If this `ArrayBuffer` has been created from Kotlin/Java, it is already holding a
46
+ * `ByteBuffer` (`isByteBuffer == true`). In this case, the returned buffer is safe to access,
47
+ * even after the `ArrayBuffer` has already been destroyed in JS.
48
+ * - If this `ArrayBuffer` has been created elsewhere (C++/JS), it is not holding a
49
+ * `ByteBuffer` (`isByteBuffer == false`). In this case, the returned buffer will either be a copy
50
+ * of the data (`copyIfNeeded == true`), or just wrapping the data (`copyIfNeeded == false`).
51
+ *
52
+ * @param copyIfNeeded If this `ArrayBuffer` is not holding a `ByteBuffer` (`isByteBuffer == false`),
53
+ * the foreign data needs to be either _wrapped_, or _copied_ to be represented as a `ByteBuffer`.
54
+ * This flag controls that behaviour.
55
+ */
56
+ fun getBuffer(copyIfNeeded: Boolean): ByteBuffer {
57
+ return getByteBuffer(copyIfNeeded)
58
+ }
59
+
60
+ /**
61
+ * Create a new **owning-** `ArrayBuffer` that holds the given `ByteBuffer`.
62
+ * The `ByteBuffer` needs to remain valid for as long as the `ArrayBuffer` is alive.
63
+ */
64
+ constructor(byteBuffer: ByteBuffer) {
65
+ if (!byteBuffer.isDirect) {
66
+ throw Error("ArrayBuffers can only be created from direct ByteBuffers, " +
67
+ "and the given ByteBuffer is not direct!")
68
+ }
69
+ mHybridData = initHybrid(byteBuffer)
70
+ }
71
+
72
+ /**
73
+ * Create a new **non-owning-** `ArrayBuffer` that holds foreign data, potentially coming from JS.
74
+ */
75
+ @Suppress("unused")
76
+ private constructor(hybridData: HybridData) {
77
+ mHybridData = hybridData
78
+ }
79
+
80
+ private external fun getByteBuffer(copyIfNeeded: Boolean): ByteBuffer
81
+ private external fun getIsOwner(): Boolean
82
+ private external fun getIsByteBuffer(): Boolean
83
+ private external fun initHybrid(buffer: ByteBuffer): HybridData
84
+ }