@thi.ng/wasm-api 2.0.4 → 2.1.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 +13 -1
- package/README.md +26 -21
- package/package.json +6 -4
- package/pointer.d.ts +12 -4
- package/pointer.js +14 -2
- package/string.d.ts +13 -3
- package/string.js +17 -6
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Change Log
|
|
2
2
|
|
|
3
|
-
- **Last updated**: 2024-
|
|
3
|
+
- **Last updated**: 2024-11-09T15:34:31Z
|
|
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,18 @@ 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
|
+
## [2.1.0](https://github.com/thi-ng/umbrella/tree/@thi.ng/wasm-api@2.1.0) (2024-11-09)
|
|
13
|
+
|
|
14
|
+
#### 🚀 Features
|
|
15
|
+
|
|
16
|
+
- add null handling in WasmStringPtr ([e8a094d](https://github.com/thi-ng/umbrella/commit/e8a094d))
|
|
17
|
+
- update logic to interpret as null pointer if addr=0
|
|
18
|
+
- update doc strings
|
|
19
|
+
- add null pointer checks, update tests ([247cbbf](https://github.com/thi-ng/umbrella/commit/247cbbf))
|
|
20
|
+
- update Pointer/Pointer64 deref logic to return undefined for null pointers
|
|
21
|
+
- add `.isNull` getter for all pointer types (incl. `WasmStringPtr`)
|
|
22
|
+
- update tests
|
|
23
|
+
|
|
12
24
|
# [2.0.0](https://github.com/thi-ng/umbrella/tree/@thi.ng/wasm-api@2.0.0) (2024-08-18)
|
|
13
25
|
|
|
14
26
|
#### 🛑 Breaking changes
|
package/README.md
CHANGED
|
@@ -460,7 +460,7 @@ Browser ESM import:
|
|
|
460
460
|
|
|
461
461
|
[JSDelivr documentation](https://www.jsdelivr.com/)
|
|
462
462
|
|
|
463
|
-
Package sizes (brotli'd, pre-treeshake): ESM: 3.
|
|
463
|
+
Package sizes (brotli'd, pre-treeshake): ESM: 3.05 KB
|
|
464
464
|
|
|
465
465
|
## Dependencies
|
|
466
466
|
|
|
@@ -520,7 +520,7 @@ interface App extends WasmExports {
|
|
|
520
520
|
|
|
521
521
|
### Zig version
|
|
522
522
|
|
|
523
|
-
Requires [Zig](https://ziglang.org) to be installed:
|
|
523
|
+
Requires [Zig](https://ziglang.org) (v0.13.x) to be installed:
|
|
524
524
|
|
|
525
525
|
```zig tangle:export/hello.zig
|
|
526
526
|
//! Example Zig application (hello.zig)
|
|
@@ -539,7 +539,7 @@ scenarios add the supplied .zig file(s) to your `build.zig` and/or source
|
|
|
539
539
|
folder):
|
|
540
540
|
|
|
541
541
|
```bash
|
|
542
|
-
# compile WASM binary (zig v0.
|
|
542
|
+
# compile WASM binary (zig v0.13)
|
|
543
543
|
zig build-exe \
|
|
544
544
|
-fno-entry -fstrip -OReleaseSmall -target wasm32-freestanding \
|
|
545
545
|
--name hello -rdynamic --import-symbols \
|
|
@@ -555,24 +555,29 @@ The resulting WASM:
|
|
|
555
555
|
|
|
556
556
|
```wasm
|
|
557
557
|
(module
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
(
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
558
|
+
(type $0 (func (param i32 i32)))
|
|
559
|
+
(type $1 (func))
|
|
560
|
+
(type $2 (func (param i32) (result i32)))
|
|
561
|
+
(import "wasmapi" "_printStr" (func $fimport$0 (param i32 i32)))
|
|
562
|
+
(global $global$0 (mut i32) (i32.const 1048576))
|
|
563
|
+
(memory $0 17)
|
|
564
|
+
(data $0 (i32.const 1048576) "hello world!\00")
|
|
565
|
+
(export "memory" (memory $0))
|
|
566
|
+
(export "start" (func $0))
|
|
567
|
+
(export "_wasm_allocate" (func $1))
|
|
568
|
+
(export "_wasm_free" (func $2))
|
|
569
|
+
(func $0
|
|
570
|
+
(call $fimport$0
|
|
571
|
+
(i32.const 1048576)
|
|
572
|
+
(i32.const 12)
|
|
573
|
+
)
|
|
574
|
+
)
|
|
575
|
+
(func $1 (param $0 i32) (result i32)
|
|
576
|
+
(i32.const 0)
|
|
577
|
+
)
|
|
578
|
+
(func $2 (param $0 i32) (param $1 i32)
|
|
579
|
+
)
|
|
580
|
+
)
|
|
576
581
|
```
|
|
577
582
|
|
|
578
583
|
### C version
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@thi.ng/wasm-api",
|
|
3
|
-
"version": "2.0
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"description": "Generic, modular, extensible API bridge and infrastructure for hybrid JS & WebAssembly projects",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"module": "./index.js",
|
|
@@ -33,12 +33,14 @@
|
|
|
33
33
|
"doc:readme": "bun ../../tools/src/module-stats.ts && bun ../../tools/src/readme.ts",
|
|
34
34
|
"pub": "yarn npm publish --access public",
|
|
35
35
|
"test": "zig test zig/tests.zig && bun test",
|
|
36
|
-
"test:build-zig": "zig build-
|
|
36
|
+
"test:build-zig-allocators": "zig build-exe -fno-entry -fstrip --stack 4096 -OReleaseSmall -target wasm32-freestanding --dep wasmapi -Mroot=test/allocators.zig -Mwasmapi=zig/lib.zig --name allocators -rdynamic --import-symbols && wasm-dis -o allocators.wast allocators.wasm && mv allocators.wasm test",
|
|
37
|
+
"test:build-zig-custom": "zig build-exe -fno-entry -fstrip --stack 4096 -OReleaseSmall -target wasm32-freestanding --dep wasmapi -Mroot=test/custom.zig -Mwasmapi=zig/lib.zig --name custom -rdynamic --import-symbols && wasm-dis -o custom.wast custom.wasm && mv custom.wasm test",
|
|
38
|
+
"test:build-zig": "yarn test:build-zig-allocators && yarn test:build-zig-custom",
|
|
37
39
|
"tool:tangle": "../../node_modules/.bin/tangle src/**/*.ts"
|
|
38
40
|
},
|
|
39
41
|
"dependencies": {
|
|
40
42
|
"@thi.ng/api": "^8.11.11",
|
|
41
|
-
"@thi.ng/arrays": "^2.10.
|
|
43
|
+
"@thi.ng/arrays": "^2.10.4",
|
|
42
44
|
"@thi.ng/checks": "^3.6.13",
|
|
43
45
|
"@thi.ng/errors": "^2.5.17",
|
|
44
46
|
"@thi.ng/hex": "^2.3.55",
|
|
@@ -119,5 +121,5 @@
|
|
|
119
121
|
"status": "alpha",
|
|
120
122
|
"year": 2022
|
|
121
123
|
},
|
|
122
|
-
"gitHead": "
|
|
124
|
+
"gitHead": "c2c371069911fdae138149fdcf937c4ad7a8c71e\n"
|
|
123
125
|
}
|
package/pointer.d.ts
CHANGED
|
@@ -10,15 +10,19 @@ import type { IWasmMemoryAccess } from "./api.js";
|
|
|
10
10
|
* The pointer always behaves like `volatile`, i.e. memoization of target values
|
|
11
11
|
* is purposfully avoided and the wrapper function is executed anew _each_ time
|
|
12
12
|
* the pointer is deref'd.
|
|
13
|
+
*
|
|
14
|
+
* Pointers with addr=0 are interpreted as null/optional pointers and
|
|
15
|
+
* {@link Pointer.deref} will return `undefined` in these cases.
|
|
13
16
|
*/
|
|
14
|
-
export declare class Pointer<T> implements IDeref<T> {
|
|
17
|
+
export declare class Pointer<T> implements IDeref<T | undefined> {
|
|
15
18
|
readonly mem: IWasmMemoryAccess;
|
|
16
19
|
readonly base: number;
|
|
17
20
|
readonly fn: Fn<number, T>;
|
|
18
21
|
constructor(mem: IWasmMemoryAccess, base: number, fn: Fn<number, T>);
|
|
19
22
|
get addr(): number;
|
|
20
23
|
set addr(addr: number);
|
|
21
|
-
|
|
24
|
+
get isNull(): boolean;
|
|
25
|
+
deref(): T | undefined;
|
|
22
26
|
}
|
|
23
27
|
/**
|
|
24
28
|
* Generic pointer facility for
|
|
@@ -31,14 +35,18 @@ export declare class Pointer<T> implements IDeref<T> {
|
|
|
31
35
|
* The pointer always behaves like `volatile`, i.e. memoization of target values
|
|
32
36
|
* is purposefully avoided and the wrapper function is executed anew _each_ time
|
|
33
37
|
* the pointer is deref'd.
|
|
38
|
+
*
|
|
39
|
+
* Pointers with addr=0 are interpreted as null/optional pointers and
|
|
40
|
+
* {@link Pointer64.deref} will return `undefined` in these cases.
|
|
34
41
|
*/
|
|
35
|
-
export declare class Pointer64<T> implements IDeref<T> {
|
|
42
|
+
export declare class Pointer64<T> implements IDeref<T | undefined> {
|
|
36
43
|
readonly mem: IWasmMemoryAccess;
|
|
37
44
|
readonly base: bigint;
|
|
38
45
|
readonly fn: Fn<bigint, T>;
|
|
39
46
|
constructor(mem: IWasmMemoryAccess, base: bigint, fn: Fn<bigint, T>);
|
|
40
47
|
get addr(): bigint;
|
|
41
48
|
set addr(addr: bigint);
|
|
42
|
-
|
|
49
|
+
get isNull(): boolean;
|
|
50
|
+
deref(): T | undefined;
|
|
43
51
|
}
|
|
44
52
|
//# sourceMappingURL=pointer.d.ts.map
|
package/pointer.js
CHANGED
|
@@ -5,13 +5,19 @@ class Pointer {
|
|
|
5
5
|
this.fn = fn;
|
|
6
6
|
}
|
|
7
7
|
get addr() {
|
|
8
|
+
this.mem.ensureMemory();
|
|
8
9
|
return this.mem.u32[this.base >>> 2];
|
|
9
10
|
}
|
|
10
11
|
set addr(addr) {
|
|
12
|
+
this.mem.ensureMemory();
|
|
11
13
|
this.mem.u32[this.base >>> 2] = addr;
|
|
12
14
|
}
|
|
15
|
+
get isNull() {
|
|
16
|
+
return this.addr === 0;
|
|
17
|
+
}
|
|
13
18
|
deref() {
|
|
14
|
-
|
|
19
|
+
const addr = this.addr;
|
|
20
|
+
return addr ? this.fn(addr) : void 0;
|
|
15
21
|
}
|
|
16
22
|
}
|
|
17
23
|
class Pointer64 {
|
|
@@ -21,13 +27,19 @@ class Pointer64 {
|
|
|
21
27
|
this.fn = fn;
|
|
22
28
|
}
|
|
23
29
|
get addr() {
|
|
30
|
+
this.mem.ensureMemory();
|
|
24
31
|
return this.mem.u64[Number(this.base >> BigInt(3))];
|
|
25
32
|
}
|
|
26
33
|
set addr(addr) {
|
|
34
|
+
this.mem.ensureMemory();
|
|
27
35
|
this.mem.u64[Number(this.base >> BigInt(3))] = addr;
|
|
28
36
|
}
|
|
37
|
+
get isNull() {
|
|
38
|
+
return this.addr === 0n;
|
|
39
|
+
}
|
|
29
40
|
deref() {
|
|
30
|
-
|
|
41
|
+
const addr = this.addr;
|
|
42
|
+
return addr ? this.fn(addr) : void 0;
|
|
31
43
|
}
|
|
32
44
|
}
|
|
33
45
|
export {
|
package/string.d.ts
CHANGED
|
@@ -80,7 +80,11 @@ export declare class WasmStringSlice implements ReadonlyWasmString {
|
|
|
80
80
|
/**
|
|
81
81
|
* Memory mapped string wrapper for C-style UTF-8 encoded and **always**
|
|
82
82
|
* zero-terminated char pointers. The actual JS string can be obtained via
|
|
83
|
-
* {@link
|
|
83
|
+
* {@link WasmStringPtr.deref} and mutated via {@link WasmStringPtr.set}.
|
|
84
|
+
*
|
|
85
|
+
* @remarks
|
|
86
|
+
* Pointers with addr=0 are interpreted as null/optional pointers. See
|
|
87
|
+
* {@link WasmStringPtr.length} and {@link WasmStringPtr.deref} for details.
|
|
84
88
|
*/
|
|
85
89
|
export declare class WasmStringPtr implements ReadonlyWasmString {
|
|
86
90
|
readonly mem: IWasmMemoryAccess;
|
|
@@ -92,13 +96,19 @@ export declare class WasmStringPtr implements ReadonlyWasmString {
|
|
|
92
96
|
*/
|
|
93
97
|
get addr(): number;
|
|
94
98
|
set addr(addr: number);
|
|
99
|
+
get isNull(): boolean;
|
|
95
100
|
/**
|
|
96
101
|
* Returns computed string length (scanning memory for zero sentinel)
|
|
102
|
+
*
|
|
103
|
+
* @remarks
|
|
104
|
+
* Always returns 0 if null pointer (i.e. if {@link WasmStringPtr.addr} is
|
|
105
|
+
* zero).
|
|
97
106
|
*/
|
|
98
107
|
get length(): number;
|
|
99
108
|
/**
|
|
100
|
-
* Returns memory as JS string (
|
|
101
|
-
* {@link
|
|
109
|
+
* Returns memory as JS string (via {@link WasmBridge.getString}). Returns
|
|
110
|
+
* empty string if null pointer (i.e. if {@link WasmStringPtr.addr} is
|
|
111
|
+
* zero).
|
|
102
112
|
*/
|
|
103
113
|
deref(): string;
|
|
104
114
|
/**
|
package/string.js
CHANGED
|
@@ -119,20 +119,30 @@ class WasmStringPtr {
|
|
|
119
119
|
this.mem.ensureMemory();
|
|
120
120
|
this.mem.u32[this.base >>> 2] = addr;
|
|
121
121
|
}
|
|
122
|
+
get isNull() {
|
|
123
|
+
return this.addr === 0;
|
|
124
|
+
}
|
|
122
125
|
/**
|
|
123
126
|
* Returns computed string length (scanning memory for zero sentinel)
|
|
127
|
+
*
|
|
128
|
+
* @remarks
|
|
129
|
+
* Always returns 0 if null pointer (i.e. if {@link WasmStringPtr.addr} is
|
|
130
|
+
* zero).
|
|
124
131
|
*/
|
|
125
132
|
get length() {
|
|
126
|
-
this.
|
|
127
|
-
|
|
128
|
-
|
|
133
|
+
const addr = this.addr;
|
|
134
|
+
if (!addr) return 0;
|
|
135
|
+
const idx = this.mem.u8.indexOf(0, addr);
|
|
136
|
+
return idx >= 0 ? idx - addr : 0;
|
|
129
137
|
}
|
|
130
138
|
/**
|
|
131
|
-
* Returns memory as JS string (
|
|
132
|
-
* {@link
|
|
139
|
+
* Returns memory as JS string (via {@link WasmBridge.getString}). Returns
|
|
140
|
+
* empty string if null pointer (i.e. if {@link WasmStringPtr.addr} is
|
|
141
|
+
* zero).
|
|
133
142
|
*/
|
|
134
143
|
deref() {
|
|
135
|
-
|
|
144
|
+
const addr = this.addr;
|
|
145
|
+
return addr ? this.mem.getString(addr, this.length) : "";
|
|
136
146
|
}
|
|
137
147
|
/**
|
|
138
148
|
* If given a JS string as arg (and if this `WasmStringPtr` instance itself
|
|
@@ -156,6 +166,7 @@ class WasmStringPtr {
|
|
|
156
166
|
*/
|
|
157
167
|
set(str) {
|
|
158
168
|
const addr = this.addr;
|
|
169
|
+
if (!addr) unsupported("can't mutate null pointer");
|
|
159
170
|
if (typeof str === "string") {
|
|
160
171
|
if (this.isConst) unsupported("can't mutate const string");
|
|
161
172
|
this.mem.ensureMemory();
|