UNPKG

@ayonli/jsext

Version:

A JavaScript extension package for building strong and modern applications.

118 lines (114 loc) 4.21 kB
'use strict'; var env = require('./env.js'); var fs = require('./fs.js'); var path = require('./path.js'); var module_web = require('./module/web.js'); var path_util = require('./path/util.js'); /** * Utility functions for working with JavaScript modules. * @module */ const wasmCache = new Map(); /** * Imports a WebAssembly module from a URL or file path (relative to the current * working directory if not absolute), or from a {@link WebAssembly.Module} * object, returns the symbols exported by the module. * * This function is available in both the browser and server runtimes such as * Node.js, Deno, Bun and Cloudflare Workers. * * This function uses cache to avoid loading the same module multiple times. * * @param imports An object containing the values to be imported by the * WebAssembly module, allowing passing values from JavaScript to WebAssembly. * * ```ts * import { importWasm } from "@ayonli/jsext/module"; * * const { timestamp } = await importWasm<{ * timestamp: () => number; // function exported by the WebAssembly module * }>("./examples/convert.wasm", { * // JavaScript module and function passed into the WebAssembly module * Date: { now: Date.now }, * }); * * console.log("The current timestamp is:", timestamp()); * ``` * * The corresponding WebAssembly module `convert.wasm` in text format looks like * this: * * ```wat * ;; examples/convert.wat * (module * (import "Date" "now" (func $now (result i32))) * (func (export "timestamp") (result i32) * call $now * ;; Convert to seconds * i32.const 1000 * i32.div_u * ) * ) * ``` * * NOTE: In Cloudflare Workers, this function cannot access the file system, we * need to import the WebAssembly module with a `import` statement or with the * `import()` function before we can use it. For example: * * ```ts * // In Cloudflare Workers * import { importWasm } from "@ayonli/jsext/module"; * import wasmModule from "./examples/convert.wasm"; * * const { timestamp } = await importWasm<{ * timestamp: () => number; // function exported by the WebAssembly module * }>(wasmModule, { * // JavaScript module and function passed into the WebAssembly module * Date: { now: Date.now }, * }); * * console.log("The current timestamp is:", timestamp()); * ``` * * NOTE: Deno v2.1+ has built-in support for importing WebAssembly modules as * JavaScript modules, it's recommended to use the built-in `import` statement * to import WebAssembly modules directly for Deno programs. */ async function importWasm(module, imports = undefined) { if ((!env.isNodeLike && !env.isDeno) || module instanceof WebAssembly.Module || (module instanceof URL && module.protocol !== "file:") || (typeof module === "string" && path_util.isUrl(module) && !path_util.isFileUrl(module))) { return await module_web.importWasm(module, imports); } const src = typeof module === "string" ? module : module.href; const filename = path_util.isFileUrl(src) ? path.toFsPath(src) : path.resolve(src); if (typeof WebAssembly.instantiateStreaming === "function") { let cache = wasmCache.get(filename); if (!cache) { const stream = fs.createReadableStream(filename); cache = Promise.resolve(new Response(stream, { headers: { "Content-Type": "application/wasm" }, })).then(res => WebAssembly.instantiateStreaming(res, imports)) .then(ins => ins.instance.exports); wasmCache.set(filename, cache); } return await cache; } else { let cache = wasmCache.get(filename); if (!cache) { cache = fs.readFile(filename) .then(bytes => WebAssembly.instantiate(bytes, imports)) .then(ins => ins.instance.exports); wasmCache.set(filename, cache); } return await cache; } } exports.importScript = module_web.importScript; exports.importStylesheet = module_web.importStylesheet; exports.interop = module_web.interop; exports.isMain = module_web.isMain; exports.importWasm = importWasm; //# sourceMappingURL=module.js.map