react-native-nitro-modules 0.10.0 → 0.12.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 (120) hide show
  1. package/NitroModules.podspec +4 -0
  2. package/README.md +2 -2
  3. package/android/CMakeLists.txt +3 -0
  4. package/android/build.gradle +27 -3
  5. package/android/src/main/cpp/JNIOnLoad.cpp +5 -5
  6. package/android/src/main/cpp/platform/NitroLogger.cpp +1 -1
  7. package/android/src/main/cpp/turbomodule/JNitroModules.cpp +41 -0
  8. package/android/src/main/cpp/turbomodule/JNitroModules.hpp +37 -0
  9. package/android/src/main/java/com/margelo/nitro/NitroModules.kt +69 -0
  10. package/android/src/main/java/com/margelo/nitro/NitroModulesPackage.kt +34 -0
  11. package/android/src/main/java/com/margelo/nitro/core/HybridObject.kt +6 -2
  12. package/android/src/newarch/NitroModulesSpec.kt +6 -0
  13. package/android/src/oldarch/NitroModulesSpec.kt +9 -0
  14. package/cpp/core/HybridFunction.hpp +13 -4
  15. package/cpp/entrypoint/HybridNitroModulesProxy.cpp +55 -0
  16. package/cpp/entrypoint/HybridNitroModulesProxy.hpp +48 -0
  17. package/cpp/entrypoint/InstallNitro.cpp +28 -0
  18. package/cpp/entrypoint/InstallNitro.hpp +41 -0
  19. package/cpp/jsi/JSIConverter+ArrayBuffer.hpp +6 -6
  20. package/cpp/jsi/JSIConverter+HostObject.hpp +73 -0
  21. package/cpp/jsi/JSIConverter+HybridObject.hpp +1 -1
  22. package/cpp/jsi/JSIConverter+Promise.hpp +1 -0
  23. package/cpp/jsi/JSIConverter+Tuple.hpp +2 -2
  24. package/cpp/jsi/JSIConverter.hpp +1 -0
  25. package/cpp/prototype/HybridObjectPrototype.cpp +4 -3
  26. package/cpp/threading/CallInvokerDispatcher.hpp +5 -0
  27. package/cpp/utils/NitroDefines.hpp +8 -0
  28. package/cpp/utils/TypeInfo.hpp +40 -20
  29. package/ios/core/ArrayBufferHolder.hpp +1 -1
  30. package/ios/core/HybridObjectSpec.swift +1 -1
  31. package/ios/platform/NitroLogger.mm +1 -2
  32. package/ios/turbomodule/NativeNitroModules+NewArch.mm +67 -0
  33. package/ios/turbomodule/NativeNitroModules+OldArch.mm +71 -0
  34. package/ios/turbomodule/NativeNitroModules.h +22 -0
  35. package/lib/BoxedHybridObject.d.ts +12 -0
  36. package/lib/BoxedHybridObject.js +1 -0
  37. package/lib/ModuleNotFoundError.js +3 -13
  38. package/lib/NitroModules.d.ts +1 -83
  39. package/lib/NitroModules.js +2 -94
  40. package/lib/NitroModulesProxy.d.ts +58 -0
  41. package/lib/NitroModulesProxy.js +1 -0
  42. package/lib/commonjs/BoxedHybridObject.js +6 -0
  43. package/lib/commonjs/BoxedHybridObject.js.map +1 -0
  44. package/lib/commonjs/ModuleNotFoundError.js +3 -15
  45. package/lib/commonjs/ModuleNotFoundError.js.map +1 -1
  46. package/lib/commonjs/NitroModules.js +11 -100
  47. package/lib/commonjs/NitroModules.js.map +1 -1
  48. package/lib/commonjs/NitroModulesProxy.js +6 -0
  49. package/lib/commonjs/NitroModulesProxy.js.map +1 -0
  50. package/lib/commonjs/turbomodule/NativeNitroModules.js +36 -0
  51. package/lib/commonjs/turbomodule/NativeNitroModules.js.map +1 -0
  52. package/lib/commonjs/turbomodule/NativeNitroModules.web.js +17 -0
  53. package/lib/commonjs/turbomodule/NativeNitroModules.web.js.map +1 -0
  54. package/lib/module/BoxedHybridObject.js +4 -0
  55. package/lib/module/BoxedHybridObject.js.map +1 -0
  56. package/lib/module/ModuleNotFoundError.js +3 -15
  57. package/lib/module/ModuleNotFoundError.js.map +1 -1
  58. package/lib/module/NitroModules.js +2 -100
  59. package/lib/module/NitroModules.js.map +1 -1
  60. package/lib/module/NitroModulesProxy.js +4 -0
  61. package/lib/module/NitroModulesProxy.js.map +1 -0
  62. package/lib/module/turbomodule/NativeNitroModules.js +31 -0
  63. package/lib/module/turbomodule/NativeNitroModules.js.map +1 -0
  64. package/lib/{NitroModulesTurboModule.web.js → module/turbomodule/NativeNitroModules.web.js} +9 -1
  65. package/lib/module/turbomodule/NativeNitroModules.web.js.map +1 -0
  66. package/lib/tsconfig.tsbuildinfo +1 -1
  67. package/lib/turbomodule/NativeNitroModules.d.ts +7 -0
  68. package/lib/turbomodule/NativeNitroModules.js +27 -0
  69. package/lib/turbomodule/NativeNitroModules.web.d.ts +2 -0
  70. package/lib/turbomodule/NativeNitroModules.web.js +9 -0
  71. package/lib/typescript/AnyMap.d.ts +20 -0
  72. package/lib/typescript/BoxedHybridObject.d.ts +13 -0
  73. package/lib/typescript/BoxedHybridObject.d.ts.map +1 -0
  74. package/lib/typescript/ModuleNotFoundError.d.ts +7 -0
  75. package/lib/typescript/ModuleNotFoundError.d.ts.map +1 -1
  76. package/lib/typescript/NitroModules.d.ts +1 -83
  77. package/lib/typescript/NitroModules.d.ts.map +1 -1
  78. package/lib/typescript/NitroModulesProxy.d.ts +59 -0
  79. package/lib/typescript/NitroModulesProxy.d.ts.map +1 -0
  80. package/lib/typescript/__tests__/index.test.d.ts +1 -0
  81. package/lib/typescript/index.d.ts +4 -0
  82. package/lib/typescript/turbomodule/NativeNitroModules.d.ts +8 -0
  83. package/lib/typescript/turbomodule/NativeNitroModules.d.ts.map +1 -0
  84. package/lib/typescript/turbomodule/NativeNitroModules.web.d.ts +3 -0
  85. package/lib/typescript/turbomodule/NativeNitroModules.web.d.ts.map +1 -0
  86. package/package.json +10 -3
  87. package/src/BoxedHybridObject.ts +13 -0
  88. package/src/ModuleNotFoundError.ts +3 -19
  89. package/src/NitroModules.ts +2 -108
  90. package/src/NitroModulesProxy.ts +61 -0
  91. package/src/turbomodule/NativeNitroModules.ts +48 -0
  92. package/src/turbomodule/NativeNitroModules.web.ts +16 -0
  93. package/android/src/main/java/com/margelo/nitro/NitroModulesPackage.java +0 -30
  94. package/cpp/turbomodule/NativeNitroModules.cpp +0 -146
  95. package/cpp/turbomodule/NativeNitroModules.h +0 -8
  96. package/cpp/turbomodule/NativeNitroModules.hpp +0 -38
  97. package/cpp/turbomodule/RegisterNativeNitroModules.cpp +0 -33
  98. package/cpp/turbomodule/RegisterNativeNitroModules.hpp +0 -21
  99. package/ios/turbomodule/NitroModuleOnLoad.mm +0 -32
  100. package/lib/NativeNitroModules.d.ts +0 -16
  101. package/lib/NativeNitroModules.js +0 -22
  102. package/lib/NativeNitroModules.web.d.ts +0 -4
  103. package/lib/NativeNitroModules.web.js +0 -3
  104. package/lib/NitroModulesTurboModule.d.ts +0 -18
  105. package/lib/NitroModulesTurboModule.js +0 -23
  106. package/lib/NitroModulesTurboModule.web.d.ts +0 -1
  107. package/lib/commonjs/NitroModulesTurboModule.js +0 -34
  108. package/lib/commonjs/NitroModulesTurboModule.js.map +0 -1
  109. package/lib/commonjs/NitroModulesTurboModule.web.js +0 -11
  110. package/lib/commonjs/NitroModulesTurboModule.web.js.map +0 -1
  111. package/lib/module/NitroModulesTurboModule.js +0 -30
  112. package/lib/module/NitroModulesTurboModule.js.map +0 -1
  113. package/lib/module/NitroModulesTurboModule.web.js +0 -7
  114. package/lib/module/NitroModulesTurboModule.web.js.map +0 -1
  115. package/lib/typescript/NitroModulesTurboModule.d.ts +0 -19
  116. package/lib/typescript/NitroModulesTurboModule.d.ts.map +0 -1
  117. package/lib/typescript/NitroModulesTurboModule.web.d.ts +0 -2
  118. package/lib/typescript/NitroModulesTurboModule.web.d.ts.map +0 -1
  119. package/src/NitroModulesTurboModule.ts +0 -50
  120. package/src/NitroModulesTurboModule.web.ts +0 -7
@@ -31,6 +31,8 @@ Pod::Spec.new do |s|
31
31
  "cpp/core/AnyMap.hpp",
32
32
  "cpp/core/ArrayBuffer.hpp",
33
33
  "cpp/core/HybridObject.hpp",
34
+ "cpp/entrypoint/HybridNitroModulesProxy.hpp",
35
+ "cpp/entrypoint/InstallNitro.hpp",
34
36
  "cpp/registry/HybridObjectRegistry.hpp",
35
37
  "cpp/jsi/JSIConverter.hpp",
36
38
  "cpp/threading/Dispatcher.hpp",
@@ -49,6 +51,8 @@ Pod::Spec.new do |s|
49
51
  "CLANG_CXX_LANGUAGE_STANDARD" => "c++20",
50
52
  # Enables C++ <-> Swift interop (by default it's only C)
51
53
  "SWIFT_OBJC_INTEROP_MODE" => "objcxx",
54
+ # Enables stricter modular headers
55
+ "DEFINES_MODULE" => "YES",
52
56
  }
53
57
 
54
58
  install_modules_dependencies(s)
package/README.md CHANGED
@@ -1,4 +1,4 @@
1
- <a href="https://margelo.io">
1
+ <a href="https://margelo.com">
2
2
  <picture>
3
3
  <source media="(prefers-color-scheme: dark)" srcset="../../docs/static/img/banner-react-native-nitro-modules-dark.png" />
4
4
  <source media="(prefers-color-scheme: light)" srcset="../../docs/static/img/banner-react-native-nitro-modules-light.png" />
@@ -203,7 +203,7 @@ The following C++ / JS types are supported out of the box:
203
203
  <td>..any <code><a href="./src/HybridObject.ts">HybridObject</a></code></td>
204
204
  <td><code>std::shared_ptr&lt;<a href="./cpp/core/HybridObject.hpp">HybridObject</a>&gt;</code></td>
205
205
  <td><code><a href="./ios/core/HybridObjectSpec.swift">HybridObjectSpec</a></code></td>
206
- <td><code><a href="./android/core/HybridObject.kt">HybridObject</a></code></td>
206
+ <td><code><a href="./android/src/main/java/com/margelo/nitro/core/HybridObject.kt">HybridObject</a></code></td>
207
207
  </tr>
208
208
  <tr>
209
209
  <td>..any <code>interface</code></td>
@@ -22,6 +22,7 @@ add_library(NitroModules SHARED
22
22
  include_directories(
23
23
  # Shared C++ includes
24
24
  ../cpp/core
25
+ ../cpp/entrypoint
25
26
  ../cpp/jsi
26
27
  ../cpp/platform
27
28
  ../cpp/registry
@@ -34,6 +35,7 @@ include_directories(
34
35
  # Android-specific C++ includes
35
36
  src/main/cpp/core
36
37
  src/main/cpp/registry
38
+ src/main/cpp/turbomodule
37
39
  src/main/cpp/platform
38
40
  src/main/cpp/utils
39
41
  )
@@ -51,4 +53,5 @@ target_link_libraries(
51
53
  fbjni::fbjni # <-- Facebook C++ JNI helpers
52
54
  ReactAndroid::jsi # <-- RN: JSI
53
55
  ReactAndroid::react_nativemodule_core # <-- RN: TurboModules Core
56
+ ReactAndroid::turbomodulejsijni # <-- RN: TurboModules utils (e.g. CallInvokerHolder)
54
57
  )
@@ -5,7 +5,7 @@ buildscript {
5
5
  }
6
6
 
7
7
  dependencies {
8
- classpath "com.android.tools.build:gradle:7.2.1"
8
+ classpath "com.android.tools.build:gradle:8.7.1"
9
9
  }
10
10
  }
11
11
 
@@ -33,6 +33,8 @@ def getExtOrIntegerDefault(name) {
33
33
  return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties["Nitro_" + name]).toInteger()
34
34
  }
35
35
 
36
+ logger.warn("[NitroModules] Your app is boosted by nitro modules! 🔥")
37
+
36
38
  android {
37
39
  namespace "com.margelo.nitro"
38
40
 
@@ -65,6 +67,26 @@ android {
65
67
  prefabPublishing true
66
68
  }
67
69
 
70
+ packagingOptions {
71
+ excludes = [
72
+ "META-INF",
73
+ "META-INF/**",
74
+ "**/libc++_shared.so",
75
+ "**/libfbjni.so",
76
+ "**/libjsi.so",
77
+ "**/libfolly_json.so",
78
+ "**/libfolly_runtime.so",
79
+ "**/libglog.so",
80
+ "**/libhermes.so",
81
+ "**/libhermes-executor-debug.so",
82
+ "**/libhermes_executor.so",
83
+ "**/libreactnativejni.so",
84
+ "**/libturbomodulejsijni.so",
85
+ "**/libreact_nativemodule_core.so",
86
+ "**/libjscexecutor.so"
87
+ ]
88
+ }
89
+
68
90
  prefab {
69
91
  NitroModules {
70
92
  headers "${project.buildDir}/headers/nitromodules/"
@@ -91,8 +113,11 @@ android {
91
113
  if (isNewArchitectureEnabled()) {
92
114
  java.srcDirs += [
93
115
  // React Codegen files
94
- "${project.buildDir}/generated/source/codegen/java"
116
+ "${project.buildDir}/generated/source/codegen/java",
117
+ "src/newarch"
95
118
  ]
119
+ } else {
120
+ java.srcDirs += ["src/oldarch"]
96
121
  }
97
122
  }
98
123
  }
@@ -119,7 +144,6 @@ if (isNewArchitectureEnabled()) {
119
144
  }
120
145
  }
121
146
 
122
-
123
147
  task prepareHeaders(type: Copy) {
124
148
  from fileTree('./src/main/cpp').filter { it.isFile() }
125
149
  from fileTree('../cpp/').filter { it.isFile() }
@@ -4,8 +4,8 @@
4
4
  #include "JAnyValue.hpp"
5
5
  #include "JArrayBuffer.hpp"
6
6
  #include "JHybridObjectRegistry.hpp"
7
+ #include "JNitroModules.hpp"
7
8
  #include "JPromise.hpp"
8
- #include "RegisterNativeNitroModules.hpp"
9
9
  #include <fbjni/fbjni.h>
10
10
  #include <jni.h>
11
11
 
@@ -13,14 +13,14 @@ using namespace margelo::nitro;
13
13
 
14
14
  JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void*) {
15
15
  return facebook::jni::initialize(vm, [] {
16
- // 1. Initialize the Nitro JSI Turbo Module
17
- RegisterNativeNitroModules::registerNativeNitroModules();
18
-
19
- // 2. Initialize all Java bindings
16
+ // 1. Initialize all core Nitro Java bindings
20
17
  JHybridObjectRegistry::registerNatives();
21
18
  JArrayBuffer::registerNatives();
22
19
  JAnyMap::registerNatives();
23
20
  JAnyValue::registerNatives();
24
21
  JPromise::registerNatives();
22
+
23
+ // 2. Initialize the React Native TurboModule C++ part
24
+ JNitroModules::registerNatives();
25
25
  });
26
26
  }
@@ -22,7 +22,7 @@ int levelToAndroidLevel(LogLevel level) {
22
22
  case LogLevel::Error:
23
23
  return ANDROID_LOG_ERROR;
24
24
  default:
25
- throw std::runtime_error("Invalid LogLevel!");
25
+ throw std::invalid_argument("Invalid LogLevel!");
26
26
  }
27
27
  }
28
28
 
@@ -0,0 +1,41 @@
1
+ //
2
+ // Created by Marc Rousavy on 07.10.24.
3
+ //
4
+
5
+ #include "JNitroModules.hpp"
6
+ #include "CallInvokerDispatcher.hpp"
7
+ #include "InstallNitro.hpp"
8
+
9
+ #include <exception>
10
+
11
+ namespace margelo::nitro {
12
+
13
+ JNitroModules::JNitroModules() = default;
14
+
15
+ jni::local_ref<JNitroModules::jhybriddata> JNitroModules::initHybrid(jni::alias_ref<JNitroModules::jhybridobject>) {
16
+ return makeCxxInstance();
17
+ }
18
+
19
+ void JNitroModules::install(jlong runtimePointer, jni::alias_ref<react::CallInvokerHolder::javaobject> callInvokerHolder) {
20
+ auto runtime = reinterpret_cast<jsi::Runtime*>(runtimePointer);
21
+ if (runtime == nullptr) {
22
+ throw std::invalid_argument("jsi::Runtime was null!");
23
+ }
24
+
25
+ if (callInvokerHolder == nullptr) {
26
+ throw std::invalid_argument("CallInvokerHolder was null!");
27
+ }
28
+ auto callInvoker = callInvokerHolder->cthis()->getCallInvoker();
29
+ if (callInvoker == nullptr) {
30
+ throw std::invalid_argument("CallInvoker was null!");
31
+ }
32
+
33
+ auto dispatcher = std::make_shared<CallInvokerDispatcher>(callInvoker);
34
+ margelo::nitro::install(*runtime, dispatcher);
35
+ }
36
+
37
+ void JNitroModules::registerNatives() {
38
+ registerHybrid({makeNativeMethod("initHybrid", JNitroModules::initHybrid), makeNativeMethod("install", JNitroModules::install)});
39
+ }
40
+
41
+ } // namespace margelo::nitro
@@ -0,0 +1,37 @@
1
+ //
2
+ // Created by Marc Rousavy on 07.10.24.
3
+ //
4
+
5
+ #pragma once
6
+
7
+ #include <ReactCommon/CallInvoker.h>
8
+ #include <ReactCommon/CallInvokerHolder.h>
9
+ #include <fbjni/fbjni.h>
10
+ #include <jsi/jsi.h>
11
+
12
+ namespace margelo::nitro {
13
+
14
+ using namespace facebook;
15
+
16
+ class JNitroModules final : public jni::HybridClass<JNitroModules> {
17
+ public:
18
+ static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/NitroModules;";
19
+
20
+ private:
21
+ explicit JNitroModules();
22
+
23
+ private:
24
+ // JNI Methods
25
+ static jni::local_ref<JNitroModules::jhybriddata> initHybrid(jni::alias_ref<jhybridobject> javaThis);
26
+ void install(jlong runtimePointer, jni::alias_ref<react::CallInvokerHolder::javaobject> callInvokerHolder);
27
+
28
+ private:
29
+ static auto constexpr TAG = "NitroModules";
30
+ using HybridBase::HybridBase;
31
+ friend HybridBase;
32
+
33
+ public:
34
+ static void registerNatives();
35
+ };
36
+
37
+ } // namespace margelo::nitro
@@ -0,0 +1,69 @@
1
+ package com.margelo.nitro
2
+
3
+ import androidx.annotation.Keep
4
+ import com.facebook.jni.HybridData
5
+ import com.facebook.proguard.annotations.DoNotStrip
6
+ import com.facebook.react.bridge.ReactApplicationContext
7
+ import com.facebook.react.bridge.ReactMethod
8
+ import com.facebook.react.common.annotations.FrameworkAPI
9
+ import com.facebook.react.turbomodule.core.CallInvokerHolderImpl
10
+ import com.facebook.react.turbomodule.core.interfaces.CallInvokerHolder
11
+
12
+ @DoNotStrip
13
+ @Keep
14
+ @OptIn(FrameworkAPI::class)
15
+ @Suppress("KotlinJniMissingFunction")
16
+ class NitroModules internal constructor(val context: ReactApplicationContext) : NitroModulesSpec(context) {
17
+ private val mHybridData: HybridData
18
+
19
+ init {
20
+ mHybridData = initHybrid()
21
+ applicationContext = context
22
+ }
23
+
24
+ override fun getName(): String {
25
+ return NAME
26
+ }
27
+
28
+ @ReactMethod(isBlockingSynchronousMethod = true)
29
+ override fun install(): String? {
30
+ try {
31
+ // 1. Get jsi::Runtime pointer
32
+ val jsContext = context.javaScriptContextHolder
33
+ ?: return "ReactApplicationContext.javaScriptContextHolder is null!"
34
+
35
+ // 2. Get CallInvokerHolder
36
+ val callInvokerHolder = context.jsCallInvokerHolder as? CallInvokerHolderImpl
37
+ ?: return "ReactApplicationContext.jsCallInvokerHolder is null!"
38
+
39
+ // 3. Install Nitro
40
+ install(jsContext.get(), callInvokerHolder)
41
+
42
+ return null
43
+ } catch (e: Throwable) {
44
+ // ?. Something went wrong! Maybe a JNI error?
45
+ return e.message
46
+ }
47
+ }
48
+
49
+ private external fun initHybrid(): HybridData
50
+ private external fun install(jsRuntimePointer: Long, callInvokerHolder: CallInvokerHolderImpl)
51
+
52
+ companion object {
53
+ /**
54
+ * The TurboModule's name.
55
+ */
56
+ const val NAME = "NitroModules"
57
+
58
+ /**
59
+ * Get the current `ReactApplicationContext`, or `null` if none is available.
60
+ */
61
+ @JvmStatic
62
+ var applicationContext: ReactApplicationContext? = null
63
+
64
+ init {
65
+ // Make sure Nitro's C++ library is loaded
66
+ JNIOnLoad.initializeNativeNitro()
67
+ }
68
+ }
69
+ }
@@ -0,0 +1,34 @@
1
+ package com.margelo.nitro
2
+
3
+ import com.facebook.react.TurboReactPackage
4
+ import com.facebook.react.bridge.NativeModule
5
+ import com.facebook.react.bridge.ReactApplicationContext
6
+ import com.facebook.react.module.model.ReactModuleInfo
7
+ import com.facebook.react.module.model.ReactModuleInfoProvider
8
+
9
+ class NitroModulesPackage : TurboReactPackage() {
10
+ override fun getModule(name: String, reactContext: ReactApplicationContext): NativeModule? {
11
+ return if (name == NitroModules.NAME) {
12
+ NitroModules(reactContext)
13
+ } else {
14
+ null
15
+ }
16
+ }
17
+
18
+ override fun getReactModuleInfoProvider(): ReactModuleInfoProvider {
19
+ return ReactModuleInfoProvider {
20
+ val moduleInfos: MutableMap<String, ReactModuleInfo> = HashMap()
21
+ val isTurboModule: Boolean = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED
22
+ moduleInfos[NitroModules.NAME] = ReactModuleInfo(
23
+ NitroModules.NAME,
24
+ NitroModules.NAME,
25
+ canOverrideExistingModule = false,
26
+ needsEagerInit = false,
27
+ hasConstants = false,
28
+ isCxxModule = false,
29
+ isTurboModule = isTurboModule
30
+ )
31
+ moduleInfos
32
+ }
33
+ }
34
+ }
@@ -4,12 +4,16 @@ import androidx.annotation.Keep
4
4
  import com.facebook.jni.HybridData
5
5
  import com.facebook.proguard.annotations.DoNotStrip
6
6
 
7
+ interface ExtendableHybridClass {
8
+ fun updateNative(hybridData: HybridData)
9
+ }
10
+
7
11
  /**
8
12
  * A base class for all Kotlin-based HybridObjects.
9
13
  */
10
14
  @Keep
11
15
  @DoNotStrip
12
- abstract class HybridObject {
16
+ abstract class HybridObject: ExtendableHybridClass {
13
17
  /**
14
18
  * Get the memory size of the Kotlin instance (plus any external heap allocations),
15
19
  * in bytes.
@@ -41,7 +45,7 @@ abstract class HybridObject {
41
45
  * Must be called in the constructor of a subclass of `HybridObject`, to initialize the C++
42
46
  * `JHybridObject` with a subclass of it.
43
47
  */
44
- protected fun updateNative(hybridData: HybridData) {
48
+ override fun updateNative(hybridData: HybridData) {
45
49
  mHybridData = hybridData
46
50
  }
47
51
  }
@@ -0,0 +1,6 @@
1
+ package com.margelo.nitro
2
+
3
+ import com.facebook.react.bridge.ReactApplicationContext
4
+
5
+ abstract class NitroModulesSpec internal constructor(context: ReactApplicationContext) : NativeNitroModulesSpec(context) {
6
+ }
@@ -0,0 +1,9 @@
1
+ package com.margelo.nitro
2
+
3
+ import com.facebook.react.bridge.ReactApplicationContext
4
+ import com.facebook.react.bridge.ReactContextBaseJavaModule
5
+ import com.facebook.react.bridge.Promise
6
+
7
+ abstract class NitroModulesSpec internal constructor(context: ReactApplicationContext) : ReactContextBaseJavaModule(context) {
8
+ abstract fun install(): String?
9
+ }
@@ -173,7 +173,14 @@ private:
173
173
  // 1. Convert jsi::Value to jsi::Object
174
174
  #ifdef NITRO_DEBUG
175
175
  if (!value.isObject()) [[unlikely]] {
176
- throw jsi::JSError(runtime, "Cannot " + getHybridFuncDebugInfo<THybrid>(funcKind, funcName) + " - `this` is not bound!");
176
+ throw jsi::JSError(runtime, "Cannot " + getHybridFuncDebugInfo<THybrid>(funcKind, funcName) +
177
+ " - `this` is not bound! Suggestions:\n"
178
+ "- Did you accidentally destructure the `HybridObject`? (`const { " +
179
+ funcName +
180
+ " } = ...`)\n"
181
+ "- Did you call `dispose()` on the `HybridObject` before?"
182
+ "- Did you accidentally call `" +
183
+ funcName + "` on the prototype directly?");
177
184
  }
178
185
  #endif
179
186
  jsi::Object object = value.getObject(runtime);
@@ -183,10 +190,12 @@ private:
183
190
  if (!object.hasNativeState(runtime)) [[unlikely]] {
184
191
  throw jsi::JSError(runtime, "Cannot " + getHybridFuncDebugInfo<THybrid>(funcKind, funcName) +
185
192
  " - `this` does not have a NativeState! Suggestions:\n"
186
- "- Did you accidentally destructure the `HybridObject` and lose a reference to the original object?\n"
193
+ "- Did you accidentally destructure the `HybridObject`? (`const { " +
194
+ funcName +
195
+ " } = ...`)\n"
187
196
  "- Did you call `dispose()` on the `HybridObject` before?"
188
197
  "- Did you accidentally call `" +
189
- funcName + "` on the prototype directly?\n");
198
+ funcName + "` on the prototype directly?");
190
199
  }
191
200
  #endif
192
201
 
@@ -215,7 +224,7 @@ private:
215
224
  template <typename THybrid>
216
225
  static inline std::string getHybridFuncFullName(FunctionKind kind, const std::string& registrationName,
217
226
  THybrid* hybridInstance = nullptr) {
218
- std::string typeName = hybridInstance != nullptr ? hybridInstance->getName() : TypeInfo::getFriendlyTypenameNoNamespace<THybrid>();
227
+ std::string typeName = hybridInstance != nullptr ? hybridInstance->getName() : TypeInfo::getFriendlyTypename<THybrid>(true);
219
228
  switch (kind) {
220
229
  case FunctionKind::METHOD:
221
230
  return typeName + "." + registrationName + "(...)";
@@ -0,0 +1,55 @@
1
+ //
2
+ // HybridNitroModulesProxy.hpp
3
+ // NitroModules
4
+ //
5
+ // Created by Marc Rousavy on 05.10.24
6
+ //
7
+
8
+ #include "HybridNitroModulesProxy.hpp"
9
+ #include "HybridObjectRegistry.hpp"
10
+ #include "NitroDefines.hpp"
11
+
12
+ namespace margelo::nitro {
13
+
14
+ void HybridNitroModulesProxy::loadHybridMethods() {
15
+ HybridObject::loadHybridMethods();
16
+
17
+ registerHybrids(this, [](Prototype& prototype) {
18
+ prototype.registerHybridMethod("createHybridObject", &HybridNitroModulesProxy::createHybridObject);
19
+ prototype.registerHybridMethod("hasHybridObject", &HybridNitroModulesProxy::hasHybridObject);
20
+ prototype.registerHybridMethod("getAllHybridObjectNames", &HybridNitroModulesProxy::getAllHybridObjectNames);
21
+
22
+ prototype.registerHybridMethod("box", &HybridNitroModulesProxy::box);
23
+
24
+ prototype.registerHybridGetter("buildType", &HybridNitroModulesProxy::getBuildType);
25
+ });
26
+ }
27
+
28
+ // Hybrid Object Registry
29
+ std::shared_ptr<HybridObject> HybridNitroModulesProxy::createHybridObject(const std::string& name) {
30
+ return HybridObjectRegistry::createHybridObject(name);
31
+ }
32
+
33
+ bool HybridNitroModulesProxy::hasHybridObject(const std::string& name) {
34
+ return HybridObjectRegistry::hasHybridObject(name);
35
+ }
36
+
37
+ std::vector<std::string> HybridNitroModulesProxy::getAllHybridObjectNames() {
38
+ return HybridObjectRegistry::getAllHybridObjectNames();
39
+ }
40
+
41
+ // Helpers
42
+ std::shared_ptr<BoxedHybridObject> HybridNitroModulesProxy::box(const std::shared_ptr<HybridObject>& hybridObject) {
43
+ return std::make_shared<BoxedHybridObject>(hybridObject);
44
+ }
45
+
46
+ // Build Info
47
+ std::string HybridNitroModulesProxy::getBuildType() {
48
+ #ifdef NITRO_DEBUG
49
+ return "debug";
50
+ #else
51
+ return "release";
52
+ #endif
53
+ }
54
+
55
+ } // namespace margelo::nitro
@@ -0,0 +1,48 @@
1
+ //
2
+ // HybridNitroModulesProxy.hpp
3
+ // NitroModules
4
+ //
5
+ // Created by Marc Rousavy on 05.10.24
6
+ //
7
+
8
+ #pragma once
9
+
10
+ #include "BoxedHybridObject.hpp"
11
+ #include "HybridObject.hpp"
12
+ #include <memory>
13
+ #include <string>
14
+
15
+ namespace margelo::nitro {
16
+
17
+ /**
18
+ * Represents the entry point for all other HybridObjects.
19
+ * The flow is as following:
20
+ * 1. (optional) Install a Dispatcher in `jsi::Runtime` to use async/callbacks.
21
+ * 2. Create an instance of `HybridNitroModulesProxy`
22
+ * 3. Pass the object from `.toObject()` it to JS (either install in global, or return somehow)
23
+ * 4. From JS, you can access methods on this HybridObject to create all other HybridObjects.
24
+ */
25
+ class HybridNitroModulesProxy : public HybridObject {
26
+ public:
27
+ explicit HybridNitroModulesProxy() : HybridObject(TAG) {}
28
+
29
+ public:
30
+ void loadHybridMethods() override;
31
+
32
+ public:
33
+ // Hybrid Object Registry
34
+ std::shared_ptr<HybridObject> createHybridObject(const std::string& name);
35
+ bool hasHybridObject(const std::string& name);
36
+ std::vector<std::string> getAllHybridObjectNames();
37
+
38
+ // Helpers
39
+ std::shared_ptr<BoxedHybridObject> box(const std::shared_ptr<HybridObject>& hybridObject);
40
+
41
+ // Build Info
42
+ std::string getBuildType();
43
+
44
+ private:
45
+ static constexpr auto TAG = "NitroModulesProxy";
46
+ };
47
+
48
+ } // namespace margelo::nitro
@@ -0,0 +1,28 @@
1
+ //
2
+ // InstallNitro.cpp
3
+ // NitroModules
4
+ //
5
+ // Created by Marc Rousavy on 05.10.24
6
+ //
7
+
8
+ #include "InstallNitro.hpp"
9
+ #include "HybridNitroModulesProxy.hpp"
10
+
11
+ namespace margelo::nitro {
12
+
13
+ void install(jsi::Runtime& runtime, std::shared_ptr<Dispatcher> dispatcher) {
14
+ // Registers a Dispatcher for Nitro to call back into the JS Runtime.
15
+ // This allows creating Promises and calling back to JS.
16
+ Dispatcher::installRuntimeGlobalDispatcher(runtime, dispatcher);
17
+
18
+ // Installs NitroModulesProxy itself into the Runtime's global.
19
+ install(runtime);
20
+ }
21
+
22
+ void install(jsi::Runtime& runtime) {
23
+ // Installs global.NitroModulesProxy
24
+ auto proxy = std::make_shared<HybridNitroModulesProxy>();
25
+ runtime.global().setProperty(runtime, "NitroModulesProxy", proxy->toObject(runtime));
26
+ }
27
+
28
+ } // namespace margelo::nitro
@@ -0,0 +1,41 @@
1
+ //
2
+ // InstallNitro.hpp
3
+ // NitroModules
4
+ //
5
+ // Created by Marc Rousavy on 05.10.24
6
+ //
7
+
8
+ #pragma once
9
+
10
+ #include "Dispatcher.hpp"
11
+ #include <jsi/jsi.h>
12
+ #include <memory>
13
+
14
+ namespace margelo::nitro {
15
+
16
+ /**
17
+ * Installs Nitro into the given JS `runtime`.
18
+ * This will create `global.NitroModulesProxy`, Nitro's entry-point,
19
+ * which can be used to create all registered HybridObjects from JS.
20
+ *
21
+ * Also registers the given `dispatcher` which allows using callbacks,
22
+ * and async code (Promises).
23
+ * The `dispatcher` needs to implement `runAsync`/`runSync` to run
24
+ * methods on whatever Thread can safely access `runtime`.
25
+ * In a non-thread-safe Runtime, it needs to be a single Thread (e.g.
26
+ * React's `CallInvoker`), but in a thread-safe Runtime it might just be
27
+ * an implementation that runs the method directly.
28
+ */
29
+ void install(jsi::Runtime& runtime, std::shared_ptr<Dispatcher> dispatcher);
30
+
31
+ /**
32
+ * Installs Nitro into the given JS `runtime`.
33
+ * This will create `global.NitroModulesProxy`, Nitro's entry-point,
34
+ * which can be used to create all registered HybridObjects from JS.
35
+ *
36
+ * No `Dispatcher` will be installed, meaning Nitro can only use synchronous
37
+ * methods.
38
+ */
39
+ void install(jsi::Runtime& runtime);
40
+
41
+ } // namespace margelo::nitro
@@ -33,18 +33,18 @@ struct JSIConverter<T, std::enable_if_t<is_shared_ptr_to_v<T, jsi::MutableBuffer
33
33
  static inline std::shared_ptr<ArrayBuffer> fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) {
34
34
  #ifdef NITRO_DEBUG
35
35
  if (!arg.isObject()) [[unlikely]] {
36
- throw std::runtime_error("Value \"" + arg.toString(runtime).utf8(runtime) +
37
- "\" is not an ArrayBuffer - "
38
- "in fact, it's not even an object!");
36
+ throw std::invalid_argument("Value \"" + arg.toString(runtime).utf8(runtime) +
37
+ "\" is not an ArrayBuffer - "
38
+ "in fact, it's not even an object!");
39
39
  }
40
40
  #endif
41
41
 
42
42
  jsi::Object object = arg.asObject(runtime);
43
43
  #ifdef NITRO_DEBUG
44
44
  if (!object.isArrayBuffer(runtime)) [[unlikely]] {
45
- throw std::runtime_error("Object \"" + arg.toString(runtime).utf8(runtime) +
46
- "\" is not an ArrayBuffer! "
47
- "Are you maybe passing a TypedArray (e.g. Uint8Array)? Try to pass it's `.buffer` value.");
45
+ throw std::invalid_argument("Object \"" + arg.toString(runtime).utf8(runtime) +
46
+ "\" is not an ArrayBuffer! "
47
+ "Are you maybe passing a TypedArray (e.g. Uint8Array)? Try to pass it's `.buffer` value.");
48
48
  }
49
49
  #endif
50
50