This specification is maintained by the AgentRules Working Group. Have enhancements or want to claim maintainership?Submit Specification →
mobilecritical PriorityID: react-native-nitro-hybridobject-lifetime-isolation

React Native Nitro Modules C++ HybridObject Lifetime & RAII Isolation

Mandates deterministic C++ smart pointer ownership boundaries and RAII encapsulation for Nitro Modules HybridObjects bridging Hermes and platform native runtimes. Prevents phantom off-heap leaks and cyclic strong references between JSI garbage-collected wrappers and native asynchronous dispatch queues.

Prohibited Anti-Pattern: Retaining Strong Shared Pointers or Unwrapped Native Resources Across the Nitro JSI Boundary Causing GC-Invisible Memory Leaks

Export Ready-to-Drop Configuration

Select format below to copy code or download file directly.

---
description: React Native Nitro Modules C++ HybridObject Lifetime & RAII Isolation - Mandates deterministic C++ smart pointer ownership boundaries and RAII encapsulation for Nitro Modules HybridObjects bridging Hermes and platform native runtimes. Prevents phantom off-heap leaks and cyclic strong references between JSI garbage-collected wrappers and native asynchronous dispatch queues.
globs: cpp/**/*.{h,hpp,cpp}, src/**/*.{ts,tsx}, android/src/main/cpp/**/*.{h,hpp,cpp}, ios/**/*.{h,hpp,m,mm,cpp}
alwaysApply: true
verified_by: "agentrules.org"
license: "CC-BY-4.0"
source: "https://agentrules.org/rules/react-native-nitro-hybridobject-lifetime-isolation"
---

# React Native Nitro Modules C++ HybridObject Lifetime & RAII Isolation

> **Severity**: CRITICAL | **Category**: mobile
> **Anti-Pattern Warning**: Retaining Strong Shared Pointers or Unwrapped Native Resources Across the Nitro JSI Boundary Causing GC-Invisible Memory Leaks

## System Constraints
You are a Principal Software Architect enforcing strict RAII and deterministic smart pointer isolation for React Native Nitro Modules C++ HybridObjects. You must prevent off-heap native memory starvation, JSI cyclic retention graphs, and use-after-free bugs caused by asynchronous execution across the Hermes GC boundary.

## Strict Guidelines
- Engineers MUST ALWAYS capture a `std::weak_ptr<T>` (via `weak_from_this()`) inside asynchronous platform callbacks, thread pool dispatches, and event listeners rather than a strong `std::shared_ptr` or raw `this` pointer.
- Engineers MUST NOT store direct `jsi::Value`, `jsi::Object`, or `jsi::Function` instances inside long-lived C++ HybridObject member fields; asynchronous callbacks must be mediated via Nitro's generated typed callbacks or `std::shared_ptr<Promise<T>>` with deterministic resolution.
- Engineers MUST wrap all unmanaged platform handles (e.g., `ANativeWindow*`, `CVImageBufferRef`, `MTLTexture`, file descriptors) inside RAII wrappers with custom deleters (`std::unique_ptr<T, Deleter>`) immediately upon acquisition.
- Code SHOULD implement an explicit native `dispose()` or `close()` method on any `HybridObject` that controls high-watermark off-heap buffers (>1MB, hardware decoders, camera streams) to invalidate resources deterministically before Hermes non-deterministic GC collection.
- Components NEVER assume Hermes GC accounts for C++ off-heap allocations; high-frequency native allocations MUST notify the runtime memory pressure monitor or pre-allocate fixed memory pools.

## Bad vs Good Implementations
### C++ HybridObject Asynchronous Callback Lifetime Guardrail

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: Capturing `this` by raw pointer or strong shared_ptr in native driver/hardware callbacks binds the C++ object lifetime to the hardware driver queue. If the JS side releases the HybridObject reference, Hermes cannot free it, and if the driver outlives the module, it triggers use-after-free or permanently leaks off-heap hardware allocations.
```cpp
#include "HybridCameraSession.hpp"

namespace margelo::nitro::camera {

void HybridCameraSession::startFrameProcessing(std::function<void(const Frame&)> onFrame) {
  // ANTI-PATTERN: Capturing strong 'this' or shared_from_this() into native dispatch queue
  // creates a cycle: JS Object -> JSI HostObject -> HybridCameraSession -> Queue -> HybridCameraSession
  // Hermes GC cannot detect native capture graph, causing an infinite phantom leak.
  _cameraPipeline->setFrameListener([this, onFrame](const NativeFrame& rawFrame) {
    Frame nitroFrame = this->convertFrame(rawFrame);
    onFrame(nitroFrame);
  });
}

} // namespace margelo::nitro::camera
```

#### Production Standard (Correct)
> **Standard**: Capturing `std::weak_ptr` breaks the retain cycle between the native platform frame emitter and the C++ HybridObject. Checking `weakSelf.lock()` deterministically ensures frame processing aborts immediately when Hermes collects the JS handle or when `dispose()` is executed.
```cpp
#include "HybridCameraSession.hpp"

namespace margelo::nitro::camera {

void HybridCameraSession::startFrameProcessing(std::function<void(const Frame&)> onFrame) {
  // Invariant: Capture weak reference to break reference cycle with native runtime
  std::weak_ptr<HybridCameraSession> weakSelf = weak_from_this();

  _cameraPipeline->setFrameListener([weakSelf, onFrame = std::move(onFrame)](const NativeFrame& rawFrame) {
    auto self = weakSelf.lock();
    if (!self || self->_isDisposed.load(std::memory_order_acquire)) {
      return; // Target instance was garbage collected by Hermes or explicitly disposed
    }
    Frame nitroFrame = self->convertFrame(rawFrame);
    onFrame(nitroFrame);
  });
}

void HybridCameraSession::dispose() noexcept {
  _isDisposed.store(true, std::memory_order_release);
  _cameraPipeline->setFrameListener(nullptr);
  _cameraPipeline->stop();
}

} // namespace margelo::nitro::camera
```

Architectural Specification & Invariant Rationale

Architectural Invariant Design: React Native Nitro Modules C++ HybridObject Lifetime & RAII Isolation

React Native Nitro Modules C++ HybridObject Lifetime & RAII Isolation defines an industrial-grade behavioral standard for mobile engineering. Mandates deterministic C++ smart pointer ownership boundaries and RAII encapsulation for Nitro Modules HybridObjects bridging Hermes and platform native runtimes. Prevents phantom off-heap leaks and cyclic strong references between JSI garbage-collected wrappers and native asynchronous dispatch queues. 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: Retaining Strong Shared Pointers or Unwrapped Native Resources Across the Nitro JSI Boundary Causing GC-Invisible Memory Leaks 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 DriftRetaining Strong Shared Pointers or Unwrapped Native Resources Across the Nitro JSI Boundary Causing GC-Invisible Memory LeaksCritical
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 capture a `std

Engineers MUST ALWAYS capture a `std::weak_ptr<T>` (via `weak_from_this()`) inside asynchronous platform callbacks, thread pool dispatches, and event listeners rather than a strong `std::shared_ptr` or raw `this` pointer.

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 store direct `jsi

Engineers MUST NOT store direct `jsi::Value`, `jsi::Object`, or `jsi::Function` instances inside long-lived C++ HybridObject member fields; asynchronous callbacks must be mediated via Nitro's generated typed callbacks or `std::shared_ptr<Promise<T>>` with deterministic resolution.

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 wrap all unmanaged platform handles (e.g., `ANativeWindow*`, `CVImageBufferRef`, `MTLTexture`, file descriptors) inside RAII wrappers with custom deleters (`std

Engineers MUST wrap all unmanaged platform handles (e.g., `ANativeWindow*`, `CVImageBufferRef`, `MTLTexture`, file descriptors) inside RAII wrappers with custom deleters (`std::unique_ptr<T, Deleter>`) immediately upon acquisition.

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 implement an explicit native `dispose()` or `close()` method on any `HybridObject` that controls high-watermark off-heap buffers (>1MB, hardware decoders, camera streams) to invalidate resources deterministically before Hermes non-deterministic GC collection.

Code SHOULD implement an explicit native `dispose()` or `close()` method on any `HybridObject` that controls high-watermark off-heap buffers (>1MB, hardware decoders, camera streams) to invalidate resources deterministically before Hermes non-deterministic GC collection.

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 assume Hermes GC accounts for C++ off-heap allocations

Components NEVER assume Hermes GC accounts for C++ off-heap allocations; high-frequency native allocations MUST notify the runtime memory pressure monitor or pre-allocate fixed memory 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.
Technical Questions & Answers

Frequently Asked Technical Questions

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

Q:Why is React Native Nitro Modules C++ HybridObject Lifetime & RAII Isolation critical for AI coding assistants?

Mandates deterministic C++ smart pointer ownership boundaries and RAII encapsulation for Nitro Modules HybridObjects bridging Hermes and platform native runtimes. Prevents phantom off-heap leaks and cyclic strong references between JSI garbage-collected wrappers and native asynchronous dispatch queues. 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 (Retaining Strong Shared Pointers or Unwrapped Native Resources Across the Nitro JSI Boundary Causing GC-Invisible Memory Leaks) 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