{"owner":"facebook","repo":"hermes","hasSkills":true,"hasMcp":false,"mcpConfig":null,"found":["CLAUDE.md"],"skills":{"CLAUDE.md":"# CLAUDE.md\n\nThis file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.\n\n## CRITICAL: Never Change the Working Directory\n\n**NEVER use `cd` to change the current directory from the project root.** Almost all operations can be performed by passing the correct path to commands and tools. Changing directories causes confusion and errors in subsequent operations.\n\nIn the rare cases where changing directory is absolutely unavoidable, use a subshell so the directory change does not persist:\n```bash\n(cd other-dir; command;)\n```\n\n## Overview\n\nHermes is a JavaScript engine optimized for fast start-up of React Native apps. It features ahead-of-time static optimization and compact bytecode.\n\n## Build Commands\n\n### Default Build: ASan+Debug with -O1\n\nAlways build and test with AddressSanitizer enabled unless the user explicitly asks otherwise or there is a specific reason not to (e.g., performance benchmarking, testing release behavior). The ASan build catches memory bugs that are otherwise silent or non-deterministic.\n\n```bash\n# Configure ASan+Debug build (the default for development)\ncmake -B cmake-build-asan -G Ninja -DCMAKE_BUILD_TYPE=Debug \\\n  -DHERMES_ENABLE_ADDRESS_SANITIZER=ON \\\n  -DCMAKE_CXX_FLAGS=\"-O1\" -DCMAKE_C_FLAGS=\"-O1\"\n```\n\n### Other Build Configurations\n\n```bash\n# Plain Debug build (no sanitizer, for debugging with full symbols)\ncmake -B cmake-build-debug -G Ninja -DCMAKE_BUILD_TYPE=Debug\n\n# Release build\ncmake -B cmake-build-release -G Ninja -DCMAKE_BUILD_TYPE=Release\n```\n\n#### Common CMake Options\n\nPass these with `-D` when configuring, e.g., `cmake -B build -DCMAKE_BUILD_TYPE=Debug -DHERMES_ENABLE_DEBUGGER=ON`\n\n**Build Type & Core Options:**\n- `CMAKE_BUILD_TYPE` - Debug or Release (required)\n- `HERMES_ENABLE_DEBUGGER` - Build with debugger support (default: OFF)\n- `HERMES_FACEBOOK_BUILD` - Build Facebook internal version (default: OFF)\n- `HERMES_ENABLE_CONTRIB_EXTENSIONS` - Include community-contributed extensions (default: ON)\n- `HERMES_ENABLE_WERROR` - Treat warnings as errors (default: OFF)\n\n**Sanitizers:**\n- `HERMES_ENABLE_ADDRESS_SANITIZER` - Enable ASan (default: OFF)\n- `HERMES_ENABLE_UNDEFINED_BEHAVIOR_SANITIZER` - Enable UBSan (default: OFF)\n- `HERMES_ENABLE_THREAD_SANITIZER` - Enable TSan (default: OFF)\n\n**GC & Memory:**\n- `HERMESVM_GCKIND` - GC type: MALLOC or HADES (default: HADES)\n- `HERMESVM_HEAP_HV_MODE` - Heap HermesValue encoding mode (default: HEAP_HV_64). See \"Heap HermesValue Modes\" section below.\n- `HERMESVM_SANITIZE_HANDLES` - Move heap after every alloc to catch stale handles (default: OFF)\n\n**Performance/Debug Tradeoffs:**\n- `HERMES_SLOW_DEBUG` - Enable slow checks in Debug builds (default: ON)\n- `HERMESVM_ALLOW_JIT` - JIT mode: 0 (off), 1 (auto), 2 (force on) (default: 0)\n\n**Compilation Modes:**\n- `HERMESVM_INTERNAL_JAVASCRIPT_NATIVE` - Use natively compiled internal JS instead of bytecode (default: OFF)\n- `HERMES_UNICODE_LITE` - Use internal no-op unicode instead of system libraries (default: OFF)\n\n**External Dependencies:**\n- `HERMES_ALLOW_BOOST_CONTEXT` - Use Boost.Context fibers: 0 (off), 1 (auto), 2 (force on) (default: 1)\n- `JSI_UNSTABLE` - Enable JSI unstable APIs (default: ON)\n- `IMPORT_HOST_COMPILERS` - Import shermes/hermesc from another build for cross-compilation\n\n### Building\n\n```bash\n# Build\ncmake --build cmake-build-asan --target hermes\n\n# Run all tests\ncmake --build cmake-build-asan --target check-hermes\n\n# Run single test\ncmake-build-asan/bin/hermes path/to/test.js\n\n# Run test262 testsuite (ONLY run it when user asks for it)\npython3 utils/test_runner.py path/to/test262/test -b cmake-build-asan/bin\n\n# Generate the preprocessed JS file from a single test262 test.\n# Then you can run the <output_file> with hermes.\npython3 utils/test_runner.py <path_to_single_test262_test> -b cmake-build-asan/bin -d > <output_file>\n```\n\n### Running Tests in Claude Code on macOS\n\nDue to a sandbox limitation in Claude Code on macOS, Python's multiprocessing module cannot create semaphores, causing the lit test runner to fail. This is a bug in the Claude Code sandbox, not in Hermes. To work around this, run tests in single-process mode:\n\n```bash\nLIT_OPTS=\"-j1\" cmake --build cmake-build-asan --target check-hermes\n```\n\nSince single-process mode is slow (~5 minutes for all tests), use the `LIT_FILTER` environment variable to run only specific tests matching a regex:\n\n```bash\n# Run only tests matching \"Array\" in their path\nLIT_OPTS=\"-j1\" LIT_FILTER=\"Array\" cmake --build cmake-build-asan --target check-hermes\n\n# Run only tests in a specific directory\nLIT_OPTS=\"-j1\" LIT_FILTER=\"BCGen\" cmake --build cmake-build-asan --target check-hermes\n```\n\nThis workaround is only needed for Claude Code on macOS. Normal users and CI systems do not need these flags.\n\n### Building a Single File\n\nFor faster iteration when modifying a single file `dir1/dir2/file.cpp`:\n\n```bash\n# Find the target the file belongs to\nfind cmake-build-asan/ -name file.cpp.o\n\n# Build just that file (example for VM files)\ncmake --build cmake-build-asan --target lib/VM/CMakeFiles/hermesVMRuntime_obj.dir/file.cpp.o\n```\n\n### Inspecting C++ File Structure\n\n```bash\n# List all functions in a file sorted by line number (requires ctags)\nutils/dump-cpp-funcs.sh file.cpp\n```\n\n## Code Architecture\n\nThe build produces two VM variants: \"regular\" (full VM with compiler) and \"lean\" (excludes parser and compiler for smaller binary size).\n\n### Core Components\n\n- **lib/VM/**: Virtual machine core - runtime, interpreter, garbage collector, object model\n- **lib/VM/JSLib/**: JavaScript standard library implemented in C++ (Array, Object, String, etc.)\n- **lib/InternalJavaScript/**: JavaScript polyfills compiled into the VM (e.g., Math.sumPrecise, Promise)\n- **lib/Parser/**: JavaScript parser\n- **lib/AST/**: Abstract syntax tree definitions\n- **lib/IR/**: Intermediate representation for optimization\n- **lib/IRGen/**: Generates IR from AST\n- **lib/BCGen/**: Bytecode generation from IR\n- **lib/Sema/**: Semantic analysis\n- **lib/Support/**: Shared utilities and data structures\n- **include/hermes/**: Public header files organized by component\n- **API/hermes/extensions/**: JSI-based runtime extensions (see Extensions section below)\n\n### Key VM Files\n\n- `lib/VM/Runtime.cpp`: Main runtime implementation\n- `lib/VM/Interpreter.cpp`: Bytecode interpreter\n- `lib/VM/Callable.cpp`: Function and callable object implementation\n- `lib/VM/JSObject.cpp`: JavaScript object model\n- `lib/VM/Operations.cpp`: Core JS operations (typeof, instanceof, etc.)\n- `lib/VM/gcs/`: Garbage collector implementations\n\n### Testing\n\n- `test/`: Lit-based integration tests organized by component\n- `unittests/`: Google Test unit tests (VMRuntime, Support, API, Parser, etc.)\n\n### Auto-Updating Tests\n\nSome lit tests use `%FileCheckOrRegen` instead of `%FileCheck`. These are auto-updating tests whose expected output can be regenerated automatically.\n\nIf such a test fails due to intentional changes (e.g., changed output format, added runtime modules affecting IDs), and you understand why the failure occurred:\n\n```bash\n# Regenerate expected output for all auto-updating tests\ncmake --build cmake-build-asan --target update-lit\n```\n\n**Important:** Only use `update-lit` when you understand the cause of the failure. Review the changes to verify they match your expectations. Do not blindly regenerate tests to make them pass.\n\n## Code Style\n\nKey conventions:\n\n- **C++17**, no exceptions or RTTI\n- **Naming**: Classes (`PascalCase`), functions/methods (`camelCase`), variables (`camelCase`), member vars (`_suffix`), constants (`SNAKE_CASE` or `kCamelCase`)\n- **structs**: PODs only; use `class` for anything with constructors/destructors\n- **Line limit**: 80 characters, 2-space indent\n- **Doc comments**: Required for every declaration\n- **Inlining**: Only trivial one-line methods in class body\n\n## Native Function Development\n\nStandard signature for VM native functions:\n```cpp\nCallResult<HermesValue> funcName(void *context, Runtime &runtime)\n```\n\nAccess arguments:\n```cpp\nNativeArgs args = runtime.getCurrentFrame().getNativeArgs();\n```\n\n## Macro-Generated Code\n\nWhen making systematic changes, check for macro-generated code:\n- `NATIVE_ERROR_TYPE` macro in `lib/VM/JSLib/Error.cpp` - generates error constructors\n- `TYPED_ARRAY` macro in `lib/VM/JSLib/TypedArray.cpp` - generates typed array constructors\n- `NATIVE_FUNCTION` macro in `include/hermes/VM/JSNativeFunctions.h` - generates function declarations\n\n## GC-Safe Coding (Runtime Code)\n\nWhen writing, modifying, or reviewing C++ code in the VM runtime (`lib/VM/`, `include/hermes/VM/`, `API/hermes/`), always invoke the `gc-safe-coding` skill first. Runtime code must follow strict GC-safety rules around handles, locals, and heap-allocated objects. The skill covers all the rules and common pitfalls.\n\n## GC Handle Patterns\n\n### Locals Pattern (preferred for new code)\n```cpp\nstruct : public Locals {\n  PinnedValue<JSObject> objHandle;\n  PinnedValue<PropertyAccessor> accessor;\n  PinnedValue<> tempValue;  // untyped\n} lv;\nLocalsRAII lraii(runtime, &lv);\n\n// Assignment from PseudoHandle\nlv.value = std::move(pseudoHandle);\n\n// Assignment from CallResult with known type\nlv.obj.castAndSetHermesValue<JSObject>(callResult.getValue());\n```\n\n### Critical: Null Prototype Handling\n```cpp\n// When traversing prototype chains, always check for null:\nif (!*protoRes) {\n  lv.O = nullptr;\n} else {\n  lv.O.castAndSetHermesValue<JSObject>(protoRes->getHermesValue());\n}\n```\n\n### PinnedHermesValue\n`PinnedHermesValue` publicly inherits from `HermesValue` — do not cast to `HermesValue` to access its methods.\n\n## Copyright Header\n\n```cpp\n/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n```\n\n## Heap HermesValue Modes\n\nThe `HERMESVM_HEAP_HV_MODE` CMake option controls how JS values are encoded in memory. This significantly affects memory usage and performance.\n\n### HEAP_HV_64 (default)\n\nAll JS values, pointers, and numbers are encoded as 64-bit values using NaN-boxing. This is the simplest mode and works on all platforms.\n\n### HEAP_HV_PREFER32\n\nEnables 32-bit HermesValue encoding when possible, saving memory at the cost of some overhead:\n\n**On 32-bit devices:** JS values and pointers are 32-bit. Numbers that don't fit in 32 bits are boxed in the heap (typically a small percentage in real apps).\n\n**On 64-bit platforms (except iOS):** JS values and pointers are 32-bit offsets into a contiguous (up to) 4GB reserved memory block. All heap memory is allocated within this block.\n\n**On iOS (64-bit):** iOS doesn't allow large virtual address space reservations by default. Hermes allocates memory in 4MB segments anywhere in the 64-bit address space. 32-bit pointers are encoded as a combination of segment table index and offset within the segment. This has more overhead than other platforms but still saves significant memory.\n\n### HEAP_HV_BOXED\n\nForces boxed doubles on all platforms. Used for testing that all code paths handle boxed doubles correctly.\n\n### Production Defaults\n\nBy default, Hermes ships with HV32 (HEAP_HV_PREFER32) on Android for memory savings, and HV64 on iOS for best performance on faster devices.\n\n## Extensions System\n\nHermes supports JSI-based extensions that add runtime functionality. Extensions use the stable JSI API rather than internal Hermes APIs, making them easier to maintain.\n\n### Directory Structure\n\n- `API/hermes/extensions/` - Core extensions maintained by the Hermes team\n- `API/hermes/extensions/contrib/` - Community-contributed extensions\n\n### Adding Extensions\n\nEach extension consists of:\n1. A JavaScript file (`NN-ExtensionName.js`) with a setup function\n2. C++ files (`ExtensionName.h/cpp`) that call the JS setup and optionally provide native helpers\n\nSee `API/hermes/extensions/README.md` for detailed instructions.\n\n### Contrib Extensions\n\nCommunity contributions go in `extensions/contrib/`. These are:\n- Maintained by contributors, not the Hermes team\n- Enabled by default, but can be disabled with `-DHERMES_ENABLE_CONTRIB_EXTENSIONS=OFF`\n- May be promoted to core if widely adopted\n\nSee `API/hermes/extensions/contrib/README.md` for contributor guidelines.\n\n## Environment-Specific Instructions\n\nThis project exists in two environments. The presence of the `facebook/` directory indicates which environment you are in. **Only read the file corresponding to the current environment:**\n\n- If `facebook/` directory exists: Internal Meta repository using Mercurial (hg) and BUCK. Read `facebook/CLAUDE-meta.md` for Meta-specific instructions. Do not read `CLAUDE-github.md`.\n- If `facebook/` directory does not exist: Public GitHub repository using Git. Read `CLAUDE-github.md` for GitHub-specific instructions.\n"},"files":{"CLAUDE.md":"# CLAUDE.md\n\nThis file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.\n\n## CRITICAL: Never Change the Working Directory\n\n**NEVER use `cd` to change the current directory from the project root.** Almost all operations can be performed by passing the correct path to commands and tools. Changing directories causes confusion and errors in subsequent operations.\n\nIn the rare cases where changing directory is absolutely unavoidable, use a subshell so the directory change does not persist:\n```bash\n(cd other-dir; command;)\n```\n\n## Overview\n\nHermes is a JavaScript engine optimized for fast start-up of React Native apps. It features ahead-of-time static optimization and compact bytecode.\n\n## Build Commands\n\n### Default Build: ASan+Debug with -O1\n\nAlways build and test with AddressSanitizer enabled unless the user explicitly asks otherwise or there is a specific reason not to (e.g., performance benchmarking, testing release behavior). The ASan build catches memory bugs that are otherwise silent or non-deterministic.\n\n```bash\n# Configure ASan+Debug build (the default for development)\ncmake -B cmake-build-asan -G Ninja -DCMAKE_BUILD_TYPE=Debug \\\n  -DHERMES_ENABLE_ADDRESS_SANITIZER=ON \\\n  -DCMAKE_CXX_FLAGS=\"-O1\" -DCMAKE_C_FLAGS=\"-O1\"\n```\n\n### Other Build Configurations\n\n```bash\n# Plain Debug build (no sanitizer, for debugging with full symbols)\ncmake -B cmake-build-debug -G Ninja -DCMAKE_BUILD_TYPE=Debug\n\n# Release build\ncmake -B cmake-build-release -G Ninja -DCMAKE_BUILD_TYPE=Release\n```\n\n#### Common CMake Options\n\nPass these with `-D` when configuring, e.g., `cmake -B build -DCMAKE_BUILD_TYPE=Debug -DHERMES_ENABLE_DEBUGGER=ON`\n\n**Build Type & Core Options:**\n- `CMAKE_BUILD_TYPE` - Debug or Release (required)\n- `HERMES_ENABLE_DEBUGGER` - Build with debugger support (default: OFF)\n- `HERMES_FACEBOOK_BUILD` - Build Facebook internal version (default: OFF)\n- `HERMES_ENABLE_CONTRIB_EXTENSIONS` - Include community-contributed extensions (default: ON)\n- `HERMES_ENABLE_WERROR` - Treat warnings as errors (default: OFF)\n\n**Sanitizers:**\n- `HERMES_ENABLE_ADDRESS_SANITIZER` - Enable ASan (default: OFF)\n- `HERMES_ENABLE_UNDEFINED_BEHAVIOR_SANITIZER` - Enable UBSan (default: OFF)\n- `HERMES_ENABLE_THREAD_SANITIZER` - Enable TSan (default: OFF)\n\n**GC & Memory:**\n- `HERMESVM_GCKIND` - GC type: MALLOC or HADES (default: HADES)\n- `HERMESVM_HEAP_HV_MODE` - Heap HermesValue encoding mode (default: HEAP_HV_64). See \"Heap HermesValue Modes\" section below.\n- `HERMESVM_SANITIZE_HANDLES` - Move heap after every alloc to catch stale handles (default: OFF)\n\n**Performance/Debug Tradeoffs:**\n- `HERMES_SLOW_DEBUG` - Enable slow checks in Debug builds (default: ON)\n- `HERMESVM_ALLOW_JIT` - JIT mode: 0 (off), 1 (auto), 2 (force on) (default: 0)\n\n**Compilation Modes:**\n- `HERMESVM_INTERNAL_JAVASCRIPT_NATIVE` - Use natively compiled internal JS instead of bytecode (default: OFF)\n- `HERMES_UNICODE_LITE` - Use internal no-op unicode instead of system libraries (default: OFF)\n\n**External Dependencies:**\n- `HERMES_ALLOW_BOOST_CONTEXT` - Use Boost.Context fibers: 0 (off), 1 (auto), 2 (force on) (default: 1)\n- `JSI_UNSTABLE` - Enable JSI unstable APIs (default: ON)\n- `IMPORT_HOST_COMPILERS` - Import shermes/hermesc from another build for cross-compilation\n\n### Building\n\n```bash\n# Build\ncmake --build cmake-build-asan --target hermes\n\n# Run all tests\ncmake --build cmake-build-asan --target check-hermes\n\n# Run single test\ncmake-build-asan/bin/hermes path/to/test.js\n\n# Run test262 testsuite (ONLY run it when user asks for it)\npython3 utils/test_runner.py path/to/test262/test -b cmake-build-asan/bin\n\n# Generate the preprocessed JS file from a single test262 test.\n# Then you can run the <output_file> with hermes.\npython3 utils/test_runner.py <path_to_single_test262_test> -b cmake-build-asan/bin -d > <output_file>\n```\n\n### Running Tests in Claude Code on macOS\n\nDue to a sandbox limitation in Claude Code on macOS, Python's multiprocessing module cannot create semaphores, causing the lit test runner to fail. This is a bug in the Claude Code sandbox, not in Hermes. To work around this, run tests in single-process mode:\n\n```bash\nLIT_OPTS=\"-j1\" cmake --build cmake-build-asan --target check-hermes\n```\n\nSince single-process mode is slow (~5 minutes for all tests), use the `LIT_FILTER` environment variable to run only specific tests matching a regex:\n\n```bash\n# Run only tests matching \"Array\" in their path\nLIT_OPTS=\"-j1\" LIT_FILTER=\"Array\" cmake --build cmake-build-asan --target check-hermes\n\n# Run only tests in a specific directory\nLIT_OPTS=\"-j1\" LIT_FILTER=\"BCGen\" cmake --build cmake-build-asan --target check-hermes\n```\n\nThis workaround is only needed for Claude Code on macOS. Normal users and CI systems do not need these flags.\n\n### Building a Single File\n\nFor faster iteration when modifying a single file `dir1/dir2/file.cpp`:\n\n```bash\n# Find the target the file belongs to\nfind cmake-build-asan/ -name file.cpp.o\n\n# Build just that file (example for VM files)\ncmake --build cmake-build-asan --target lib/VM/CMakeFiles/hermesVMRuntime_obj.dir/file.cpp.o\n```\n\n### Inspecting C++ File Structure\n\n```bash\n# List all functions in a file sorted by line number (requires ctags)\nutils/dump-cpp-funcs.sh file.cpp\n```\n\n## Code Architecture\n\nThe build produces two VM variants: \"regular\" (full VM with compiler) and \"lean\" (excludes parser and compiler for smaller binary size).\n\n### Core Components\n\n- **lib/VM/**: Virtual machine core - runtime, interpreter, garbage collector, object model\n- **lib/VM/JSLib/**: JavaScript standard library implemented in C++ (Array, Object, String, etc.)\n- **lib/InternalJavaScript/**: JavaScript polyfills compiled into the VM (e.g., Math.sumPrecise, Promise)\n- **lib/Parser/**: JavaScript parser\n- **lib/AST/**: Abstract syntax tree definitions\n- **lib/IR/**: Intermediate representation for optimization\n- **lib/IRGen/**: Generates IR from AST\n- **lib/BCGen/**: Bytecode generation from IR\n- **lib/Sema/**: Semantic analysis\n- **lib/Support/**: Shared utilities and data structures\n- **include/hermes/**: Public header files organized by component\n- **API/hermes/extensions/**: JSI-based runtime extensions (see Extensions section below)\n\n### Key VM Files\n\n- `lib/VM/Runtime.cpp`: Main runtime implementation\n- `lib/VM/Interpreter.cpp`: Bytecode interpreter\n- `lib/VM/Callable.cpp`: Function and callable object implementation\n- `lib/VM/JSObject.cpp`: JavaScript object model\n- `lib/VM/Operations.cpp`: Core JS operations (typeof, instanceof, etc.)\n- `lib/VM/gcs/`: Garbage collector implementations\n\n### Testing\n\n- `test/`: Lit-based integration tests organized by component\n- `unittests/`: Google Test unit tests (VMRuntime, Support, API, Parser, etc.)\n\n### Auto-Updating Tests\n\nSome lit tests use `%FileCheckOrRegen` instead of `%FileCheck`. These are auto-updating tests whose expected output can be regenerated automatically.\n\nIf such a test fails due to intentional changes (e.g., changed output format, added runtime modules affecting IDs), and you understand why the failure occurred:\n\n```bash\n# Regenerate expected output for all auto-updating tests\ncmake --build cmake-build-asan --target update-lit\n```\n\n**Important:** Only use `update-lit` when you understand the cause of the failure. Review the changes to verify they match your expectations. Do not blindly regenerate tests to make them pass.\n\n## Code Style\n\nKey conventions:\n\n- **C++17**, no exceptions or RTTI\n- **Naming**: Classes (`PascalCase`), functions/methods (`camelCase`), variables (`camelCase`), member vars (`_suffix`), constants (`SNAKE_CASE` or `kCamelCase`)\n- **structs**: PODs only; use `class` for anything with constructors/destructors\n- **Line limit**: 80 characters, 2-space indent\n- **Doc comments**: Required for every declaration\n- **Inlining**: Only trivial one-line methods in class body\n\n## Native Function Development\n\nStandard signature for VM native functions:\n```cpp\nCallResult<HermesValue> funcName(void *context, Runtime &runtime)\n```\n\nAccess arguments:\n```cpp\nNativeArgs args = runtime.getCurrentFrame().getNativeArgs();\n```\n\n## Macro-Generated Code\n\nWhen making systematic changes, check for macro-generated code:\n- `NATIVE_ERROR_TYPE` macro in `lib/VM/JSLib/Error.cpp` - generates error constructors\n- `TYPED_ARRAY` macro in `lib/VM/JSLib/TypedArray.cpp` - generates typed array constructors\n- `NATIVE_FUNCTION` macro in `include/hermes/VM/JSNativeFunctions.h` - generates function declarations\n\n## GC-Safe Coding (Runtime Code)\n\nWhen writing, modifying, or reviewing C++ code in the VM runtime (`lib/VM/`, `include/hermes/VM/`, `API/hermes/`), always invoke the `gc-safe-coding` skill first. Runtime code must follow strict GC-safety rules around handles, locals, and heap-allocated objects. The skill covers all the rules and common pitfalls.\n\n## GC Handle Patterns\n\n### Locals Pattern (preferred for new code)\n```cpp\nstruct : public Locals {\n  PinnedValue<JSObject> objHandle;\n  PinnedValue<PropertyAccessor> accessor;\n  PinnedValue<> tempValue;  // untyped\n} lv;\nLocalsRAII lraii(runtime, &lv);\n\n// Assignment from PseudoHandle\nlv.value = std::move(pseudoHandle);\n\n// Assignment from CallResult with known type\nlv.obj.castAndSetHermesValue<JSObject>(callResult.getValue());\n```\n\n### Critical: Null Prototype Handling\n```cpp\n// When traversing prototype chains, always check for null:\nif (!*protoRes) {\n  lv.O = nullptr;\n} else {\n  lv.O.castAndSetHermesValue<JSObject>(protoRes->getHermesValue());\n}\n```\n\n### PinnedHermesValue\n`PinnedHermesValue` publicly inherits from `HermesValue` — do not cast to `HermesValue` to access its methods.\n\n## Copyright Header\n\n```cpp\n/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n```\n\n## Heap HermesValue Modes\n\nThe `HERMESVM_HEAP_HV_MODE` CMake option controls how JS values are encoded in memory. This significantly affects memory usage and performance.\n\n### HEAP_HV_64 (default)\n\nAll JS values, pointers, and numbers are encoded as 64-bit values using NaN-boxing. This is the simplest mode and works on all platforms.\n\n### HEAP_HV_PREFER32\n\nEnables 32-bit HermesValue encoding when possible, saving memory at the cost of some overhead:\n\n**On 32-bit devices:** JS values and pointers are 32-bit. Numbers that don't fit in 32 bits are boxed in the heap (typically a small percentage in real apps).\n\n**On 64-bit platforms (except iOS):** JS values and pointers are 32-bit offsets into a contiguous (up to) 4GB reserved memory block. All heap memory is allocated within this block.\n\n**On iOS (64-bit):** iOS doesn't allow large virtual address space reservations by default. Hermes allocates memory in 4MB segments anywhere in the 64-bit address space. 32-bit pointers are encoded as a combination of segment table index and offset within the segment. This has more overhead than other platforms but still saves significant memory.\n\n### HEAP_HV_BOXED\n\nForces boxed doubles on all platforms. Used for testing that all code paths handle boxed doubles correctly.\n\n### Production Defaults\n\nBy default, Hermes ships with HV32 (HEAP_HV_PREFER32) on Android for memory savings, and HV64 on iOS for best performance on faster devices.\n\n## Extensions System\n\nHermes supports JSI-based extensions that add runtime functionality. Extensions use the stable JSI API rather than internal Hermes APIs, making them easier to maintain.\n\n### Directory Structure\n\n- `API/hermes/extensions/` - Core extensions maintained by the Hermes team\n- `API/hermes/extensions/contrib/` - Community-contributed extensions\n\n### Adding Extensions\n\nEach extension consists of:\n1. A JavaScript file (`NN-ExtensionName.js`) with a setup function\n2. C++ files (`ExtensionName.h/cpp`) that call the JS setup and optionally provide native helpers\n\nSee `API/hermes/extensions/README.md` for detailed instructions.\n\n### Contrib Extensions\n\nCommunity contributions go in `extensions/contrib/`. These are:\n- Maintained by contributors, not the Hermes team\n- Enabled by default, but can be disabled with `-DHERMES_ENABLE_CONTRIB_EXTENSIONS=OFF`\n- May be promoted to core if widely adopted\n\nSee `API/hermes/extensions/contrib/README.md` for contributor guidelines.\n\n## Environment-Specific Instructions\n\nThis project exists in two environments. The presence of the `facebook/` directory indicates which environment you are in. **Only read the file corresponding to the current environment:**\n\n- If `facebook/` directory exists: Internal Meta repository using Mercurial (hg) and BUCK. Read `facebook/CLAUDE-meta.md` for Meta-specific instructions. Do not read `CLAUDE-github.md`.\n- If `facebook/` directory does not exist: Public GitHub repository using Git. Read `CLAUDE-github.md` for GitHub-specific instructions.\n"},"items":[{"name":"CLAUDE.md","path":"CLAUDE.md","title":"CLAUDE.md","content":"# CLAUDE.md\n\nThis file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.\n\n## CRITICAL: Never Change the Working Directory\n\n**NEVER use `cd` to change the current directory from the project root.** Almost all operations can be performed by passing the correct path to commands and tools. Changing directories causes confusion and errors in subsequent operations.\n\nIn the rare cases where changing directory is absolutely unavoidable, use a subshell so the directory change does not persist:\n```bash\n(cd other-dir; command;)\n```\n\n## Overview\n\nHermes is a JavaScript engine optimized for fast start-up of React Native apps. It features ahead-of-time static optimization and compact bytecode.\n\n## Build Commands\n\n### Default Build: ASan+Debug with -O1\n\nAlways build and test with AddressSanitizer enabled unless the user explicitly asks otherwise or there is a specific reason not to (e.g., performance benchmarking, testing release behavior). The ASan build catches memory bugs that are otherwise silent or non-deterministic.\n\n```bash\n# Configure ASan+Debug build (the default for development)\ncmake -B cmake-build-asan -G Ninja -DCMAKE_BUILD_TYPE=Debug \\\n  -DHERMES_ENABLE_ADDRESS_SANITIZER=ON \\\n  -DCMAKE_CXX_FLAGS=\"-O1\" -DCMAKE_C_FLAGS=\"-O1\"\n```\n\n### Other Build Configurations\n\n```bash\n# Plain Debug build (no sanitizer, for debugging with full symbols)\ncmake -B cmake-build-debug -G Ninja -DCMAKE_BUILD_TYPE=Debug\n\n# Release build\ncmake -B cmake-build-release -G Ninja -DCMAKE_BUILD_TYPE=Release\n```\n\n#### Common CMake Options\n\nPass these with `-D` when configuring, e.g., `cmake -B build -DCMAKE_BUILD_TYPE=Debug -DHERMES_ENABLE_DEBUGGER=ON`\n\n**Build Type & Core Options:**\n- `CMAKE_BUILD_TYPE` - Debug or Release (required)\n- `HERMES_ENABLE_DEBUGGER` - Build with debugger support (default: OFF)\n- `HERMES_FACEBOOK_BUILD` - Build Facebook internal version (default: OFF)\n- `HERMES_ENABLE_CONTRIB_EXTENSIONS` - Include community-contributed extensions (default: ON)\n- `HERMES_ENABLE_WERROR` - Treat warnings as errors (default: OFF)\n\n**Sanitizers:**\n- `HERMES_ENABLE_ADDRESS_SANITIZER` - Enable ASan (default: OFF)\n- `HERMES_ENABLE_UNDEFINED_BEHAVIOR_SANITIZER` - Enable UBSan (default: OFF)\n- `HERMES_ENABLE_THREAD_SANITIZER` - Enable TSan (default: OFF)\n\n**GC & Memory:**\n- `HERMESVM_GCKIND` - GC type: MALLOC or HADES (default: HADES)\n- `HERMESVM_HEAP_HV_MODE` - Heap HermesValue encoding mode (default: HEAP_HV_64). See \"Heap HermesValue Modes\" section below.\n- `HERMESVM_SANITIZE_HANDLES` - Move heap after every alloc to catch stale handles (default: OFF)\n\n**Performance/Debug Tradeoffs:**\n- `HERMES_SLOW_DEBUG` - Enable slow checks in Debug builds (default: ON)\n- `HERMESVM_ALLOW_JIT` - JIT mode: 0 (off), 1 (auto), 2 (force on) (default: 0)\n\n**Compilation Modes:**\n- `HERMESVM_INTERNAL_JAVASCRIPT_NATIVE` - Use natively compiled internal JS instead of bytecode (default: OFF)\n- `HERMES_UNICODE_LITE` - Use internal no-op unicode instead of system libraries (default: OFF)\n\n**External Dependencies:**\n- `HERMES_ALLOW_BOOST_CONTEXT` - Use Boost.Context fibers: 0 (off), 1 (auto), 2 (force on) (default: 1)\n- `JSI_UNSTABLE` - Enable JSI unstable APIs (default: ON)\n- `IMPORT_HOST_COMPILERS` - Import shermes/hermesc from another build for cross-compilation\n\n### Building\n\n```bash\n# Build\ncmake --build cmake-build-asan --target hermes\n\n# Run all tests\ncmake --build cmake-build-asan --target check-hermes\n\n# Run single test\ncmake-build-asan/bin/hermes path/to/test.js\n\n# Run test262 testsuite (ONLY run it when user asks for it)\npython3 utils/test_runner.py path/to/test262/test -b cmake-build-asan/bin\n\n# Generate the preprocessed JS file from a single test262 test.\n# Then you can run the <output_file> with hermes.\npython3 utils/test_runner.py <path_to_single_test262_test> -b cmake-build-asan/bin -d > <output_file>\n```\n\n### Running Tests in Claude Code on macOS\n\nDue to a sandbox limitation in Claude Code on macOS, Python's multiprocessing module cannot create semaphores, causing the lit test runner to fail. This is a bug in the Claude Code sandbox, not in Hermes. To work around this, run tests in single-process mode:\n\n```bash\nLIT_OPTS=\"-j1\" cmake --build cmake-build-asan --target check-hermes\n```\n\nSince single-process mode is slow (~5 minutes for all tests), use the `LIT_FILTER` environment variable to run only specific tests matching a regex:\n\n```bash\n# Run only tests matching \"Array\" in their path\nLIT_OPTS=\"-j1\" LIT_FILTER=\"Array\" cmake --build cmake-build-asan --target check-hermes\n\n# Run only tests in a specific directory\nLIT_OPTS=\"-j1\" LIT_FILTER=\"BCGen\" cmake --build cmake-build-asan --target check-hermes\n```\n\nThis workaround is only needed for Claude Code on macOS. Normal users and CI systems do not need these flags.\n\n### Building a Single File\n\nFor faster iteration when modifying a single file `dir1/dir2/file.cpp`:\n\n```bash\n# Find the target the file belongs to\nfind cmake-build-asan/ -name file.cpp.o\n\n# Build just that file (example for VM files)\ncmake --build cmake-build-asan --target lib/VM/CMakeFiles/hermesVMRuntime_obj.dir/file.cpp.o\n```\n\n### Inspecting C++ File Structure\n\n```bash\n# List all functions in a file sorted by line number (requires ctags)\nutils/dump-cpp-funcs.sh file.cpp\n```\n\n## Code Architecture\n\nThe build produces two VM variants: \"regular\" (full VM with compiler) and \"lean\" (excludes parser and compiler for smaller binary size).\n\n### Core Components\n\n- **lib/VM/**: Virtual machine core - runtime, interpreter, garbage collector, object model\n- **lib/VM/JSLib/**: JavaScript standard library implemented in C++ (Array, Object, String, etc.)\n- **lib/InternalJavaScript/**: JavaScript polyfills compiled into the VM (e.g., Math.sumPrecise, Promise)\n- **lib/Parser/**: JavaScript parser\n- **lib/AST/**: Abstract syntax tree definitions\n- **lib/IR/**: Intermediate representation for optimization\n- **lib/IRGen/**: Generates IR from AST\n- **lib/BCGen/**: Bytecode generation from IR\n- **lib/Sema/**: Semantic analysis\n- **lib/Support/**: Shared utilities and data structures\n- **include/hermes/**: Public header files organized by component\n- **API/hermes/extensions/**: JSI-based runtime extensions (see Extensions section below)\n\n### Key VM Files\n\n- `lib/VM/Runtime.cpp`: Main runtime implementation\n- `lib/VM/Interpreter.cpp`: Bytecode interpreter\n- `lib/VM/Callable.cpp`: Function and callable object implementation\n- `lib/VM/JSObject.cpp`: JavaScript object model\n- `lib/VM/Operations.cpp`: Core JS operations (typeof, instanceof, etc.)\n- `lib/VM/gcs/`: Garbage collector implementations\n\n### Testing\n\n- `test/`: Lit-based integration tests organized by component\n- `unittests/`: Google Test unit tests (VMRuntime, Support, API, Parser, etc.)\n\n### Auto-Updating Tests\n\nSome lit tests use `%FileCheckOrRegen` instead of `%FileCheck`. These are auto-updating tests whose expected output can be regenerated automatically.\n\nIf such a test fails due to intentional changes (e.g., changed output format, added runtime modules affecting IDs), and you understand why the failure occurred:\n\n```bash\n# Regenerate expected output for all auto-updating tests\ncmake --build cmake-build-asan --target update-lit\n```\n\n**Important:** Only use `update-lit` when you understand the cause of the failure. Review the changes to verify they match your expectations. Do not blindly regenerate tests to make them pass.\n\n## Code Style\n\nKey conventions:\n\n- **C++17**, no exceptions or RTTI\n- **Naming**: Classes (`PascalCase`), functions/methods (`camelCase`), variables (`camelCase`), member vars (`_suffix`), constants (`SNAKE_CASE` or `kCamelCase`)\n- **structs**: PODs only; use `class` for anything with constructors/destructors\n- **Line limit**: 80 characters, 2-space indent\n- **Doc comments**: Required for every declaration\n- **Inlining**: Only trivial one-line methods in class body\n\n## Native Function Development\n\nStandard signature for VM native functions:\n```cpp\nCallResult<HermesValue> funcName(void *context, Runtime &runtime)\n```\n\nAccess arguments:\n```cpp\nNativeArgs args = runtime.getCurrentFrame().getNativeArgs();\n```\n\n## Macro-Generated Code\n\nWhen making systematic changes, check for macro-generated code:\n- `NATIVE_ERROR_TYPE` macro in `lib/VM/JSLib/Error.cpp` - generates error constructors\n- `TYPED_ARRAY` macro in `lib/VM/JSLib/TypedArray.cpp` - generates typed array constructors\n- `NATIVE_FUNCTION` macro in `include/hermes/VM/JSNativeFunctions.h` - generates function declarations\n\n## GC-Safe Coding (Runtime Code)\n\nWhen writing, modifying, or reviewing C++ code in the VM runtime (`lib/VM/`, `include/hermes/VM/`, `API/hermes/`), always invoke the `gc-safe-coding` skill first. Runtime code must follow strict GC-safety rules around handles, locals, and heap-allocated objects. The skill covers all the rules and common pitfalls.\n\n## GC Handle Patterns\n\n### Locals Pattern (preferred for new code)\n```cpp\nstruct : public Locals {\n  PinnedValue<JSObject> objHandle;\n  PinnedValue<PropertyAccessor> accessor;\n  PinnedValue<> tempValue;  // untyped\n} lv;\nLocalsRAII lraii(runtime, &lv);\n\n// Assignment from PseudoHandle\nlv.value = std::move(pseudoHandle);\n\n// Assignment from CallResult with known type\nlv.obj.castAndSetHermesValue<JSObject>(callResult.getValue());\n```\n\n### Critical: Null Prototype Handling\n```cpp\n// When traversing prototype chains, always check for null:\nif (!*protoRes) {\n  lv.O = nullptr;\n} else {\n  lv.O.castAndSetHermesValue<JSObject>(protoRes->getHermesValue());\n}\n```\n\n### PinnedHermesValue\n`PinnedHermesValue` publicly inherits from `HermesValue` — do not cast to `HermesValue` to access its methods.\n\n## Copyright Header\n\n```cpp\n/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n```\n\n## Heap HermesValue Modes\n\nThe `HERMESVM_HEAP_HV_MODE` CMake option controls how JS values are encoded in memory. This significantly affects memory usage and performance.\n\n### HEAP_HV_64 (default)\n\nAll JS values, pointers, and numbers are encoded as 64-bit values using NaN-boxing. This is the simplest mode and works on all platforms.\n\n### HEAP_HV_PREFER32\n\nEnables 32-bit HermesValue encoding when possible, saving memory at the cost of some overhead:\n\n**On 32-bit devices:** JS values and pointers are 32-bit. Numbers that don't fit in 32 bits are boxed in the heap (typically a small percentage in real apps).\n\n**On 64-bit platforms (except iOS):** JS values and pointers are 32-bit offsets into a contiguous (up to) 4GB reserved memory block. All heap memory is allocated within this block.\n\n**On iOS (64-bit):** iOS doesn't allow large virtual address space reservations by default. Hermes allocates memory in 4MB segments anywhere in the 64-bit address space. 32-bit pointers are encoded as a combination of segment table index and offset within the segment. This has more overhead than other platforms but still saves significant memory.\n\n### HEAP_HV_BOXED\n\nForces boxed doubles on all platforms. Used for testing that all code paths handle boxed doubles correctly.\n\n### Production Defaults\n\nBy default, Hermes ships with HV32 (HEAP_HV_PREFER32) on Android for memory savings, and HV64 on iOS for best performance on faster devices.\n\n## Extensions System\n\nHermes supports JSI-based extensions that add runtime functionality. Extensions use the stable JSI API rather than internal Hermes APIs, making them easier to maintain.\n\n### Directory Structure\n\n- `API/hermes/extensions/` - Core extensions maintained by the Hermes team\n- `API/hermes/extensions/contrib/` - Community-contributed extensions\n\n### Adding Extensions\n\nEach extension consists of:\n1. A JavaScript file (`NN-ExtensionName.js`) with a setup function\n2. C++ files (`ExtensionName.h/cpp`) that call the JS setup and optionally provide native helpers\n\nSee `API/hermes/extensions/README.md` for detailed instructions.\n\n### Contrib Extensions\n\nCommunity contributions go in `extensions/contrib/`. These are:\n- Maintained by contributors, not the Hermes team\n- Enabled by default, but can be disabled with `-DHERMES_ENABLE_CONTRIB_EXTENSIONS=OFF`\n- May be promoted to core if widely adopted\n\nSee `API/hermes/extensions/contrib/README.md` for contributor guidelines.\n\n## Environment-Specific Instructions\n\nThis project exists in two environments. The presence of the `facebook/` directory indicates which environment you are in. **Only read the file corresponding to the current environment:**\n\n- If `facebook/` directory exists: Internal Meta repository using Mercurial (hg) and BUCK. Read `facebook/CLAUDE-meta.md` for Meta-specific instructions. Do not read `CLAUDE-github.md`.\n- If `facebook/` directory does not exist: Public GitHub repository using Git. Read `CLAUDE-github.md` for GitHub-specific instructions.\n","category":"root","tokens":3213}]}