Security News
Fluent Assertions Faces Backlash After Abandoning Open Source Licensing
Fluent Assertions is facing backlash after dropping the Apache license for a commercial model, leaving users blindsided and questioning contributor rights.
@deislabs/wasm-linker-js
Advanced tools
This is an experimental JavaScript library that helps instantiating WebAssembly modules with imports by providing functionality to link JavaScript objects (functions, memories, globals) as imports, as well as automatically perform name based resolution for linking entire modules.
The API loosely follows the Wasmtime linker, (see the linker documentation), and it exposes asynchronous import functionality enabled by Binaryen and Asyncify.
For more examples of using the Linker in both TypeScript and JavaScript, check the linker tests and the Node.js examples.
First, add the package to your project:
$ npm install @deislabs/wasm-linker-js
Note that in order to run the examples shown here,
binaryen
is also required (npm install binaryen
), in order to show the text format of the WebAssembly modules. In real world scenarios that is not necessary, and the modules can be compiled from their binary representation without additional dependencies.
Assuming we are trying to instantiate the module represented in its text format
below (transformed to its binary representation using Binaryen), we
can satisfy its import using the define
method available on the linker:
const { Linker } = require("@deislabs/wasm-linker-js");
const { parseText } = require("binaryen");
const usingAdd = `
(module
(import "calculator" "add" (func $calc_add (param i32 i32) (result i32)))
(memory 1 1)
(export "memory" (memory 0))
(export "add" (func $add))
(func $add (param i32) (param i32) (result i32)
(return
(call $calc_add
(local.get 0)
(local.get 1)
)
)
)
)
`;
(async () => {
var linker = new Linker();
// The "usingAdd" module imports calculator.add.
// We define it, provide a JS implementation, then
// instantiate it.
linker.define("calculator", "add", (a, b) => a + b);
var calc = await linker.instantiate(parseText(usingAdd).emitBinary());
var result = calc.instance.exports.add(1, 2);
console.log(result);
})();
If we have a compiled module that exports items (defined below in its text
format and contained in the add
constant) that our initial module needs to
import, we can add it to the linker, then continue instantiating our module
(defined above in its text format and contained in the usingAdd
constant):
const { Linker } = require("@deislabs/wasm-linker-js");
const { parseText } = require("binaryen");
const add = `
(module
(memory 1 1)
(export "memory" (memory 0))
(export "add" (func $add))
(func $add (param i32) (param i32) (result i32)
(return
(i32.add
(local.get 0)
(local.get 1)
)
)
)
)
`;
(async () => {
var linker = new Linker();
// The "usingAdd" module above imports calculator.add.
// We link a module that exports the functionality
// required, then instantiate the module that uses it.
await linker.module(
"calculator",
new WebAssembly.Module(parseText(add).emitBinary())
);
var calc = await linker.instantiate(parseText(usingAdd).emitBinary());
var result = calc.instance.exports.add(1, 2);
console.log(result);
})();
The current WebAssembly MVP does not have a way of waiting for the execution of asynchronous imports (see this issue). To enable this functionality, Binaryen has a pass that transforms a Wasm module and allows it to pause and resume by unwiding and rewinding the call stack. When enabled, this library can use the JavaScript wrapper of Asyncify and define asynchronous import functions for WebAssembly modules (note that the Asyncify pass must have been applied to the module before instantiating using the linker):
const { Linker } = require("@deislabs/wasm-linker-js");
const { parseText } = require("binaryen");
(async () => {
var useAsyncify = true;
var linker = new Linker(useAsyncify);
// Notice how we define an asynchronous import, which
// will wait for 1.5s before returning the result.
var sleep = function (ms) {
return new Promise((resolve) => {
setTimeout(resolve, ms);
});
};
linker.define("calculator", "add", async (a, b) => {
await sleep(1500);
return a + b;
});
let bytes = parseText(usingAdd);
// we perform the asyncify compiler pass from Binaryen
bytes.runPasses(["asyncify"]);
var calc = await linker.instantiate(bytes.emitBinary());
var result = await calc.instance.exports.add(1, 2);
console.log(result);
})();
For browsers that support the WebAssembly streaming APIs, the linker exposes two
methods that can be used to efficiently instantiate modules from a streamed
source: moduleStreaming
, which instantiates a module and adds its exports to
the linker's cache, and instantiateStreaming
, which instantiates a module and
returns its the WebAssemblyInstantiatedSource
:
(async () => {
var linker = new Linker();
await linker.moduleStreaming("calculator", fetch("calculator.wasm"));
var mod = await linker.instantiateStreaming(fetch("using_calculator.wasm"));
console.log(mod.instance.exports.multiply(3, 4));
}
See the documentation for the browser streaming APIs for more information about instantiating modules from streamed sources.
The linker also allows adding an already instantiated module, through the
instance
method, and aliasing a module under a new name, through the alias
method. Most public methods defined on the Linker have a correspondent in the
Wasmtime Linker, and we try to keep the APIs similar.
instance
method).examples/
directory in
this repository. While functional, the implementation is far from ideal - the
WebPack configuration for generating a browser-compatible library is not
optimal (this should be changed to use ECMAScript modules).This project welcomes contributions through the GitHub pull request process. Prerequisites to building the project:
npm
To iterate on the project locally:
$ npm run build
$ npm test
$ npm run examples
This project has adopted the Microsoft Open Source Code of Conduct.
For more information see the Code of Conduct FAQ or contact opencode@microsoft.com with any additional questions or comments.
FAQs
A simple WebAssembly linker
We found that @deislabs/wasm-linker-js demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 3 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Fluent Assertions is facing backlash after dropping the Apache license for a commercial model, leaving users blindsided and questioning contributor rights.
Research
Security News
Socket researchers uncover the risks of a malicious Python package targeting Discord developers.
Security News
The UK is proposing a bold ban on ransomware payments by public entities to disrupt cybercrime, protect critical services, and lead global cybersecurity efforts.