Skip to main content
JSI (JavaScript Interface) is the foundational abstraction layer that enables React Native’s new architecture. It provides a C++ interface for JavaScript engines, allowing direct, synchronous communication between JavaScript and native code without the overhead of bridge serialization.

What is JSI?

JSI is defined in ReactCommon/jsi/jsi/jsi.h and provides:
  • Engine abstraction - Write code that works with any JavaScript engine
  • Direct interop - JavaScript can call C++ directly and vice versa
  • Type safety - Strongly typed C++ representations of JavaScript values
  • Memory efficiency - Zero-copy access to data where possible
  • Synchronous execution - No async overhead for simple operations

Core Philosophy

JSI separates the “what” from the “how”:
  • What: Interface for interacting with JavaScript values and executing code
  • How: Each engine (Hermes, V8, JavaScriptCore) provides its own implementation
This enables React Native to:
  • Switch JavaScript engines without changing application code
  • Optimize for different platforms (Hermes for mobile, V8 for desktop)
  • Support new engines as they emerge

Architecture

Runtime Interface

The jsi::Runtime is the central interface to a JavaScript execution environment:
Key principles:
  • Abstract interface - No engine-specific code
  • Pure virtual - Each engine provides concrete implementation
  • Exception safe - Throws jsi::JSError for JavaScript errors

Value Types

JSI provides C++ classes representing JavaScript values:

Primitive Values

JSI values use move semantics (not copyable) to ensure thread safety and prevent accidental duplication.

String

Strings are:
  • Immutable - Cannot be modified after creation
  • Reference-counted - Managed by the JavaScript engine
  • Efficient - May share storage with JavaScript strings

Object

Array

Function

Host Objects

Host objects are C++ objects exposed to JavaScript:
Creating a host object:
Now in JavaScript:
Host objects power:
  • TurboModules - Native modules as host objects
  • Native state - Attach C++ state to JavaScript objects
  • Custom APIs - Expose any C++ functionality to JavaScript

Native State

Attach C++ objects to JavaScript objects as hidden state:
Use cases:
  • Shadow nodes - Attach C++ shadow nodes to JavaScript fiber nodes
  • Resource handles - Store native resource handles (file descriptors, etc.)
  • Cache data - Avoid repeated serialization/deserialization

Threading and Safety

Thread Affinity

JSI values are NOT thread-safe. Each value must only be used on the thread that created it (the JavaScript thread).
Rules:
  • jsi::Value, jsi::Object, etc. cannot be copied, only moved
  • Do not store JSI values in data structures accessed from multiple threads
  • Use RuntimeExecutor to schedule work on the JavaScript thread

RuntimeExecutor

Safely access the runtime from any thread:

Thread-Safe Patterns

Sharing Data to JavaScript

Sharing Data from JavaScript

JSI Decorators

Decorators wrap a runtime to add functionality. Defined in jsi/decorator.h:
Use cases:
  • Profiling - Time function calls, memory allocations
  • Debugging - Log all JavaScript operations
  • Security - Restrict access to certain APIs
  • Testing - Mock or stub JavaScript behavior

Instrumentation

JSI provides instrumentation hooks defined in jsi/instrumentation.h:
Enables:
  • Memory profiling - Track object allocations
  • Performance monitoring - Measure function call overhead
  • Leak detection - Find objects not being released
  • React DevTools - Power debugging features

Error Handling

JSError

JavaScript errors are represented as jsi::JSError:

Throwing Errors to JavaScript

In JavaScript:

Memory Management

Automatic Memory Management

JSI objects are automatically managed:
  • JavaScript engine handles garbage collection
  • C++ smart pointers manage native objects
  • No manual reference counting needed

Move Semantics

JSI values use move semantics for safety:
Benefits:
  • Thread safety - Cannot accidentally share across threads
  • Clear ownership - Ownership transfer is explicit
  • Performance - No unnecessary copies

Weak References

Prevent reference cycles:

Integration with JavaScript Engines

Hermes

Facebook’s JavaScript engine optimized for React Native:
Hermes features:
  • Bytecode compilation - Precompile JavaScript to bytecode
  • Efficient memory - Optimized for mobile devices
  • Fast startup - Faster than JavaScriptCore on mobile

JavaScriptCore

Apple’s JavaScript engine:
Used on iOS when Hermes is not enabled.

V8

Google’s JavaScript engine:
Optional, used in some React Native platforms.

Practical Examples

Calling JavaScript from C++

Calling C++ from JavaScript

JavaScript:

Returning Promises

JavaScript:

Working with Arrays

Working with Objects

Performance Considerations

Minimize String Conversions

Cache Property Names

Batch Operations

Debugging JSI

Logging

LLDB/GDB Debugging

Set breakpoints in native code:

Xcode Instruments

  • Time Profiler - Find slow JSI operations
  • Allocations - Track JSI object creation
  • Leaks - Find unreleased JSI objects

Further Reading

TurboModules

See JSI in action with TurboModules

Fabric Renderer

How Fabric uses JSI for rendering

Architecture Overview

JSI’s role in React Native architecture

Threading Model

Thread safety with JSI