Skip to content

Allow extending hyperlight-js-runtime with custom native modules #48

@simongdavies

Description

@simongdavies

Summary

I'd like to add custom native Rust modules to the JS runtime without forking hyperlight-js-runtime. Currently the native module registry is internal and not extensible.

Use Case

Some operations are too slow in pure JavaScript. For example, DEFLATE compression is ~50-100x slower than native Rust, which can cause CPU timeouts on large inputs. I want to add native modules that run inside the same Hyperlight guest VM without maintaining a full fork of the runtime.

Desired Outcome

  1. Build a custom runtime binary that includes all default native modules (io, crypto, console, require) plus my own
  2. Use the same mechanism that upstream uses to declare native modules
  3. Automatically inherit new native modules when upstream adds them

Proposed Approach

  1. Expose hyperlight-js-runtime as a library — add [lib] to Cargo.toml so custom runtimes can link against it

  2. Provide a native_modules! macro that generates a NativeModuleLoader. The macro always chains to the upstream loader first, then checks additional modules:

    // Upstream uses:
    native_modules! {
        "io" => io::js_io,
        "crypto" => crypto::js_crypto,
        "console" => console::js_console,
        "require" => require::js_require,
    }
    
    // Extender uses (upstream modules are inherited automatically):
    native_modules! {
        "compression" => my_compression_module,
    }

    The macro-generated loader delegates to hyperlight_js_runtime::NativeModuleLoader for any module it doesn't recognize, so extenders automatically get all upstream modules without listing them.

  3. Build-time binary override — add an env var check in hyperlight-js/build.rs so custom runtime binaries can be embedded instead of the default:

    HYPERLIGHT_JS_RUNTIME_PATH=/path/to/custom-runtime cargo build

Benefits

  • Same macro used by upstream and extenders
  • Extenders automatically inherit upstream modules via delegation
  • Compile-time only — no runtime registration or mutation

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions