Skip to content

v0.2.4

Latest

Choose a tag to compare

@Anthony-Bondu Anthony-Bondu released this 01 Oct 12:00
ad4c924

Makes the whole-bundle output parse end to end on Static Hermes (HBC 98), names captures and imports from what the bytecode binds, and adds end-to-end tests that fail on a crash, on top of v0.2.3.

What's new

  • Every module parses: on a 17,781-module HBC 98 reference bundle, modules that failed to parse go from 2,089 to 0 and unrendered function bodies ({ ... } holes) from 370,854 to 274. The causes were in the IR builder: JmpBuiltinIs was read as a typeof test and printed typeof x === "unknown" 7,606 times, a Jmp adopted its target block and truncated every try/catch that followed, a derived class whose class and home object share one register exported its prototype under the class name, and a class binding's block environment was written over the factory's slot 0 (const MessageQueue = global next to class MessageQueue).
  • Rendering is bounded: hermesc creates a non-escaping closure afresh at every call site and a chainable API creates a closure of itself, so embedding bodies by id never converged and one pass reached 5 GB of text. Repeated, immediately-called and cyclic closures are declared once (Tarjan SCC over the creation graph), never outside the scope of their free names, and class methods are rendered from the whole-program bodies. Lines go from 4.3M to 2.76M while moment, whose 8,825 class methods were missing, grows from 3,514 lines to 111,379.
  • Captures take the name their owner binds: a closure created with a block environment now has that block scope as parent, capture origins are recorded when they are baked and a late pass renames every capture to the owner's current binding, uninitialised slots are declared, and super forces an arrow. Identifiers never declared drop from 331,732 to 85,079, closure_N references from 598,388 to 118,852, argN parameters from 293,231 to 116,975.
  • Imports resolve: the require parameter kept its positional role next to importDefault on modern factories (it was arg1 in 5,592 modules), every factory is named from its roles, a module's default-export function name identifies it and survives sharing, and React, react-native and AssetRegistry are recognised by their complete export surface. Imports to an unnamed module_N fall from 22,821 to 15,782 while imports as a whole rise from 68,306 to 91,748.
  • Codegen: labels are emitted only when a jump names them (5,654 to 0), a let assigned in a branch and read after it is declared where the read can see it, a captured store is never reduced to its side effect (set = new Set() had become new Set();), let t = A; if (!A) folds to t = A || B, and non-ASCII object keys are escaped.
  • The cache loads: the msgpack decoder's depth limit refused every whole-bundle snapshot and silently rebuilt, so each --modules or --json inspection cost a full run. A refusal is now logged and the limit lifted; an inspection takes seconds.
  • End-to-end tests: the built binary is run on every corpus bytecode in a child process with a time budget, and on tracked crash-regression fixtures that run in CI. The round trip now fails on a decompiler that aborts instead of counting it as "no output".

Fixed issues

  • #24 by @luca-regne: a JSX props object holding an element built from itself (props.children = React.createElement(View, props)) overflowed the stack in the props substitution on every HBC version. The expansion now stops at the cycle and keeps the variable reference, as proposed in #25; the reproducer is a tracked fixture for v59, v84, v96 and v98.
  • #21 by @FlexUnder: the assembler stripped the leading letters of a mnemonic that starts with a hex digit (CreateEnvironment read as reateEnvironment, Call1 as ll1). An offset prefix must now be a token of its own, as in #22 by @Abel-Guta.

Downloads

Each archive contains the hermes-decomp and hermes-mcp binaries. Verify with shasum -a 256 -c SHA256SUMS.

File SHA256
hermes-decomp-v0.2.4-linux-x86_64.tar.gz 6e070410432575698657b38d3497f66fd91c0c00f63880d6776703d81d99b5ac
hermes-decomp-v0.2.4-linux-arm64.tar.gz 09d70f25ae159a815c71d6ab29e0779af94b194606a7917c8a74485698298b45
hermes-decomp-v0.2.4-macos-arm64.tar.gz 4794eb85476c5c223a0d8553228cc9e8e1a7d0a1730d31570f63c555753f891c
hermes-decomp-v0.2.4-windows-x86_64.zip 2609474a9099fe5887a54d92ac3fd1c5101ce1d8adb310465798021f8422e860