Repository navigation
Sync Hermes static_h@26fbb82f and build hermes.dll at JSI 22 - #408
Vladimir Morozov (vmoroz) merged 12 commits into
Conversation
There was a problem hiding this comment.
Note
Copilot was unable to run its full agentic suite in this review.
Copilot review overview
No open issues 🎉
What changed in this PR
Syncs hermes-windows with upstream Hermes (static_h@26fbb82f) while preserving Windows-specific behaviors, and updates tooling/build/test infrastructure to support JSI 22 usage inside hermes.dll plus new reliability/export gates.
Changes:
- Updates sandbox + C ABI plumbing for new/changed JSI methods and ABI entries (e.g., array length, isArray, typed arrays, error creation), and improves sandbox regeneration documentation/tooling.
- Adds
Workerextension (guarded byJSI_UNSTABLE) and strengthens extension buffer safety by rooting ArrayBuffers in typed-array views. - Adds a hermes.dll export allowlist checker (unit-tested) and wires it into local builds + CI; extends CDP to retain evaluated sources and adds stubs for missing Debugger methods.
| File | Description |
|---|---|
| API/hermes_sandbox/external/hermes_sandbox_impl_dbg_compiled.h | Updates generated export list for sandbox debug artifact |
| API/hermes_sandbox/README.md | Documents JSI support and sandbox regeneration steps/constraints |
| API/hermes_sandbox/HermesSandboxRuntime.cpp | Implements/overrides more JSI methods safely for untrusted sandbox JS |
| API/hermes_sandbox/CMakeLists.txt | Tightens wasm link flags & sanitizer handling for generated C |
| API/hermes_node_api_jsi/NodeApiJsiRuntime.cpp | Aligns Node-API JSI behavior with JSI 22 semantics (arrays/proxies) |
| API/hermes_node_api/hermes_node_api.cpp | Updates VM object creation to use hidden classes as needed |
| API/hermes_abi/hermes_vtable.cpp | Adjusts ABI behaviors for proxies/arrays, error propagation, and array length |
| API/hermes_abi/hermes_abi.h | Updates vtable signatures (e.g., get_array_length, object_is_array) |
| API/hermes_abi/HermesABIRuntimeWrapper.cpp | Adapts wrapper to new ABI result types and overload visibility |
| API/hermes_abi/CMakeLists.txt | Links hermesabi against full VM archive (hermesvm_a) |
| API/hermes/extensions/contrib/TextDecoder.cpp | Fixes buffer lifetime by rooting backing ArrayBuffer during decode |
| API/hermes/extensions/Worker.h | Adds public header for Worker extension install hook |
| API/hermes/extensions/Worker.cpp | Adds Worker implementation using threads, message queues, serialization |
| API/hermes/extensions/TextEncoder.cpp | Updates typed-array buffer access to new TypedArrayBufferInfo API |
| API/hermes/extensions/JSIUtils.h | Makes typed-array buffer view GC-safe by keeping ArrayBuffer alive |
| API/hermes/extensions/JSIUtils.cpp | Validates byte ranges and returns rooted buffer view |
| API/hermes/extensions/Intrinsics.h | Captures DataView getters for robust brand-checking |
| API/hermes/extensions/Intrinsics.cpp | Implements intrinsic capture & DataView brand-check helpers |
| API/hermes/extensions/Extensions.cpp | Installs Worker extension under JSI_UNSTABLE |
| API/hermes/extensions/CMakeLists.txt | Adds Worker.cpp to extensions build |
| API/hermes/extensions/11-Worker.js | Adds JS setup script that installs globalThis.Worker |
| API/hermes/cdp/tools/message_types.txt | Adds Debugger message types for new methods |
| API/hermes/cdp/RuntimeDomainAgent.h | Adds retention hook for evaluated script sources |
| API/hermes/cdp/RuntimeDomainAgent.cpp | Retains evaluated sources so Debugger can serve them back |
| API/hermes/cdp/RemoteObjectConverters.cpp | Matches V8 behavior by avoiding duplicate exception text |
| API/hermes/cdp/MessageTypes.h | Adds new CDP request/response types (script source, breakpoints) |
| API/hermes/cdp/MessageTypes.cpp | Implements JSON conversion + dispatch for new CDP message types |
| API/hermes/cdp/EvaluatedScriptSources.h | New bounded cache for sources of Runtime.evaluate-created scripts |
| API/hermes/cdp/EvaluatedScriptSources.cpp | Implements retention, assignment, and eviction for evaluated sources |
| API/hermes/cdp/DebuggerDomainCoordinator.h | Threads evaluated-source cache through debugger coordinator |
| API/hermes/cdp/DebuggerDomainCoordinator.cpp | Assigns evaluated sources on script-load events |
| API/hermes/cdp/DebuggerDomainAgent.h | Adds Debugger.getScriptSource and getPossibleBreakpoints APIs |
| API/hermes/cdp/DebuggerDomainAgent.cpp | Implements getScriptSource + stub getPossibleBreakpoints |
| API/hermes/cdp/CDPDebugAPI.h | Stores evaluated-source cache within CDPDebugAPI |
| API/hermes/cdp/CDPDebugAPI.cpp | Passes evaluated-source cache into debugger coordinator |
| API/hermes/cdp/CDPAgent.cpp | Wires new CDP APIs into command handling and agent construction |
| API/hermes/TracingRuntime.h | Adds tracing overrides for new JSI methods and JSON parsing |
| API/hermes/TracingRuntime.cpp | Implements traceable Math wrappers and new trace records |
| API/hermes/TraceInterpreter.cpp | Replays new trace records and installs traceable math wrappers |
| API/hermes/SynthTraceParser.cpp | Parses new trace record types (UInt8Array, errors, array push) |
| API/hermes/SynthTrace.h | Adds new SynthTrace record types and error-type enum |
| API/hermes/SynthTrace.cpp | Serializes new SynthTrace record types to JSON |
| API/hermes/CompileJS.h | Adds compile flags for ES6 block scoping and async generators |
| API/hermes/CompileJS.cpp | Wires new compile options into compiler flags |
| API/hermes/CMakeLists.txt | Adds evaluated-source implementation to build; restores Android JNI deps |
| API/CMakeLists.txt | Adds conditional N-API subdirectory based on HERMES_ENABLE_NAPI |
| AGENTS.md | Documents export gate + Windows fork behaviors to preserve |
| .syncignore | Fixes Node API unittest path casing |
| .github/dependabot.yml | Adds Dependabot updates for external/node-api-cts |
| .claude/skills/regenerate-sandbox/verify_generated.py | Adds sandbox output verifier for imports/exports/ABI/paths/ids |
| .claude/skills/regenerate-sandbox/references/troubleshooting.md | Adds sandbox regeneration troubleshooting reference |
| .claude/skills/regenerate-sandbox/references/testing.md | Adds sandbox testing reference |
| .claude/skills/regenerate-sandbox/references/jsi.md | Adds sandbox JSI guidance/reference |
| .claude/skills/regenerate-sandbox/references/checks.md | Adds sandbox output checking + stack budget reference |
| .claude/skills/regenerate-sandbox/references/building.md | Adds sandbox build tool/version guidance |
| .claude/skills/regenerate-sandbox/references/abi.md | Adds ABI/mirror change rules for sandbox |
| .claude/skills/regenerate-sandbox/SKILL.md | Adds skill doc to guide regenerations consistently |
| .claude/skills/modify-jsi-features/SKILL.md | Adds/records guidance for adding new JSI functionality |
| .claude/skills/gc-safe-coding/SKILL.md | Expands GC safety guidance (incl. SymbolID pitfalls) |
| .claude/agents/code-reviewer.md | Updates tool list reference |
| .ado/scripts/package.json | Adds test:exports script |
| .ado/scripts/hermes-exports.txt | Adds reviewed C-export allowlist for hermes.dll |
| .ado/scripts/check-exports.ts | Implements hermes.dll export allowlist + C++/DATA/forwarder rejection |
| .ado/scripts/check-exports.test.ts | Adds unit tests for export checker |
| .ado/scripts/build.js | Runs export checks after build/copy and in staged outputs; sets PYTHONIOENCODING |
| .ado/scripts/README.md | Documents export checker and how to run tests |
| .ado/build-template.yml | Runs export checker tests and updates step name to include export gate |
Review effort: Lite
- Pin @rnx-kit/fork-sync to exact 0.6.0 (0.6.1 is not on the approved feed). - sync.ts: pass the repository root to fork-sync via -C. - sync-config.json: use snapshot fetch mode and keep local deletions. - dev.ps1: require Node 24+ before restoring fork-sync and .ado/scripts, and restore them with lock-aware npm ci --ignore-scripts. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1aa3f58 to
a67ab34
Compare
Benchmark ResultsTotal benchmarks: 204 Inputs: baseline/baseline.json, bench_result.json v8 (6176ms, 5522ms) -10.6%
test-suites (317886ms, 305573ms) -3.9%
micros (60876ms, 60840ms) -0.1%
jit-benches (8563ms, 6314ms) -26.3%
many-subclasses (73437ms, 81676ms) +11.2%
map-objects (3627ms, 1955ms) -46.1%
map-strings (4335ms, 2312ms) -46.7%
nbody (3448ms, 2827ms) -18.0%
string-switch (6503ms, 6625ms) +1.9%
raytracer (5608ms, 5590ms) -0.3%
MiniReact (30332ms, 21769ms) -28.2%
widgets (12934ms, 12748ms) -1.4%
|
|
/azp run |
Import facebook/hermes static_h at 26fbb82 with fork-sync 0.6.0 (snapshot mode, local deletions kept) and integrate it with the Windows fork: - hermes.dll producers and internal JSI clients build at JSI 22; public JSI headers still fall back to 21; JSI_UNSTABLE stays ON. - Keep fork Node-API, WinGlob Unicode and Intl providers; upstream NAPI stays off on Windows; remove the deleted upstream ICU backend. - Keep MicrotaskQueue=false support (RNW bridge mode) over upstream d800198, with tests for both queue modes. - Keep the HermesExport.h CREATE_SHARED_LIBRARY guard; hermes.dll exports C names only. - Suppress CRT/WER dialogs in Node-API test mains and Static Hermes programs; bound Node-API child-process tests with a timeout. - Fix shermes CRT flag selection for clang; add Proxy array JSI test. npm/Yarn lock reconciliation for imported packages follows in a separate commit. The regenerated wasm2c sandbox sources (API/hermes_sandbox/external/hermes_sandbox_impl_{dbg,opt}_compiled*) are left out and land in a follow-up pull request, because GitHub cannot diff them in place. Until then the sandbox and its APITests variant are skipped. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Make external/node-api-cts/.npmrc registry-free like the other committed .npmrc files, add its package-lock.json (no resolved URLs), and update the hermes-parser and flow-bundler yarn.lock files lock-only for the imported manifest changes. Locks were resolved anonymously through PackageFeedProxy. No auth, security resolutions kept, no downgrades. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- README: add the grouped JSI 22 row with static_h hashes, keep main hashes, note 606a424 (main) and b10cafd (static_h) are the same JSI 21, and map React Native 0.80=19, 0.81=20, 0.82-0.85=21, 0.86+/main=22. hermes.dll builds at 22; public headers fall back to 21; RNW uses 21 over the C API. - Add default-built, unlinked compile-only objects that compile the public JSI headers, jsi.cpp and decorators at JSI 20 and at the header fallback (21). - Fix stale jsi.h comments about the default version and header name. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Check every built hermes.dll copy with dumpbin /nologo /exports from build.js so `dev build` and the ADO build step share one gate. Fail on tool errors, empty or unparseable output, C++ (MSVC/Itanium) names, DATA, ordinal-only and forwarded exports, missing required names, and unknown C names (add them to hermes-exports.txt). hoost_* exports are optional only on ARM64EC. Add unit tests and run them in the ADO pipeline next to the npm source lint tests. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Upstream static_h moved destruction of JSI HostObject, HostFunction and NativeState owners to an always-on finalizer worker thread. hermes-windows keeps today's behavior: when RuntimeConfig::FinalizerThreadRunner is unset (the jsr/hermes.dll path), owners are destroyed inline in their VM finalizer and no worker thread is created. An explicitly supplied runner keeps the upstream worker. Tests cover every owner kind in both modes. NodeApi child-process tests now run each child in a job object (KILL_ON_JOB_CLOSE) so a timeout also ends grandchildren, and the test-host copies of hermes.dll are refreshed whenever the DLL changes. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…tion - APITests: query the Hades background thread only in debug builds, so release builds with handle sanitization compile; that configuration checks exactly-once finalization. - JSI tests: use the checked asArray conversion for the revoked Proxy case, because getArray validates only in debug builds. - NodeApi tests: match the exact abort status and output of the debug and release CRT, and treat a reused protected PID as gone. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Suppress CRT/WER crash dialogs in hermes_rt, hdb, and hbc-diff, which run lit and test262 Intl tests. - Merge adjacent JSI_VERSION >= 22 guards in decorator.h, jsi.h, and jsi-inl.h; preprocessed output is unchanged at JSI 20, 21, and 22. - Drop the custom-runner cases from OwnerFinalizationTest; the FinalizerThreadRunner test keeps that coverage. - Set up the VS environment once per build for the export check. - Restore executable bits on three imported scripts, fix the NodeApi spelling in .syncignore, and document the export check and the fork behaviors to keep on every sync in AGENTS.md. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The imported bootstrap loop in tools/hermes-parser/js/scripts/build.sh called bare `yarn`, bypassing the repository's pinned Yarn 4 that microsoft#378 routed every other call in this script through. Use run_yarn there as well. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
a67ab34 to
ee808ec
Compare
|
/azp run |
|
Azure Pipelines: Successfully started running 1 pipeline(s). |
When TZ is set, the UCRT's tzset() updates _timezone and _daylight but keeps the DST bias of the host's timezone, which is 0 on hosts without DST such as UTC build agents. localtime_s() then flags DST without shifting the fields, so the new DateCache reported standard time during DST (for example UTC-8 instead of UTC-7 for TZ=PST8PDT in July) and DateUtilTest failed in CI. Apply the one-hour shift in that case, and add a test that emulates such a host. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Existing build trees configured with the generated sandbox sources failed to build after the sources were deleted, because CMake watched the folder only while the sources were missing. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
/azp run |
|
Azure Pipelines: Successfully started running 1 pipeline(s). |
There was a problem hiding this comment.
🔵 Needs a closer look
Changes to VM layouts, bytecode compatibility, and cross-architecture native linkage require platform-owner review and native execution results that cannot be independently validated in this source-only environment.
No open issues 🎉
1 resolved since last review
Review effort: Balanced
hermes-windows does not ship the sandbox. Its generated wasm2c sources
(API/hermes_sandbox/external/hermes_sandbox_impl_{dbg,opt}_compiled*) are
~200 MB per upstream regeneration, and GitHub cannot diff them in place.
#408 removed them; list them in .syncignore so future syncs keep them out,
including new file names. The sandbox stays skipped while they are absent.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Summary
Sync hermes-windows with facebook/hermes
static_hat26fbb82f, and keep theWindows-specific behavior that React Native Windows and other hermes.dll consumers
depend on.
Upstream import
static_h@26fbb82fwith the updated fork-sync tool (0.6.0, snapshot mode),so later syncs replay cleanly and our deliberate deletions stay deleted.
(bundled ICU by default, WinGlob, system ICU), the Node-API implementation,
MicrotaskQueue=falsesupport, and theHermesExport.hshared-library guard.JSI 22 inside hermes.dll
default to JSI 21, and new test targets compile a JSI 20 and a JSI 21 consumer, so
existing apps keep building unchanged.
Host-object finalizers stay inline
background thread. hermes-windows keeps today's behavior: they are destroyed inline
during finalization unless a host explicitly sets
FinalizerThreadRunner. Thisavoids new cross-thread destruction for RNW and other consumers.
hermes.dll export check
.\dev buildand in every CI build cell. It fails ifhermes.dll exports any C++ (mangled) name or misses any required C export, including
the
_sh_*/hoost_*exports that Static Hermes needs. The allowlist ishermes-exports.txt; AGENTS.md explains how to update it.Test reliability
hermes_rt,hdb,hbc-diff, and Static Hermes programs), so a failing test can't leave a modaldialog on a build agent. Note:
_sh_initnow prints a stack trace on fatal signals,which also turns off WER crash reports for Static Hermes-compiled programs.
grandchild processes behind.
Package restore
through PackageFeedProxy. The new
external/node-api-cts/.npmrcnames no registry,like the other committed
.npmrcfiles, so Dependabot can update it (follows Use PackageFeedProxy for npm and Yarn restores #404and Keep committed npm and Yarn configs registry-free for Dependabot #405); its directory is added to Dependabot.
Windows date offsets with TZ set
localtime_s. WhenTZisset, the UCRT keeps the host's DST bias, which is 0 on hosts without DST, so
TZ=PST8PDTreported UTC-8 in July. The fix applies the one-hour shift in thatcase, restoring the previous behavior; a new test emulates such a host.
Sandbox sources land separately
API/hermes_sandbox/external/hermes_sandbox_impl_{dbg,opt}_compiled*). GitHubcannot diff them in place, which left this PR with no file list, so this PR
deletes the old ones and a follow-up PR adds the new ones. Until then the sandbox
and its
APITestsvariant are skipped. Nothing shipped uses the sandbox.Test Plan
.\dev build --test --jstest --test262-intlon x64, x86, ARM64 and ARM64EC (nativeARM64 machine for the ARM ones), debug and release: all native suites pass, JS
regression tests have no unexpected failures, Test262 intl402 passes 348/348, and
the export check passes for every DLL. UWP builds and BinSkim pass.
playground-composition ARM64 app (Debug and Release) built against it, loaded its
hermes.dll, rendered RNTester, reloaded, and closed/reopened cleanly. Two other RNW
samples fail the same way with RNW's current Hermes package, so that is an RNW
issue unrelated to this change.