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.
This loader requires AssemblyScript ~0.18, Node.js >= 12 and webpack 5
# with npm
npm install as-loader
npm install --save-dev assemblyscript
# with yarn
yarn add as-loader
yarn add --dev assemblyscript
The minimal webpack.config.js
:
module.exports = {
entry: "src/index.ts",
resolve: {
extensions: [".ts", ".js"],
},
module: {
rules: [
{
test: /\.ts$/,
include: path.resolve(__dirname, "src/assembly"),
loader: "as-loader",
options: {
// optional loader and compiler options
}
},
{
test: /\.ts$/,
exclude: path.resolve(__dirname, "src/assembly"),
loader: "ts-loader",
},
],
},
};
By default, the loader emits a .wasm
file (+ .wasm.map
if source maps are enabled) and
creates CommonJS module that exports URL to the emitted .wasm
file.
If you enable fallback
option, the loader will emit additional .js
file (+ .js.map
if source maps are enabled)
and will expose async fallback()
function which dynamically imports fallback module.
To simplify loading logic, you can use as-loader/runtime
loader which uses
@assemblyscript/loader, or
as-loader/runtime/bind
loader which uses as-bind.
These loaders provide correct types, checks for WebAssembly support, and uses fallback if available.
import * as myModule from "./assembly/myModule";
import { instantiate } from "as-loader/runtime";
async function loadAndRun() {
const { exports } = await instantiate(myModule);
exports.myFunction(100);
}
loadAndRun();
import * as myModule from "./assembly/myModule";
import { instantiate } from "@assemblyscript/loader";
async function loadAndRun() {
const { exports } = await instantiate<typeof myModule>(
// workaround for TypeScript
fetch((myModule as unknown) as string)
);
exports.myFunction(100);
}
loadAndRun();
For more details, check src/runtime directory
as-loader/runtime
This runtime loader uses @assemblyscript/loader under the hood.
export interface WasmModuleInstance<TModule> {
type: "wasm";
exports: AsLoaderRuntime & PointerCastObject<TModule>;
module: WebAssembly.Module;
instance: WebAssembly.Instance;
}
export interface JsModuleInstance<TModule> {
type: "js";
exports: TModule;
}
export type ModuleInstance<TModule> =
| WasmModuleInstance<TModule>
| JsModuleInstance<TModule>;
export function instantiate<TModule>(
module: TModule,
load: (url: string) => Promise<unknown>,
imports?: object,
fallback: boolean = false,
supports?: () => boolean
): Promise<ModuleInstance<TModule>>
as-loader/runtime
binding code example:// ./src/assembly/sayHello.ts
export function sayHello(firstName: string, lastName: string): string {
return `Hello ${firstName} ${lastName}!`;
}
// ./src/sayHello.ts
import * as sayHelloModule from "./assembly/sayHello";
import { instantiate } from "as-loader/runtime";
export async function loadModule(): Promise<typeof sayHelloModule> {
const { exports } = await instantiate(sayHelloModule, fetch);
const { __pin, __unpin, __newString, __getString } = exports;
function sayHello(firstName: string, lastName: string): string {
const firstNamePtr = __pin(__newString(firstName));
const lastNamePtr = __pin(__newString(lastName));
const result = __getString(
exports.sayHello(firstNamePtr, lastNamePtr)
);
__unpin(firstNamePtr);
__unpin(lastNamePtr);
return result;
}
return { sayHello };
}
as-loader/runtime/bind
This runtime loader uses as-bind under the hood.
Requires bind
option enabled in the webpack loader configuration.
Keep in mind that currently it's recommended to manually set
Function.returnType
export interface BoundWasmModuleInstance<TModule, TImports> {
type: "wasm-bound";
exports: AsLoaderRuntime & BoundExports<TModule>;
unboundExports: AsLoaderRuntime & PointerCastObject<TModule>;
importObject: TImports;
module: WebAssembly.Module;
instance: WebAssembly.Instance;
}
export interface JsModuleInstance<TModule> {
type: "js";
exports: TModule;
}
type BoundModuleInstance<TModule, TImports> =
| BoundWasmModuleInstance<TModule, TImports>
| JsModuleInstance<TModule>;
export function instantiate<TModule, TImports>(
module: TModule,
load: (url: string) => Promise<unknown>,
imports?: TImports,
fallback: boolean = false,
supports?: () => boolean
): Promise<BoundModuleInstance<TModule, TImports>>
as-loader/runtime/bind
binding code example:// ./src/assembly/sayHello.ts
export function sayHello(firstName: string, lastName: string): string {
return `Hello ${firstName} ${lastName}!`;
}
// ./src/sayHello.ts
import * as sayHelloModule from "./assembly/sayHello";
import { instantiate } from "as-loader/runtime/bind";
export async function loadModule(): Promise<typeof sayHelloModule> {
const module = await instantiate(sayHelloModule, fetch);
return { sayHello: module.exports.sayHello };
}
There are 2 aspects that you have to consider when interacting with a WebAssembly module:
WebAssembly doesn't support function arguments and returns others than number | boolean | bigint
yet.
Because of that, you have to manually translate between WebAssembly pointers and JavaScript objects.
The alternative is to enable the bind
option and use as-loader/runtime/bind
loader which uses an as-bind library.
This simplifies passing types like strings and arrays.
WebAssembly doesn't provide Garbage Collector yet (proposal) - to manage memory,
AssemblyScript offers very lightweight GC implementation. If you use it (see runtime
option),
you have to manually __pin
and __unpin
pointers
to instruct GC if given data can be collected or not.
If you need to support older browsers like Internet Explorer or Edge < 16,
you can use the fallback
option. A fallback module is different from WebAssembly one because you don't have to bind it.
// webpack.config.js
module.exports = {
entry: "src/index.ts",
resolve: {
extensions: [".ts", ".js"],
},
module: {
rules: [
{
test: /\.ts$/,
include: path.resolve(__dirname, "src/assembly"),
use: [
// fallback loader (must be before as-loader)
{
loader: "ts-loader",
options: {
transpileOnly: true
}
},
// as-loader, apart from building .wasm file,
// will forward assembly script files to the fallback loader above
// to build a .js file
{
loader: "as-loader",
options: {
fallback: true
}
}
]
},
{
test: /\.ts$/,
exclude: path.resolve(__dirname, "src/assembly"),
loader: "ts-loader",
},
],
},
};
// ./src/assembly/sayHello.ts
export function sayHello(firstName: string, lastName: string): string {
return `Hello ${firstName} ${lastName}!`;
}
// ./src/sayHello.ts
import * as sayHelloModule from "./assembly/sayHello";
import { instantiate } from "as-loader/runtime";
export async function loadModule(): Promise<typeof sayHelloModule> {
// set fallback option to true (opt-in)
const module = await instantiate(sayHelloModule, fetch, undefined, true);
if (module.type === 'wasm') {
const { __pin, __unpin, __newString, __getString } = exports;
function sayHello(firstName: string, lastName: string): string {
const firstNamePtr = __pin(__newString(firstName));
const lastNamePtr = __pin(__newString(lastName));
const result = __getString(
exports.sayHello(firstNamePtr, lastNamePtr)
);
__unpin(firstNamePtr);
__unpin(lastNamePtr);
return result;
}
return { sayHello };
} else {
return { sayHello: module.exports.sayHello }
}
}
Name | Type | Description |
---|---|---|
name | string | Output asset name template, [name].[contenthash].wasm by default. |
bind | boolean | If true, adds as-bind library files to the compilation (required if you want to use as-loader/runtime/bind ). |
fallback | boolean | If true, creates additional JavaScript file which can be used if WebAssembly is not supported. |
raw | boolean | If true, returns binary instead of emitting file. Use for chaining with other loaders. |
Options passed to the AssemblyScript compiler.
Name | Type | Description |
---|---|---|
debug | boolean | Enables debug information in emitted binaries, enabled by default in webpack development mode. |
optimizeLevel | number | How much to focus on optimizing code, 3 by default. [0-3] |
shrinkLevel | number | How much to focus on shrinking code size, 1 by default. [0-2] |
coverage | boolean | Re-optimizes until no further improvements can be made. |
noAssert | boolean | Replaces assertions with just their value without trapping, enabled by default in webpack production mode. |
importMemory | boolean | Imports the memory provided as 'env.memory'. |
noExportMemory | boolean | Does not export the memory as 'memory'. |
initialMemory | number | Sets the initial memory size in pages. |
maximumMemory | number | Sets the maximum memory size in pages. |
sharedMemory | boolean | Declare memory as shared. Requires maximumMemory. |
importTable | boolean | Imports the function table provided as 'env.table'. |
exportTable | boolean | Exports the function table as 'table'. |
runtime | string | Specifies the runtime variant to include in the program. Available runtime are: "incremental" (default), "minimal", "stub" |
exportRuntime | boolean | Exports the runtime helpers (__new, __collect etc.). Enabled by default. |
explicitStart | boolean | Exports an explicit '_start' function to call. |
enable | string[] | Enables WebAssembly features being disabled by default. Available features are: "sign-extension", "bulk-memory", "simd", "threads", "reference-types", "gc" |
disable | string[] | Disables WebAssembly features being enabled by default. Available features are: "mutable-globals" |
lowMemoryLimit | boolean | Enforces very low (<64k) memory constraints. |
memoryBase | number | Sets the start offset of emitted memory segments. |
tableBase | number | Sets the start offset of emitted table elements. |
trapMode | string | Sets the trap mode to use. Available modes are: "allow", "clamp", "js" |
noValidate | boolean | Skips validating the module using Binaryen. |
MIT
FAQs
AssemblyScript loader for webpack
The npm package as-loader receives a total of 8 weekly downloads. As such, as-loader popularity was classified as not popular.
We found that as-loader demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer 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.