react-native-vroom-chart 0.17.0 → 0.18.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.
package/README.md CHANGED
@@ -15,7 +15,7 @@ import { VroomChart } from 'react-native-vroom-chart';
15
15
 
16
16
  ## Peer dependencies
17
17
 
18
- - `react-native` ≥ 0.76
18
+ - `react-native` ≥ 0.78, New Architecture enabled — the chart installs its JSI bindings through the TurboModule JSI-bindings hooks, which have no legacy-bridge equivalent
19
19
  - `@shopify/react-native-skia` ≥ 2.11.0 — provides the Skia runtime we draw into. vroom links RN-Skia's native internals (`cpp/api`) and tracks that package closely; those headers have no semver guarantee.
20
20
 
21
21
  - `react-native-gesture-handler` ≥ 2.16 — long-press / pan / pinch recognition
@@ -2,7 +2,8 @@
2
2
  #
3
3
  # Builds libvroomchart.so from the same platform-agnostic JSI glue and chart
4
4
  # core the iOS podspec compiles (see ../react-native-vroom-chart.podspec),
5
- # plus this directory's small JNI entry point (src/main/cpp/VroomChartJni.cpp).
5
+ # plus this directory's fbjni entry points (src/main/cpp/OnLoad.cpp and
6
+ # src/main/cpp/VroomChartJsiBindings.cpp).
6
7
  #
7
8
  # RN-Skia's headers (JsiSkNativeObjects.h, JsiSkPicture.h, and the
8
9
  # RNSkPlatformContext.h they pull in) aren't consumed via CMake's prefab
@@ -27,6 +28,7 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
27
28
  set(CMAKE_POSITION_INDEPENDENT_CODE ON)
28
29
 
29
30
  find_package(ReactAndroid REQUIRED CONFIG)
31
+ find_package(fbjni REQUIRED CONFIG)
30
32
  # Prefab package name matches the Gradle project name AGP autolinking assigns
31
33
  # RN-Skia (":shopify_react-native-skia"), not the "rnskia" module name inside
32
34
  # its own `prefab { rnskia { ... } }` block — that block key becomes the
@@ -70,7 +72,8 @@ add_library(vroomchart SHARED
70
72
  "${CMAKE_CURRENT_SOURCE_DIR}/../cpp/VroomChartHostObject.cpp"
71
73
  "${CMAKE_CURRENT_SOURCE_DIR}/../cpp/VroomFontMgr.cpp"
72
74
  ${VROOM_CORE_SOURCES}
73
- "${CMAKE_CURRENT_SOURCE_DIR}/src/main/cpp/VroomChartJni.cpp"
75
+ "${CMAKE_CURRENT_SOURCE_DIR}/src/main/cpp/VroomChartJsiBindings.cpp"
76
+ "${CMAKE_CURRENT_SOURCE_DIR}/src/main/cpp/OnLoad.cpp"
74
77
  )
75
78
 
76
79
  target_include_directories(vroomchart PRIVATE
@@ -132,9 +135,16 @@ target_link_options(vroomchart PRIVATE
132
135
  "-Wl,-z,common-page-size=16384"
133
136
  )
134
137
 
138
+ # BindingsInstallerHolder's constructors are compiled into libreactnative.so
139
+ # (RN folds the turbomodulejsijni object library into it), so linking
140
+ # ReactAndroid::reactnative is what resolves the newObjectCxxArgs instantiation
141
+ # in src/main/cpp/VroomChartJsiBindings.cpp. fbjni supplies the JavaClass /
142
+ # registerNatives machinery that wraps it.
135
143
  target_link_libraries(vroomchart
136
144
  ${VROOM_LOG_LIB}
137
145
  ReactAndroid::jsi
146
+ ReactAndroid::reactnative
147
+ fbjni::fbjni
138
148
  shopify_react-native-skia::rnskia
139
149
  vroom_skia_prebuilt
140
150
  )
package/android/README.md CHANGED
@@ -1,12 +1,22 @@
1
1
  # Android bridge
2
2
 
3
3
  Android equivalent of `../ios/`: a small TurboModule
4
- ([`VroomChartModule.kt`](src/main/java/com/vroom/chart/VroomChartModule.kt)) whose
5
- `install()` hands the JSI runtime pointer to a native `vroomchart` library
6
- (built by [`CMakeLists.txt`](CMakeLists.txt)) that installs
7
- `global.VroomChartJSI` via the same platform-agnostic
8
- [`../cpp/VroomJsiInstaller.cpp`](../cpp/VroomJsiInstaller.cpp) the iOS bridge
9
- uses.
4
+ ([`VroomChartModule.kt`](src/main/java/com/vroom/chart/VroomChartModule.kt))
5
+ implementing `TurboModuleWithJSIBindings`. `TurboModuleManager` calls its
6
+ `getBindingsInstaller()` when it instantiates the module and runs the returned
7
+ holder against the JSI runtime, which installs `global.VroomChartJSI` via the
8
+ same platform-agnostic
9
+ [`../cpp/VroomJsiInstaller.cpp`](../cpp/VroomJsiInstaller.cpp) the iOS module
10
+ uses. The native `vroomchart` library (built by
11
+ [`CMakeLists.txt`](CMakeLists.txt)) binds that method in
12
+ [`src/main/cpp/VroomChartJsiBindings.cpp`](src/main/cpp/VroomChartJsiBindings.cpp),
13
+ registered from [`src/main/cpp/OnLoad.cpp`](src/main/cpp/OnLoad.cpp).
14
+
15
+ This replaced an earlier `install()`-driven path that read the runtime pointer
16
+ out of `ReactContext.javaScriptContextHolder`. That still works on current
17
+ React Native, but the bindings hook is the supported entry point and matches
18
+ what iOS now has to do — `[RCTBridge currentBridge]` returns `nil` once
19
+ `RCT_REMOVE_LEGACY_ARCH` is on, which is the default from React Native 0.85.
10
20
 
11
21
  The chart core (`../cpp/_core_src`) and the platform font-manager helper
12
22
  (`../cpp/VroomFontMgr.*`) are unmodified and shared across iOS and Android —
@@ -108,6 +108,16 @@ android {
108
108
  }
109
109
  }
110
110
 
111
+ // prefab copies every consumed module's .so into our intermediates. RN and
112
+ // RN-Skia already ship these in their own AARs, so packaging a second copy
113
+ // here makes app assembly fail on duplicate libraries.
114
+ packagingOptions {
115
+ exclude "**/libc++_shared.so"
116
+ exclude "**/libfbjni.so"
117
+ exclude "**/libjsi.so"
118
+ exclude "**/libreactnative.so"
119
+ }
120
+
111
121
  lintOptions {
112
122
  abortOnError false
113
123
  }
@@ -0,0 +1,10 @@
1
+ #include <jni.h>
2
+
3
+ #include <fbjni/fbjni.h>
4
+
5
+ #include "VroomChartJsiBindings.h"
6
+
7
+ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* /*reserved*/) {
8
+ return facebook::jni::initialize(
9
+ vm, [] { vroom::VroomChartJsiBindings::registerNatives(); });
10
+ }
@@ -0,0 +1,35 @@
1
+ #include "VroomChartJsiBindings.h"
2
+
3
+ #include <memory>
4
+
5
+ #include <jsi/jsi.h>
6
+
7
+ #include "VroomJsiInstaller.h"
8
+
9
+ namespace vroom {
10
+
11
+ namespace jni = facebook::jni;
12
+ namespace jsi = facebook::jsi;
13
+ using facebook::react::BindingsInstallerHolder;
14
+ using facebook::react::CallInvoker;
15
+
16
+ void VroomChartJsiBindings::registerNatives() {
17
+ // makeNativeMethod is a macro, so it cannot be namespace-qualified.
18
+ javaClassLocal()->registerNatives({
19
+ makeNativeMethod(
20
+ "getBindingsInstaller",
21
+ VroomChartJsiBindings::getBindingsInstaller),
22
+ });
23
+ }
24
+
25
+ jni::local_ref<BindingsInstallerHolder::javaobject>
26
+ VroomChartJsiBindings::getBindingsInstaller(
27
+ jni::alias_ref<VroomChartJsiBindings> /*jobj*/) {
28
+ // callInvoker is unused: every chart call is synchronous on the JS thread.
29
+ return BindingsInstallerHolder::newObjectCxxArgs(
30
+ [](jsi::Runtime& runtime, const std::shared_ptr<CallInvoker>&) {
31
+ installJsi(runtime);
32
+ });
33
+ }
34
+
35
+ } // namespace vroom
@@ -0,0 +1,27 @@
1
+ #pragma once
2
+
3
+ #include <ReactCommon/BindingsInstallerHolder.h>
4
+ #include <fbjni/fbjni.h>
5
+
6
+ namespace vroom {
7
+
8
+ // Binds com.vroom.chart.VroomChartModule.getBindingsInstaller() (see
9
+ // ../java/com/vroom/chart/VroomChartModule.kt) to C++. The holder it returns
10
+ // is invoked by TurboModuleManager with the JSI runtime, which is where
11
+ // vroom::installJsi() runs. This is the Android counterpart of iOS's
12
+ // -installJSIBindingsWithRuntime:callInvoker: in ../../ios/VroomChartModule.mm.
13
+ class VroomChartJsiBindings
14
+ : public facebook::jni::JavaClass<VroomChartJsiBindings> {
15
+ public:
16
+ static constexpr const char* kJavaDescriptor =
17
+ "Lcom/vroom/chart/VroomChartModule;";
18
+
19
+ static void registerNatives();
20
+
21
+ private:
22
+ static facebook::jni::local_ref<
23
+ facebook::react::BindingsInstallerHolder::javaobject>
24
+ getBindingsInstaller(facebook::jni::alias_ref<VroomChartJsiBindings> jobj);
25
+ };
26
+
27
+ } // namespace vroom
@@ -1,19 +1,24 @@
1
1
  package com.vroom.chart
2
2
 
3
+ import com.facebook.proguard.annotations.DoNotStrip
3
4
  import com.facebook.react.bridge.ReactApplicationContext
4
5
  import com.facebook.react.module.annotations.ReactModule
6
+ import com.facebook.react.turbomodule.core.interfaces.BindingsInstallerHolder
7
+ import com.facebook.react.turbomodule.core.interfaces.TurboModuleWithJSIBindings
5
8
 
6
- // TurboModule counterpart to ../../ios/VroomChartModule.mm. `install()` hands
7
- // the JSI runtime pointer to the native `vroomchart` library (see
8
- // ../../CMakeLists.txt), which installs `global.VroomChartJSI` via the same
9
- // platform-agnostic vroom::installJsi() the iOS bridge calls.
9
+ // TurboModule counterpart to ../../ios/VroomChartModule.mm. TurboModuleManager
10
+ // calls getBindingsInstaller() when it instantiates this module and runs the
11
+ // returned installer against the JSI runtime, which exposes
12
+ // `global.VroomChartJSI` via the same platform-agnostic vroom::installJsi()
13
+ // the iOS module calls. Implemented in ../../cpp/VroomChartJsiBindings.cpp and
14
+ // bound by ../../cpp/OnLoad.cpp.
10
15
  //
11
16
  // `NativeVroomChartSpec` is generated by React Native's codegen from
12
17
  // ../../../src/NativeVroomChart.ts (codegenConfig.android.javaPackageName in
13
18
  // package.json) — the same class name iOS's codegen generates.
14
19
  @ReactModule(name = NativeVroomChartSpec.NAME)
15
20
  class VroomChartModule(reactContext: ReactApplicationContext) :
16
- NativeVroomChartSpec(reactContext) {
21
+ NativeVroomChartSpec(reactContext), TurboModuleWithJSIBindings {
17
22
 
18
23
  companion object {
19
24
  init {
@@ -21,11 +26,10 @@ class VroomChartModule(reactContext: ReactApplicationContext) :
21
26
  }
22
27
  }
23
28
 
24
- private external fun nativeInstall(runtimePointer: Long): Boolean
29
+ @DoNotStrip external override fun getBindingsInstaller(): BindingsInstallerHolder
25
30
 
26
- override fun install(): Boolean {
27
- val runtimePointer =
28
- reactApplicationContext.javaScriptContextHolder?.get() ?: return false
29
- return nativeInstall(runtimePointer)
30
- }
31
+ // Reaching this module from JS means TurboModuleManager already ran the
32
+ // installer above. JS verifies global.VroomChartJSI itself rather than
33
+ // trusting this return value — see ../../../src/useChartCore.ts.
34
+ override fun install(): Boolean = true
31
35
  }
@@ -75,6 +75,12 @@ static void ensureAxisTypeface() {
75
75
  }
76
76
 
77
77
  void installJsi(jsi::Runtime& runtime) {
78
+ // Honor the idempotence the header promises: re-running this would replace
79
+ // the global with a fresh `create`, orphaning handles JS already holds.
80
+ if (runtime.global().hasProperty(runtime, "VroomChartJSI")) {
81
+ return;
82
+ }
83
+
78
84
  ensureAxisTypeface();
79
85
 
80
86
  auto create = jsi::Function::createFromHostFunction(
package/ios/README.md CHANGED
@@ -1,7 +1,19 @@
1
- # iOS shim (placeholder)
1
+ # iOS bridge
2
2
 
3
- When native is wired up, this directory will hold the Objective-C++ view
4
- and module that host the chart and forward gestures into the C++ core.
3
+ A single TurboModule, [`VroomChartModule`](VroomChartModule.mm), conforming to
4
+ `RCTTurboModuleWithJSIBindings`. `RCTTurboModuleManager` calls
5
+ `-installJSIBindingsWithRuntime:callInvoker:` as soon as it instantiates the
6
+ module — before the module object reaches JS — and that installs
7
+ `global.VroomChartJSI` via the platform-agnostic
8
+ [`../cpp/VroomJsiInstaller.cpp`](../cpp/VroomJsiInstaller.cpp) Android also
9
+ uses. There is no native view: the chart renders into an `SkPicture` that
10
+ `<Canvas>` from `@shopify/react-native-skia` paints.
5
11
 
6
- The accompanying `react-native-vroom-chart.podspec` at the package root will
7
- build `cpp/` + `ios/` + the linked `@vroomchart/core` static library.
12
+ This replaced a `[RCTBridge currentBridge]` `RCTCxxBridge.runtime` lookup,
13
+ which stopped working in React Native 0.85. That release enables
14
+ `RCT_REMOVE_LEGACY_ARCH` by default, under which `RCTBridge` compiles down to
15
+ a stub whose `+currentBridge` returns `nil`.
16
+
17
+ [`../react-native-vroom-chart.podspec`](../react-native-vroom-chart.podspec)
18
+ builds `cpp/` + `ios/` plus the core sources mirrored in from
19
+ `packages/core/`.
@@ -1,11 +1,8 @@
1
1
  #import <Foundation/Foundation.h>
2
2
  #import <React/RCTBridgeModule.h>
3
-
4
- #ifdef RCT_NEW_ARCH_ENABLED
3
+ #import <ReactCommon/RCTTurboModuleWithJSIBindings.h>
5
4
  #import <VroomChartSpec/VroomChartSpec.h>
6
- @interface VroomChartModule : NSObject <NativeVroomChartSpec>
7
- #else
8
- @interface VroomChartModule : NSObject <RCTBridgeModule>
9
- #endif
5
+
6
+ @interface VroomChartModule : NSObject <NativeVroomChartSpec, RCTTurboModuleWithJSIBindings>
10
7
 
11
8
  @end
@@ -1,6 +1,5 @@
1
1
  #import "VroomChartModule.h"
2
2
 
3
- #import <React/RCTBridge+Private.h>
4
3
  #import <ReactCommon/CallInvoker.h>
5
4
  #import <jsi/jsi.h>
6
5
 
@@ -8,37 +7,32 @@
8
7
 
9
8
  using namespace facebook;
10
9
 
11
- @implementation VroomChartModule
10
+ @implementation VroomChartModule {
11
+ BOOL _didInstall;
12
+ }
12
13
 
13
14
  RCT_EXPORT_MODULE(VroomChartModule)
14
15
 
15
- // Called from JS via NativeVroomChart.install(). Grabs the JSI runtime from the
16
- // bridge and asks the C++ installer to expose global.VroomChartJSI.
16
+ // RCTTurboModuleManager calls this as soon as it instantiates the module
17
+ // before the module object reaches JS so global.VroomChartJSI always exists
18
+ // by the time anything imports NativeVroomChart.
17
19
  //
18
- // The TurboModule version (new arch) and the legacy version both end up here.
20
+ // callInvoker is unused: every chart call is synchronous on the JS thread.
21
+ - (void)installJSIBindingsWithRuntime:(jsi::Runtime &)runtime
22
+ callInvoker:(const std::shared_ptr<react::CallInvoker> &)callInvoker
23
+ {
24
+ vroom::installJsi(runtime);
25
+ _didInstall = YES;
26
+ }
27
+
19
28
  - (NSNumber *)install
20
29
  {
21
- RCTBridge *bridge = [RCTBridge currentBridge];
22
- RCTCxxBridge *cxxBridge = (RCTCxxBridge *)bridge;
23
- if (cxxBridge == nil) {
24
- return @NO;
25
- }
26
-
27
- jsi::Runtime *runtime = (jsi::Runtime *)cxxBridge.runtime;
28
- if (runtime == nullptr) {
29
- return @NO;
30
- }
31
-
32
- vroom::installJsi(*runtime);
33
- return @YES;
30
+ return @(_didInstall);
34
31
  }
35
32
 
36
- #ifdef RCT_NEW_ARCH_ENABLED
37
- - (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
38
- (const facebook::react::ObjCTurboModule::InitParams &)params
33
+ - (std::shared_ptr<react::TurboModule>)getTurboModule:(const react::ObjCTurboModule::InitParams &)params
39
34
  {
40
- return std::make_shared<facebook::react::NativeVroomChartSpecJSI>(params);
35
+ return std::make_shared<react::NativeVroomChartSpecJSI>(params);
41
36
  }
42
- #endif
43
37
 
44
38
  @end
package/lib/index.js CHANGED
@@ -482,10 +482,11 @@ var EMPTY_FOOTPRINTS = footprintsToSpec({ prints: [] });
482
482
  var installed = false;
483
483
  function ensureInstalled() {
484
484
  if (installed) return;
485
- const ok = NativeVroomChart_default.install();
486
- if (!ok) throw new Error("VroomChartModule.install() returned false");
485
+ NativeVroomChart_default.install();
487
486
  if (typeof globalThis.VroomChartJSI === "undefined") {
488
- throw new Error("global.VroomChartJSI undefined after install()");
487
+ throw new Error(
488
+ "global.VroomChartJSI is undefined \u2014 VroomChartModule did not install its JSI bindings. This requires react-native >= 0.78 with the New Architecture enabled."
489
+ );
489
490
  }
490
491
  installed = true;
491
492
  }