A packer that adds a webpage to WASM module, making it self-hosted!
At the moment, Browsers can not execute WebAssembly as a native single page app. Hopefully, this will change at some point. This 'packer' allows you to preserve the WebAssembly interpretation, unchanged, while adding an HTML loader as a form of polyfill for the native loader environment.
That said you could also regard it as a more general tool for WebAssembly plugins, as a form of hypervisor. Provide a stage2 loader that emulates the host environment within an HTML page. This could be, for instance, a WASI environment with a file system in local storage. Such an app can be ran natively or deployed to a browser as a 'hardware-agnostic' alternative, from a single binary file.
How to use it
The 'packer' acts as a filter for a WebAssembly module. It's a standard clap app if you want to explore its command line options.
# Assume you want to deploy a 'TodoMVC' app:
wasm-as-html --index-html /my/index.html /my/todomvc.js < /my/todomvc_bg.wasm > todomvc.html
See [examples/yew/Readme.md] for a specific description.
There's an experimental
--edit flag. This replaces stage1 with an auto-reload driver, which will periodically refetch the document to compare hashes. It will the invoke the entrypoint with the new bytes, again.
How it works
init and default export take this exact argument to instantiate the bindings marked as its main function.
The technical inner workings:
The first section in WASM is a custom one that parses as HTML. The trick take from here implemented in an program fashion. Note that this
stage0is not of arbitrary size. Otherwise the WebAssembly length encoding of the section's length will cause problems as they parse as good characters. This reads the first custom section of name
The second section is another custom one, which is our stage1 with arbitrary contents. We almost immediately dispatch here from stage0 leaving behind all notions of HTML that we started with. We're now preparing the web page for the module packed as stage2. That is, loading a new skeleton with expected elements that the module might need to bootstrap itself.
It reads the section title polyglot_stage1_html for contents of a new page, as well as the first
polyglot_stage2for the subsequent module.
WIP: additionally, an auxiliary
.zip file can be passed. The packer then ensures that the result is also a valid zip archive with all files intact and such that they are accessible from the webassembly module as a custom module.