Skip to content

Add versioned bytecode file support to qjsc and qjs#541

Open
zzjjob wants to merge 1 commit into
bellard:masterfrom
zzjjob:feature/checked-bytecode-files-upstream
Open

Add versioned bytecode file support to qjsc and qjs#541
zzjjob wants to merge 1 commit into
bellard:masterfrom
zzjjob:feature/checked-bytecode-files-upstream

Conversation

@zzjjob

@zzjjob zzjjob commented Jul 14, 2026

Copy link
Copy Markdown

Supersedes #540, which was automatically closed when the source fork was recreated.

Summary

  • add qjsc -b / qjsc --bytecode to write compiled scripts or modules directly to .qbc files
  • add qjs --bytecode to load and execute those files, including module resolution, top-level await, and script arguments
  • wrap the serialized QuickJS object in a fixed 64-byte header containing a magic value, CONFIG_VERSION, payload length, checksum, and reserved flags
  • reject unsupported versions, malformed headers, size mismatches, unsupported flags, and corrupted payloads before deserialization
  • run the existing test suite through both source and bytecode-file paths

Motivation

qjsc currently emits C source or native executables, but it does not provide a direct file artifact for applications that want to compile JavaScript once and execute it later with the same QuickJS build. Using the raw JS_WriteObject() payload directly also provides no framing for compatibility or integrity checks.

This change adds a small versioned container around the existing QuickJS bytecode representation. Files are intentionally bound to the exact QuickJS CONFIG_VERSION; bytecode from another version is rejected with a clear diagnostic.

Usage

qjsc --bytecode -o app.qbc app.js
qjs --bytecode app.qbc arg1 arg2

qjsc --bytecode -m -o module.qbc module.mjs
qjs --bytecode module.qbc

When -o is omitted, qjsc --bytecode writes out.qbc. Bytecode output accepts exactly one input file and is not combined with byte-swapping.

File format and trust model

The wrapper validates container structure, QuickJS version, payload length, and an FNV-1a checksum. The checksum detects accidental corruption; it is not a cryptographic signature or a sandbox boundary. As with other native bytecode formats, .qbc files should be loaded only from trusted sources.

Tests

  • make test
  • source and generated-QBC execution for the existing language, builtin, loop, bigint, module, worker, std, and read/write handler tests
  • script arguments and ES module execution with top-level await
  • clean rejection of bad magic, version mismatch, and checksum corruption

This PR contains only commit a2c571acad9a4079fc0e29aacc4da7bbef94d4ff on top of master.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant