Dans une vraie app
Dans la pratique, un dev d’app n’écrit presque jamais de JSI à la main : il le consomme via les Turbo Modules, l’Expo Modules API ou Nitro. Le concept compte quand même pour lire un crash. Une stack trace qui passe par jsi::Runtime, HostObject ou facebook::jsi::Function indique que le problème est dans la couche d’appel natif, pas dans votre JavaScript. Et un appel JSI synchrone bloque le thread JS tant qu’il n’a pas rendu la main : une méthode native lente appelée dans un onScroll se voit immédiatement.
Le piège classique vient du threading. Un objet JSI appartient au runtime qui l’a créé ; y toucher depuis un autre thread (une callback réseau, un gestionnaire natif) corrompt la mémoire ou crashe sans message utile. Les librairies sérieuses passent par CallInvoker pour revenir sur le thread JS. Autre cas : les workers de Reanimated ont leur propre runtime JSI, d’où l’impossibilité d’appeler une fonction du thread JS depuis un worklet sans scheduleOnRN (runOnJS avant Reanimated 4).
Ce que je regarde : le moteur réellement utilisé (global.HermesInternal), les librairies qui déclarent du C++ dans leur podspec ou CMakeLists.txt, et si le projet mélange des modules bridge en interop et des modules JSI qui touchent les mêmes ressources natives.
Termes liés
New Architecture
La réécriture du cœur de React Native (Fabric, Turbo Modules, JSI), activée par défaut depuis la 0.76 et seule architecture depuis la 0.82.
Turbo Modules
Les modules natifs de la New Architecture : une spec TypeScript, du code généré par Codegen, et un chargement à la demande via JSI.
Fabric
Le renderer de la New Architecture : un cœur C++ partagé entre iOS et Android qui calcule le layout de façon synchrone.
Hermes
Le moteur JavaScript de Meta pour React Native, par défaut depuis la 0.70, qui précompile le bundle en bytecode au build.
Nitro Modules
Le framework de Margelo pour écrire des modules natifs en Swift, Kotlin ou C++ exposés à JavaScript via JSI, avec des bindings générés depuis TypeScript.