Skip to content

Add mquickjs variant support with host function callbacks#249

Open
justjake wants to merge 17 commits intomainfrom
mquickjs
Open

Add mquickjs variant support with host function callbacks#249
justjake wants to merge 17 commits intomainfrom
mquickjs

Conversation

@justjake
Copy link
Owner

Summary

  • Add mquickjs (MicroQuickJS) as a new variant option for quickjs-emscripten
  • Implement host function callbacks (vm.newFunction()) for mquickjs
  • Add runtime feature detection API (hasSupport(), assertHasSupport())

Details

mquickjs Variant

mquickjs is a minimal QuickJS fork targeted at embedded systems (~10KB RAM, ~100KB ROM). It lacks:

  • Modules (ES6 import/export)
  • Promises
  • Symbols (built-in)
  • BigInt
  • Intrinsics configuration

Host Function Callbacks

mquickjs requires compile-time stdlib customization since its function table is ROM-resident. This PR adds:

  • c/qts_mquickjs_stdlib.c: Custom stdlib generator that includes qts_host_trampoline in the function table
  • Build rules in Variant.mk to compile the stdlib generator with host cc and generate the header with -m32 for wasm32
  • QTS_NewFunction implementation using JS_NewCFunctionParams to create closures with host_ref_id

Feature Detection

Runtime API to detect which features are available in each variant:

if (QuickJS.hasSupport("modules")) {
  // Use module features
}

// Or throw if feature not available
QuickJS.assertHasSupport("promises", "evalCode with module flag");

Test plan

  • Build mquickjs-wasmfile-debug-sync variant successfully
  • Basic eval works: vm.evalCode('1 + 2') returns 3
  • Host functions work: vm.newFunction('add', ...) can be called from JS
  • Regular quickjs variants still build and work correctly

🤖 Generated with Claude Code

justjake and others added 17 commits February 16, 2026 10:25
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
git-subtree-dir: vendor/mquickjs
git-subtree-split: ee50431eac9b14b99f722b537ec4cac0c8dd75ab
- Add MQuickJS to CLibrary enum and build matrix
- Exclude singlefile and asyncify builds for mquickjs
- Add mquickjs-specific object files and defines in Variant.mk

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add QTS_Has*Support() C functions to detect variant capabilities
- Create interface-mquickjs.c with mquickjs-specific implementation
- Add QuickJSFeature type and QuickJSUnsupported error class
- Add hasSupport() and assertHasSupport() methods to QuickJSWASMModule
- Update Variant.mk to select interface file based on variant

Features detected: modules, promises, symbols, bigint, intrinsics, eval

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Create QuickJSFeatures class with has() and assertHas() methods
- Expose features via module.features, runtime.features, context.features
- All share the same QuickJSFeatures instance per module
- Add feature checks to unsupported operations:
  - newUniqueSymbol, newSymbolFor, getSymbol (symbols)
  - newBigInt, getBigInt (bigint)
  - newPromise (promises)
  - setModuleLoader (modules)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Updates generated Makefiles with INTERFACE_SOURCE variable and
regenerates ffi.ts files with QTS_Has*Support function declarations.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Adds mquickjs vendor subtree from bellard/mquickjs and regenerates
all variant packages with feature detection FFI functions.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
mquickjs was missing JS_GetContextOpaque function which is needed by
quickjs-emscripten to store runtime data in the context. Added the
function to both mquickjs.h and mquickjs.c.

Also generates mquickjs_atom.h which is required for building mquickjs.

All variants rebuilt with feature detection support (QTS_Has*Support).

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
git-subtree-dir: vendor/mquickjs
git-subtree-split: ee50431eac9b14b99f722b537ec4cac0c8dd75ab
- Add QTS_NewHostRef and QTS_GetHostRefId to interface-mquickjs.c
- Fix Variant.mk to use quickjs-amalgam.o for quickjs-ng variants
- Update mquickjs patch file to use git diff format
- Add mquickjs_atom.h generated file
- Regenerate all variant packages and docs

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The helper allows tests to declare feature requirements:
- If feature is supported: test runs normally
- If feature is NOT supported: test passes if it either succeeds
  OR throws QuickJSUnsupported

Usage:
  requiresFeature('bigint', () => { ... })  // uses vm.features
  requiresFeature('bigint', module.features, () => { ... })  // explicit

Updated bigint and symbol tests to use the new helper.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implement vm.newFunction() for mquickjs by creating a custom stdlib that
includes a host function trampoline. mquickjs requires compile-time stdlib
customization since its function table is ROM-resident.

Key changes:
- Add c/qts_mquickjs_stdlib.c: Custom stdlib with qts_host_trampoline in
  the function table at JS_CFUNCTION_USER (index 1)
- Update templates/Variant.mk: Add rules to compile stdlib generator with
  host cc and generate header with -m32 flag for wasm32 compatibility
- Update c/interface-mquickjs.c: Use generated qts_mquickjs_stdlib header
- Add QTS_HasFunctionsSupport FFI function returning 1 for mquickjs

The trampoline is called when JS invokes a host-created function. It
extracts the host_ref_id from the closure params and dispatches to the
host callback via qts_host_call_function.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Replace runtime C feature detection with static TypeScript configuration:

- Add LIBRARY_FEATURES constant in prepareVariants.ts defining feature
  support for each C library (quickjs, quickjs-ng, mquickjs)
- Add QuickJSFeature type and QuickJSFeatureRecord to variant-types.ts
- Generate features property in each variant's index.ts
- Update module.ts to accept features from variant instead of FFI
- Remove QTS_Has*Support() C functions from interface.c and
  interface-mquickjs.c
- Remove corresponding FFI declarations from ffi.ts and ffi-async.ts

This ensures feature availability is defined once in prepareVariants.ts
and automatically propagated to all generated variants.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
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

Comments