This specification is maintained by the AgentRules Working Group. Have enhancements or want to claim maintainership?Submit Specification →
mobilecritical PriorityID: react-native-bridgeless-jsi-direct-memory-invariants

React Native Bridgeless TurboModule JSI Direct-Memory Thread-Affinity Guardrail

Enforces strict C++ thread-affinity barriers and synchronous lifecycle guarantees for direct-memory JSI operations in React Native Bridgeless mode. Prohibits capturing raw jsi::ArrayBuffer pointers or unpinned heap references across worker threads without deterministic deep copying or runtime marshaling. Prevents fatal Hermes/V8 engine panics, heap corruption, and use-after-free vulnerabilities caused by asynchronous garbage collection during concurrent native access.

Prohibited Anti-Pattern: Escaping raw jsi::ArrayBuffer memory pointers to asynchronous worker threads without JS thread pinning

Export Ready-to-Drop Configuration

Select format below to copy code or download file directly.

---
description: React Native Bridgeless TurboModule JSI Direct-Memory Thread-Affinity Guardrail - Enforces strict C++ thread-affinity barriers and synchronous lifecycle guarantees for direct-memory JSI operations in React Native Bridgeless mode. Prohibits capturing raw jsi::ArrayBuffer pointers or unpinned heap references across worker threads without deterministic deep copying or runtime marshaling. Prevents fatal Hermes/V8 engine panics, heap corruption, and use-after-free vulnerabilities caused by asynchronous garbage collection during concurrent native access.
globs: ios/**/*.{h,mm,cpp}, android/src/main/jni/**/*.{h,cpp}, cpp/**/*.{h,cpp}, src/**/*.{ts,tsx}
alwaysApply: true
verified_by: "agentrules.org"
license: "CC-BY-4.0"
source: "https://agentrules.org/rules/react-native-bridgeless-jsi-direct-memory-invariants"
---

# React Native Bridgeless TurboModule JSI Direct-Memory Thread-Affinity Guardrail

> **Severity**: CRITICAL | **Category**: mobile
> **Anti-Pattern Warning**: Escaping raw jsi::ArrayBuffer memory pointers to asynchronous worker threads without JS thread pinning

## System Constraints
You are a Principal Software Architect enforcing React Native Bridgeless TurboModule JSI Direct-Memory Invariants. You must prevent memory corruption, concurrent mutation crashes, and use-after-free (UAF) bugs arising from naked JSI pointer escapes and cross-thread access. Never allow direct memory buffers (jsi::ArrayBuffer) or jsi::Value instances to be passed into background threads, libuv workers, GCD queues, or std::thread without deep copying on the JS thread. Mandate that all return paths to JavaScript execute exclusively on the JS thread via react::CallInvoker.

## Strict Guidelines
- Engineers MUST ALWAYS deep-copy raw buffer bytes (via jsi::ArrayBuffer::data()) synchronously on the active JSI thread before dispatching execution to background queues or thread pools.
- Engineers MUST NOT capture raw jsi::Runtime&, jsi::Value, jsi::Object, or bare memory pointers inside asynchronous C++ lambdas, std::async, or dispatch_async blocks.
- Engineers MUST marshal any native-to-JS callbacks or ArrayBuffer handoffs strictly through react::CallInvoker::invokeAsync or react::CallInvoker::invokeSync to preserve thread affinity.
- Code SHOULD validate the boundary size (buffer.size(runtime)) before memory operations to prevent out-of-bounds reads during synchronous direct-memory interactions.
- Components NEVER hold long-lived raw pointers to WebAssembly memory or TypedArray allocations across tick cycles without explicit pinning or native ownership transfer semantics.

## Bad vs Good Implementations
### C++ TurboModule Direct ArrayBuffer Memory Processing

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: The raw memory pointer obtained from `arrayBuffer.data(rt)` is valid only during the synchronous lifetime of the JSI function call on the JS thread. Passing it into a background queue causes a race condition: Hermes garbage collection can invalidate or reclaim the memory while the background thread executes, causing undefined behavior, memory corruption, and native SIGSEGV crashes.
```cpp
// CRITICAL FLAW: Escaping raw JSI buffer pointer to background GCD queue
jni::local_ref<jhybridobject> NativeImageProcessor::processFrame(
    facebook::jsi::Runtime &rt,
    const facebook::jsi::Object &bufferObj) {
  auto arrayBuffer = bufferObj.getArrayBuffer(rt);
  uint8_t* rawData = arrayBuffer.data(rt); // Pointer bound to Hermes GC lifecycle
  size_t length = arrayBuffer.size(rt);

  // UAF: Hermes GC can collect or relocate arrayBuffer on the JS thread
  // while the background queue reads or writes to rawData!
  dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    processRawBytesUnsafe(rawData, length);
  });
  return nullptr;
}
```

#### Production Standard (Correct)
> **Standard**: Data is deep-copied into a `std::vector<uint8_t>` while on the JS thread within the synchronous call boundary. The background task owns the copied vector, preventing data races with Hermes GC. The result is safely marshaled back onto the JS thread using `react::CallInvoker::invokeAsync`, satisfying JSI's single-threaded runtime constraint.
```cpp
// PRODUCTION STANDARD: Synchronous heap copy on JS thread + CallInvoker marshaling
void NativeImageProcessor::processFrame(
    facebook::jsi::Runtime &rt,
    const facebook::jsi::Object &bufferObj,
    const facebook::jsi::Function &callback) {
  auto arrayBuffer = bufferObj.getArrayBuffer(rt);
  size_t length = arrayBuffer.size(rt);
  
  // 1. Thread Barrier: Synchronously clone direct memory while pinned on JS thread
  std::vector<uint8_t> threadSafePayload(arrayBuffer.data(rt), arrayBuffer.data(rt) + length);
  auto sharedCallback = std::make_shared<facebook::jsi::Function>(callback.asFunction(rt));
  auto jsInvoker = this->jsInvoker_; // std::shared_ptr<facebook::react::CallInvoker>

  // 2. Offload processing to background queue with safe, owned memory
  dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), [threadSafePayload = std::move(threadSafePayload), sharedCallback, jsInvoker]() mutable {
    auto resultPayload = processRawBytesSafe(threadSafePayload);

    // 3. Return execution to the JS thread via CallInvoker
    jsInvoker->invokeAsync([sharedCallback, resultPayload = std::move(resultPayload)](facebook::jsi::Runtime &runtime) {
      auto outBuffer = runtime.global()
          .getPropertyAsFunction(runtime, "ArrayBuffer")
          .callAsConstructor(runtime, static_cast<double>(resultPayload.size()))
          .getObject(runtime)
          .getArrayBuffer(runtime);
      
      std::memcpy(outBuffer.data(runtime), resultPayload.data(), resultPayload.size());
      sharedCallback->call(runtime, outBuffer);
    });
  });
}
```

Recommended MCP Servers (mcp-serverlist.com)

Equip agent with system tools to verify code for this stack.

Architectural Specification & Invariant Rationale

Architectural Invariant Design: React Native Bridgeless TurboModule JSI Direct-Memory Thread-Affinity Guardrail

React Native Bridgeless TurboModule JSI Direct-Memory Thread-Affinity Guardrail defines an industrial-grade behavioral standard for mobile engineering. Enforces strict C++ thread-affinity barriers and synchronous lifecycle guarantees for direct-memory JSI operations in React Native Bridgeless mode. Prohibits capturing raw jsi::ArrayBuffer pointers or unpinned heap references across worker threads without deterministic deep copying or runtime marshaling. Prevents fatal Hermes/V8 engine panics, heap corruption, and use-after-free vulnerabilities caused by asynchronous garbage collection during concurrent native access. Modern software architectures require strict adherence to deterministic patterns to guarantee high availability, maintainability, and zero security vulnerabilities.

Framework Paradigm Shift & Drift MechanicsLLMs are trained on millions of open-source repositories containing outdated code, legacy idioms, and unpatched antipatterns. When coding assistants generate implementations for this stack, they default to common statistical tokens: Escaping raw jsi::ArrayBuffer memory pointers to asynchronous worker threads without JS thread pinning Without an explicit system instruction file, developers spend hours debugging silent failures.
Failure Modes & Production Blast Radius

Hazard Analysis: What Breaks Without This Rule

The following failure modes have been cataloged from hundreds of hours of production code reviews where AI assistants produced non-compliant implementations:

Failure ModeAI Symptom (The Anti-Pattern)SeverityProduction Impact & Remedy
AI Hallucination & Deprecation DriftEscaping raw jsi::ArrayBuffer memory pointers to asynchronous worker threads without JS thread pinningCritical
Violating this industrial standard introduces regression bugs, security risks, and unexpected runtime failures in production.
Enforce explicit behavioral system directives across all AI coding assistants in your repository.
Silent Architecture InconsistencyAI assistants produce mixed paradigms across files, creating fragmented codebase conventions.Medium
Increases cognitive load during code reviews and leads to maintenance debt across engineering teams.
Pin project conventions in .cursor/rules, CLAUDE.md, and AGENTS.md so all team agents follow identical guardrails.
Architectural Directives in Detail

Step-by-Step Production Directives

Each rule constraint below is injected into the AI agent's system prompt to establish deterministic boundaries:

1

Engineers MUST ALWAYS deep-copy raw buffer bytes (via jsi

Engineers MUST ALWAYS deep-copy raw buffer bytes (via jsi::ArrayBuffer::data()) synchronously on the active JSI thread before dispatching execution to background queues or thread pools.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
2

Engineers MUST NOT capture raw jsi

Engineers MUST NOT capture raw jsi::Runtime&, jsi::Value, jsi::Object, or bare memory pointers inside asynchronous C++ lambdas, std::async, or dispatch_async blocks.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
3

Engineers MUST marshal any native-to-JS callbacks or ArrayBuffer handoffs strictly through react

Engineers MUST marshal any native-to-JS callbacks or ArrayBuffer handoffs strictly through react::CallInvoker::invokeAsync or react::CallInvoker::invokeSync to preserve thread affinity.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
4

Code SHOULD validate the boundary size (buffer.size(runtime)) before memory operations to prevent out-of-bounds reads during synchronous direct-memory interactions.

Code SHOULD validate the boundary size (buffer.size(runtime)) before memory operations to prevent out-of-bounds reads during synchronous direct-memory interactions.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
5

Components NEVER hold long-lived raw pointers to WebAssembly memory or TypedArray allocations across tick cycles without explicit pinning or native ownership transfer semantics.

Components NEVER hold long-lived raw pointers to WebAssembly memory or TypedArray allocations across tick cycles without explicit pinning or native ownership transfer semantics.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
Technical Questions & Answers

Frequently Asked Technical Questions

Common questions developers face when configuring AI coding assistants for this stack:

Q:Why is React Native Bridgeless TurboModule JSI Direct-Memory Thread-Affinity Guardrail critical for AI coding assistants?

Enforces strict C++ thread-affinity barriers and synchronous lifecycle guarantees for direct-memory JSI operations in React Native Bridgeless mode. Prohibits capturing raw jsi::ArrayBuffer pointers or unpinned heap references across worker threads without deterministic deep copying or runtime marshaling. Prevents fatal Hermes/V8 engine panics, heap corruption, and use-after-free vulnerabilities caused by asynchronous garbage collection during concurrent native access. Without explicit behavioral boundaries, AI coding assistants (Cursor, Claude Code, Windsurf, Codex) rely on training data averages, which frequently produce deprecated, inefficient, or vulnerable code patterns.

Q:How does adopting this rule prevent AI hallucinations?

This rule explicitly declares what the AI must avoid (Escaping raw jsi::ArrayBuffer memory pointers to asynchronous worker threads without JS thread pinning) and prescribes verified positive examples. Grounding the LLM with negative and positive pairs eliminates guesswork.

Q:Which AI coding environments are supported?

This specification is multi-platform compatible: Cursor (.cursor/rules/*.mdc & .cursorrules), Anthropic Claude Code (CLAUDE.md), Windsurf (.windsurfrules), Codex / Cline (AGENTS.md), and GitHub Copilot (.github/copilot-instructions.md).

Q:Can I combine this rule with other technology stacks?

Yes. Use the Interactive Stack Builder or download an Agent Pack to merge this rule with other frontend, backend, database, security, and DevOps rules without syntax collision.

Open Specification · CC BY 4.0·Free for Personal, Team & Commercial In-Repo Use

Citation & Open Source Attribution Guidelines

This specification is licensed under Creative Commons Attribution 4.0 International (CC BY 4.0). You are completely free to adapt and share this rule in your workspace. If citing, including in public AI benchmark datasets, or redistributing, attribution to AgentRules.org is required.

Related MOBILE Rules

View all rules →
1 Rule in Stack

React