tezvyn:

JSI Host Objects: Exposing C++ to JavaScript

AI-drafted, machine-checkedSource: github.comadvanced

A JSI Host Object is a C++ object exposed directly to your JavaScript runtime, bypassing React Native's slow, serializing bridge. It's used in high-performance native modules like database adapters.

WHY IT EXISTS The original React Native bridge communicated between JavaScript and native code by serializing everything into JSON strings. This process is asynchronous and slow, creating a bottleneck for performance-sensitive tasks. JSI (JavaScript Interface) was created to allow direct, synchronous communication by giving C++ and JavaScript a shared understanding of objects.

THE MENTAL MODEL Think of a Host Object as a C++ object given a special passport to live inside the JavaScript world. It's a proxy or an ambassador. When your JavaScript code calls a method on this object, like myNativeDb.query(), the call is directly and synchronously forwarded to the underlying C++ object's method. There is no serialization, no message passing, and no queue.

HOW IT WORKS To create a Host Object, you define a C++ class that inherits from jsi::HostObject. You must implement its virtual methods, primarily get() and set(). The get(name) method acts as a router: when JS code tries to access a property (e.g., myObject.someValue), this C++ method is invoked with the property name. Your code is then responsible for returning the appropriate jsi::Value, which could be a number, a string, or even a jsi::Function wrapping another C++ method. The C++ object's lifetime is managed manually.

WHEN TO USE IT Use Host Objects when building performance-critical native modules where the latency of the asynchronous bridge is unacceptable. This is common for libraries that require high-throughput, synchronous communication. Prime examples include native database libraries like WatermelonDB or Realm, and sophisticated animation or gesture libraries that need to sync state between JS and native on every frame.

WHEN NOT TO USE IT Avoid Host Objects for simple native modules where the functionality is not performance-critical and can be handled asynchronously. The complexity of writing and maintaining C++, especially with manual memory management, introduces significant risk. If your calls are infrequent and the data is simple, the traditional TurboModule or even the legacy bridge approach is safer and easier.

ONE CANONICAL EXAMPLE A native database library exposes its connection object to JavaScript as a Host Object. In JS, you can write const records = myDbConnection.query('SELECT * FROM users'). This query access triggers the get() method in C++, which identifies the property name "query", retrieves the C++ function for querying, and executes it immediately with the provided arguments, returning the results directly to JavaScript.

Read the original → github.com

Get five bites like this every day.

Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.