@thi.ng/wasm-api 0.5.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +60 -1
- package/README.md +425 -16
- package/api.d.ts +217 -3
- package/api.js +9 -1
- package/bin/wasm-api +12 -0
- package/bridge.d.ts +41 -7
- package/bridge.js +45 -9
- package/cli.d.ts +5 -0
- package/cli.js +142 -0
- package/codegen/typescript.d.ts +35 -0
- package/codegen/typescript.js +189 -0
- package/codegen/utils.d.ts +30 -0
- package/codegen/utils.js +30 -0
- package/codegen/zig.d.ts +25 -0
- package/codegen/zig.js +75 -0
- package/codegen.d.ts +53 -0
- package/codegen.js +148 -0
- package/doc/assets/main.js +52 -0
- package/doc/assets/search.js +1 -0
- package/include/wasmapi.h +60 -0
- package/{zig/core.zig → include/wasmapi.zig} +45 -32
- package/index.d.ts +4 -0
- package/index.js +4 -0
- package/package.json +31 -7
- package/dev/custom.zig +0 -12
- package/dev/fieldinfo.zig +0 -135
- package/dev/hello.zig +0 -14
- package/dev/zig-cache/o/0fd683610fe16c12563bf410950c8193/builtin.zig +0 -39
- package/test/custom.zig +0 -16
- package/test/zig-cache/o/117d44467ded6ce3864cde3c180ef73c/builtin.zig +0 -39
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Change Log
|
|
2
2
|
|
|
3
|
-
- **Last updated**: 2022-08-
|
|
3
|
+
- **Last updated**: 2022-08-16T16:05:07Z
|
|
4
4
|
- **Generator**: [thi.ng/monopub](https://thi.ng/monopub)
|
|
5
5
|
|
|
6
6
|
All notable changes to this project will be documented in this file.
|
|
@@ -9,6 +9,65 @@ See [Conventional Commits](https://conventionalcommits.org/) for commit guidelin
|
|
|
9
9
|
**Note:** Unlisted _patch_ versions only involve non-code or otherwise excluded changes
|
|
10
10
|
and/or version bumps of transitive dependencies.
|
|
11
11
|
|
|
12
|
+
## [0.8.0](https://github.com/thi-ng/umbrella/tree/@thi.ng/wasm-api@0.8.0) (2022-08-16)
|
|
13
|
+
|
|
14
|
+
#### 🚀 Features
|
|
15
|
+
|
|
16
|
+
- add preliminary string handling support ([3da4efe](https://github.com/thi-ng/umbrella/commit/3da4efe))
|
|
17
|
+
- update/rename IWasmMemoryAccess (add string getter/setter)
|
|
18
|
+
- update StructField.type (add `string`)
|
|
19
|
+
- add CodeGenOpts.stringType option
|
|
20
|
+
- update codegen fns
|
|
21
|
+
- update TS & Zig codegen impls
|
|
22
|
+
|
|
23
|
+
## [0.7.0](https://github.com/thi-ng/umbrella/tree/@thi.ng/wasm-api@0.7.0) (2022-08-15)
|
|
24
|
+
|
|
25
|
+
#### 🚀 Features
|
|
26
|
+
|
|
27
|
+
- add CLI wrapper for codegens ([683a560](https://github.com/thi-ng/umbrella/commit/683a560))
|
|
28
|
+
- update TSOpts & TS codegen ([4f6bbbf](https://github.com/thi-ng/umbrella/commit/4f6bbbf))
|
|
29
|
+
- add `uppercaseEnum` option to force UC enum IDs
|
|
30
|
+
- update helper predicates ([65b23d4](https://github.com/thi-ng/umbrella/commit/65b23d4))
|
|
31
|
+
|
|
32
|
+
#### 🩹 Bug fixes
|
|
33
|
+
|
|
34
|
+
- allow signed ints for enum tags ([78d0822](https://github.com/thi-ng/umbrella/commit/78d0822))
|
|
35
|
+
- correct TS __mapArray codegen ([289b137](https://github.com/thi-ng/umbrella/commit/289b137))
|
|
36
|
+
|
|
37
|
+
## [0.6.0](https://github.com/thi-ng/umbrella/tree/@thi.ng/wasm-api@0.6.0) (2022-08-15)
|
|
38
|
+
|
|
39
|
+
#### 🚀 Features
|
|
40
|
+
|
|
41
|
+
- add C11 header/include file, update WasmBridge ([a67dc00](https://github.com/thi-ng/umbrella/commit/a67dc00))
|
|
42
|
+
- migrate headers/includes to /include
|
|
43
|
+
- rename "core" import section => "wasmapi"
|
|
44
|
+
- rename WasmBridge.core => WasmBridge.api
|
|
45
|
+
- update pkg file
|
|
46
|
+
- update codegens, add opts, fix alignments ([5c1fec5](https://github.com/thi-ng/umbrella/commit/5c1fec5))
|
|
47
|
+
- add global CodeGenOpts
|
|
48
|
+
- update generateTypes() to consider new opts
|
|
49
|
+
- add global USIZE type (for pointer sizes & codegens)
|
|
50
|
+
- add options for Zig codegen (extra debug helpers)
|
|
51
|
+
- simplify TS codegen
|
|
52
|
+
- fix sizeOf() for struct fields
|
|
53
|
+
- make prepareType() idempotent
|
|
54
|
+
- add bindings code generator framework ([17ee06f](https://github.com/thi-ng/umbrella/commit/17ee06f))
|
|
55
|
+
- add/update deps
|
|
56
|
+
- add preliminary codegens for Zig & TS
|
|
57
|
+
- add supporting types & utils
|
|
58
|
+
- add generateTypes() codegen facade fn
|
|
59
|
+
- update allocate/free() fns, update Zig core API ([8a55989](https://github.com/thi-ng/umbrella/commit/8a55989))
|
|
60
|
+
- add _wasm_free() Zig impl
|
|
61
|
+
- add printFmt() Zig fn
|
|
62
|
+
- update WasmBridge.allocate() (add clear option)
|
|
63
|
+
- update WasmBridge.free()
|
|
64
|
+
- ensure memory in WasmBridge.getString()
|
|
65
|
+
- add/update docstrings
|
|
66
|
+
|
|
67
|
+
#### ♻️ Refactoring
|
|
68
|
+
|
|
69
|
+
- extract WasmMemViews interface, update test WASM ([4c73e65](https://github.com/thi-ng/umbrella/commit/4c73e65))
|
|
70
|
+
|
|
12
71
|
## [0.5.0](https://github.com/thi-ng/umbrella/tree/@thi.ng/wasm-api@0.5.0) (2022-08-08)
|
|
13
72
|
|
|
14
73
|
#### 🚀 Features
|
package/README.md
CHANGED
|
@@ -12,30 +12,53 @@ This project is part of the
|
|
|
12
12
|
- [About](#about)
|
|
13
13
|
- [Custom API modules](#custom-api-modules)
|
|
14
14
|
- [Object indices & handles](#object-indices--handles)
|
|
15
|
+
- [Data bindings & code generators](#data-bindings--code-generators)
|
|
16
|
+
- [CLI generator](#cli-generator)
|
|
17
|
+
- [Data type definitions](#data-type-definitions)
|
|
18
|
+
- [Example usage](#example-usage)
|
|
19
|
+
- [String handling](#string-handling)
|
|
15
20
|
- [Status](#status)
|
|
16
21
|
- [Installation](#installation)
|
|
17
22
|
- [Dependencies](#dependencies)
|
|
18
23
|
- [API](#api)
|
|
24
|
+
- [Basic usage example](#basic-usage-example)
|
|
25
|
+
- [Zig version](#zig-version)
|
|
26
|
+
- [C11 version](#c11-version)
|
|
19
27
|
- [Authors](#authors)
|
|
20
28
|
- [License](#license)
|
|
21
29
|
|
|
22
30
|
## About
|
|
23
31
|
|
|
24
|
-
|
|
32
|
+
Generic, modular, extensible API bridge, glue code and bindings code generator for hybrid JS & WebAssembly projects.
|
|
25
33
|
|
|
26
|
-
This package provides a
|
|
27
|
-
[`WasmBridge`](https://docs.thi.ng/umbrella/wasm-api/classes/WasmBridge.html)
|
|
28
|
-
class as interop basis and a much reduced boilerplate for hybrid JS/WebAssembly
|
|
29
|
-
applications. At the moment only a minimal core API is provided (i.e. for debug
|
|
30
|
-
output, string, pointer, typed array accessors [8/16/32/64 bit (u)ints, 32/64
|
|
31
|
-
bit floats]), but in the future we aim to also supply support modules for DOM
|
|
32
|
-
manipulation, WebGL, WebGPU, WebAudio etc.
|
|
34
|
+
This package provides a the following:
|
|
33
35
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
+
1. A small, generic and modular
|
|
37
|
+
[`WasmBridge`](https://docs.thi.ng/umbrella/wasm-api/classes/WasmBridge.html)
|
|
38
|
+
class as interop basis and much reduced boilerplate for hybrid JS/WebAssembly
|
|
39
|
+
applications.
|
|
40
|
+
2. A minimal core API for debug output, string, pointer, typed array accessors
|
|
41
|
+
for 8/16/32/64 bit (u)ints and 32/64 bit floats. In the future we aim to also
|
|
42
|
+
supply support modules for DOM manipulation, WebGL, WebGPU, WebAudio etc.
|
|
43
|
+
3. [Include files for C11/C++ and
|
|
44
|
+
Zig](https://github.com/thi-ng/umbrella/tree/develop/packages/wasm-api/include),
|
|
45
|
+
defining WASM imports of the JS [core
|
|
46
|
+
API](https://docs.thi.ng/umbrella/wasm-api/interfaces/CoreAPI.html) defined
|
|
47
|
+
by this package
|
|
48
|
+
4. Extensible shared datatype code generators for (currently)
|
|
49
|
+
[Zig](https://ziglang.org) & TypeScript. The latter also generates fully type
|
|
50
|
+
checked memory-mapped accessors of WASM-side data. In general, all languages
|
|
51
|
+
with a WebAssembly target are supported, however currently only bindings for
|
|
52
|
+
these few langs are included.
|
|
53
|
+
5. [CLI frontend/utility](#cli-generator) to invoke the code generator(s)
|
|
36
54
|
|
|
37
55
|
### Custom API modules
|
|
38
56
|
|
|
57
|
+
The [`WasmBridge`](https://docs.thi.ng/umbrella/wasm-api/classes/WasmBridge.html) is extensible via custom defined API modules. Such API extensions
|
|
58
|
+
will consist of a collection of JS/TS functions & variables, their related
|
|
59
|
+
counterparts (import definitions) for the WASM target and (optionally) some
|
|
60
|
+
shared data types ([bindings for which _can_ be generated by this package too](#data-bindings--code-generators)).
|
|
61
|
+
|
|
39
62
|
On the JS side, custom API modules can be easily integrated via the [`IWasmAPI`
|
|
40
63
|
interface](https://docs.thi.ng/umbrella/wasm-api/interfaces/IWasmAPI.html). The
|
|
41
64
|
following example provides a brief overview:
|
|
@@ -113,12 +136,12 @@ export fn test_randomVec2() void {
|
|
|
113
136
|
|
|
114
137
|
Since only numeric values can be exchanged between the WASM module and the JS
|
|
115
138
|
host, any JS native objects the WASM side might want to be working with must be
|
|
116
|
-
managed in JS. For this purpose the [`ObjectIndex`
|
|
139
|
+
managed manually in JS. For this purpose the [`ObjectIndex`
|
|
117
140
|
class](https://docs.thi.ng/umbrella/wasm-api/classes/ObjectIndex.html) can be
|
|
118
141
|
used by API modules to handle ID generation (incl. recycling, using
|
|
119
142
|
[@thi.ng/idgen](https://github.com/thi-ng/umbrella/tree/develop/packages/idgen))
|
|
120
|
-
|
|
121
|
-
then need to be exchanged with the WASM module...
|
|
143
|
+
and the indexing of different types of JS objects/values. Only the numeric IDs
|
|
144
|
+
(handles) will then need to be exchanged with the WASM module...
|
|
122
145
|
|
|
123
146
|
```ts
|
|
124
147
|
import { ObjectIndex } from "@thi.ng/wasm-api";
|
|
@@ -156,6 +179,278 @@ canvases.delete(0);
|
|
|
156
179
|
// true
|
|
157
180
|
```
|
|
158
181
|
|
|
182
|
+
### Data bindings & code generators
|
|
183
|
+
|
|
184
|
+
The package provides an extensible codegeneration framework to simplify the
|
|
185
|
+
bilateral design & exchange of data structures shared between the WASM & JS host
|
|
186
|
+
env. Currently, code generators for TypeScript & Zig are supplied (more are
|
|
187
|
+
planned). A CLI wrapper is worked on too.
|
|
188
|
+
|
|
189
|
+
#### CLI generator
|
|
190
|
+
|
|
191
|
+
The package includes a [small CLI
|
|
192
|
+
wrapper](https://github.com/thi-ng/umbrella/blob/develop/packages/wasm-api/src/cli.ts)
|
|
193
|
+
to invoke the codegenerator(s) from JSON type definitions and to write the
|
|
194
|
+
generated source code(s) to different files:
|
|
195
|
+
|
|
196
|
+
```text
|
|
197
|
+
$ npx @thi.ng/wasm-api
|
|
198
|
+
|
|
199
|
+
█ █ █ │
|
|
200
|
+
██ █ │
|
|
201
|
+
█ █ █ █ █ █ █ █ │ @thi.ng/wasm-api 0.6.0
|
|
202
|
+
█ █ █ █ █ █ █ █ █ │ Multi-language data bindings code generator
|
|
203
|
+
█ │
|
|
204
|
+
█ █ │
|
|
205
|
+
|
|
206
|
+
usage: wasm-api [OPTS] JSON-INPUT-FILE(S) ...
|
|
207
|
+
wasm-api --help
|
|
208
|
+
|
|
209
|
+
Flags:
|
|
210
|
+
|
|
211
|
+
-d, --debug enable debug output
|
|
212
|
+
--dry-run enable dry run (don't overwrite files)
|
|
213
|
+
|
|
214
|
+
Main:
|
|
215
|
+
|
|
216
|
+
-c FILE, --config FILE JSON config file with codegen options
|
|
217
|
+
-l ID[,..], --lang ID[,..] [multiple] target language: "ts", "zig" (default: ["ts","zig"])
|
|
218
|
+
-o FILE, --out FILE [multiple] output file path
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
By default, the CLI generates sources for both TypeScript and Zig (in this
|
|
222
|
+
order!). Order is important, since the output file paths must be given in the
|
|
223
|
+
same order as the target languages. It's recommended to be more explicit. An
|
|
224
|
+
example invocation looks like:
|
|
225
|
+
|
|
226
|
+
```bash
|
|
227
|
+
wasm-api --config codegen-opts.json \
|
|
228
|
+
--lang ts -o src/generated.ts \
|
|
229
|
+
--lang zig -o src.zig/generated.zig \
|
|
230
|
+
typedefs.json
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
The structure of the config file is as follows (all optional):
|
|
234
|
+
|
|
235
|
+
```text
|
|
236
|
+
{
|
|
237
|
+
global: { ... },
|
|
238
|
+
ts: { ... },
|
|
239
|
+
zig: { ... },
|
|
240
|
+
}
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
More details about possible
|
|
244
|
+
[`global`](https://docs.thi.ng/umbrella/wasm-api/interfaces/CodeGenOpts.html),
|
|
245
|
+
[`ts`](https://docs.thi.ng/umbrella/wasm-api/interfaces/TSOpts.html) and
|
|
246
|
+
[`zig`](https://docs.thi.ng/umbrella/wasm-api/interfaces/ZigOpts.html) config
|
|
247
|
+
options & values.
|
|
248
|
+
|
|
249
|
+
#### Data type definitions
|
|
250
|
+
|
|
251
|
+
Currently, the code generator supports structs and enums. See API docs for
|
|
252
|
+
further details:
|
|
253
|
+
|
|
254
|
+
- [`Enum`](https://docs.thi.ng/umbrella/wasm-api/interfaces/Enum.html)
|
|
255
|
+
- [`EnumValue`](https://docs.thi.ng/umbrella/wasm-api/interfaces/EnumValue.html)
|
|
256
|
+
- [`Struct`](https://docs.thi.ng/umbrella/wasm-api/interfaces/Struct.html)
|
|
257
|
+
- [`StructField`](https://docs.thi.ng/umbrella/wasm-api/interfaces/StructField.html)
|
|
258
|
+
- [`TopLevelType`](https://docs.thi.ng/umbrella/wasm-api/interfaces/TopLevelType.html)
|
|
259
|
+
|
|
260
|
+
#### Example usage
|
|
261
|
+
|
|
262
|
+
Below is an example file with JSON type definitions and the resulting source
|
|
263
|
+
codes:
|
|
264
|
+
|
|
265
|
+
**⬇︎ CLICK TO EXPAND EACH CODE BLOCK ⬇︎**
|
|
266
|
+
|
|
267
|
+
<details><summary>types.json (Type definitions)</summary>
|
|
268
|
+
|
|
269
|
+
```json
|
|
270
|
+
[
|
|
271
|
+
{
|
|
272
|
+
"name": "Foo",
|
|
273
|
+
"type": "struct",
|
|
274
|
+
"doc": "Example struct",
|
|
275
|
+
"auto": true,
|
|
276
|
+
"fields": [
|
|
277
|
+
{ "name": "id", "type": "u8", "doc": "Unique ID" },
|
|
278
|
+
{ "name": "bars", "type": "Bar", "tag": "array", "len": 3 },
|
|
279
|
+
{ "name": "color", "type": "f32", "tag": "vec", "len": 4 }
|
|
280
|
+
]
|
|
281
|
+
},
|
|
282
|
+
{
|
|
283
|
+
"name": "Bar",
|
|
284
|
+
"type": "struct",
|
|
285
|
+
"fields": [
|
|
286
|
+
{ "name": "kind", "type": "Kind" },
|
|
287
|
+
{ "name": "flags", "type": "u32" }
|
|
288
|
+
]
|
|
289
|
+
},
|
|
290
|
+
{
|
|
291
|
+
"name": "Kind",
|
|
292
|
+
"type": "enum",
|
|
293
|
+
"tag": "u16",
|
|
294
|
+
"values": [
|
|
295
|
+
"unknown",
|
|
296
|
+
{ "name": "good", "value": 100 },
|
|
297
|
+
{ "name": "best", "value": 1000 }
|
|
298
|
+
]
|
|
299
|
+
}
|
|
300
|
+
]
|
|
301
|
+
```
|
|
302
|
+
</details>
|
|
303
|
+
|
|
304
|
+
<details><summary>generated.ts (generated TypeScript source)</summary>
|
|
305
|
+
|
|
306
|
+
```ts
|
|
307
|
+
/** Generated by @thi.ng/wasm-api at 2022-08-15T22:32:21.189Z - DO NOT EDIT! */
|
|
308
|
+
|
|
309
|
+
import type { WasmTypeBase, WasmTypeConstructor } from "@thi.ng/wasm-api";
|
|
310
|
+
|
|
311
|
+
/** Example struct */
|
|
312
|
+
export interface Foo extends WasmTypeBase {
|
|
313
|
+
color: Float32Array;
|
|
314
|
+
bars: Bar[];
|
|
315
|
+
/** Unique ID */
|
|
316
|
+
id: number;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
export const $Foo: WasmTypeConstructor<Foo> = (mem) => ({
|
|
320
|
+
get align() { return 16; },
|
|
321
|
+
get size() { return 48; },
|
|
322
|
+
instance: (base) => ({
|
|
323
|
+
get __base() { return base; },
|
|
324
|
+
get __bytes() { return mem.u8.subarray(base, base + 48); },
|
|
325
|
+
get color(): Float32Array {
|
|
326
|
+
const addr = base >>> 2;
|
|
327
|
+
return mem.f32.subarray(addr, addr + 4);
|
|
328
|
+
},
|
|
329
|
+
get bars(): Bar[] {
|
|
330
|
+
const addr = (base + 16);
|
|
331
|
+
const inst = $Bar(mem);
|
|
332
|
+
const slice: Bar[] = [];
|
|
333
|
+
for(let i = 0; i < 3; i++) slice.push(inst.instance(addr + i * 24));
|
|
334
|
+
return slice;
|
|
335
|
+
},
|
|
336
|
+
get id(): number {
|
|
337
|
+
return mem.u8[(base + 40)];
|
|
338
|
+
},
|
|
339
|
+
set id(x: number) {
|
|
340
|
+
mem.u8[(base + 40)] = x;
|
|
341
|
+
},
|
|
342
|
+
})
|
|
343
|
+
});
|
|
344
|
+
|
|
345
|
+
export interface Bar extends WasmTypeBase {
|
|
346
|
+
kind: Kind;
|
|
347
|
+
flags: number;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
export const $Bar: WasmTypeConstructor<Bar> = (mem) => ({
|
|
351
|
+
get align() { return 4; },
|
|
352
|
+
get size() { return 8; },
|
|
353
|
+
instance: (base) => ({
|
|
354
|
+
get __base() { return base; },
|
|
355
|
+
get __bytes() { return mem.u8.subarray(base, base + 8); },
|
|
356
|
+
get kind(): Kind {
|
|
357
|
+
return mem.u16[base >>> 1];
|
|
358
|
+
},
|
|
359
|
+
set kind(x: Kind) {
|
|
360
|
+
mem.u16[base >>> 1] = x;
|
|
361
|
+
},
|
|
362
|
+
get flags(): number {
|
|
363
|
+
return mem.u32[(base + 4) >>> 2];
|
|
364
|
+
},
|
|
365
|
+
set flags(x: number) {
|
|
366
|
+
mem.u32[(base + 4) >>> 2] = x;
|
|
367
|
+
},
|
|
368
|
+
})
|
|
369
|
+
});
|
|
370
|
+
|
|
371
|
+
export enum Kind {
|
|
372
|
+
UNKNOWN,
|
|
373
|
+
GOOD = 100,
|
|
374
|
+
BEST = 1000,
|
|
375
|
+
}
|
|
376
|
+
```
|
|
377
|
+
</details>
|
|
378
|
+
|
|
379
|
+
<details><summary>generated.zig (generated Zig source)</summary>
|
|
380
|
+
|
|
381
|
+
```zig
|
|
382
|
+
//! Generated by @thi.ng/wasm-api at 2022-08-15T22:32:21.191Z - DO NOT EDIT!
|
|
383
|
+
|
|
384
|
+
/// Example struct
|
|
385
|
+
pub const Foo = struct {
|
|
386
|
+
color: @Vector(4, f32),
|
|
387
|
+
bars: [3]Bar,
|
|
388
|
+
/// Unique ID
|
|
389
|
+
id: u8,
|
|
390
|
+
};
|
|
391
|
+
|
|
392
|
+
pub const Bar = struct {
|
|
393
|
+
kind: Kind,
|
|
394
|
+
flags: u32,
|
|
395
|
+
};
|
|
396
|
+
|
|
397
|
+
pub const Kind = enum(u16) {
|
|
398
|
+
unknown,
|
|
399
|
+
good = 100,
|
|
400
|
+
best = 1000,
|
|
401
|
+
};
|
|
402
|
+
```
|
|
403
|
+
</details>
|
|
404
|
+
|
|
405
|
+
On the TypeScript/JS side, the memory-mapped wrappers (e.g. `$Foo` and `$Bar`)
|
|
406
|
+
can be used in combination with the `WasmBridge` to obtain fully typed views
|
|
407
|
+
(according to the generated types) of the underlying WASM memory. Basic usage is
|
|
408
|
+
like:
|
|
409
|
+
|
|
410
|
+
```ts
|
|
411
|
+
import { WasmBridge } from "@thi.ng/wasm-api";
|
|
412
|
+
import { $Foo, Kind } from "./generated.ts";
|
|
413
|
+
|
|
414
|
+
const bridge = new WasmBridge();
|
|
415
|
+
// bridge initialization omitted here (see other examples below)
|
|
416
|
+
// ...
|
|
417
|
+
|
|
418
|
+
// Create an instance using the bridge's memory views
|
|
419
|
+
// and mapping a `Foo` struct from given address
|
|
420
|
+
// (e.g. obtained from an exported WASM function/value)
|
|
421
|
+
const foo = $Foo(bridge).instance(0x10000);
|
|
422
|
+
|
|
423
|
+
// then use like normal JS object
|
|
424
|
+
foo.color
|
|
425
|
+
// Float32Array(4) [0.1, 0.2, 0.3, 0.4]
|
|
426
|
+
|
|
427
|
+
// this even applies to arrays using other types
|
|
428
|
+
foo.bars[2].kind = Kind.BEST;
|
|
429
|
+
|
|
430
|
+
// IMPORTANT: any modifications like this are directly
|
|
431
|
+
// applied to the underlying WASM memory...
|
|
432
|
+
```
|
|
433
|
+
|
|
434
|
+
**IMPORTANT:** Struct field setters are currently only supported for single
|
|
435
|
+
values, incl. enums, strings, structs. The latter 2 will always be copied by
|
|
436
|
+
value (mem copy). Arrays or slices of strings do not currently provide write
|
|
437
|
+
access...
|
|
438
|
+
|
|
439
|
+
### String handling
|
|
440
|
+
|
|
441
|
+
Most low-level languages deal with strings very differently and alas there's no
|
|
442
|
+
general standard. Some have UTF-8/16 support, others don't. In some languages
|
|
443
|
+
(incl. C & Zig), strings are stored as zero terminated, in others they aren't...
|
|
444
|
+
It's outside the scope of this package to provide an allround out-of-the-box
|
|
445
|
+
solution. However, the code generators provide the global `stringType` option to
|
|
446
|
+
interpret the `string` type of a struct field in different ways:
|
|
447
|
+
|
|
448
|
+
- `slice` (default): Considers strings as Zig-style slices (i.e. pointer + length)
|
|
449
|
+
- `ptr`: Considers strings as C-style raw `*char` pointer (without any length)
|
|
450
|
+
|
|
451
|
+
Note: If setting this global option to `ptr`, it also has to be stated for the
|
|
452
|
+
TypeScript code generator explicitly.
|
|
453
|
+
|
|
159
454
|
### Status
|
|
160
455
|
|
|
161
456
|
**ALPHA** - bleeding edge / work-in-progress
|
|
@@ -185,12 +480,22 @@ node --experimental-repl-await
|
|
|
185
480
|
> const wasmApi = await import("@thi.ng/wasm-api");
|
|
186
481
|
```
|
|
187
482
|
|
|
188
|
-
Package sizes (gzipped, pre-treeshake): ESM:
|
|
483
|
+
Package sizes (gzipped, pre-treeshake): ESM: 4.32 KB
|
|
484
|
+
|
|
485
|
+
**IMPORTANT:** The package includes various code generators and supporting
|
|
486
|
+
functions which are NOT required during runtime. Hence the actual package size
|
|
487
|
+
in production will be MUCH smaller!
|
|
189
488
|
|
|
190
489
|
## Dependencies
|
|
191
490
|
|
|
192
491
|
- [@thi.ng/api](https://github.com/thi-ng/umbrella/tree/develop/packages/api)
|
|
492
|
+
- [@thi.ng/args](https://github.com/thi-ng/umbrella/tree/develop/packages/args)
|
|
493
|
+
- [@thi.ng/binary](https://github.com/thi-ng/umbrella/tree/develop/packages/binary)
|
|
494
|
+
- [@thi.ng/checks](https://github.com/thi-ng/umbrella/tree/develop/packages/checks)
|
|
495
|
+
- [@thi.ng/compare](https://github.com/thi-ng/umbrella/tree/develop/packages/compare)
|
|
496
|
+
- [@thi.ng/defmulti](https://github.com/thi-ng/umbrella/tree/develop/packages/defmulti)
|
|
193
497
|
- [@thi.ng/errors](https://github.com/thi-ng/umbrella/tree/develop/packages/errors)
|
|
498
|
+
- [@thi.ng/file-io](https://github.com/thi-ng/umbrella/tree/develop/packages/file-io)
|
|
194
499
|
- [@thi.ng/hex](https://github.com/thi-ng/umbrella/tree/develop/packages/hex)
|
|
195
500
|
- [@thi.ng/idgen](https://github.com/thi-ng/umbrella/tree/develop/packages/idgen)
|
|
196
501
|
- [@thi.ng/logger](https://github.com/thi-ng/umbrella/tree/develop/packages/logger)
|
|
@@ -199,6 +504,8 @@ Package sizes (gzipped, pre-treeshake): ESM: 1.61 KB
|
|
|
199
504
|
|
|
200
505
|
[Generated API docs](https://docs.thi.ng/umbrella/wasm-api/)
|
|
201
506
|
|
|
507
|
+
## Basic usage example
|
|
508
|
+
|
|
202
509
|
```ts
|
|
203
510
|
import { WasmBridge, WasmExports } from "@thi.ng/wasm-api";
|
|
204
511
|
import { readFileSync } from "fs";
|
|
@@ -223,12 +530,20 @@ interface App extends WasmExports {
|
|
|
223
530
|
})();
|
|
224
531
|
```
|
|
225
532
|
|
|
533
|
+
### Zig version
|
|
534
|
+
|
|
535
|
+
Requires [Zig](https://ziglang.org) to be installed:
|
|
536
|
+
|
|
226
537
|
```zig
|
|
227
538
|
//! Example Zig application (hello.zig)
|
|
228
539
|
|
|
229
540
|
/// import externals
|
|
230
541
|
/// see build command for configuration
|
|
231
542
|
const js = @import("wasmapi");
|
|
543
|
+
const std = @import("std");
|
|
544
|
+
|
|
545
|
+
// set custom memory allocator (here to disable)
|
|
546
|
+
pub const WASM_ALLOCATOR: ?std.mem.Allocator = null;
|
|
232
547
|
|
|
233
548
|
export fn start() void {
|
|
234
549
|
js.printStr("hello world!");
|
|
@@ -242,7 +557,7 @@ folder):
|
|
|
242
557
|
```bash
|
|
243
558
|
# compile WASM binary
|
|
244
559
|
zig build-lib \
|
|
245
|
-
--pkg-begin wasmapi node_modules/@thi.ng/wasm-api/
|
|
560
|
+
--pkg-begin wasmapi node_modules/@thi.ng/wasm-api/include/wasmapi.zig --pkg-end \
|
|
246
561
|
-target wasm32-freestanding \
|
|
247
562
|
-O ReleaseSmall -dynamic --strip \
|
|
248
563
|
hello.zig
|
|
@@ -257,18 +572,112 @@ The resulting WASM:
|
|
|
257
572
|
(module
|
|
258
573
|
(type $i32_i32_=>_none (func (param i32 i32)))
|
|
259
574
|
(type $none_=>_none (func))
|
|
260
|
-
(
|
|
575
|
+
(type $i32_=>_i32 (func (param i32) (result i32)))
|
|
576
|
+
(import "wasmapi" "_printStr" (func $fimport$0 (param i32 i32)))
|
|
261
577
|
(global $global$0 (mut i32) (i32.const 65536))
|
|
262
578
|
(memory $0 2)
|
|
263
579
|
(data (i32.const 65536) "hello world!\00")
|
|
264
580
|
(export "memory" (memory $0))
|
|
265
581
|
(export "start" (func $0))
|
|
582
|
+
(export "_wasm_allocate" (func $1))
|
|
583
|
+
(export "_wasm_free" (func $2))
|
|
266
584
|
(func $0
|
|
267
585
|
(call $fimport$0
|
|
268
586
|
(i32.const 65536)
|
|
269
587
|
(i32.const 12)
|
|
270
588
|
)
|
|
271
589
|
)
|
|
590
|
+
(func $1 (param $0 i32) (result i32)
|
|
591
|
+
(i32.const 0)
|
|
592
|
+
)
|
|
593
|
+
(func $2 (param $0 i32) (param $1 i32)
|
|
594
|
+
)
|
|
595
|
+
)
|
|
596
|
+
```
|
|
597
|
+
|
|
598
|
+
### C11 version
|
|
599
|
+
|
|
600
|
+
Requires [Emscripten](https://emscripten.org/) to be installed:
|
|
601
|
+
|
|
602
|
+
```c
|
|
603
|
+
#include <wasmapi.h>
|
|
604
|
+
|
|
605
|
+
void WASM_KEEP start() {
|
|
606
|
+
wasm_printStr0("hello world!");
|
|
607
|
+
}
|
|
608
|
+
```
|
|
609
|
+
|
|
610
|
+
Building the WASM module:
|
|
611
|
+
|
|
612
|
+
```bash
|
|
613
|
+
emcc -Os -Inode_modules/@thi.ng/wasm-api/include -DWASMAPI_NO_MALLOC \
|
|
614
|
+
-sERROR_ON_UNDEFINED_SYMBOLS=0 --no-entry \
|
|
615
|
+
-o hello.wasm hello.c
|
|
616
|
+
```
|
|
617
|
+
|
|
618
|
+
Resulting WASM:
|
|
619
|
+
|
|
620
|
+
```wasm
|
|
621
|
+
(module
|
|
622
|
+
(type $i32_=>_none (func (param i32)))
|
|
623
|
+
(type $none_=>_none (func))
|
|
624
|
+
(type $i32_=>_i32 (func (param i32) (result i32)))
|
|
625
|
+
(type $none_=>_i32 (func (result i32)))
|
|
626
|
+
(import "wasmapi" "_printStr0" (func $fimport$0 (param i32)))
|
|
627
|
+
(global $global$0 (mut i32) (i32.const 5243936))
|
|
628
|
+
(memory $0 256 256)
|
|
629
|
+
(data (i32.const 1024) "hello world!")
|
|
630
|
+
(table $0 2 2 funcref)
|
|
631
|
+
(elem (i32.const 1) $0)
|
|
632
|
+
(export "memory" (memory $0))
|
|
633
|
+
(export "_wasm_allocate" (func $1))
|
|
634
|
+
(export "_wasm_free" (func $2))
|
|
635
|
+
(export "start" (func $3))
|
|
636
|
+
(export "__indirect_function_table" (table $0))
|
|
637
|
+
(export "_initialize" (func $0))
|
|
638
|
+
(export "__errno_location" (func $7))
|
|
639
|
+
(export "stackSave" (func $4))
|
|
640
|
+
(export "stackRestore" (func $5))
|
|
641
|
+
(export "stackAlloc" (func $6))
|
|
642
|
+
(func $0
|
|
643
|
+
(nop)
|
|
644
|
+
)
|
|
645
|
+
(func $1 (param $0 i32) (result i32)
|
|
646
|
+
(i32.const 0)
|
|
647
|
+
)
|
|
648
|
+
(func $2 (param $0 i32)
|
|
649
|
+
(nop)
|
|
650
|
+
)
|
|
651
|
+
(func $3
|
|
652
|
+
(call $fimport$0
|
|
653
|
+
(i32.const 1024)
|
|
654
|
+
)
|
|
655
|
+
)
|
|
656
|
+
(func $4 (result i32)
|
|
657
|
+
(global.get $global$0)
|
|
658
|
+
)
|
|
659
|
+
(func $5 (param $0 i32)
|
|
660
|
+
(global.set $global$0
|
|
661
|
+
(local.get $0)
|
|
662
|
+
)
|
|
663
|
+
)
|
|
664
|
+
(func $6 (param $0 i32) (result i32)
|
|
665
|
+
(global.set $global$0
|
|
666
|
+
(local.tee $0
|
|
667
|
+
(i32.and
|
|
668
|
+
(i32.sub
|
|
669
|
+
(global.get $global$0)
|
|
670
|
+
(local.get $0)
|
|
671
|
+
)
|
|
672
|
+
(i32.const -16)
|
|
673
|
+
)
|
|
674
|
+
)
|
|
675
|
+
)
|
|
676
|
+
(local.get $0)
|
|
677
|
+
)
|
|
678
|
+
(func $7 (result i32)
|
|
679
|
+
(i32.const 1040)
|
|
680
|
+
)
|
|
272
681
|
)
|
|
273
682
|
```
|
|
274
683
|
|