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

React Native 0.76 Bridgeless JSI HostObject Lifetime Pinning and Thread-Affinity Standard

Enforces strict lifetime pinning and thread-affinity guarantees for C++ JSI HostObjects operating within React Native 0.76 Bridgeless mode. Eliminates native use-after-free (UAF) memory corruption and GC race conditions caused by cross-thread dereferencing of Hermes/JSI handles without CallInvoker synchronization.

Prohibited Anti-Pattern: Dangling HostObject Pointer Access and Unsynchronized Thread Invocations During Bridgeless GC Sweeps

Export Ready-to-Drop Configuration

Select format below to copy code or download file directly.

---
description: React Native 0.76 Bridgeless JSI HostObject Lifetime Pinning and Thread-Affinity Standard - Enforces strict lifetime pinning and thread-affinity guarantees for C++ JSI HostObjects operating within React Native 0.76 Bridgeless mode. Eliminates native use-after-free (UAF) memory corruption and GC race conditions caused by cross-thread dereferencing of Hermes/JSI handles without CallInvoker synchronization.
globs: src/**/*.{ts,tsx}, specs/**/*.{ts,tsx}, cpp/**/*.{cpp,h,hpp}
alwaysApply: true
verified_by: "agentrules.org"
license: "CC-BY-4.0"
source: "https://agentrules.org/rules/react-native-bridgeless-jsi-hostobject-memory-pinning"
---

# React Native 0.76 Bridgeless JSI HostObject Lifetime Pinning and Thread-Affinity Standard

> **Severity**: CRITICAL | **Category**: mobile
> **Anti-Pattern Warning**: Dangling HostObject Pointer Access and Unsynchronized Thread Invocations During Bridgeless GC Sweeps

## System Constraints
You are a Principal Software Architect enforcing React Native 0.76 Bridgeless JSI HostObject Memory Pinning. You must reject any JSI or TurboModule implementation that permits C++ HostObjects, raw pointers, or JSI values to cross thread boundaries without explicit std::shared_ptr pinning and CallInvoker-based thread hops. Enforce deterministic teardown and strict JS-thread affinity to prevent GC use-after-free crashes.

## Strict Guidelines
- Engineers MUST ALWAYS dispatch all JSI HostObject access and JSI runtime manipulations directly on the JavaScript thread via facebook::react::CallInvoker.
- Engineers MUST NOT capture raw pointers or raw jsi::HostObject references inside asynchronous native worker thread lambdas or non-pinned callbacks.
- C++ implementations MUST inherit from std::enable_shared_from_this to maintain reference counts across asynchronous task boundaries until explicit JS release.
- TypeScript consumers MUST manage HostObject lifecycles using deterministic disposal patterns (e.g., Symbol.dispose or explicit .dispose() wrappers) instead of relying on non-deterministic Hermes GC FinalizationRegistry.
- Native methods invoked from TypeScript across bridgeless boundaries MUST validate HostObject liveliness state flags before dereferencing underlying native memory handles.
- Components NEVER store naked JSI HostObjects inside React state hooks without an associated lifecycle-pinned manager to prevent leaks across unmount cycles.

## Bad vs Good Implementations
### Unsafe Raw Pointer Capture vs Thread-Safe Pinned HostObject Handle Pattern

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: The HostObject handle is stored directly in an unbound JS class without pinning semantics or runtime validation. If the outer context drops reference or re-renders, Hermes sweeps the HostObject proxy while the async task runs, dereferencing freed native memory.
```typescript
import { NativeModules } from 'react-native';

interface NativeBufferHostObject {
  read(): ArrayBuffer;
  release(): void;
}

// ANTI-PATTERN: Direct reliance on implicit GC sweep for native HostObject.
// Under RN 0.76 Bridgeless, background threads mutating the buffer race with
// Hermes GC collection, triggering SIGSEGV (use-after-free).
export class AudioStreamSession {
  private buffer: NativeBufferHostObject | null = null;

  public startSession(): void {
    // Native creates HostObject without pinning shared_ptr
    this.buffer = global.__audioHostObjectFactory();
  }

  public async processChunkAsync(): Promise<ArrayBuffer | null> {
    if (!this.buffer) return null;
    
    // Native worker thread dereferences HostObject while JS GC cleans up buffer wrapper
    return new Promise((resolve) => {
      setTimeout(() => {
        // CRASH: Hermes thread sweeps HostObject while setTimeout callback executes
        resolve(this.buffer ? this.buffer.read() : null);
      }, 100);
    });
  }
}
```

#### Production Standard (Correct)
> **Standard**: Implements deterministic lifetime control with TypeScript Disposable semantics and defensive checks against invalidated C++ HostObjects. Native backing instances synchronize destruction using CallInvoker, preventing Hermes GC from causing use-after-free crashes.
```typescript
interface SafeNativeBufferHostObject {
  read(): ArrayBuffer;
  dispose(): void;
  isDisposed(): boolean;
}

declare const __safeAudioHostObjectFactory: () => SafeNativeBufferHostObject;

// PRODUCTION FIX: Explicit pinned lifecycle, CallInvoker integration, and deterministic disposal
export class AudioStreamSession implements Disposable {
  private buffer: SafeNativeBufferHostObject | null = null;
  private isSessionActive: boolean = false;

  public startSession(): void {
    if (this.buffer && !this.buffer.isDisposed()) {
      this.buffer.dispose();
    }
    // Returns a HostObject pinned by std::shared_ptr and bound to JS CallInvoker
    this.buffer = __safeAudioHostObjectFactory();
    this.isSessionActive = true;
  }

  public async processChunkAsync(): Promise<ArrayBuffer | null> {
    if (!this.isSessionActive || !this.buffer || this.buffer.isDisposed()) {
      throw new Error('[JSI:HostObject] Attempted access to unpinned or released native resource');
    }

    const pinnedBuffer = this.buffer;
    return new Promise<ArrayBuffer>((resolve, reject) => {
      try {
        if (pinnedBuffer.isDisposed()) {
          throw new Error('[JSI:HostObject] HostObject invalidated prior to invocation');
        }
        const data = pinnedBuffer.read();
        resolve(data);
      } catch (err) {
        reject(err);
      }
    });
  }

  public [Symbol.dispose](): void {
    this.dispose();
  }

  public dispose(): void {
    this.isSessionActive = false;
    if (this.buffer && !this.buffer.isDisposed()) {
      // Explicitly triggers native shared_ptr release and unregisters from JS CallInvoker
      this.buffer.dispose();
      this.buffer = null;
    }
  }
}
```

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 0.76 Bridgeless JSI HostObject Lifetime Pinning and Thread-Affinity Standard

React Native 0.76 Bridgeless JSI HostObject Lifetime Pinning and Thread-Affinity Standard defines an industrial-grade behavioral standard for mobile engineering. Enforces strict lifetime pinning and thread-affinity guarantees for C++ JSI HostObjects operating within React Native 0.76 Bridgeless mode. Eliminates native use-after-free (UAF) memory corruption and GC race conditions caused by cross-thread dereferencing of Hermes/JSI handles without CallInvoker synchronization. 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: Dangling HostObject Pointer Access and Unsynchronized Thread Invocations During Bridgeless GC Sweeps 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 DriftDangling HostObject Pointer Access and Unsynchronized Thread Invocations During Bridgeless GC SweepsCritical
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 dispatch all JSI HostObject access and JSI runtime manipulations directly on the JavaScript thread via facebook

Engineers MUST ALWAYS dispatch all JSI HostObject access and JSI runtime manipulations directly on the JavaScript thread via facebook::react::CallInvoker.

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 pointers or raw jsi

Engineers MUST NOT capture raw pointers or raw jsi::HostObject references inside asynchronous native worker thread lambdas or non-pinned callbacks.

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

C++ implementations MUST inherit from std

C++ implementations MUST inherit from std::enable_shared_from_this to maintain reference counts across asynchronous task boundaries until explicit JS release.

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

TypeScript consumers MUST manage HostObject lifecycles using deterministic disposal patterns (e.g., Symbol.dispose or explicit .dispose() wrappers) instead of relying on non-deterministic Hermes GC FinalizationRegistry.

TypeScript consumers MUST manage HostObject lifecycles using deterministic disposal patterns (e.g., Symbol.dispose or explicit .dispose() wrappers) instead of relying on non-deterministic Hermes GC FinalizationRegistry.

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

Native methods invoked from TypeScript across bridgeless boundaries MUST validate HostObject liveliness state flags before dereferencing underlying native memory handles.

Native methods invoked from TypeScript across bridgeless boundaries MUST validate HostObject liveliness state flags before dereferencing underlying native memory handles.

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.
6

Components NEVER store naked JSI HostObjects inside React state hooks without an associated lifecycle-pinned manager to prevent leaks across unmount cycles.

Components NEVER store naked JSI HostObjects inside React state hooks without an associated lifecycle-pinned manager to prevent leaks across unmount cycles.

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 0.76 Bridgeless JSI HostObject Lifetime Pinning and Thread-Affinity Standard critical for AI coding assistants?

Enforces strict lifetime pinning and thread-affinity guarantees for C++ JSI HostObjects operating within React Native 0.76 Bridgeless mode. Eliminates native use-after-free (UAF) memory corruption and GC race conditions caused by cross-thread dereferencing of Hermes/JSI handles without CallInvoker synchronization. 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 (Dangling HostObject Pointer Access and Unsynchronized Thread Invocations During Bridgeless GC Sweeps) 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