Visit project on GitHub
Set theme to dark

WebAssembly/WASM

Cloudflare Workers supports running small WebAssembly modules within either script-based or module-based workers.

Denoflare provides a simple way to serve and deploy workers with WebAssembly components, building on Deno's built-in WebAssembly support .

Module-based workers

For module-based Cloudflare Workers, Cloudflare requires WASM to be specified with an ES6 import of the form import module from "./hello.wasm" (module is then a WebAssembly.Module ).

Since this is not valid in browsers/Deno, nor valid under the proposed WebAssembly/ES Module Integration , Denoflare needs to slighty modify the standard bundled module worker it uploads to Cloudflare during a denoflare push.

It also needs to have syntax that will run in denoflare serve in both local isolation modes, as well incorporate well into other Deno projects unrelated to Denoflare.

To accomplish this, Denoflare provides a special function called importWasm that will load WASM properly in Deno and both modes of denoflare serve, and will be rewritten during denoflare push to the syntax required by Cloudflare. importWasm is just a small standard Deno function , it builds on import.meta.url and Deno's recent support for local file:// fetch.

worker.ts

import { importWasm } from 'https://raw.githubusercontent.com/skymethod/denoflare/v0.4.4/common/import_wasm.ts';
const module = await importWasm(import.meta.url, './hello.wasm');
// import module from './hello.wasm';
// is the replacement used when pushing to Cloudflare

export default {
    fetch(): Response {
        try {
            // call hello.wasm
            const instance = new WebAssembly.Instance(module);
            const result = (instance.exports.main as CallableFunction)();

            const html = `<h3>Result from hello.wasm call: ${result}</h3>`;
            return new Response(html, { status: 200, headers: { 'Content-Type': 'text/html; charset=utf-8' } });
        } catch (e) {
            const html = `${e}`;
            return new Response(html, { status: 500, headers: { 'Content-Type': 'text/html; charset=utf-8' } });
        }
    }
};

See the hello-wasm-worker example for more information.

Script-based workers

For the older script-based Cloudflare Workers, WebAssembly modules are injected using global environment variable variable bindings .

Define your environment variable name and wasmModule in the script's bindings section in your .denoflare configuration file, then use the injected global variable at runtime, it will be a WebAssembly.Module .

worker.js

self.addEventListener('fetch', event => {
    event.respondWith(safeHandleRequest(event));
});

async function safeHandleRequest(event) {
    try {
        // call hello.wasm
        const instance = new WebAssembly.Instance(helloModule);
        const result = instance.exports.main();

        const html = `<h3>Result from hello.wasm call: ${result}</h3>`;
        return new Response(html, { status: 200, headers: { 'Content-Type': 'text/html; charset=utf-8' } });
    } catch (e) {
        const html = `${e}`;
        return new Response(html, { status: 500, headers: { 'Content-Type': 'text/html; charset=utf-8' } });
    }
}

snippet from .denoflare config file

"wasm-script-worker": {
    "path": "/path/to/worker.js",
    "bindings": {
        "helloModule": { "wasmModule": "/path/to/hello.wasm" },
    }
}