Skip to content

JSI Modules

s edited this page Aug 1, 2026 · 5 revisions

JSI Modules

The JSI Module backend generates a synchronous C++ interface using React Native's JavaScript Interface (JSI). It is a supported generator backend; generation, Android compilation, and execution by the target PluginHost remain separate gates.

Use JSI only when

  • JavaScript truly needs the result synchronously;
  • every export is short, deterministic, and safe on the JavaScript thread;
  • the exact PluginHost and React Native/JSI libraries are compatible;
  • the linker namespace and enforcing SELinux policy permit the extracted .so to execute.

Do not use JSI for file or network I/O, waits, locks, compression, long parsing, or unpredictable computation. Use JNI for C/C++ work that can be asynchronous.

Generate a module

supernote-module doctor --type jsi
supernote-module add local-math-jsi --type jsi --yes

The derived JavaScript name is MathJsi and the Android namespace is com.example.math_jsi.

Write and call the export

Edit:

local_modules/local-math-jsi/android/src/main/cpp/math.cpp
// @SupernoteExport
double add(double left, double right) {
  return left + right;
}

Call it synchronously—do not use await:

import MathJsi from 'local-math-jsi';

const total = MathJsi.add(20, 22);

Errors are synchronous too. The same C/C++ signature and ownership rules as JNI apply.

Three support gates

  1. Generation: this tool creates HostFunctions, declarations, a loader, build wiring, and autolinking.
  2. Compilation: the parent project must resolve compatible React Native/JSI headers and build the module .so.
  3. Execution: PluginHost must expose compatible libraries, load the child library, install the runtime functions, and receive SELinux permission to execute it from the extracted plugin location.

This repository implements and tests the first gate. Its CI does not prove the second or third.

Project-maintainer device testing on 2026-07-30 found that the generated loading pattern executed on a userdebug/permissive configuration, while an enforcing retail configuration denied execution of the extracted .so with dlopen ... Permission denied and an SELinux { execute } denial. Permissive success is not retail support.

This matches the current official Plugin Principles, which describe Java/TurboModule access followed by Java-to-C/C++ and do not promise direct JS/TS-to-C/C++ calls.

Regenerate and validate

supernote-module validate local-math-jsi --build --verbose

A successful generated-module build still does not prove that PluginHost can execute the library. In the existing plugin's normal logs, filter for the generated SupernoteJsiMathJsi tag and ReactNativeJS.

If logs show Permission denied or avc: denied { execute }, use Native/JNI or obtain firmware/PluginHost support for an executable library location. The generator cannot modify SELinux policy. See Compatibility and Troubleshooting.

Clone this wiki locally