@thi.ng/wasm-api
Advanced tools
Comparing version 0.5.0 to 0.6.0
148
api.d.ts
@@ -1,3 +0,4 @@ | ||
import type { Fn, Fn2 } from "@thi.ng/api"; | ||
import type { FloatType, Fn, Fn2 } from "@thi.ng/api"; | ||
import type { WasmBridge } from "./bridge.js"; | ||
export declare const PKG_NAME = "@thi.ng/wasm-api"; | ||
export declare type BigIntArray = bigint[] | BigInt64Array | BigUint64Array; | ||
@@ -63,9 +64,19 @@ /** | ||
* | ||
* @remarks | ||
* In the supplied Zig bindings (/zig/core.zig) this is a no-op (currently). | ||
* | ||
* @param addr | ||
* @param numBytes | ||
*/ | ||
_wasm_free(addr: number): void; | ||
_wasm_free(addr: number, numBytes: number): void; | ||
} | ||
export interface WasmMemViews { | ||
i8: Int8Array; | ||
u8: Uint8Array; | ||
i16: Int16Array; | ||
u16: Uint16Array; | ||
i32: Int32Array; | ||
u32: Uint32Array; | ||
i64: BigInt64Array; | ||
u64: BigUint64Array; | ||
f32: Float32Array; | ||
f64: Float64Array; | ||
} | ||
/** | ||
@@ -104,2 +115,129 @@ * Core API of WASM imports defined by the {@link WasmBridge}. The same | ||
} | ||
export interface WasmTypeBase { | ||
/** | ||
* Base address in linear WASM memory. | ||
*/ | ||
readonly __base: number; | ||
/** | ||
* Obtain as byte buffer | ||
*/ | ||
readonly __bytes: Uint8Array; | ||
} | ||
export interface WasmType<T> { | ||
readonly align: number; | ||
readonly size: number; | ||
instance: Fn<number, T>; | ||
} | ||
export declare type WasmTypeConstructor<T> = Fn<WasmMemViews, WasmType<T>>; | ||
export declare type WasmInt = "i8" | "i16" | "i32" | "i64"; | ||
export declare type WasmUint = "u8" | "u16" | "u32" | "u64"; | ||
export declare type WasmFloat = FloatType; | ||
export declare type WasmPrim = WasmInt | WasmUint | WasmFloat; | ||
export declare type TypeColl = Record<string, TopLevelType>; | ||
export interface TypeInfo { | ||
/** | ||
* Auto-computed size (in bytes) | ||
* | ||
* @internal | ||
*/ | ||
__size?: number; | ||
/** | ||
* Auto-computed offset (in bytes) in parent struct | ||
* | ||
* @internal | ||
*/ | ||
__offset?: number; | ||
/** | ||
* Auto-computed alignment (in bytes) | ||
* | ||
* @internal | ||
*/ | ||
__align?: number; | ||
} | ||
export interface TopLevelType extends TypeInfo { | ||
name: string; | ||
doc?: string; | ||
type: "struct" | "enum"; | ||
} | ||
export interface Struct extends TopLevelType { | ||
type: "struct"; | ||
fields: StructField[]; | ||
/** | ||
* If true, struct fields will be re-ordered in descending order based on | ||
* their {@link TypeInfo.__align} size. | ||
* | ||
* @defaultValue false | ||
*/ | ||
auto?: boolean; | ||
} | ||
export interface StructField extends TypeInfo { | ||
/** | ||
* Field name (prefix: "__" is reserved) | ||
*/ | ||
name: string; | ||
/** | ||
* Field docstring (can be multiline, will be formatted) | ||
*/ | ||
doc?: string; | ||
/** | ||
* Field type tag/qualifier (note: `slice` & `vec` are only supported by | ||
* Zig & TS) | ||
* | ||
* @defaultValue "scalar" | ||
*/ | ||
tag?: "scalar" | "array" | "ptr" | "slice" | "vec"; | ||
/** | ||
* Field base type. If not a {@link WasmPrim} or `opaque`, the value is | ||
* interpreted as another type name in the {@link TypeColl}. | ||
* | ||
* TODO `opaque` currently unsupported. | ||
*/ | ||
type: WasmPrim | "opaque" | string; | ||
/** | ||
* TODO currently unsupported! | ||
*/ | ||
sentinel?: number; | ||
/** | ||
* Array or vector length | ||
*/ | ||
len?: number; | ||
/** | ||
* TODO currently unsupported! | ||
*/ | ||
default?: any; | ||
} | ||
export interface Enum extends TopLevelType { | ||
type: "enum"; | ||
/** | ||
* No u64 support, due to Typescript not supporting bigint enum values | ||
*/ | ||
tag: Exclude<WasmUint, "u64">; | ||
values: (string | EnumValue)[]; | ||
} | ||
export interface EnumValue { | ||
name: string; | ||
value?: number; | ||
doc?: string; | ||
} | ||
export interface ICodeGen { | ||
/** | ||
* Optional prelude source, to be prepended before any generated type defs. | ||
*/ | ||
pre?: string; | ||
/** | ||
* Optional source code to be appended after any generated type defs. | ||
*/ | ||
post?: string; | ||
doc: (doc: string, indent: string, acc: string[], topLevel?: boolean) => void; | ||
enum: (type: Enum, types: TypeColl, acc: string[]) => void; | ||
struct: (type: Struct, types: TypeColl, acc: string[]) => void; | ||
} | ||
/** | ||
* WASM usize type. Assuming wasm32 until wasm64 surfaces, then need an option. | ||
*/ | ||
export declare const USIZE = "u32"; | ||
/** | ||
* Byte size of {@link USIZE}. | ||
*/ | ||
export declare const USIZE_SIZE = 4; | ||
//# sourceMappingURL=api.d.ts.map |
10
api.js
@@ -1,1 +0,9 @@ | ||
export {}; | ||
export const PKG_NAME = "@thi.ng/wasm-api"; | ||
/** | ||
* WASM usize type. Assuming wasm32 until wasm64 surfaces, then need an option. | ||
*/ | ||
export const USIZE = "u32"; | ||
/** | ||
* Byte size of {@link USIZE}. | ||
*/ | ||
export const USIZE_SIZE = 4; |
/// <reference types="node" /> | ||
import type { NumericArray } from "@thi.ng/api"; | ||
import type { ILogger } from "@thi.ng/logger"; | ||
import type { BigIntArray, CoreAPI, IWasmAPI, WasmExports } from "./api.js"; | ||
import type { BigIntArray, CoreAPI, IWasmAPI, WasmExports, WasmMemViews } from "./api.js"; | ||
export declare const OutOfMemoryError: { | ||
@@ -31,3 +31,3 @@ new (msg?: string | undefined): { | ||
*/ | ||
export declare class WasmBridge<T extends WasmExports = WasmExports> { | ||
export declare class WasmBridge<T extends WasmExports = WasmExports> implements WasmMemViews { | ||
modules: Record<string, IWasmAPI<T>>; | ||
@@ -49,3 +49,3 @@ logger: ILogger; | ||
exports: T; | ||
core: CoreAPI; | ||
api: CoreAPI; | ||
constructor(modules?: Record<string, IWasmAPI<T>>, logger?: ILogger); | ||
@@ -100,3 +100,3 @@ /** | ||
* // imports defined by the core API of the bridge itself | ||
* core: { ... }, | ||
* wasmapi: { ... }, | ||
* // imports defined by the CustomAPI module | ||
@@ -127,3 +127,4 @@ * custom: { ... } | ||
* start address of the new memory block. If unsuccessful, throws an | ||
* {@link OutOfMemoryError}. | ||
* {@link OutOfMemoryError}. If `clear` is true, the allocated region will | ||
* be zero-filled. | ||
* | ||
@@ -134,5 +135,15 @@ * @remarks | ||
* @param numBytes | ||
* @param clear | ||
*/ | ||
allocate(numBytes: number): number; | ||
free(addr: number): void; | ||
allocate(numBytes: number, clear?: boolean): number; | ||
/** | ||
* Frees a previous allocated memory region using the exported WASM core API | ||
* function {@link WasmExports._wasm_free} (implementation specific). The | ||
* `numBytes` value must be the same as previously given to | ||
* {@link WasmBridge.allocate}. | ||
* | ||
* @param addr | ||
* @param numBytes | ||
*/ | ||
free(addr: number, numBytes: number): void; | ||
getI8(addr: number): number; | ||
@@ -178,3 +189,26 @@ getU8(addr: number): number; | ||
setF64Array(addr: number, buf: NumericArray): this; | ||
/** | ||
* Reads UTF-8 encoded string from given address and optional byte length. | ||
* The default length is 0, which will be interpreted as a zero-terminated | ||
* string. Returns string. | ||
* | ||
* @param addr | ||
* @param len | ||
*/ | ||
getString(addr: number, len?: number): string; | ||
/** | ||
* Encodes given string as UTF-8 and writes it to WASM memory starting at | ||
* `addr`. By default the string will be zero-terminated and only `maxBytes` | ||
* will be written. Returns the number of bytes written. | ||
* | ||
* @remarks | ||
* An error will be thrown if the encoded string doesn't fully fit into the | ||
* designated memory region (also note that there might need to be space for | ||
* the additional sentinel/termination byte). | ||
* | ||
* @param str | ||
* @param addr | ||
* @param maxBytes | ||
* @param terminate | ||
*/ | ||
setString(str: string, addr: number, maxBytes: number, terminate?: boolean): number; | ||
@@ -181,0 +215,0 @@ getElementById(addr: number, len?: number): HTMLElement; |
@@ -31,3 +31,3 @@ import { defError } from "@thi.ng/errors/deferror"; | ||
const logA = (method) => (addr, len) => this.logger.debug(method(addr, len).join(", ")); | ||
this.core = { | ||
this.api = { | ||
printI8: logN, | ||
@@ -140,3 +140,3 @@ printU8: logN, | ||
* // imports defined by the core API of the bridge itself | ||
* core: { ... }, | ||
* wasmapi: { ... }, | ||
* // imports defined by the CustomAPI module | ||
@@ -156,3 +156,3 @@ * custom: { ... } | ||
if (!this.imports) { | ||
this.imports = { core: this.core }; | ||
this.imports = { wasmapi: this.api }; | ||
for (let id in this.modules) { | ||
@@ -182,3 +182,4 @@ if (this.imports[id] !== undefined) { | ||
* start address of the new memory block. If unsuccessful, throws an | ||
* {@link OutOfMemoryError}. | ||
* {@link OutOfMemoryError}. If `clear` is true, the allocated region will | ||
* be zero-filled. | ||
* | ||
@@ -189,4 +190,5 @@ * @remarks | ||
* @param numBytes | ||
* @param clear | ||
*/ | ||
allocate(numBytes) { | ||
allocate(numBytes, clear = false) { | ||
const addr = this.exports._wasm_allocate(numBytes); | ||
@@ -197,7 +199,17 @@ if (!addr) | ||
this.ensureMemory(); | ||
clear && this.u8.fill(0, addr, addr + numBytes); | ||
return addr; | ||
} | ||
free(addr) { | ||
this.logger.debug(`freeing memory @ 0x${U32(addr)}`); | ||
this.exports._wasm_free(addr); | ||
/** | ||
* Frees a previous allocated memory region using the exported WASM core API | ||
* function {@link WasmExports._wasm_free} (implementation specific). The | ||
* `numBytes` value must be the same as previously given to | ||
* {@link WasmBridge.allocate}. | ||
* | ||
* @param addr | ||
* @param numBytes | ||
*/ | ||
free(addr, numBytes) { | ||
this.logger.debug(`freeing memory @ 0x${U32(addr)} .. 0x${U32(addr + numBytes - 1)}`); | ||
this.exports._wasm_free(addr, numBytes); | ||
} | ||
@@ -352,5 +364,29 @@ getI8(addr) { | ||
} | ||
/** | ||
* Reads UTF-8 encoded string from given address and optional byte length. | ||
* The default length is 0, which will be interpreted as a zero-terminated | ||
* string. Returns string. | ||
* | ||
* @param addr | ||
* @param len | ||
*/ | ||
getString(addr, len = 0) { | ||
this.ensureMemory(); | ||
return this.utf8Decoder.decode(this.u8.subarray(addr, len > 0 ? addr + len : this.u8.indexOf(0, addr))); | ||
} | ||
/** | ||
* Encodes given string as UTF-8 and writes it to WASM memory starting at | ||
* `addr`. By default the string will be zero-terminated and only `maxBytes` | ||
* will be written. Returns the number of bytes written. | ||
* | ||
* @remarks | ||
* An error will be thrown if the encoded string doesn't fully fit into the | ||
* designated memory region (also note that there might need to be space for | ||
* the additional sentinel/termination byte). | ||
* | ||
* @param str | ||
* @param addr | ||
* @param maxBytes | ||
* @param terminate | ||
*/ | ||
setString(str, addr, maxBytes, terminate = true) { | ||
@@ -357,0 +393,0 @@ maxBytes = Math.min(maxBytes, this.u8.length - addr); |
# Change Log | ||
- **Last updated**: 2022-08-08T22:36:17Z | ||
- **Last updated**: 2022-08-15T15:40:55Z | ||
- **Generator**: [thi.ng/monopub](https://thi.ng/monopub) | ||
@@ -12,2 +12,36 @@ | ||
## [0.6.0](https://github.com/thi-ng/umbrella/tree/@thi.ng/wasm-api@0.6.0) (2022-08-15) | ||
#### 🚀 Features | ||
- add C11 header/include file, update WasmBridge ([a67dc00](https://github.com/thi-ng/umbrella/commit/a67dc00)) | ||
- migrate headers/includes to /include | ||
- rename "core" import section => "wasmapi" | ||
- rename WasmBridge.core => WasmBridge.api | ||
- update pkg file | ||
- update codegens, add opts, fix alignments ([5c1fec5](https://github.com/thi-ng/umbrella/commit/5c1fec5)) | ||
- add global CodeGenOpts | ||
- update generateTypes() to consider new opts | ||
- add global USIZE type (for pointer sizes & codegens) | ||
- add options for Zig codegen (extra debug helpers) | ||
- simplify TS codegen | ||
- fix sizeOf() for struct fields | ||
- make prepareType() idempotent | ||
- add bindings code generator framework ([17ee06f](https://github.com/thi-ng/umbrella/commit/17ee06f)) | ||
- add/update deps | ||
- add preliminary codegens for Zig & TS | ||
- add supporting types & utils | ||
- add generateTypes() codegen facade fn | ||
- update allocate/free() fns, update Zig core API ([8a55989](https://github.com/thi-ng/umbrella/commit/8a55989)) | ||
- add _wasm_free() Zig impl | ||
- add printFmt() Zig fn | ||
- update WasmBridge.allocate() (add clear option) | ||
- update WasmBridge.free() | ||
- ensure memory in WasmBridge.getString() | ||
- add/update docstrings | ||
#### ♻️ Refactoring | ||
- extract WasmMemViews interface, update test WASM ([4c73e65](https://github.com/thi-ng/umbrella/commit/4c73e65)) | ||
## [0.5.0](https://github.com/thi-ng/umbrella/tree/@thi.ng/wasm-api@0.5.0) (2022-08-08) | ||
@@ -14,0 +48,0 @@ |
export * from "./api.js"; | ||
export * from "./bridge.js"; | ||
export * from "./codegen.js"; | ||
export * from "./object-index.js"; | ||
export * from "./codegen/typescript.js"; | ||
export * from "./codegen/zig.js"; | ||
export * from "./codegen/utils.js"; | ||
//# sourceMappingURL=index.d.ts.map |
export * from "./api.js"; | ||
export * from "./bridge.js"; | ||
export * from "./codegen.js"; | ||
export * from "./object-index.js"; | ||
export * from "./codegen/typescript.js"; | ||
export * from "./codegen/zig.js"; | ||
export * from "./codegen/utils.js"; |
{ | ||
"name": "@thi.ng/wasm-api", | ||
"version": "0.5.0", | ||
"description": "Modular, extensible API bridge and generic glue code between JS & WebAssembly", | ||
"version": "0.6.0", | ||
"description": "Generic, modular, extensible API bridge, glue code and bindings code generator for hybrid JS & WebAssembly projects", | ||
"type": "module", | ||
@@ -35,9 +35,13 @@ "module": "./index.js", | ||
"test": "testament test", | ||
"test:build-zig": "zig build-lib -O ReleaseSmall -target wasm32-freestanding -dynamic --strip --pkg-begin wasmapi zig/core.zig --pkg-end test/custom.zig && wasm-dis -o custom.wast custom.wasm && cp custom.wasm test" | ||
"test:build-zig": "zig build-lib -O ReleaseSmall -target wasm32-freestanding -dynamic --strip --pkg-begin wasmapi include/wasmapi.zig --pkg-end test/custom.zig && wasm-dis -o custom.wast custom.wasm && cp custom.wasm test" | ||
}, | ||
"dependencies": { | ||
"@thi.ng/api": "^8.3.9", | ||
"@thi.ng/api": "^8.4.0", | ||
"@thi.ng/binary": "^3.3.3", | ||
"@thi.ng/checks": "^3.2.4", | ||
"@thi.ng/compare": "^2.1.10", | ||
"@thi.ng/defmulti": "^2.1.12", | ||
"@thi.ng/errors": "^2.1.10", | ||
"@thi.ng/hex": "^2.1.9", | ||
"@thi.ng/idgen": "^2.1.10", | ||
"@thi.ng/idgen": "^2.1.11", | ||
"@thi.ng/logger": "^1.2.0" | ||
@@ -55,2 +59,5 @@ }, | ||
"api", | ||
"bindings", | ||
"c", | ||
"codegen", | ||
"id", | ||
@@ -78,3 +85,4 @@ "logger", | ||
"*.d.ts", | ||
"*.zig" | ||
"codegen", | ||
"include" | ||
], | ||
@@ -91,2 +99,14 @@ "exports": { | ||
}, | ||
"./codegen": { | ||
"default": "./codegen.js" | ||
}, | ||
"./codegen/typescript": { | ||
"default": "./codegen/typescript.js" | ||
}, | ||
"./codegen/utils": { | ||
"default": "./codegen/utils.js" | ||
}, | ||
"./codegen/zig": { | ||
"default": "./codegen/zig.js" | ||
}, | ||
"./object-index": { | ||
@@ -100,3 +120,3 @@ "default": "./object-index.js" | ||
}, | ||
"gitHead": "e579cb171fc720cbf0b71d3a5f4adfacccdaf214\n" | ||
"gitHead": "295e76c6f68ef34ba2117ff77612848e09f5c587\n" | ||
} |
185
README.md
@@ -15,2 +15,6 @@ <!-- This file is generated - DO NOT EDIT! --> | ||
- [Object indices & handles](#object-indices--handles) | ||
- [Data bindings & code generators](#data-bindings--code-generators) | ||
- [Data type definitions](#data-type-definitions) | ||
- [Code generation](#code-generation) | ||
- [Example usage](#example-usage) | ||
- [Status](#status) | ||
@@ -20,2 +24,5 @@ - [Installation](#installation) | ||
- [API](#api) | ||
- [Basic usage example](#basic-usage-example) | ||
- [Zig version](#zig-version) | ||
- [C11 version](#c11-version) | ||
- [Authors](#authors) | ||
@@ -26,17 +33,28 @@ - [License](#license) | ||
Modular, extensible API bridge and generic glue code between JS & WebAssembly. | ||
Generic, modular, extensible API bridge, glue code and bindings code generator for hybrid JS & WebAssembly projects. | ||
This package provides a small, generic and modular | ||
This package provides a the following: | ||
1. A small, generic and modular | ||
[`WasmBridge`](https://docs.thi.ng/umbrella/wasm-api/classes/WasmBridge.html) | ||
class as interop basis and a much reduced boilerplate for hybrid JS/WebAssembly | ||
applications. At the moment only a minimal core API is provided (i.e. for debug | ||
output, string, pointer, typed array accessors [8/16/32/64 bit (u)ints, 32/64 | ||
bit floats]), but in the future we aim to also supply support modules for DOM | ||
manipulation, WebGL, WebGPU, WebAudio etc. | ||
class as interop basis and much reduced boilerplate for hybrid JS/WebAssembly | ||
applications. | ||
2. A minimal core API for debug output, string, pointer, typed array accessors | ||
(8/16/32/64 bit (u)ints, 32/64 bit floats). In the future we aim to also supply | ||
support modules for DOM manipulation, WebGL, WebGPU, WebAudio etc. | ||
3. Extensible shared datatype code generators for (currently) | ||
[Zig](https://ziglang.org) & TypeScript. The latter also generates fully type | ||
checked memory-mapped accessors of WASM-side data. In general, all languages | ||
with a WebAssembly target are supported, however currently only bindings for | ||
these few langs are included. | ||
4. Include files for C11 and Zig, defining imports for the JS core API defined | ||
by this package | ||
In general, all languages with a WebAssembly target are supported, however | ||
currently only bindings for [Zig](https://ziglang.org) are included. | ||
### Custom API modules | ||
The WasmBridge is extensible via custom defined API modules. Such API extensions | ||
will consist of a collection of JS/TS functions & variables, their related | ||
counterparts (import definitions) for the WASM target and (optionally) some | ||
shared data types (bindings for which _can_ be generated by this package too). | ||
On the JS side, custom API modules can be easily integrated via the [`IWasmAPI` | ||
@@ -119,8 +137,8 @@ interface](https://docs.thi.ng/umbrella/wasm-api/interfaces/IWasmAPI.html). The | ||
host, any JS native objects the WASM side might want to be working with must be | ||
managed in JS. For this purpose the [`ObjectIndex` | ||
managed manually in JS. For this purpose the [`ObjectIndex` | ||
class](https://docs.thi.ng/umbrella/wasm-api/classes/ObjectIndex.html) can be | ||
used by API modules to handle ID generation (incl. recycling, using | ||
[@thi.ng/idgen](https://github.com/thi-ng/umbrella/tree/develop/packages/idgen)) | ||
& indexing of different types of JS objects/values. Only the numeric IDs will | ||
then need to be exchanged with the WASM module... | ||
and the indexing of different types of JS objects/values. Only the numeric IDs | ||
(handles) will then need to be exchanged with the WASM module... | ||
@@ -163,2 +181,25 @@ ```ts | ||
### Data bindings & code generators | ||
The package provides an extensible codegeneration framework to simplify the | ||
bilateral design & exchange of data structures shared between the WASM & JS host | ||
env. Currently, code generators for TypeScript & Zig are supplied (more are | ||
planned). A CLI wrapper is worked on too. | ||
#### Data type definitions | ||
TODO | ||
##### Struct | ||
##### Enum | ||
#### Code generation | ||
TODO | ||
#### Example usage | ||
TODO | ||
### Status | ||
@@ -193,7 +234,15 @@ | ||
Package sizes (gzipped, pre-treeshake): ESM: 1.61 KB | ||
Package sizes (gzipped, pre-treeshake): ESM: 3.98 KB | ||
**IMPORTANT:** The package includes various code generators and supporting | ||
functions which are NOT required during runtime. Hence the actual package size | ||
in production will be MUCH smaller! | ||
## Dependencies | ||
- [@thi.ng/api](https://github.com/thi-ng/umbrella/tree/develop/packages/api) | ||
- [@thi.ng/binary](https://github.com/thi-ng/umbrella/tree/develop/packages/binary) | ||
- [@thi.ng/checks](https://github.com/thi-ng/umbrella/tree/develop/packages/checks) | ||
- [@thi.ng/compare](https://github.com/thi-ng/umbrella/tree/develop/packages/compare) | ||
- [@thi.ng/defmulti](https://github.com/thi-ng/umbrella/tree/develop/packages/defmulti) | ||
- [@thi.ng/errors](https://github.com/thi-ng/umbrella/tree/develop/packages/errors) | ||
@@ -208,2 +257,4 @@ - [@thi.ng/hex](https://github.com/thi-ng/umbrella/tree/develop/packages/hex) | ||
## Basic usage example | ||
```ts | ||
@@ -233,2 +284,6 @@ import { WasmBridge, WasmExports } from "@thi.ng/wasm-api"; | ||
### Zig version | ||
Requires [Zig](https://ziglang.org) to be installed: | ||
```zig | ||
@@ -240,3 +295,7 @@ //! Example Zig application (hello.zig) | ||
const js = @import("wasmapi"); | ||
const std = @import("std"); | ||
// set custom memory allocator (here to disable) | ||
pub const WASM_ALLOCATOR: ?std.mem.Allocator = null; | ||
export fn start() void { | ||
@@ -254,3 +313,3 @@ js.printStr("hello world!"); | ||
zig build-lib \ | ||
--pkg-begin wasmapi node_modules/@thi.ng/wasm-api/zig/core.zig --pkg-end \ | ||
--pkg-begin wasmapi node_modules/@thi.ng/wasm-api/include/wasmapi.zig --pkg-end \ | ||
-target wasm32-freestanding \ | ||
@@ -270,3 +329,4 @@ -O ReleaseSmall -dynamic --strip \ | ||
(type $none_=>_none (func)) | ||
(import "core" "_printStr" (func $fimport$0 (param i32 i32))) | ||
(type $i32_=>_i32 (func (param i32) (result i32))) | ||
(import "wasmapi" "_printStr" (func $fimport$0 (param i32 i32))) | ||
(global $global$0 (mut i32) (i32.const 65536)) | ||
@@ -277,2 +337,4 @@ (memory $0 2) | ||
(export "start" (func $0)) | ||
(export "_wasm_allocate" (func $1)) | ||
(export "_wasm_free" (func $2)) | ||
(func $0 | ||
@@ -284,5 +346,96 @@ (call $fimport$0 | ||
) | ||
(func $1 (param $0 i32) (result i32) | ||
(i32.const 0) | ||
) | ||
(func $2 (param $0 i32) (param $1 i32) | ||
) | ||
) | ||
``` | ||
### C11 version | ||
Requires [Emscripten](https://emscripten.org/) to be installed: | ||
```c | ||
#include <wasmapi.h> | ||
void WASM_KEEP start() { | ||
wasm_printStr0("hello world!"); | ||
} | ||
``` | ||
Building the WASM module: | ||
```bash | ||
emcc -Os -Inode_modules/@thi.ng/wasm-api/include -DWASMAPI_NO_MALLOC \ | ||
-sERROR_ON_UNDEFINED_SYMBOLS=0 --no-entry \ | ||
-o hello.wasm hello.c | ||
``` | ||
Resulting WASM: | ||
```wasm | ||
(module | ||
(type $i32_=>_none (func (param i32))) | ||
(type $none_=>_none (func)) | ||
(type $i32_=>_i32 (func (param i32) (result i32))) | ||
(type $none_=>_i32 (func (result i32))) | ||
(import "wasmapi" "_printStr0" (func $fimport$0 (param i32))) | ||
(global $global$0 (mut i32) (i32.const 5243936)) | ||
(memory $0 256 256) | ||
(data (i32.const 1024) "hello world!") | ||
(table $0 2 2 funcref) | ||
(elem (i32.const 1) $0) | ||
(export "memory" (memory $0)) | ||
(export "_wasm_allocate" (func $1)) | ||
(export "_wasm_free" (func $2)) | ||
(export "start" (func $3)) | ||
(export "__indirect_function_table" (table $0)) | ||
(export "_initialize" (func $0)) | ||
(export "__errno_location" (func $7)) | ||
(export "stackSave" (func $4)) | ||
(export "stackRestore" (func $5)) | ||
(export "stackAlloc" (func $6)) | ||
(func $0 | ||
(nop) | ||
) | ||
(func $1 (param $0 i32) (result i32) | ||
(i32.const 0) | ||
) | ||
(func $2 (param $0 i32) | ||
(nop) | ||
) | ||
(func $3 | ||
(call $fimport$0 | ||
(i32.const 1024) | ||
) | ||
) | ||
(func $4 (result i32) | ||
(global.get $global$0) | ||
) | ||
(func $5 (param $0 i32) | ||
(global.set $global$0 | ||
(local.get $0) | ||
) | ||
) | ||
(func $6 (param $0 i32) (result i32) | ||
(global.set $global$0 | ||
(local.tee $0 | ||
(i32.and | ||
(i32.sub | ||
(global.get $global$0) | ||
(local.get $0) | ||
) | ||
(i32.const -16) | ||
) | ||
) | ||
) | ||
(local.get $0) | ||
) | ||
(func $7 (result i32) | ||
(i32.const 1040) | ||
) | ||
) | ||
``` | ||
## Authors | ||
@@ -289,0 +442,0 @@ |
90138
22
1427
446
9
+ Added@thi.ng/binary@^3.3.3
+ Added@thi.ng/checks@^3.2.4
+ Added@thi.ng/compare@^2.1.10
+ Added@thi.ng/defmulti@^2.1.12
+ Added@thi.ng/binary@3.4.44(transitive)
+ Added@thi.ng/checks@3.7.1(transitive)
+ Added@thi.ng/compare@2.4.13(transitive)
+ Added@thi.ng/defmulti@2.1.45(transitive)
Updated@thi.ng/api@^8.4.0
Updated@thi.ng/idgen@^2.1.11