@thi.ng/wasm-api 1.4.36 → 1.4.38
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 +1 -1
- package/README.md +1 -1
- package/api.js +6 -2
- package/bridge.js +436 -409
- package/object-index.js +74 -72
- package/package.json +14 -11
- package/pointer.js +34 -58
- package/string.js +201 -218
package/string.js
CHANGED
|
@@ -1,224 +1,207 @@
|
|
|
1
1
|
import { isNumber } from "@thi.ng/checks/is-number";
|
|
2
2
|
import { unsupported } from "@thi.ng/errors/unsupported";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
this.setSlice(terminate ? [slice[0], slice[1] - 1] : slice, terminate);
|
|
106
|
-
return slice;
|
|
107
|
-
}
|
|
108
|
-
toJSON() {
|
|
109
|
-
return this.deref();
|
|
110
|
-
}
|
|
111
|
-
toString() {
|
|
112
|
-
return this.deref();
|
|
113
|
-
}
|
|
114
|
-
valueOf() {
|
|
115
|
-
return this.deref();
|
|
116
|
-
}
|
|
3
|
+
class WasmStringSlice {
|
|
4
|
+
constructor(mem, base, isConst = true, terminated = true) {
|
|
5
|
+
this.mem = mem;
|
|
6
|
+
this.base = base;
|
|
7
|
+
this.isConst = isConst;
|
|
8
|
+
this.terminated = terminated;
|
|
9
|
+
this.maxLen = this.length;
|
|
10
|
+
}
|
|
11
|
+
maxLen;
|
|
12
|
+
/**
|
|
13
|
+
* Returns string start address (deref'd pointer).
|
|
14
|
+
*/
|
|
15
|
+
get addr() {
|
|
16
|
+
this.mem.ensureMemory();
|
|
17
|
+
return this.mem.u32[this.base >>> 2];
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Returns string length (read from memory)
|
|
21
|
+
*/
|
|
22
|
+
get length() {
|
|
23
|
+
this.mem.ensureMemory();
|
|
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
|
+
this.mem.ensureMemory();
|
|
52
|
+
if (typeof str === "string") {
|
|
53
|
+
if (this.isConst)
|
|
54
|
+
unsupported("can't mutate const string");
|
|
55
|
+
this.mem.u32[this.base + 4 >>> 2] = this.mem.setString(
|
|
56
|
+
str,
|
|
57
|
+
this.addr,
|
|
58
|
+
this.maxLen + ~~this.terminated,
|
|
59
|
+
this.terminated
|
|
60
|
+
);
|
|
61
|
+
} else {
|
|
62
|
+
this.mem.u32[this.base >>> 2] = str.addr;
|
|
63
|
+
this.mem.u32[this.base + 4 >>> 2] = str.length;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
setSlice(...args) {
|
|
67
|
+
this.mem.ensureMemory();
|
|
68
|
+
const [slice, terminated] = isNumber(args[0]) ? [[args[0], args[1]], args[2]] : [args[0], args[1]];
|
|
69
|
+
this.mem.u32[this.base >>> 2] = slice[0];
|
|
70
|
+
this.mem.u32[this.base + 4 >>> 2] = slice[1];
|
|
71
|
+
this.terminated = terminated;
|
|
72
|
+
return slice;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Encodes given string to UTF-8 (by default zero terminated), allocates
|
|
76
|
+
* memory for it, updates this slice and returns a {@link MemorySlice} of
|
|
77
|
+
* the allocated region.
|
|
78
|
+
*
|
|
79
|
+
* @remarks
|
|
80
|
+
* If `terminated` is true, the stored slice length will **NOT** include the
|
|
81
|
+
* sentinel! E.g. the slice length of zero-terminated string `"abc"` is 3,
|
|
82
|
+
* but the number of allocated bytes is 4. This is done for compatibility
|
|
83
|
+
* with Zig's sentinel-terminated slice handling (e.g. `[:0]u8` slices).
|
|
84
|
+
*
|
|
85
|
+
* Regardless of `terminated` setting, the returned `MemorySlice` **always**
|
|
86
|
+
* covers the entire allocated region!
|
|
87
|
+
*
|
|
88
|
+
* @param str
|
|
89
|
+
* @param terminate
|
|
90
|
+
*/
|
|
91
|
+
setAlloc(str, terminate = true) {
|
|
92
|
+
const slice = __alloc(this.mem, str, terminate);
|
|
93
|
+
this.setSlice(terminate ? [slice[0], slice[1] - 1] : slice, terminate);
|
|
94
|
+
return slice;
|
|
95
|
+
}
|
|
96
|
+
toJSON() {
|
|
97
|
+
return this.deref();
|
|
98
|
+
}
|
|
99
|
+
toString() {
|
|
100
|
+
return this.deref();
|
|
101
|
+
}
|
|
102
|
+
valueOf() {
|
|
103
|
+
return this.deref();
|
|
104
|
+
}
|
|
117
105
|
}
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
toJSON() {
|
|
207
|
-
return this.deref();
|
|
208
|
-
}
|
|
209
|
-
toString() {
|
|
210
|
-
return this.deref();
|
|
211
|
-
}
|
|
212
|
-
valueOf() {
|
|
213
|
-
return this.deref();
|
|
214
|
-
}
|
|
106
|
+
class WasmStringPtr {
|
|
107
|
+
constructor(mem, base, isConst = true) {
|
|
108
|
+
this.mem = mem;
|
|
109
|
+
this.base = base;
|
|
110
|
+
this.isConst = isConst;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Returns string start address (deref'd pointer).
|
|
114
|
+
*/
|
|
115
|
+
get addr() {
|
|
116
|
+
this.mem.ensureMemory();
|
|
117
|
+
return this.mem.u32[this.base >>> 2];
|
|
118
|
+
}
|
|
119
|
+
set addr(addr) {
|
|
120
|
+
this.mem.ensureMemory();
|
|
121
|
+
this.mem.u32[this.base >>> 2] = addr;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Returns computed string length (scanning memory for zero sentinel)
|
|
125
|
+
*/
|
|
126
|
+
get length() {
|
|
127
|
+
this.mem.ensureMemory();
|
|
128
|
+
const idx = this.mem.u8.indexOf(0, this.addr);
|
|
129
|
+
return idx >= 0 ? idx - this.addr : 0;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Returns memory as JS string (aka wrapper for
|
|
133
|
+
* {@link WasmBridge.getString}).
|
|
134
|
+
*/
|
|
135
|
+
deref() {
|
|
136
|
+
return this.mem.getString(this.addr, this.length);
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* If given a JS string as arg (and if this `WasmStringPtr` instance itself
|
|
140
|
+
* is not a `const` pointer), attempts to overwrite this wrapped string's
|
|
141
|
+
* memory with bytes from given string. If given another
|
|
142
|
+
* {@link WasmStringPtr}, it merely overrides the pointer to the new one
|
|
143
|
+
* (always succeeds).
|
|
144
|
+
*
|
|
145
|
+
* @remarks
|
|
146
|
+
* Unlike with {@link WasmStringSlice.set} this implementation which
|
|
147
|
+
* performs bounds checking when copying bytes from a JS string, this method
|
|
148
|
+
* only throws an error if the new string is longer than the available
|
|
149
|
+
* memory (from the start address until the end of the WASM memory).
|
|
150
|
+
* **Therefore, this is as (un)safe as a C pointer and should be used with
|
|
151
|
+
* caution!**
|
|
152
|
+
*
|
|
153
|
+
* Passing a `WasmStringPtr` instance as arg is faster than JS string since
|
|
154
|
+
* only the pointer itself will be updated.
|
|
155
|
+
*
|
|
156
|
+
* @param str
|
|
157
|
+
*/
|
|
158
|
+
set(str) {
|
|
159
|
+
const addr = this.addr;
|
|
160
|
+
if (typeof str === "string") {
|
|
161
|
+
if (this.isConst)
|
|
162
|
+
unsupported("can't mutate const string");
|
|
163
|
+
this.mem.ensureMemory();
|
|
164
|
+
this.mem.setString(str, addr, this.mem.u8.byteLength - addr, true);
|
|
165
|
+
} else {
|
|
166
|
+
this.addr = str.addr;
|
|
167
|
+
this.isConst = str.isConst;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Encodes given string to UTF-8 (by default zero terminated), allocates
|
|
172
|
+
* memory for it, updates this pointer to new address and returns allocated
|
|
173
|
+
* {@link MemorySlice}.
|
|
174
|
+
*
|
|
175
|
+
* @remarks
|
|
176
|
+
* See {@link WasmStringSlice.setAlloc} for important details.
|
|
177
|
+
*
|
|
178
|
+
* @param str
|
|
179
|
+
*/
|
|
180
|
+
setAlloc(str) {
|
|
181
|
+
const slice = __alloc(this.mem, str, true);
|
|
182
|
+
this.mem.u32[this.base >>> 2] = slice[0];
|
|
183
|
+
return slice;
|
|
184
|
+
}
|
|
185
|
+
toJSON() {
|
|
186
|
+
return this.deref();
|
|
187
|
+
}
|
|
188
|
+
toString() {
|
|
189
|
+
return this.deref();
|
|
190
|
+
}
|
|
191
|
+
valueOf() {
|
|
192
|
+
return this.deref();
|
|
193
|
+
}
|
|
215
194
|
}
|
|
216
195
|
const __alloc = (mem, str, terminate) => {
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
196
|
+
const buf = new TextEncoder().encode(str);
|
|
197
|
+
const slice = mem.allocate(buf.length + ~~terminate);
|
|
198
|
+
if (slice[1] > 0) {
|
|
199
|
+
mem.u8.set(buf, slice[0]);
|
|
200
|
+
terminate && (mem.u8[slice[0] + buf.length] = 0);
|
|
201
|
+
}
|
|
202
|
+
return slice;
|
|
203
|
+
};
|
|
204
|
+
export {
|
|
205
|
+
WasmStringPtr,
|
|
206
|
+
WasmStringSlice
|
|
224
207
|
};
|