jscd 0.3.1

Reverse bytenode-compiled .jsc (V8 code cache) back to JavaScript
Documentation
# Contributing

Issues and pull requests are welcome — in English or Chinese.

## Build

```sh
cargo build --release        # -> target/release/jscd
cargo test                   # unit + integration tests (56)
```

Rust **1.96+** (the workspace toolchain pin; the cure-based AST layer itself needs 1.74). `cargo fmt` is **not**
enforced: the code is hand-formatted (long explanatory comments, aligned tables) — please match
the surrounding style rather than reformatting wholesale.

## Gates a change has to pass

- `cargo test` — unit and integration tests.
- `cargo clippy --all-targets -- -D warnings` — the project keeps **zero warnings**; a plain
  `cargo build` must be silent too.
- `scripts/ci_smoke.sh` — compiles every fixture to a real `.jsc` with the `node` on `PATH`,
  decompiles it and gates the product with `node --check`. Where a trustworthy read-only-heap name
  table exists (macOS — see `EMBEDDED_RO_MAP_PLATFORM` in `src/decompile.rs`) it also
  byte-compares the 5 whole-script fixtures against their originals; elsewhere those fixtures get
  the syntax gate only, because built-in names degrade to `<ro…>` placeholders there. No npm
  packages needed.
- If you touched version handling, run the behaviour matrix for at least the affected Node lines:
  `bash scripts/verify_behavior.sh 20.20.2` (Node versions come from `mise`; see the README's
  Verification section for the full matrix and its numbers).

## Adding a fixture

1. **Behaviour fixture** — a file in `tests/fixtures/behav/` whose source defines a top-level
   `function target(...)` (see the existing ones), plus an entry in
   `tests/fixtures/behav/cases.json`:

   ```json
   "my_case": { "cases": [[1, 2], ["a", "b"]] }
   ```

   `cases` is the list of argument lists `target` is called with; the returned values are compared
   against the original. Two optional keys: `min_node` (major version whose parser the syntax
   needs — the cell is skipped below it, e.g. `?.` needs 14) and `same_node_original` (run the
   original with the *same* Node version as the artifact instead of the host's V8 — use it when the
   case's native semantics differ between V8 versions).
2. **Whole-script fixture** — a file in `tests/fixtures/scripts/`; it is picked up automatically
   and its stdout + exit code are compared against the original script.

Fixtures are compiled on the fly by `scripts/mkcorpus.js` (bytenode's exact flags +
`createCachedData()`); no `.jsc` is checked in. The fixture list is read from `cases.json`, so a
new entry joins the matrix automatically.

## Notes

- `docs/VERSIONS.md` — per-V8-version engineering notes (Chinese), the place to record a new
  version finding.
- The CLI help section embedded in both READMEs is generated: after changing any help text
  (or cutting a release) run `python3 scripts/update_readme_help.py` — it rewrites the marked
  block in place, `--check` just reports drift.
- `docs/stream-format.md` — the serialized-payload format notes.
- Version numbers: `build.rs` injects the git tag as `jscd --version` (and falls back to the
  `Cargo.toml` version when there is no `.git`, e.g. a crates.io install); releases are cut with
  `scripts/release.sh vX.Y.Z`, which requires `Cargo.toml` to carry the same version. After the CI
  release finishes, publish the crate with `cargo publish`.