react-native-ariel 0.1.0-dev.5 → 0.1.0-dev.52

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 (32) hide show
  1. package/Ariel.podspec +2 -2
  2. package/README.md +74 -98
  3. package/android/build.gradle +11 -9
  4. package/android/generated/{android/app/build/generated/source/codegen/java/com/facebook/fbreact/specs → java/com/ariel}/NativeArielSpec.java +1 -1
  5. package/android/generated/{android/app/build/generated/source/codegen/jni → jni}/CMakeLists.txt +9 -1
  6. package/android/generated/jni/react/renderer/components/ArielSpec/ArielSpecJSI-generated.cpp +32 -0
  7. package/android/generated/jni/react/renderer/components/ArielSpec/ArielSpecJSI.h +80 -0
  8. package/android/proguard-rules.pro +4 -0
  9. package/android/src/main/java/com/ariel/ArielModule.kt +11 -1
  10. package/cpp/generated/mermaid_wrapper.cpp +2369 -0
  11. package/cpp/generated/mermaid_wrapper.hpp +77 -0
  12. package/cpp/mermaid_wrapper.cpp +1 -0
  13. package/ios/generated/ArielSpecJSI-generated.cpp +32 -0
  14. package/ios/generated/ArielSpecJSI.h +80 -0
  15. package/lib/module/generated/web/wasm-bindgen/react_native_ariel.d.ts +202 -0
  16. package/lib/module/generated/web/wasm-bindgen/react_native_ariel.js +579 -0
  17. package/lib/module/generated/web/wasm-bindgen/react_native_ariel_bg.wasm +0 -0
  18. package/lib/module/generated/web/wasm-bindgen/react_native_ariel_bg.wasm.d.ts +116 -0
  19. package/lib/module/index.web.js +4 -6
  20. package/lib/module/index.web.js.map +1 -2
  21. package/package.json +31 -25
  22. package/react-native.config.js +0 -1
  23. package/android/CMakeLists.txt +0 -79
  24. package/android/generated/android/app/build/generated/source/codegen/jni/react/renderer/components/ArielSpec/ArielSpecJSI.h +0 -45
  25. package/ios/generated/build/generated/ios/ReactCodegen/ArielSpecJSI.h +0 -45
  26. package/lib/typescript/src/index.web.d.ts +0 -8
  27. package/lib/typescript/src/index.web.d.ts.map +0 -1
  28. package/src/generated/web/wasm-bindgen/package.json +0 -15
  29. /package/android/generated/{android/app/build/generated/source/codegen/jni → jni}/ArielSpec-generated.cpp +0 -0
  30. /package/android/generated/{android/app/build/generated/source/codegen/jni → jni}/ArielSpec.h +0 -0
  31. /package/ios/generated/{build/generated/ios/ReactCodegen/ArielSpec → ArielSpec}/ArielSpec-generated.mm +0 -0
  32. /package/ios/generated/{build/generated/ios/ReactCodegen/ArielSpec → ArielSpec}/ArielSpec.h +0 -0
package/Ariel.podspec CHANGED
@@ -13,9 +13,9 @@ Pod::Spec.new do |s|
13
13
  s.authors = package["author"]
14
14
 
15
15
  s.platforms = { :ios => min_ios_version_supported }
16
- s.source = { :git => "https://github.com/rinfi/ariel.git", :tag => "#{s.version}" }
16
+ s.source = { :git => "https://github.com/rinfimate/ariel.git", :tag => "#{s.version}" }
17
17
 
18
- s.source_files = "ios/**/*.{h,m,mm,swift}", "ios/generated/**/*.{h,m,mm}", "cpp/**/*.{hpp,cpp,c,h}", "cpp/generated/**/*.{hpp,cpp,c,h}"
18
+ s.source_files = "ios/**/*.{h,m,mm,swift}", "cpp/**/*.{hpp,cpp,c,h}"
19
19
  s.vendored_frameworks = "ArielFramework.xcframework"
20
20
  s.dependency "uniffi-bindgen-react-native", "0.31.0-2"
21
21
 
package/README.md CHANGED
@@ -29,7 +29,7 @@ Every other Mermaid solution for React Native requires a DOM, a WebView, or a he
29
29
  yarn add react-native-ariel react-native-svg
30
30
  ```
31
31
 
32
- > **Note:** Ariel uses custom native code and requires [Expo Dev Client](https://docs.expo.dev/develop/development-builds/introduction/) it does not work with Expo Go.
32
+ > **Requirements:** React Native **≥ 0.73** with **New Architecture enabled**. On RN 0.73–0.75 you must set `newArchEnabled=true` in `android/gradle.properties` and enable it in your iOS Podfile New Architecture became the default in RN 0.76.
33
33
 
34
34
  ---
35
35
 
@@ -38,33 +38,57 @@ yarn add react-native-ariel react-native-svg
38
38
  ### Simple render
39
39
 
40
40
  ```typescript
41
- import { renderMermaid } from 'react-native-ariel';
41
+ import { useState, useEffect } from 'react';
42
+ import { View } from 'react-native';
42
43
  import { SvgXml } from 'react-native-svg';
43
-
44
- const svg = renderMermaid('flowchart TD\n A[Hello] --> B[World]');
45
-
46
- <SvgXml xml={svg} width="100%" />
44
+ import { renderMermaid, uniffiInitAsync } from 'react-native-ariel';
45
+
46
+ export default function DiagramView() {
47
+ const [svg, setSvg] = useState<string | null>(null);
48
+
49
+ useEffect(() => {
50
+ async function run() {
51
+ // uniffiInitAsync is a no-op on native and loads the WASM module on web.
52
+ // Always await it before rendering so the same code works on both platforms.
53
+ await uniffiInitAsync();
54
+ try {
55
+ setSvg(renderMermaid('flowchart TD\n A[Hello] --> B[World]'));
56
+ } catch (e) {
57
+ console.error('Render failed:', e);
58
+ }
59
+ }
60
+ run();
61
+ }, []);
62
+
63
+ return <View>{svg && <SvgXml xml={svg} width="100%" />}</View>;
64
+ }
47
65
  ```
48
66
 
67
+ `renderMermaid` is **synchronous** on native — no async overhead after init.
68
+
49
69
  ### With theme and layout control
50
70
 
51
71
  ```typescript
52
- import { renderMermaidWithOptions, ArielTheme } from 'react-native-ariel';
72
+ import { renderMermaidWithOptions, uniffiInitAsync, ArielTheme } from 'react-native-ariel';
53
73
 
54
- const theme = ArielTheme.modern(); // or ArielTheme.mermaidDefault()
55
- const config = { nodeSpacing: 50, rankSpacing: 80, aspectRatioHint: null };
74
+ const config = { nodeSpacing: 50, rankSpacing: 80 };
56
75
 
57
- const svg = renderMermaidWithOptions(diagram, theme, config);
76
+ await uniffiInitAsync();
77
+ const svg = renderMermaidWithOptions(diagram, ArielTheme.modern(), config);
78
+ // or: ArielTheme.mermaidDefault()
58
79
  ```
59
80
 
60
81
  ### With timing metrics
61
82
 
62
83
  ```typescript
63
- import { renderMermaidWithTiming, ArielTheme } from 'react-native-ariel';
84
+ import { renderMermaidWithTiming, uniffiInitAsync, ArielTheme } from 'react-native-ariel';
85
+
86
+ const config = { nodeSpacing: 50, rankSpacing: 80 };
64
87
 
88
+ await uniffiInitAsync();
65
89
  const result = renderMermaidWithTiming(diagram, ArielTheme.modern(), config);
66
90
  console.log(`Total: ${result.totalMs.toFixed(2)}ms`);
67
- // Parse: 420µs Layout: 610µs Render: 200µs
91
+ // parseUs / layoutUs / renderUs are bigint (µs); totalMs is number (ms)
68
92
  ```
69
93
 
70
94
  ### Full pipeline (parse once, render with multiple themes)
@@ -74,9 +98,13 @@ import {
74
98
  parseDiagram,
75
99
  computeDiagramLayout,
76
100
  renderSvgFromLayout,
101
+ uniffiInitAsync,
77
102
  ArielTheme,
78
103
  } from 'react-native-ariel';
79
104
 
105
+ const config = { nodeSpacing: 50, rankSpacing: 80 };
106
+
107
+ await uniffiInitAsync();
80
108
  const parsed = parseDiagram('flowchart LR\n A --> B --> C');
81
109
  const layout = computeDiagramLayout(parsed, ArielTheme.modern(), config);
82
110
  const svg = renderSvgFromLayout(layout, ArielTheme.modern(), config);
@@ -95,18 +123,6 @@ Logs are written to **Android Logcat**, the **Xcode console** on iOS, and the **
95
123
 
96
124
  > **Note:** When timing is on, every render call allocates a format string regardless of whether you can see the output. This is cheap but not free. The flag is intended for debugging — avoid shipping with `setTimingLogs(true)` hardcoded.
97
125
 
98
- ### Web (WASM) initialisation
99
-
100
- On web, call `uniffiInitAsync` before any render calls:
101
-
102
- ```typescript
103
- import { uniffiInitAsync } from 'react-native-ariel';
104
-
105
- uniffiInitAsync().then(() => {
106
- // safe to call renderMermaid here
107
- });
108
- ```
109
-
110
126
  ---
111
127
 
112
128
  ## API
@@ -120,6 +136,7 @@ uniffiInitAsync().then(() => {
120
136
  | `computeDiagramLayout(parsed, theme, config)` | Layout stage — returns opaque `ArielLayout` |
121
137
  | `renderSvgFromLayout(layout, theme, config)` | SVG stage from pre-computed layout |
122
138
  | `setTimingLogs(enabled)` | Toggle timing output to console (default: off) |
139
+ | `uniffiInitAsync()` | Load WASM module on web; no-op on native. Call once before rendering |
123
140
  | `ArielTheme.modern()` | Modern theme — see below |
124
141
  | `ArielTheme.mermaidDefault()` | Classic Mermaid theme — see below |
125
142
 
@@ -147,9 +164,8 @@ const svg = renderMermaidWithOptions(diagram, ArielTheme.mermaidDefault(), confi
147
164
 
148
165
  ```typescript
149
166
  {
150
- nodeSpacing?: number | null;
151
- rankSpacing?: number | null;
152
- aspectRatioHint?: number | null;
167
+ nodeSpacing?: number;
168
+ rankSpacing?: number;
153
169
  }
154
170
  ```
155
171
 
@@ -158,10 +174,10 @@ const svg = renderMermaidWithOptions(diagram, ArielTheme.mermaidDefault(), confi
158
174
  ```typescript
159
175
  {
160
176
  svg: string;
161
- parseUs: number;
162
- layoutUs: number;
163
- renderUs: number;
164
- totalMs: number;
177
+ parseUs: bigint; // microseconds (u64)
178
+ layoutUs: bigint; // microseconds (u64)
179
+ renderUs: bigint; // microseconds (u64)
180
+ totalMs: number; // milliseconds (f64)
165
181
  }
166
182
  ```
167
183
 
@@ -174,7 +190,7 @@ const svg = renderMermaidWithOptions(diagram, ArielTheme.mermaidDefault(), confi
174
190
  | Tool | Purpose | Install |
175
191
  |---|---|---|
176
192
  | [Rust](https://rustup.rs) | Compile the Rust crate | `curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs \| sh` |
177
- | [Node.js](https://nodejs.org) ≥ 20 | JS toolchain | nodejs.org |
193
+ | [Node.js](https://nodejs.org) ≥ 22 | JS toolchain | nodejs.org |
178
194
  | Yarn | Package manager | `npm i -g yarn` |
179
195
  | [Android Studio](https://developer.android.com/studio) | Android SDK + NDK | See below |
180
196
  | Xcode ≥ 15 | iOS builds (macOS only) | Mac App Store |
@@ -199,7 +215,7 @@ rustup target add wasm32-unknown-unknown
199
215
  ### Clone and install
200
216
 
201
217
  ```sh
202
- git clone https://github.com/rinfi/ariel.git
218
+ git clone https://github.com/rinfimate/ariel.git
203
219
  cd ariel
204
220
  yarn
205
221
  ```
@@ -222,119 +238,79 @@ This works on **Windows**, **macOS**, and **Linux** and writes to `src/generated
222
238
 
223
239
  ### Android
224
240
 
225
- Compiles the Rust crate for all Android ABIs and places `.a` / `.so` files under `android/src/main/jniLibs/`. Run `yarn ubrn:generate` first if you haven't already.
241
+ Compiles the Rust crate for all Android ABIs and places `.a` files under `android/src/main/jniLibs/`. Run `yarn ubrn:generate` first if you haven't already.
226
242
 
227
243
  ```sh
228
244
  yarn ubrn:generate # generates src/generated/rn/ and cpp/
229
245
  yarn ubrn:android # compiles for arm64-v8a, armeabi-v7a, x86_64, x86
246
+ yarn bob build # compiles TypeScript → lib/
230
247
  ```
231
248
 
232
249
  ### iOS (macOS only)
233
250
 
234
- Compiles for device + simulator and runs `pod install`. Run `yarn ubrn:generate` first.
251
+ Compiles for device + simulator. Run `yarn ubrn:generate` first.
235
252
 
236
253
  ```sh
237
254
  yarn ubrn:generate # generates src/generated/rn/ and cpp/
238
255
  yarn ubrn:ios # compiles for aarch64-apple-ios, x86_64-apple-ios, aarch64-apple-ios-sim
256
+ yarn bob build # compiles TypeScript → lib/
239
257
  ```
240
258
 
241
259
  ### Web (WASM)
242
260
 
243
- Compiles to `wasm32-unknown-unknown` and produces a `.wasm` bundle under `src/generated/web/`. Run `yarn ubrn:generate` first.
261
+ Compiles to `wasm32-unknown-unknown` and produces a `.wasm` bundle. Run `yarn ubrn:generate` first.
244
262
 
245
263
  ```sh
246
264
  yarn ubrn:generate # generates src/generated/web/ (WASM TypeScript bindings)
247
265
  yarn ubrn:web # compiles the WASM crate with wasm-pack
266
+ yarn bob build # compiles TypeScript → lib/ and copies WASM into lib/module/
248
267
  ```
249
268
 
250
- ### Rust unit tests
251
-
252
- ```sh
253
- cargo test --manifest-path rust/mermaid_wrapper/Cargo.toml
254
- ```
255
-
256
- ### TypeScript tests
257
-
258
- ```sh
259
- yarn test
260
- ```
261
-
262
- ### Clean generated files
263
-
264
- Removes all `ubrn`-generated native code so you can rebuild from scratch.
265
-
266
- ```sh
267
- yarn ubrn:clean
268
- ```
269
-
270
- ---
271
-
272
- ## Running the example app
273
-
274
- The `example/` directory is an Expo app with a live Mermaid editor — type a diagram, see the SVG update in real time with timing stats.
269
+ ### Building the npm package
275
270
 
276
- ### Step 1 Generate bindings (all platforms, run once)
271
+ To produce a publishable tarball locally (mirrors what CI does, skipping iOS):
277
272
 
278
273
  ```sh
279
274
  yarn ubrn:generate
280
- ```
281
-
282
- ### Step 2 — Build native libs for your target platform
283
-
284
- ```sh
285
- # Android
286
275
  yarn ubrn:android
287
-
288
- # iOS (macOS only)
289
- yarn ubrn:ios
290
-
291
- # Web — compile WASM bundle
292
276
  yarn ubrn:web
277
+ yarn bob build
278
+ npm pack --ignore-scripts
293
279
  ```
294
280
 
295
- ### Step 3 — Run the example
281
+ ### Rust unit tests
296
282
 
297
- **Web** (no emulator needed — opens in your browser):
298
283
  ```sh
299
- yarn example:web
284
+ cargo test --manifest-path rust/mermaid_wrapper/Cargo.toml
300
285
  ```
301
286
 
302
- **Android** (emulator or USB device with debugging enabled):
303
- ```sh
304
- yarn example:android
305
- ```
287
+ ### TypeScript tests
306
288
 
307
- **iOS** (macOS only):
308
289
  ```sh
309
- yarn example:ios
290
+ yarn test
310
291
  ```
311
292
 
312
- ### With Expo Dev Client (install on device)
293
+ ### Clean generated files
313
294
 
314
- For a shareable installable build that includes the Ariel native module:
295
+ Removes all `ubrn`-generated native code so you can rebuild from scratch.
315
296
 
316
297
  ```sh
317
- # Install EAS CLI
318
- npm install -g eas-cli
319
-
320
- # Build dev client (free for public repos)
321
- eas build --profile development
322
-
323
- # Install the .apk / .ipa on your device, then run:
324
- yarn example:android # or example:ios
298
+ yarn ubrn:clean
325
299
  ```
326
300
 
327
301
  ---
328
302
 
329
303
  ## CI
330
304
 
331
- Three GitHub Actions workflows run on every push to `main`:
305
+ On every push to `main` and on pull requests, `ci.yml` runs:
332
306
 
333
- | Workflow | Runner | What it does |
307
+ | Job | Runner | What it does |
334
308
  |---|---|---|
335
- | `build-android.yml` | `ubuntu-latest` | Runs Rust unit tests, builds Android `.so` libs |
336
- | `build-ios.yml` | `macos-latest` | Builds iOS `.xcframework` |
337
- | `build-web.yml` | `ubuntu-latest` | Builds WASM bindings |
309
+ | `test-rust` | `ubuntu-latest` | Rust unit tests |
310
+ | `build-android` | `ubuntu-latest` | Cross-compiles Rust for all Android ABIs |
311
+ | `build-ios` | `macos-latest` | Builds iOS xcframework |
312
+ | `build-web` | `ubuntu-latest` | Builds WASM bundle |
313
+ | `publish` | `ubuntu-latest` | Publishes to npm (push to main or release only) |
338
314
 
339
315
  iOS uses GitHub's free `macos-latest` runner (unlimited minutes on public repos).
340
316
 
@@ -342,7 +318,7 @@ iOS uses GitHub's free `macos-latest` runner (unlimited minutes on public repos)
342
318
 
343
319
  ## License
344
320
 
345
- MIT © 2026 [Rochanglien Infimate](https://github.com/rinfi)
321
+ MIT © 2026 [Rochanglien Infimate](https://github.com/rinfimate)
346
322
 
347
323
  ---
348
324
 
@@ -28,9 +28,7 @@ def isNewArchitectureEnabled() {
28
28
  apply plugin: "com.android.library"
29
29
  apply plugin: "kotlin-android"
30
30
 
31
- if (isNewArchitectureEnabled()) {
32
- apply plugin: "com.facebook.react"
33
- }
31
+ apply plugin: "com.facebook.react"
34
32
 
35
33
  def getExtOrDefault(name) {
36
34
  return rootProject.ext.has(name) ? rootProject.ext.get(name) : project.properties["Ariel_" + name]
@@ -120,6 +118,12 @@ android {
120
118
  }
121
119
  }
122
120
 
121
+ android {
122
+ packagingOptions {
123
+ excludes += ['lib/*/libjsi.so', 'lib/*/libturbomodulejsijni.so', 'lib/*/libreact_nativemodule_core.so']
124
+ }
125
+ }
126
+
123
127
  repositories {
124
128
  mavenCentral()
125
129
  google()
@@ -135,10 +139,8 @@ dependencies {
135
139
  implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
136
140
  }
137
141
 
138
- if (isNewArchitectureEnabled()) {
139
- react {
140
- jsRootDir = file("../src/")
141
- libraryName = "Ariel"
142
- codegenJavaPackageName = "com.ariel"
143
- }
142
+ react {
143
+ jsRootDir = file("../src/")
144
+ libraryName = "Ariel"
145
+ codegenJavaPackageName = "com.ariel"
144
146
  }
@@ -10,7 +10,7 @@
10
10
  * @nolint
11
11
  */
12
12
 
13
- package com.facebook.fbreact.specs;
13
+ package com.ariel;
14
14
 
15
15
  import com.facebook.proguard.annotations.DoNotStrip;
16
16
  import com.facebook.react.bridge.ReactApplicationContext;
@@ -25,4 +25,12 @@ target_link_libraries(
25
25
  reactnative
26
26
  )
27
27
 
28
- target_compile_reactnative_options(react_codegen_ArielSpec PRIVATE)
28
+ target_compile_options(
29
+ react_codegen_ArielSpec
30
+ PRIVATE
31
+ -DLOG_TAG=\"ReactNative\"
32
+ -fexceptions
33
+ -frtti
34
+ -std=c++20
35
+ -Wall
36
+ )
@@ -0,0 +1,32 @@
1
+ /**
2
+ * This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
3
+ *
4
+ * Do not edit this file as changes may cause incorrect behavior and will be lost
5
+ * once the code is regenerated.
6
+ *
7
+ * @generated by codegen project: GenerateModuleCpp.js
8
+ */
9
+
10
+ #include "ArielSpecJSI.h"
11
+
12
+ namespace facebook::react {
13
+
14
+ static jsi::Value __hostFunction_NativeArielCxxSpecJSI_installRustCrate(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
15
+ return static_cast<NativeArielCxxSpecJSI *>(&turboModule)->installRustCrate(
16
+ rt
17
+ );
18
+ }
19
+ static jsi::Value __hostFunction_NativeArielCxxSpecJSI_cleanupRustCrate(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
20
+ return static_cast<NativeArielCxxSpecJSI *>(&turboModule)->cleanupRustCrate(
21
+ rt
22
+ );
23
+ }
24
+
25
+ NativeArielCxxSpecJSI::NativeArielCxxSpecJSI(std::shared_ptr<CallInvoker> jsInvoker)
26
+ : TurboModule("Ariel", jsInvoker) {
27
+ methodMap_["installRustCrate"] = MethodMetadata {0, __hostFunction_NativeArielCxxSpecJSI_installRustCrate};
28
+ methodMap_["cleanupRustCrate"] = MethodMetadata {0, __hostFunction_NativeArielCxxSpecJSI_cleanupRustCrate};
29
+ }
30
+
31
+
32
+ } // namespace facebook::react
@@ -0,0 +1,80 @@
1
+ /**
2
+ * This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
3
+ *
4
+ * Do not edit this file as changes may cause incorrect behavior and will be lost
5
+ * once the code is regenerated.
6
+ *
7
+ * @generated by codegen project: GenerateModuleH.js
8
+ */
9
+
10
+ #pragma once
11
+
12
+ #include <ReactCommon/TurboModule.h>
13
+ #include <react/bridging/Bridging.h>
14
+
15
+ namespace facebook::react {
16
+
17
+
18
+ class JSI_EXPORT NativeArielCxxSpecJSI : public TurboModule {
19
+ protected:
20
+ NativeArielCxxSpecJSI(std::shared_ptr<CallInvoker> jsInvoker);
21
+
22
+ public:
23
+ virtual bool installRustCrate(jsi::Runtime &rt) = 0;
24
+ virtual bool cleanupRustCrate(jsi::Runtime &rt) = 0;
25
+
26
+ };
27
+
28
+ template <typename T>
29
+ class JSI_EXPORT NativeArielCxxSpec : public TurboModule {
30
+ public:
31
+ jsi::Value create(jsi::Runtime &rt, const jsi::PropNameID &propName) override {
32
+ return delegate_.create(rt, propName);
33
+ }
34
+
35
+ std::vector<jsi::PropNameID> getPropertyNames(jsi::Runtime& runtime) override {
36
+ return delegate_.getPropertyNames(runtime);
37
+ }
38
+
39
+ static constexpr std::string_view kModuleName = "Ariel";
40
+
41
+ protected:
42
+ NativeArielCxxSpec(std::shared_ptr<CallInvoker> jsInvoker)
43
+ : TurboModule(std::string{NativeArielCxxSpec::kModuleName}, jsInvoker),
44
+ delegate_(reinterpret_cast<T*>(this), jsInvoker) {}
45
+
46
+
47
+ private:
48
+ class Delegate : public NativeArielCxxSpecJSI {
49
+ public:
50
+ Delegate(T *instance, std::shared_ptr<CallInvoker> jsInvoker) :
51
+ NativeArielCxxSpecJSI(std::move(jsInvoker)), instance_(instance) {
52
+
53
+ }
54
+
55
+ bool installRustCrate(jsi::Runtime &rt) override {
56
+ static_assert(
57
+ bridging::getParameterCount(&T::installRustCrate) == 1,
58
+ "Expected installRustCrate(...) to have 1 parameters");
59
+
60
+ return bridging::callFromJs<bool>(
61
+ rt, &T::installRustCrate, jsInvoker_, instance_);
62
+ }
63
+ bool cleanupRustCrate(jsi::Runtime &rt) override {
64
+ static_assert(
65
+ bridging::getParameterCount(&T::cleanupRustCrate) == 1,
66
+ "Expected cleanupRustCrate(...) to have 1 parameters");
67
+
68
+ return bridging::callFromJs<bool>(
69
+ rt, &T::cleanupRustCrate, jsInvoker_, instance_);
70
+ }
71
+
72
+ private:
73
+ friend class NativeArielCxxSpec;
74
+ T *instance_;
75
+ };
76
+
77
+ Delegate delegate_;
78
+ };
79
+
80
+ } // namespace facebook::react
@@ -0,0 +1,4 @@
1
+ # Generated by uniffi-bindgen-react-native
2
+ -dontwarn java.awt.*
3
+ -keep class com.sun.jna.* { *; }
4
+ -keepclassmembers class * extends com.sun.jna.* { public *; }
@@ -23,10 +23,20 @@ class ArielModule(reactContext: ReactApplicationContext) :
23
23
  val context = this.reactApplicationContext
24
24
  return nativeInstallRustCrate(
25
25
  context.javaScriptContextHolder!!.get(),
26
- context.jsCallInvokerHolder!!
26
+ resolveCallInvokerHolder(context)
27
27
  )
28
28
  }
29
29
 
30
+ private fun resolveCallInvokerHolder(context: ReactApplicationContext): CallInvokerHolder {
31
+ // RN 0.74+ exposes getJSCallInvokerHolder() on ReactContext directly.
32
+ // RN 0.73 only has it on CatalystInstance — use reflection to handle both.
33
+ val direct = context.javaClass.methods.firstOrNull { it.name == "getJSCallInvokerHolder" }
34
+ if (direct != null) return direct.invoke(context) as CallInvokerHolder
35
+ @Suppress("DEPRECATION")
36
+ val ci = checkNotNull(context.catalystInstance) { "No CatalystInstance" }
37
+ return ci.javaClass.methods.first { it.name == "getJSCallInvokerHolder" }.invoke(ci) as CallInvokerHolder
38
+ }
39
+
30
40
  override fun cleanupRustCrate(): Boolean {
31
41
  return nativeCleanupRustCrate(
32
42
  this.reactApplicationContext.javaScriptContextHolder!!.get()