@thi.ng/wasm-api 0.9.0 → 0.11.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 +169 -127
- package/api.d.ts +102 -23
- package/api.js +1 -0
- package/bridge.d.ts +35 -6
- package/bridge.js +55 -15
- package/cli.js +27 -6
- package/codegen/c.d.ts +33 -0
- package/codegen/c.js +100 -0
- package/codegen/c11.d.ts +22 -0
- package/codegen/c11.js +125 -0
- package/codegen/typescript.d.ts +2 -12
- package/codegen/typescript.js +120 -84
- package/codegen/utils.d.ts +48 -1
- package/codegen/utils.js +55 -0
- package/codegen/zig.d.ts +2 -9
- package/codegen/zig.js +54 -28
- package/codegen.d.ts +1 -23
- package/codegen.js +31 -8
- package/doc/assets/main.js +52 -0
- package/doc/assets/search.js +1 -0
- package/include/wasmapi.h +38 -23
- package/include/wasmapi.zig +69 -65
- package/index.d.ts +3 -0
- package/index.js +3 -0
- package/package.json +37 -19
- package/pointer.d.ts +23 -0
- package/pointer.js +27 -0
- package/string.d.ts +97 -0
- package/string.js +145 -0
package/index.js
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
export * from "./api.js";
|
|
2
2
|
export * from "./bridge.js";
|
|
3
3
|
export * from "./codegen.js";
|
|
4
|
+
export * from "./codegen/c11.js";
|
|
4
5
|
export * from "./codegen/typescript.js";
|
|
5
6
|
export * from "./codegen/utils.js";
|
|
6
7
|
export * from "./codegen/zig.js";
|
|
7
8
|
export * from "./object-index.js";
|
|
9
|
+
export * from "./pointer.js";
|
|
10
|
+
export * from "./string.js";
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@thi.ng/wasm-api",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Generic, modular, extensible API bridge, glue code and bindings code
|
|
3
|
+
"version": "0.11.0",
|
|
4
|
+
"description": "Generic, modular, extensible API bridge, polyglot glue code and bindings code generators for hybrid JS & WebAssembly projects",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"module": "./index.js",
|
|
7
7
|
"typings": "./index.d.ts",
|
|
@@ -36,35 +36,44 @@
|
|
|
36
36
|
"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"
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@thi.ng/api": "^8.4.
|
|
40
|
-
"@thi.ng/args": "^2.2.
|
|
41
|
-
"@thi.ng/binary": "^3.3.
|
|
42
|
-
"@thi.ng/checks": "^3.2.
|
|
43
|
-
"@thi.ng/compare": "^2.1.
|
|
44
|
-
"@thi.ng/defmulti": "^2.1.
|
|
45
|
-
"@thi.ng/errors": "^2.
|
|
46
|
-
"@thi.ng/file-io": "^0.3.
|
|
47
|
-
"@thi.ng/hex": "^2.
|
|
48
|
-
"@thi.ng/idgen": "^2.1.
|
|
49
|
-
"@thi.ng/logger": "^1.
|
|
39
|
+
"@thi.ng/api": "^8.4.2",
|
|
40
|
+
"@thi.ng/args": "^2.2.2",
|
|
41
|
+
"@thi.ng/binary": "^3.3.5",
|
|
42
|
+
"@thi.ng/checks": "^3.2.5",
|
|
43
|
+
"@thi.ng/compare": "^2.1.12",
|
|
44
|
+
"@thi.ng/defmulti": "^2.1.14",
|
|
45
|
+
"@thi.ng/errors": "^2.2.0",
|
|
46
|
+
"@thi.ng/file-io": "^0.3.11",
|
|
47
|
+
"@thi.ng/hex": "^2.2.0",
|
|
48
|
+
"@thi.ng/idgen": "^2.1.13",
|
|
49
|
+
"@thi.ng/logger": "^1.3.0",
|
|
50
|
+
"@thi.ng/paths": "^5.1.15"
|
|
50
51
|
},
|
|
51
52
|
"devDependencies": {
|
|
52
|
-
"@microsoft/api-extractor": "^7.
|
|
53
|
-
"@thi.ng/testament": "^0.
|
|
53
|
+
"@microsoft/api-extractor": "^7.31.1",
|
|
54
|
+
"@thi.ng/testament": "^0.3.0",
|
|
54
55
|
"rimraf": "^3.0.2",
|
|
55
56
|
"tools": "^0.0.1",
|
|
56
57
|
"typedoc": "^0.22.17",
|
|
57
|
-
"typescript": "^4.
|
|
58
|
+
"typescript": "^4.8.3"
|
|
58
59
|
},
|
|
59
60
|
"keywords": [
|
|
61
|
+
"allocator",
|
|
60
62
|
"api",
|
|
61
63
|
"bindings",
|
|
62
64
|
"c",
|
|
63
65
|
"codegen",
|
|
66
|
+
"enum",
|
|
67
|
+
"event",
|
|
64
68
|
"id",
|
|
65
69
|
"logger",
|
|
66
70
|
"memory",
|
|
71
|
+
"polyglot",
|
|
72
|
+
"string",
|
|
73
|
+
"struct",
|
|
74
|
+
"typedarray",
|
|
67
75
|
"typescript",
|
|
76
|
+
"utf8",
|
|
68
77
|
"wasm",
|
|
69
78
|
"webassembly",
|
|
70
79
|
"wrapper",
|
|
@@ -97,8 +106,8 @@
|
|
|
97
106
|
"./bridge": {
|
|
98
107
|
"default": "./bridge.js"
|
|
99
108
|
},
|
|
100
|
-
"./codegen": {
|
|
101
|
-
"default": "./codegen.js"
|
|
109
|
+
"./codegen/c11": {
|
|
110
|
+
"default": "./codegen/c11.js"
|
|
102
111
|
},
|
|
103
112
|
"./codegen/typescript": {
|
|
104
113
|
"default": "./codegen/typescript.js"
|
|
@@ -109,13 +118,22 @@
|
|
|
109
118
|
"./codegen/zig": {
|
|
110
119
|
"default": "./codegen/zig.js"
|
|
111
120
|
},
|
|
121
|
+
"./codegen": {
|
|
122
|
+
"default": "./codegen.js"
|
|
123
|
+
},
|
|
112
124
|
"./object-index": {
|
|
113
125
|
"default": "./object-index.js"
|
|
126
|
+
},
|
|
127
|
+
"./pointer": {
|
|
128
|
+
"default": "./pointer.js"
|
|
129
|
+
},
|
|
130
|
+
"./string": {
|
|
131
|
+
"default": "./string.js"
|
|
114
132
|
}
|
|
115
133
|
},
|
|
116
134
|
"thi.ng": {
|
|
117
135
|
"status": "alpha",
|
|
118
136
|
"year": 2022
|
|
119
137
|
},
|
|
120
|
-
"gitHead": "
|
|
138
|
+
"gitHead": "973139c5aa3b50081020f4cc726a7cc330f77fc7\n"
|
|
121
139
|
}
|
package/pointer.d.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { Fn, IDeref } from "@thi.ng/api";
|
|
2
|
+
import type { IWasmMemoryAccess } from "./api.js";
|
|
3
|
+
/**
|
|
4
|
+
* Generic pointer facility which on {@link Pointer.deref()} calls wrapper
|
|
5
|
+
* function (provided as ctor arg) to realise the pointer's target value. The
|
|
6
|
+
* pointer's target address can be accessed via {@link Pointer.addr}
|
|
7
|
+
* (read/write).
|
|
8
|
+
*
|
|
9
|
+
* @remarks
|
|
10
|
+
* The pointer always behaves like `volatile`, i.e. memoization of target values
|
|
11
|
+
* is purposfully avoided and the wrapper function is executed anew _each_ time
|
|
12
|
+
* the pointer is deref'd.
|
|
13
|
+
*/
|
|
14
|
+
export declare class Pointer<T> implements IDeref<T> {
|
|
15
|
+
readonly mem: IWasmMemoryAccess;
|
|
16
|
+
readonly base: number;
|
|
17
|
+
readonly fn: Fn<number, T>;
|
|
18
|
+
constructor(mem: IWasmMemoryAccess, base: number, fn: Fn<number, T>);
|
|
19
|
+
get addr(): number;
|
|
20
|
+
set addr(addr: number);
|
|
21
|
+
deref(): T;
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=pointer.d.ts.map
|
package/pointer.js
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generic pointer facility which on {@link Pointer.deref()} calls wrapper
|
|
3
|
+
* function (provided as ctor arg) to realise the pointer's target value. The
|
|
4
|
+
* pointer's target address can be accessed via {@link Pointer.addr}
|
|
5
|
+
* (read/write).
|
|
6
|
+
*
|
|
7
|
+
* @remarks
|
|
8
|
+
* The pointer always behaves like `volatile`, i.e. memoization of target values
|
|
9
|
+
* is purposfully avoided and the wrapper function is executed anew _each_ time
|
|
10
|
+
* the pointer is deref'd.
|
|
11
|
+
*/
|
|
12
|
+
export class Pointer {
|
|
13
|
+
constructor(mem, base, fn) {
|
|
14
|
+
this.mem = mem;
|
|
15
|
+
this.base = base;
|
|
16
|
+
this.fn = fn;
|
|
17
|
+
}
|
|
18
|
+
get addr() {
|
|
19
|
+
return this.mem.u32[this.base >>> 2];
|
|
20
|
+
}
|
|
21
|
+
set addr(addr) {
|
|
22
|
+
this.mem.u32[this.base >>> 2] = addr;
|
|
23
|
+
}
|
|
24
|
+
deref() {
|
|
25
|
+
return this.fn(this.addr);
|
|
26
|
+
}
|
|
27
|
+
}
|
package/string.d.ts
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import type { IDeref } from "@thi.ng/api";
|
|
2
|
+
import type { IWasmMemoryAccess } from "./api.js";
|
|
3
|
+
/**
|
|
4
|
+
* Memory mapped string wrapper for Zig-style UTF-8 encoded byte slices (aka
|
|
5
|
+
* pointer & length pair). The actual JS string can be obtained via
|
|
6
|
+
* {@link WasmStringSlice.deref} and mutated via {@link WasmStringSlice.set}.
|
|
7
|
+
*/
|
|
8
|
+
export declare class WasmStringSlice implements IDeref<string> {
|
|
9
|
+
readonly mem: IWasmMemoryAccess;
|
|
10
|
+
readonly base: number;
|
|
11
|
+
readonly isConst: boolean;
|
|
12
|
+
readonly max: number;
|
|
13
|
+
constructor(mem: IWasmMemoryAccess, base: number, isConst?: boolean);
|
|
14
|
+
/**
|
|
15
|
+
* Returns string start address (deref'd pointer).
|
|
16
|
+
*/
|
|
17
|
+
get addr(): number;
|
|
18
|
+
/**
|
|
19
|
+
* Returns string length (read from memory)
|
|
20
|
+
*/
|
|
21
|
+
get length(): number;
|
|
22
|
+
/**
|
|
23
|
+
* Returns memory as JS string (aka wrapper for
|
|
24
|
+
* {@link WasmBridge.getString}).
|
|
25
|
+
*/
|
|
26
|
+
deref(): string;
|
|
27
|
+
/**
|
|
28
|
+
* If given a JS string as arg (and if **not** a const slice), attempts to
|
|
29
|
+
* overwrite this wrapped string's memory with bytes from given string. If
|
|
30
|
+
* given another {@link WasmStringSlice} as arg, only the slice pointer &
|
|
31
|
+
* new length will be updated (always succeeds).
|
|
32
|
+
*
|
|
33
|
+
* @remarks
|
|
34
|
+
* When copying bytes from a JS string, an error will be thrown if the new
|
|
35
|
+
* string is longer than the _original_ length of the slice (i.e. from when
|
|
36
|
+
* this `WasmStringSlice` wrapper instance was created). Also updates the
|
|
37
|
+
* slice's length field to new string length.
|
|
38
|
+
*
|
|
39
|
+
* Passing a `WasmString` instance as arg is faster than JS string since
|
|
40
|
+
* only the slice definition itself will be updated.
|
|
41
|
+
*
|
|
42
|
+
* @param str
|
|
43
|
+
*/
|
|
44
|
+
set(str: string | WasmStringSlice): void;
|
|
45
|
+
toJSON(): string;
|
|
46
|
+
toString(): string;
|
|
47
|
+
valueOf(): string;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Memory mapped string wrapper for C-style UTF-8 encoded and zero-terminated
|
|
51
|
+
* char pointers. The actual JS string can be obtained via
|
|
52
|
+
* {@link WasmStringSlice.deref} and mutated via {@link WasmStringSlice.set}.
|
|
53
|
+
*/
|
|
54
|
+
export declare class WasmStringPtr implements IDeref<string> {
|
|
55
|
+
readonly mem: IWasmMemoryAccess;
|
|
56
|
+
readonly base: number;
|
|
57
|
+
readonly isConst: boolean;
|
|
58
|
+
constructor(mem: IWasmMemoryAccess, base: number, isConst?: boolean);
|
|
59
|
+
/**
|
|
60
|
+
* Returns string start address (deref'd pointer).
|
|
61
|
+
*/
|
|
62
|
+
get addr(): number;
|
|
63
|
+
set addr(addr: number);
|
|
64
|
+
/**
|
|
65
|
+
* Returns computed string length (scanning memory for zero sentinel)
|
|
66
|
+
*/
|
|
67
|
+
get length(): number;
|
|
68
|
+
/**
|
|
69
|
+
* Returns memory as JS string (aka wrapper for
|
|
70
|
+
* {@link WasmBridge.getString}).
|
|
71
|
+
*/
|
|
72
|
+
deref(): string;
|
|
73
|
+
/**
|
|
74
|
+
* If given a JS string as arg (and if not a const pointer), attempts to
|
|
75
|
+
* overwrite this wrapped string's memory with bytes from given string. If
|
|
76
|
+
* given another {@link WasmStringPtr}, it merely overrides the pointer to
|
|
77
|
+
* the new one (always succeeds).
|
|
78
|
+
*
|
|
79
|
+
* @remarks
|
|
80
|
+
* Unlike with {@link WasmStringSlice.set} this implementation which
|
|
81
|
+
* performs bounds checking when copying bytes from a JS string, this method
|
|
82
|
+
* only throws an error if the new string is longer than the available
|
|
83
|
+
* memory (from the start address until the end of the WASM memory).
|
|
84
|
+
* **Therefore, this is as (un)safe as a C pointer and should be used with
|
|
85
|
+
* caution!**
|
|
86
|
+
*
|
|
87
|
+
* Passing a `WasmStringPtr` instance as arg is faster than JS string since
|
|
88
|
+
* only the pointer itself will be updated.
|
|
89
|
+
*
|
|
90
|
+
* @param str
|
|
91
|
+
*/
|
|
92
|
+
set(str: string | WasmStringPtr): void;
|
|
93
|
+
toJSON(): string;
|
|
94
|
+
toString(): string;
|
|
95
|
+
valueOf(): string;
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=string.d.ts.map
|
package/string.js
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { unsupported } from "@thi.ng/errors/unsupported";
|
|
2
|
+
/**
|
|
3
|
+
* Memory mapped string wrapper for Zig-style UTF-8 encoded byte slices (aka
|
|
4
|
+
* pointer & length pair). The actual JS string can be obtained via
|
|
5
|
+
* {@link WasmStringSlice.deref} and mutated via {@link WasmStringSlice.set}.
|
|
6
|
+
*/
|
|
7
|
+
export class WasmStringSlice {
|
|
8
|
+
constructor(mem, base, isConst = true) {
|
|
9
|
+
this.mem = mem;
|
|
10
|
+
this.base = base;
|
|
11
|
+
this.isConst = isConst;
|
|
12
|
+
this.max = this.length;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Returns string start address (deref'd pointer).
|
|
16
|
+
*/
|
|
17
|
+
get addr() {
|
|
18
|
+
return this.mem.u32[this.base >>> 2];
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Returns string length (read from memory)
|
|
22
|
+
*/
|
|
23
|
+
get length() {
|
|
24
|
+
return this.mem.u32[(this.base + 4) >>> 2];
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Returns memory as JS string (aka wrapper for
|
|
28
|
+
* {@link WasmBridge.getString}).
|
|
29
|
+
*/
|
|
30
|
+
deref() {
|
|
31
|
+
return this.mem.getString(this.addr, this.length);
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* If given a JS string as arg (and if **not** a const slice), attempts to
|
|
35
|
+
* overwrite this wrapped string's memory with bytes from given string. If
|
|
36
|
+
* given another {@link WasmStringSlice} as arg, only the slice pointer &
|
|
37
|
+
* new length will be updated (always succeeds).
|
|
38
|
+
*
|
|
39
|
+
* @remarks
|
|
40
|
+
* When copying bytes from a JS string, an error will be thrown if the new
|
|
41
|
+
* string is longer than the _original_ length of the slice (i.e. from when
|
|
42
|
+
* this `WasmStringSlice` wrapper instance was created). Also updates the
|
|
43
|
+
* slice's length field to new string length.
|
|
44
|
+
*
|
|
45
|
+
* Passing a `WasmString` instance as arg is faster than JS string since
|
|
46
|
+
* only the slice definition itself will be updated.
|
|
47
|
+
*
|
|
48
|
+
* @param str
|
|
49
|
+
*/
|
|
50
|
+
set(str) {
|
|
51
|
+
if (typeof str === "string") {
|
|
52
|
+
if (this.isConst)
|
|
53
|
+
unsupported("can't mutate const string");
|
|
54
|
+
this.mem.u32[(this.base + 4) >>> 2] = this.mem.setString(str, this.addr, this.max + 1, true);
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
this.mem.u32[this.base >>> 2] = str.addr;
|
|
58
|
+
this.mem.u32[(this.base + 4) >>> 2] = str.length;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
toJSON() {
|
|
62
|
+
return this.deref();
|
|
63
|
+
}
|
|
64
|
+
toString() {
|
|
65
|
+
return this.deref();
|
|
66
|
+
}
|
|
67
|
+
valueOf() {
|
|
68
|
+
return this.deref();
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Memory mapped string wrapper for C-style UTF-8 encoded and zero-terminated
|
|
73
|
+
* char pointers. The actual JS string can be obtained via
|
|
74
|
+
* {@link WasmStringSlice.deref} and mutated via {@link WasmStringSlice.set}.
|
|
75
|
+
*/
|
|
76
|
+
export class WasmStringPtr {
|
|
77
|
+
constructor(mem, base, isConst = true) {
|
|
78
|
+
this.mem = mem;
|
|
79
|
+
this.base = base;
|
|
80
|
+
this.isConst = isConst;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Returns string start address (deref'd pointer).
|
|
84
|
+
*/
|
|
85
|
+
get addr() {
|
|
86
|
+
return this.mem.u32[this.base >>> 2];
|
|
87
|
+
}
|
|
88
|
+
set addr(addr) {
|
|
89
|
+
this.mem.u32[this.base >>> 2] = addr;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Returns computed string length (scanning memory for zero sentinel)
|
|
93
|
+
*/
|
|
94
|
+
get length() {
|
|
95
|
+
const addr = this.addr;
|
|
96
|
+
const idx = this.mem.u8.indexOf(0, addr);
|
|
97
|
+
return idx >= 0 ? idx - addr : 0;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Returns memory as JS string (aka wrapper for
|
|
101
|
+
* {@link WasmBridge.getString}).
|
|
102
|
+
*/
|
|
103
|
+
deref() {
|
|
104
|
+
return this.mem.getString(this.addr, this.length);
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* If given a JS string as arg (and if not a const pointer), attempts to
|
|
108
|
+
* overwrite this wrapped string's memory with bytes from given string. If
|
|
109
|
+
* given another {@link WasmStringPtr}, it merely overrides the pointer to
|
|
110
|
+
* the new one (always succeeds).
|
|
111
|
+
*
|
|
112
|
+
* @remarks
|
|
113
|
+
* Unlike with {@link WasmStringSlice.set} this implementation which
|
|
114
|
+
* performs bounds checking when copying bytes from a JS string, this method
|
|
115
|
+
* only throws an error if the new string is longer than the available
|
|
116
|
+
* memory (from the start address until the end of the WASM memory).
|
|
117
|
+
* **Therefore, this is as (un)safe as a C pointer and should be used with
|
|
118
|
+
* caution!**
|
|
119
|
+
*
|
|
120
|
+
* Passing a `WasmStringPtr` instance as arg is faster than JS string since
|
|
121
|
+
* only the pointer itself will be updated.
|
|
122
|
+
*
|
|
123
|
+
* @param str
|
|
124
|
+
*/
|
|
125
|
+
set(str) {
|
|
126
|
+
const addr = this.addr;
|
|
127
|
+
if (typeof str === "string") {
|
|
128
|
+
if (this.isConst)
|
|
129
|
+
unsupported("can't mutate const string");
|
|
130
|
+
this.mem.setString(str, addr, this.mem.u8.byteLength - addr, true);
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
this.addr = str.addr;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
toJSON() {
|
|
137
|
+
return this.deref();
|
|
138
|
+
}
|
|
139
|
+
toString() {
|
|
140
|
+
return this.deref();
|
|
141
|
+
}
|
|
142
|
+
valueOf() {
|
|
143
|
+
return this.deref();
|
|
144
|
+
}
|
|
145
|
+
}
|