@thi.ng/wasm-api 1.4.35 → 1.4.37

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/bridge.js CHANGED
@@ -1,419 +1,446 @@
1
- import { __decorate } from "tslib";
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
+ var __decorateClass = (decorators, target, key, kind) => {
4
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
5
+ for (var i = decorators.length - 1, decorator; i >= 0; i--)
6
+ if (decorator = decorators[i])
7
+ result = (kind ? decorator(target, key, result) : decorator(result)) || result;
8
+ if (kind && result)
9
+ __defProp(target, key, result);
10
+ return result;
11
+ };
2
12
  import { INotifyMixin } from "@thi.ng/api/mixins/inotify";
3
13
  import { topoSort } from "@thi.ng/arrays/topo-sort";
4
14
  import { assert } from "@thi.ng/errors/assert";
5
15
  import { defError } from "@thi.ng/errors/deferror";
6
16
  import { U16, U32, U64BIG, U8, hexdumpLines } from "@thi.ng/hex";
7
17
  import { ConsoleLogger } from "@thi.ng/logger/console";
8
- import { EVENT_MEMORY_CHANGED, EVENT_PANIC, } from "./api.js";
9
- export const Panic = defError(() => "Panic");
10
- export const OutOfMemoryError = defError(() => "Out of memory");
11
- /**
12
- * The main interop API bridge between the JS host environment and a WebAssembly
13
- * module. This class provides a small core API with various typed accessors and
14
- * utils to exchange data (scalars, arrays, strings etc.) via the WASM module's
15
- * memory.
16
- *
17
- * @remarks
18
- * All typed memory accessors are assuming the given lookup addresses are
19
- * properly aligned to the corresponding primitive types (e.g. f32 values are
20
- * aligned to 4 byte boundaries, f64 to 8 bytes etc.) Unaligned access is
21
- * explicitly **not supported**! If you need such, please refer to other
22
- * mechanisms like JS `DataView`...
23
- *
24
- * 64bit integers are handled via JS `BigInt` and hence require the host env to
25
- * support it. No polyfills are provided.
26
- */
27
- let WasmBridge = class WasmBridge {
28
- logger;
29
- id = "wasmapi";
30
- i8;
31
- u8;
32
- i16;
33
- u16;
34
- i32;
35
- u32;
36
- i64;
37
- u64;
38
- f32;
39
- f64;
40
- utf8Decoder = new TextDecoder();
41
- utf8Encoder = new TextEncoder();
42
- imports;
43
- exports;
44
- api;
45
- modules;
46
- constructor(modules = [], logger = new ConsoleLogger("wasm")) {
47
- this.logger = logger;
48
- const logN = (x) => this.logger.debug(x);
49
- const logA = (method) => (addr, len) => this.logger.debug(() => method(addr, len).join(", "));
50
- this.api = {
51
- printI8: logN,
52
- printU8: logN,
53
- printI16: logN,
54
- printU16: logN,
55
- printI32: logN,
56
- printU32: (x) => this.logger.debug(x >>> 0),
57
- printI64: (x) => this.logger.debug(x),
58
- printU64: (x) => this.logger.debug(x),
59
- printF32: logN,
60
- printF64: logN,
61
- printU8Hex: (x) => this.logger.debug(() => `0x${U8(x)}`),
62
- printU16Hex: (x) => this.logger.debug(() => `0x${U16(x)}`),
63
- printU32Hex: (x) => this.logger.debug(() => `0x${U32(x)}`),
64
- printU64Hex: (x) => this.logger.debug(() => `0x${U64BIG(x)}`),
65
- printHexdump: (addr, len) => {
66
- this.ensureMemory();
67
- for (let line of hexdumpLines(this.u8, addr, len)) {
68
- this.logger.debug(line);
69
- }
70
- },
71
- _printI8Array: logA(this.getI8Array.bind(this)),
72
- _printU8Array: logA(this.getU8Array.bind(this)),
73
- _printI16Array: logA(this.getI16Array.bind(this)),
74
- _printU16Array: logA(this.getU16Array.bind(this)),
75
- _printI32Array: logA(this.getI32Array.bind(this)),
76
- _printU32Array: logA(this.getU32Array.bind(this)),
77
- _printI64Array: logA(this.getI64Array.bind(this)),
78
- _printU64Array: logA(this.getU64Array.bind(this)),
79
- _printF32Array: logA(this.getF32Array.bind(this)),
80
- _printF64Array: logA(this.getF64Array.bind(this)),
81
- printStrZ: (addr) => this.logger.debug(() => this.getString(addr, 0)),
82
- _printStr: (addr, len) => this.logger.debug(() => this.getString(addr, len)),
83
- debug: () => {
84
- debugger;
85
- },
86
- _panic: (addr, len) => {
87
- const msg = this.getString(addr, len);
88
- if (!this.notify({ id: EVENT_PANIC, value: msg })) {
89
- throw new Panic(msg);
90
- }
91
- },
92
- timer: () => performance.now(),
93
- epoch: () => BigInt(Date.now()),
94
- };
95
- this.modules = modules.reduce((acc, x) => {
96
- assert(acc[x.id] === undefined && x.id !== this.id, `duplicate API module ID: ${x.id}`);
97
- acc[x.id] = x;
98
- return acc;
99
- }, {});
100
- }
101
- /**
102
- * Instantiates WASM module from given `src` (and optional provided extra
103
- * imports), then automatically calls {@link WasmBridge.init} with the
104
- * modules exports.
105
- *
106
- * @remarks
107
- * If the given `src` is a `Response` or `Promise<Response>`, the module
108
- * will be instantiated via `WebAssembly.instantiateStreaming()`, otherwise
109
- * the non-streaming version will be used.
110
- *
111
- * @param src
112
- * @param imports
113
- */
114
- async instantiate(src, imports) {
115
- const $src = await src;
116
- const $imports = { ...this.getImports(), ...imports };
117
- const wasm = await ($src instanceof Response
118
- ? WebAssembly.instantiateStreaming($src, $imports)
119
- : WebAssembly.instantiate($src, $imports));
120
- return this.init(wasm.instance.exports);
121
- }
122
- /**
123
- * Receives the WASM module's combined exports, stores them for future
124
- * reference and then initializes all declared bridge child API modules in
125
- * their stated dependency order. Returns false if any of the module
126
- * initializations failed.
127
- *
128
- * @remarks
129
- * Emits the {@link EVENT_MEMORY_CHANGED} event just before returning (and
130
- * AFTER all child API modules have been initialized).
131
- *
132
- * @param exports
133
- */
134
- async init(exports) {
135
- this.exports = exports;
136
- this.ensureMemory(false);
137
- for (let id of topoSort(this.modules, (module) => module.dependencies)) {
138
- assert(!!this.modules[id], `missing API module: ${id}`);
139
- this.logger.debug(`initializing API module: ${id}`);
140
- const status = await this.modules[id].init(this);
141
- if (!status)
142
- return false;
143
- }
144
- this.notify({ id: EVENT_MEMORY_CHANGED, value: this.exports.memory });
145
- return true;
146
- }
147
- /**
148
- * Called automatically during initialization and from other memory
149
- * accessors. Initializes and/or updates the various typed WASM memory views
150
- * (e.g. after growing the WASM memory and the previous buffer becoming
151
- * detached). Unless `notify` is false, the {@link EVENT_MEMORY_CHANGED}
152
- * event will be emitted if the memory views had to be updated.
153
- *
154
- * @param notify
155
- */
156
- ensureMemory(notify = true) {
157
- const buf = this.exports.memory.buffer;
158
- if (this.u8 && this.u8.buffer === buf)
159
- return;
160
- this.i8 = new Int8Array(buf);
161
- this.u8 = new Uint8Array(buf);
162
- this.i16 = new Int16Array(buf);
163
- this.u16 = new Uint16Array(buf);
164
- this.i32 = new Int32Array(buf);
165
- this.u32 = new Uint32Array(buf);
166
- this.i64 = new BigInt64Array(buf);
167
- this.u64 = new BigUint64Array(buf);
168
- this.f32 = new Float32Array(buf);
169
- this.f64 = new Float64Array(buf);
170
- notify &&
171
- this.notify({
172
- id: EVENT_MEMORY_CHANGED,
173
- value: this.exports.memory,
174
- });
175
- }
176
- /**
177
- * Required use for WASM module instantiation to provide JS imports to the
178
- * module. Returns an object of all WASM imports declared by the bridge core
179
- * API and any provided bridge API modules.
180
- *
181
- * @remarks
182
- * Each API module's imports will be in their own WASM import object/table,
183
- * named using the same key which is defined by the JS side of the module
184
- * via {@link IWasmAPI.id}. The bridge's core API is named `wasmapi` and is
185
- * reserved.
186
- *
187
- * @example
188
- * The following creates a bridge with a fictional `custom` API module:
189
- *
190
- * ```ts
191
- * const bridge = new WasmBridge([new CustomAPI()]);
192
- *
193
- * // get combined imports object
194
- * bridge.getImports();
195
- * {
196
- * // imports defined by the core API of the bridge itself
197
- * wasmapi: { ... },
198
- * // imports defined by the CustomAPI module
199
- * custom: { ... }
200
- * }
201
- * ```
202
- *
203
- * Any related API bindings on the WASM (Zig) side then also need to refer
204
- * to these custom import sections (also see `/zig/core.zig`):
205
- *
206
- * ```zig
207
- * pub export "custom" fn foo(x: u32) void;
208
- * ```
209
- */
210
- getImports() {
211
- if (!this.imports) {
212
- this.imports = { [this.id]: this.api };
213
- for (let id in this.modules) {
214
- this.imports[id] = this.modules[id].getImports();
215
- }
216
- }
217
- return this.imports;
218
- }
219
- growMemory(numPages) {
220
- this.exports.memory.grow(numPages);
18
+ import {
19
+ EVENT_MEMORY_CHANGED,
20
+ EVENT_PANIC
21
+ } from "./api.js";
22
+ const Panic = defError(() => "Panic");
23
+ const OutOfMemoryError = defError(() => "Out of memory");
24
+ let WasmBridge = class {
25
+ constructor(modules = [], logger = new ConsoleLogger("wasm")) {
26
+ this.logger = logger;
27
+ const logN = (x) => this.logger.debug(x);
28
+ const logA = (method) => (addr, len) => this.logger.debug(() => method(addr, len).join(", "));
29
+ this.api = {
30
+ printI8: logN,
31
+ printU8: logN,
32
+ printI16: logN,
33
+ printU16: logN,
34
+ printI32: logN,
35
+ printU32: (x) => this.logger.debug(x >>> 0),
36
+ printI64: (x) => this.logger.debug(x),
37
+ printU64: (x) => this.logger.debug(x),
38
+ printF32: logN,
39
+ printF64: logN,
40
+ printU8Hex: (x) => this.logger.debug(() => `0x${U8(x)}`),
41
+ printU16Hex: (x) => this.logger.debug(() => `0x${U16(x)}`),
42
+ printU32Hex: (x) => this.logger.debug(() => `0x${U32(x)}`),
43
+ printU64Hex: (x) => this.logger.debug(() => `0x${U64BIG(x)}`),
44
+ printHexdump: (addr, len) => {
221
45
  this.ensureMemory();
222
- }
223
- allocate(numBytes, clear = false) {
224
- const addr = this.exports._wasm_allocate(numBytes);
225
- if (!addr)
226
- throw new OutOfMemoryError(`unable to allocate: ${numBytes}`);
227
- this.logger.fine(() => `allocated ${numBytes} bytes @ 0x${U32(addr)} .. 0x${U32(addr + numBytes - 1)}`);
228
- this.ensureMemory();
229
- clear && this.u8.fill(0, addr, addr + numBytes);
230
- return [addr, numBytes];
231
- }
232
- free([addr, numBytes]) {
233
- this.logger.fine(() => `freeing memory @ 0x${U32(addr)} .. 0x${U32(addr + numBytes - 1)}`);
234
- this.exports._wasm_free(addr, numBytes);
235
- }
236
- getI8(addr) {
237
- return this.i8[addr];
238
- }
239
- getU8(addr) {
240
- return this.u8[addr];
241
- }
242
- getI16(addr) {
243
- return this.i16[addr >> 1];
244
- }
245
- getU16(addr) {
246
- return this.u16[addr >> 1];
247
- }
248
- getI32(addr) {
249
- return this.i32[addr >> 2];
250
- }
251
- getU32(addr) {
252
- return this.u32[addr >> 2];
253
- }
254
- getI64(addr) {
255
- return this.i64[addr >> 3];
256
- }
257
- getU64(addr) {
258
- return this.u64[addr >> 3];
259
- }
260
- getF32(addr) {
261
- return this.f32[addr >> 2];
262
- }
263
- getF64(addr) {
264
- return this.f64[addr >> 3];
265
- }
266
- setI8(addr, x) {
267
- this.i8[addr] = x;
268
- return this;
269
- }
270
- setU8(addr, x) {
271
- this.u8[addr] = x;
272
- return this;
273
- }
274
- setI16(addr, x) {
275
- this.i16[addr >> 1] = x;
276
- return this;
277
- }
278
- setU16(addr, x) {
279
- this.u16[addr >> 1] = x;
280
- return this;
281
- }
282
- setI32(addr, x) {
283
- this.i32[addr >> 2] = x;
284
- return this;
285
- }
286
- setU32(addr, x) {
287
- this.u32[addr >> 2] = x;
288
- return this;
289
- }
290
- setI64(addr, x) {
291
- this.i64[addr >> 3] = x;
292
- return this;
293
- }
294
- setU64(addr, x) {
295
- this.u64[addr >> 3] = x;
296
- return this;
297
- }
298
- setF32(addr, x) {
299
- this.f32[addr >> 2] = x;
300
- return this;
301
- }
302
- setF64(addr, x) {
303
- this.f64[addr >> 3] = x;
304
- return this;
305
- }
306
- getI8Array(addr, len) {
307
- return this.i8.subarray(addr, addr + len);
308
- }
309
- getU8Array(addr, len) {
310
- return this.u8.subarray(addr, addr + len);
311
- }
312
- getI16Array(addr, len) {
313
- addr >>= 1;
314
- return this.i16.subarray(addr, addr + len);
315
- }
316
- getU16Array(addr, len) {
317
- addr >>= 1;
318
- return this.u16.subarray(addr, addr + len);
319
- }
320
- getI32Array(addr, len) {
321
- addr >>= 2;
322
- return this.i32.subarray(addr, addr + len);
323
- }
324
- getU32Array(addr, len) {
325
- addr >>= 2;
326
- return this.u32.subarray(addr, addr + len);
327
- }
328
- getI64Array(addr, len) {
329
- addr >>= 3;
330
- return this.i64.subarray(addr, addr + len);
331
- }
332
- getU64Array(addr, len) {
333
- addr >>= 3;
334
- return this.u64.subarray(addr, addr + len);
335
- }
336
- getF32Array(addr, len) {
337
- addr >>= 2;
338
- return this.f32.subarray(addr, addr + len);
339
- }
340
- getF64Array(addr, len) {
341
- addr >>= 3;
342
- return this.f64.subarray(addr, addr + len);
343
- }
344
- setI8Array(addr, buf) {
345
- this.i8.set(buf, addr);
346
- return this;
347
- }
348
- setU8Array(addr, buf) {
349
- this.u8.set(buf, addr);
350
- return this;
351
- }
352
- setI16Array(addr, buf) {
353
- this.i16.set(buf, addr >> 1);
354
- return this;
355
- }
356
- setU16Array(addr, buf) {
357
- this.u16.set(buf, addr >> 1);
358
- return this;
359
- }
360
- setI32Array(addr, buf) {
361
- this.i32.set(buf, addr >> 2);
362
- return this;
363
- }
364
- setU32Array(addr, buf) {
365
- this.u32.set(buf, addr >> 2);
366
- return this;
367
- }
368
- setI64Array(addr, buf) {
369
- this.i64.set(buf, addr >> 3);
370
- return this;
371
- }
372
- setU64Array(addr, buf) {
373
- this.u64.set(buf, addr >> 3);
374
- return this;
375
- }
376
- setF32Array(addr, buf) {
377
- this.f32.set(buf, addr >> 2);
378
- return this;
379
- }
380
- setF64Array(addr, buf) {
381
- this.f64.set(buf, addr >> 3);
382
- return this;
383
- }
384
- getString(addr, len = 0) {
385
- this.ensureMemory();
386
- return this.utf8Decoder.decode(this.u8.subarray(addr, len > 0 ? addr + len : this.u8.indexOf(0, addr)));
387
- }
388
- setString(str, addr, maxBytes, terminate = true) {
389
- this.ensureMemory();
390
- maxBytes = Math.min(maxBytes, this.u8.length - addr);
391
- const len = this.utf8Encoder.encodeInto(str, this.u8.subarray(addr, addr + maxBytes)).written;
392
- assert(len != null && len < maxBytes + (terminate ? 0 : 1), `error writing string to 0x${U32(addr)} (max. ${maxBytes} bytes, got at least ${str.length})`);
393
- if (terminate) {
394
- this.u8[addr + len] = 0;
46
+ for (let line of hexdumpLines(this.u8, addr, len)) {
47
+ this.logger.debug(line);
395
48
  }
396
- return len;
397
- }
398
- getElementById(addr, len = 0) {
399
- const id = this.getString(addr, len);
400
- const el = document.getElementById(id);
401
- assert(!!el, `missing DOM element #${id}`);
402
- return el;
403
- }
404
- /** {@inheritDoc @thi.ng/api#INotify.addListener} */
405
- // @ts-ignore: mixin
406
- // prettier-ignore
407
- addListener(id, fn, scope) { }
408
- /** {@inheritDoc @thi.ng/api#INotify.removeListener} */
409
- // @ts-ignore: mixin
410
- // prettier-ignore
411
- removeListener(id, fn, scope) { }
412
- /** {@inheritDoc @thi.ng/api#INotify.notify} */
413
- // @ts-ignore: mixin
414
- notify(event) { }
49
+ },
50
+ _printI8Array: logA(this.getI8Array.bind(this)),
51
+ _printU8Array: logA(this.getU8Array.bind(this)),
52
+ _printI16Array: logA(this.getI16Array.bind(this)),
53
+ _printU16Array: logA(this.getU16Array.bind(this)),
54
+ _printI32Array: logA(this.getI32Array.bind(this)),
55
+ _printU32Array: logA(this.getU32Array.bind(this)),
56
+ _printI64Array: logA(this.getI64Array.bind(this)),
57
+ _printU64Array: logA(this.getU64Array.bind(this)),
58
+ _printF32Array: logA(this.getF32Array.bind(this)),
59
+ _printF64Array: logA(this.getF64Array.bind(this)),
60
+ printStrZ: (addr) => this.logger.debug(() => this.getString(addr, 0)),
61
+ _printStr: (addr, len) => this.logger.debug(() => this.getString(addr, len)),
62
+ debug: () => {
63
+ debugger;
64
+ },
65
+ _panic: (addr, len) => {
66
+ const msg = this.getString(addr, len);
67
+ if (!this.notify({ id: EVENT_PANIC, value: msg })) {
68
+ throw new Panic(msg);
69
+ }
70
+ },
71
+ timer: () => performance.now(),
72
+ epoch: () => BigInt(Date.now())
73
+ };
74
+ this.modules = modules.reduce((acc, x) => {
75
+ assert(
76
+ acc[x.id] === void 0 && x.id !== this.id,
77
+ `duplicate API module ID: ${x.id}`
78
+ );
79
+ acc[x.id] = x;
80
+ return acc;
81
+ }, {});
82
+ }
83
+ id = "wasmapi";
84
+ i8;
85
+ u8;
86
+ i16;
87
+ u16;
88
+ i32;
89
+ u32;
90
+ i64;
91
+ u64;
92
+ f32;
93
+ f64;
94
+ utf8Decoder = new TextDecoder();
95
+ utf8Encoder = new TextEncoder();
96
+ imports;
97
+ exports;
98
+ api;
99
+ modules;
100
+ /**
101
+ * Instantiates WASM module from given `src` (and optional provided extra
102
+ * imports), then automatically calls {@link WasmBridge.init} with the
103
+ * modules exports.
104
+ *
105
+ * @remarks
106
+ * If the given `src` is a `Response` or `Promise<Response>`, the module
107
+ * will be instantiated via `WebAssembly.instantiateStreaming()`, otherwise
108
+ * the non-streaming version will be used.
109
+ *
110
+ * @param src
111
+ * @param imports
112
+ */
113
+ async instantiate(src, imports) {
114
+ const $src = await src;
115
+ const $imports = { ...this.getImports(), ...imports };
116
+ const wasm = await ($src instanceof Response ? WebAssembly.instantiateStreaming($src, $imports) : WebAssembly.instantiate($src, $imports));
117
+ return this.init(wasm.instance.exports);
118
+ }
119
+ /**
120
+ * Receives the WASM module's combined exports, stores them for future
121
+ * reference and then initializes all declared bridge child API modules in
122
+ * their stated dependency order. Returns false if any of the module
123
+ * initializations failed.
124
+ *
125
+ * @remarks
126
+ * Emits the {@link EVENT_MEMORY_CHANGED} event just before returning (and
127
+ * AFTER all child API modules have been initialized).
128
+ *
129
+ * @param exports
130
+ */
131
+ async init(exports) {
132
+ this.exports = exports;
133
+ this.ensureMemory(false);
134
+ for (let id of topoSort(
135
+ this.modules,
136
+ (module) => module.dependencies
137
+ )) {
138
+ assert(!!this.modules[id], `missing API module: ${id}`);
139
+ this.logger.debug(`initializing API module: ${id}`);
140
+ const status = await this.modules[id].init(this);
141
+ if (!status)
142
+ return false;
143
+ }
144
+ this.notify({ id: EVENT_MEMORY_CHANGED, value: this.exports.memory });
145
+ return true;
146
+ }
147
+ /**
148
+ * Called automatically during initialization and from other memory
149
+ * accessors. Initializes and/or updates the various typed WASM memory views
150
+ * (e.g. after growing the WASM memory and the previous buffer becoming
151
+ * detached). Unless `notify` is false, the {@link EVENT_MEMORY_CHANGED}
152
+ * event will be emitted if the memory views had to be updated.
153
+ *
154
+ * @param notify
155
+ */
156
+ ensureMemory(notify = true) {
157
+ const buf = this.exports.memory.buffer;
158
+ if (this.u8 && this.u8.buffer === buf)
159
+ return;
160
+ this.i8 = new Int8Array(buf);
161
+ this.u8 = new Uint8Array(buf);
162
+ this.i16 = new Int16Array(buf);
163
+ this.u16 = new Uint16Array(buf);
164
+ this.i32 = new Int32Array(buf);
165
+ this.u32 = new Uint32Array(buf);
166
+ this.i64 = new BigInt64Array(buf);
167
+ this.u64 = new BigUint64Array(buf);
168
+ this.f32 = new Float32Array(buf);
169
+ this.f64 = new Float64Array(buf);
170
+ notify && this.notify({
171
+ id: EVENT_MEMORY_CHANGED,
172
+ value: this.exports.memory
173
+ });
174
+ }
175
+ /**
176
+ * Required use for WASM module instantiation to provide JS imports to the
177
+ * module. Returns an object of all WASM imports declared by the bridge core
178
+ * API and any provided bridge API modules.
179
+ *
180
+ * @remarks
181
+ * Each API module's imports will be in their own WASM import object/table,
182
+ * named using the same key which is defined by the JS side of the module
183
+ * via {@link IWasmAPI.id}. The bridge's core API is named `wasmapi` and is
184
+ * reserved.
185
+ *
186
+ * @example
187
+ * The following creates a bridge with a fictional `custom` API module:
188
+ *
189
+ * ```ts
190
+ * const bridge = new WasmBridge([new CustomAPI()]);
191
+ *
192
+ * // get combined imports object
193
+ * bridge.getImports();
194
+ * {
195
+ * // imports defined by the core API of the bridge itself
196
+ * wasmapi: { ... },
197
+ * // imports defined by the CustomAPI module
198
+ * custom: { ... }
199
+ * }
200
+ * ```
201
+ *
202
+ * Any related API bindings on the WASM (Zig) side then also need to refer
203
+ * to these custom import sections (also see `/zig/core.zig`):
204
+ *
205
+ * ```zig
206
+ * pub export "custom" fn foo(x: u32) void;
207
+ * ```
208
+ */
209
+ getImports() {
210
+ if (!this.imports) {
211
+ this.imports = { [this.id]: this.api };
212
+ for (let id in this.modules) {
213
+ this.imports[id] = this.modules[id].getImports();
214
+ }
215
+ }
216
+ return this.imports;
217
+ }
218
+ growMemory(numPages) {
219
+ this.exports.memory.grow(numPages);
220
+ this.ensureMemory();
221
+ }
222
+ allocate(numBytes, clear = false) {
223
+ const addr = this.exports._wasm_allocate(numBytes);
224
+ if (!addr)
225
+ throw new OutOfMemoryError(`unable to allocate: ${numBytes}`);
226
+ this.logger.fine(
227
+ () => `allocated ${numBytes} bytes @ 0x${U32(addr)} .. 0x${U32(
228
+ addr + numBytes - 1
229
+ )}`
230
+ );
231
+ this.ensureMemory();
232
+ clear && this.u8.fill(0, addr, addr + numBytes);
233
+ return [addr, numBytes];
234
+ }
235
+ free([addr, numBytes]) {
236
+ this.logger.fine(
237
+ () => `freeing memory @ 0x${U32(addr)} .. 0x${U32(
238
+ addr + numBytes - 1
239
+ )}`
240
+ );
241
+ this.exports._wasm_free(addr, numBytes);
242
+ }
243
+ getI8(addr) {
244
+ return this.i8[addr];
245
+ }
246
+ getU8(addr) {
247
+ return this.u8[addr];
248
+ }
249
+ getI16(addr) {
250
+ return this.i16[addr >> 1];
251
+ }
252
+ getU16(addr) {
253
+ return this.u16[addr >> 1];
254
+ }
255
+ getI32(addr) {
256
+ return this.i32[addr >> 2];
257
+ }
258
+ getU32(addr) {
259
+ return this.u32[addr >> 2];
260
+ }
261
+ getI64(addr) {
262
+ return this.i64[addr >> 3];
263
+ }
264
+ getU64(addr) {
265
+ return this.u64[addr >> 3];
266
+ }
267
+ getF32(addr) {
268
+ return this.f32[addr >> 2];
269
+ }
270
+ getF64(addr) {
271
+ return this.f64[addr >> 3];
272
+ }
273
+ setI8(addr, x) {
274
+ this.i8[addr] = x;
275
+ return this;
276
+ }
277
+ setU8(addr, x) {
278
+ this.u8[addr] = x;
279
+ return this;
280
+ }
281
+ setI16(addr, x) {
282
+ this.i16[addr >> 1] = x;
283
+ return this;
284
+ }
285
+ setU16(addr, x) {
286
+ this.u16[addr >> 1] = x;
287
+ return this;
288
+ }
289
+ setI32(addr, x) {
290
+ this.i32[addr >> 2] = x;
291
+ return this;
292
+ }
293
+ setU32(addr, x) {
294
+ this.u32[addr >> 2] = x;
295
+ return this;
296
+ }
297
+ setI64(addr, x) {
298
+ this.i64[addr >> 3] = x;
299
+ return this;
300
+ }
301
+ setU64(addr, x) {
302
+ this.u64[addr >> 3] = x;
303
+ return this;
304
+ }
305
+ setF32(addr, x) {
306
+ this.f32[addr >> 2] = x;
307
+ return this;
308
+ }
309
+ setF64(addr, x) {
310
+ this.f64[addr >> 3] = x;
311
+ return this;
312
+ }
313
+ getI8Array(addr, len) {
314
+ return this.i8.subarray(addr, addr + len);
315
+ }
316
+ getU8Array(addr, len) {
317
+ return this.u8.subarray(addr, addr + len);
318
+ }
319
+ getI16Array(addr, len) {
320
+ addr >>= 1;
321
+ return this.i16.subarray(addr, addr + len);
322
+ }
323
+ getU16Array(addr, len) {
324
+ addr >>= 1;
325
+ return this.u16.subarray(addr, addr + len);
326
+ }
327
+ getI32Array(addr, len) {
328
+ addr >>= 2;
329
+ return this.i32.subarray(addr, addr + len);
330
+ }
331
+ getU32Array(addr, len) {
332
+ addr >>= 2;
333
+ return this.u32.subarray(addr, addr + len);
334
+ }
335
+ getI64Array(addr, len) {
336
+ addr >>= 3;
337
+ return this.i64.subarray(addr, addr + len);
338
+ }
339
+ getU64Array(addr, len) {
340
+ addr >>= 3;
341
+ return this.u64.subarray(addr, addr + len);
342
+ }
343
+ getF32Array(addr, len) {
344
+ addr >>= 2;
345
+ return this.f32.subarray(addr, addr + len);
346
+ }
347
+ getF64Array(addr, len) {
348
+ addr >>= 3;
349
+ return this.f64.subarray(addr, addr + len);
350
+ }
351
+ setI8Array(addr, buf) {
352
+ this.i8.set(buf, addr);
353
+ return this;
354
+ }
355
+ setU8Array(addr, buf) {
356
+ this.u8.set(buf, addr);
357
+ return this;
358
+ }
359
+ setI16Array(addr, buf) {
360
+ this.i16.set(buf, addr >> 1);
361
+ return this;
362
+ }
363
+ setU16Array(addr, buf) {
364
+ this.u16.set(buf, addr >> 1);
365
+ return this;
366
+ }
367
+ setI32Array(addr, buf) {
368
+ this.i32.set(buf, addr >> 2);
369
+ return this;
370
+ }
371
+ setU32Array(addr, buf) {
372
+ this.u32.set(buf, addr >> 2);
373
+ return this;
374
+ }
375
+ setI64Array(addr, buf) {
376
+ this.i64.set(buf, addr >> 3);
377
+ return this;
378
+ }
379
+ setU64Array(addr, buf) {
380
+ this.u64.set(buf, addr >> 3);
381
+ return this;
382
+ }
383
+ setF32Array(addr, buf) {
384
+ this.f32.set(buf, addr >> 2);
385
+ return this;
386
+ }
387
+ setF64Array(addr, buf) {
388
+ this.f64.set(buf, addr >> 3);
389
+ return this;
390
+ }
391
+ getString(addr, len = 0) {
392
+ this.ensureMemory();
393
+ return this.utf8Decoder.decode(
394
+ this.u8.subarray(
395
+ addr,
396
+ len > 0 ? addr + len : this.u8.indexOf(0, addr)
397
+ )
398
+ );
399
+ }
400
+ setString(str, addr, maxBytes, terminate = true) {
401
+ this.ensureMemory();
402
+ maxBytes = Math.min(maxBytes, this.u8.length - addr);
403
+ const len = this.utf8Encoder.encodeInto(
404
+ str,
405
+ this.u8.subarray(addr, addr + maxBytes)
406
+ ).written;
407
+ assert(
408
+ len != null && len < maxBytes + (terminate ? 0 : 1),
409
+ `error writing string to 0x${U32(
410
+ addr
411
+ )} (max. ${maxBytes} bytes, got at least ${str.length})`
412
+ );
413
+ if (terminate) {
414
+ this.u8[addr + len] = 0;
415
+ }
416
+ return len;
417
+ }
418
+ getElementById(addr, len = 0) {
419
+ const id = this.getString(addr, len);
420
+ const el = document.getElementById(id);
421
+ assert(!!el, `missing DOM element #${id}`);
422
+ return el;
423
+ }
424
+ /** {@inheritDoc @thi.ng/api#INotify.addListener} */
425
+ // @ts-ignore: mixin
426
+ // prettier-ignore
427
+ addListener(id, fn, scope) {
428
+ }
429
+ /** {@inheritDoc @thi.ng/api#INotify.removeListener} */
430
+ // @ts-ignore: mixin
431
+ // prettier-ignore
432
+ removeListener(id, fn, scope) {
433
+ }
434
+ /** {@inheritDoc @thi.ng/api#INotify.notify} */
435
+ // @ts-ignore: mixin
436
+ notify(event) {
437
+ }
415
438
  };
416
- WasmBridge = __decorate([
417
- INotifyMixin
439
+ WasmBridge = __decorateClass([
440
+ INotifyMixin
418
441
  ], WasmBridge);
419
- export { WasmBridge };
442
+ export {
443
+ OutOfMemoryError,
444
+ Panic,
445
+ WasmBridge
446
+ };