@thi.ng/wasm-api 0.4.0 → 0.7.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/api.d.ts CHANGED
@@ -1,5 +1,6 @@
1
- import type { Fn, Fn2 } from "@thi.ng/api";
1
+ import type { BigType, FloatType, Fn, Fn2 } from "@thi.ng/api";
2
2
  import type { WasmBridge } from "./bridge.js";
3
+ export declare const PKG_NAME = "@thi.ng/wasm-api";
3
4
  export declare type BigIntArray = bigint[] | BigInt64Array | BigUint64Array;
4
5
  /**
5
6
  * Common interface for WASM/JS child APIs which will be used in combination
@@ -27,7 +28,8 @@ export interface IWasmAPI<T extends WasmExports = WasmExports> {
27
28
  }
28
29
  /**
29
30
  * Base interface of exports declared by the WASM module. At the very least, the
30
- * module needs to export its memory.
31
+ * module needs to export its memory and the functions defined in this
32
+ * interface.
31
33
  *
32
34
  * @remarks
33
35
  * This interface is supposed to be extended with the concrete exports defined
@@ -39,9 +41,42 @@ export interface IWasmAPI<T extends WasmExports = WasmExports> {
39
41
  export interface WasmExports {
40
42
  /**
41
43
  * The WASM module's linear memory buffer. The `WasmBridge` automatically
42
- * creates various typed views of that memory.
44
+ * creates various typed views of that memory (i.e. u8, u16, u32, f32 etc.)
43
45
  */
44
46
  memory: WebAssembly.Memory;
47
+ /**
48
+ * Implementation specific memory allocation function (likely heap-based).
49
+ * If successful returns address of new memory block, or zero if
50
+ * unsuccessful.
51
+ *
52
+ * @remarks
53
+ * In the supplied Zig bindings (see `/zig/core.zig`), by default this is
54
+ * using the `std.heap.GeneralPurposeAllocator` (which also automatically
55
+ * handles growing the WASM memory), however as mentioned the underlying
56
+ * mechanism is purposefully left to the actual WASM-side implementation. In
57
+ * a C program, this would likely use `malloc()` or similar...
58
+ */
59
+ _wasm_allocate(numBytes: number): number;
60
+ /**
61
+ * Implementation specific function to free a previously allocated chunk of
62
+ * of WASM memory (allocated via {@link WasmExports._wasm_allocate}).
63
+ *
64
+ * @param addr
65
+ * @param numBytes
66
+ */
67
+ _wasm_free(addr: number, numBytes: number): void;
68
+ }
69
+ export interface WasmMemViews {
70
+ i8: Int8Array;
71
+ u8: Uint8Array;
72
+ i16: Int16Array;
73
+ u16: Uint16Array;
74
+ i32: Int32Array;
75
+ u32: Uint32Array;
76
+ i64: BigInt64Array;
77
+ u64: BigUint64Array;
78
+ f32: Float32Array;
79
+ f64: Float64Array;
45
80
  }
46
81
  /**
47
82
  * Core API of WASM imports defined by the {@link WasmBridge}. The same
@@ -76,4 +111,179 @@ export interface CoreAPI extends WebAssembly.ModuleImports {
76
111
  _printStr0: (addr: number) => void;
77
112
  _printStr: (addr: number, len: number) => void;
78
113
  }
114
+ export interface WasmTypeBase {
115
+ /**
116
+ * Base address in linear WASM memory.
117
+ */
118
+ readonly __base: number;
119
+ /**
120
+ * Obtain as byte buffer
121
+ */
122
+ readonly __bytes: Uint8Array;
123
+ }
124
+ export interface WasmType<T> {
125
+ readonly align: number;
126
+ readonly size: number;
127
+ instance: Fn<number, T>;
128
+ }
129
+ export declare type WasmTypeConstructor<T> = Fn<WasmMemViews, WasmType<T>>;
130
+ export declare type WasmInt = "i8" | "i16" | "i32" | "i64";
131
+ export declare type WasmUint = "u8" | "u16" | "u32" | "u64";
132
+ export declare type WasmFloat = FloatType;
133
+ export declare type WasmPrim = WasmInt | WasmUint | WasmFloat;
134
+ export declare type WasmPrim32 = Exclude<WasmPrim, BigType>;
135
+ export declare type TypeColl = Record<string, TopLevelType>;
136
+ export interface TypeInfo {
137
+ /**
138
+ * Auto-computed size (in bytes)
139
+ *
140
+ * @internal
141
+ */
142
+ __size?: number;
143
+ /**
144
+ * Auto-computed offset (in bytes) in parent struct
145
+ *
146
+ * @internal
147
+ */
148
+ __offset?: number;
149
+ /**
150
+ * Auto-computed alignment (in bytes)
151
+ *
152
+ * @internal
153
+ */
154
+ __align?: number;
155
+ }
156
+ export interface TopLevelType extends TypeInfo {
157
+ /**
158
+ * Type name
159
+ */
160
+ name: string;
161
+ /**
162
+ * Optional (multi-line) docstring for this type
163
+ */
164
+ doc?: string;
165
+ /**
166
+ * Type / kind
167
+ */
168
+ type: "struct" | "enum";
169
+ }
170
+ export interface Struct extends TopLevelType {
171
+ type: "struct";
172
+ /**
173
+ * List of struct fields (might be re-ordered if {@link Struct.auto} is
174
+ * enabled).
175
+ */
176
+ fields: StructField[];
177
+ /**
178
+ * If true, struct fields will be re-ordered in descending order based on
179
+ * their {@link TypeInfo.__align} size. This might result in overall smaller
180
+ * structs due to minimizing inter-field padding.
181
+ *
182
+ * @defaultValue false
183
+ */
184
+ auto?: boolean;
185
+ }
186
+ export interface StructField extends TypeInfo {
187
+ /**
188
+ * Field name (prefix: "__" is reserved)
189
+ */
190
+ name: string;
191
+ /**
192
+ * Field docstring (can be multiline, will be formatted)
193
+ */
194
+ doc?: string;
195
+ /**
196
+ * Field type tag/qualifier (note: `slice` & `vec` are only supported by Zig
197
+ * & TS).
198
+ *
199
+ * @remarks
200
+ * - Array & vector fields are statically sized (using
201
+ * {@link StructField.len})
202
+ * - Pointers are emitted as single-value pointers (where this distinction
203
+ * exist), i.e. even if they're pointing to multiple values, there's no
204
+ * explicit length encoded/available
205
+ * - Zig slices are essentially a pointer w/ associated length
206
+ * - Zig vectors will be processed using SIMD (if enabled in WASM target)
207
+ * and therefore will have stricter (larger) alignment requirements.
208
+ *
209
+ * @defaultValue "scalar"
210
+ */
211
+ tag?: "scalar" | "array" | "ptr" | "slice" | "vec";
212
+ /**
213
+ * Field base type. If not a {@link WasmPrim} or `opaque`, the value is
214
+ * interpreted as another type name in the {@link TypeColl}.
215
+ *
216
+ * TODO `opaque` currently unsupported.
217
+ * TODO add string support (see {@link StructField.sentinel})
218
+ */
219
+ type: WasmPrim | "opaque" | string;
220
+ /**
221
+ * TODO currently unsupported & ignored!
222
+ */
223
+ sentinel?: number;
224
+ /**
225
+ * Array or vector length (see {@link StructField.tag})
226
+ */
227
+ len?: number;
228
+ /**
229
+ * TODO currently unsupported & ignored!
230
+ */
231
+ default?: any;
232
+ }
233
+ export interface Enum extends TopLevelType {
234
+ type: "enum";
235
+ /**
236
+ * No i64/u64 support, due to Typescript not supporting bigint enum values
237
+ */
238
+ tag: Exclude<WasmPrim32, FloatType>;
239
+ /**
240
+ * List of possible values/IDs. Use {@link EnumValue}s for more detailed
241
+ * config.
242
+ */
243
+ values: (string | EnumValue)[];
244
+ }
245
+ export interface EnumValue {
246
+ /**
247
+ * Enum value name/ID
248
+ */
249
+ name: string;
250
+ /**
251
+ * Optional associated numeric value
252
+ */
253
+ value?: number;
254
+ /**
255
+ * Optional docstring for this value
256
+ */
257
+ doc?: string;
258
+ }
259
+ export interface ICodeGen {
260
+ /**
261
+ * Optional prelude source, to be prepended before any generated type defs.
262
+ */
263
+ pre?: string;
264
+ /**
265
+ * Optional source code to be appended after any generated type defs.
266
+ */
267
+ post?: string;
268
+ /**
269
+ * Docstring codegen
270
+ */
271
+ doc: (doc: string, indent: string, acc: string[], topLevel?: boolean) => void;
272
+ /**
273
+ * Codegen for enum types.
274
+ */
275
+ enum: (type: Enum, types: TypeColl, acc: string[]) => void;
276
+ /**
277
+ * Codegen for struct types.
278
+ */
279
+ struct: (type: Struct, types: TypeColl, acc: string[]) => void;
280
+ }
281
+ /**
282
+ * WASM usize type. Assuming wasm32 until wasm64 surfaces, then need an option.
283
+ */
284
+ export declare const USIZE = "u32";
285
+ /**
286
+ * Byte size of {@link USIZE}.
287
+ */
288
+ export declare const USIZE_SIZE = 4;
79
289
  //# sourceMappingURL=api.d.ts.map
package/api.js CHANGED
@@ -1 +1,9 @@
1
- export {};
1
+ export const PKG_NAME = "@thi.ng/wasm-api";
2
+ /**
3
+ * WASM usize type. Assuming wasm32 until wasm64 surfaces, then need an option.
4
+ */
5
+ export const USIZE = "u32";
6
+ /**
7
+ * Byte size of {@link USIZE}.
8
+ */
9
+ export const USIZE_SIZE = 4;
package/bin/wasm-api ADDED
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env bash
2
+
3
+ # https://stackoverflow.com/a/246128/294515
4
+ SOURCE="${BASH_SOURCE[0]}"
5
+ while [ -h "$SOURCE" ]; do
6
+ DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )"
7
+ SOURCE="$(readlink "$SOURCE")"
8
+ [[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE"
9
+ done
10
+ DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )"
11
+
12
+ /usr/bin/env node "$DIR/../cli.js" "$DIR" "$@"
package/bridge.d.ts CHANGED
@@ -1,6 +1,17 @@
1
+ /// <reference types="node" />
1
2
  import type { NumericArray } from "@thi.ng/api";
2
3
  import type { ILogger } from "@thi.ng/logger";
3
- import type { BigIntArray, CoreAPI, IWasmAPI, WasmExports } from "./api.js";
4
+ import type { BigIntArray, CoreAPI, IWasmAPI, WasmExports, WasmMemViews } from "./api.js";
5
+ export declare const OutOfMemoryError: {
6
+ new (msg?: string | undefined): {
7
+ name: string;
8
+ message: string;
9
+ stack?: string | undefined;
10
+ };
11
+ captureStackTrace(targetObject: object, constructorOpt?: Function | undefined): void;
12
+ prepareStackTrace?: ((err: Error, stackTraces: NodeJS.CallSite[]) => any) | undefined;
13
+ stackTraceLimit: number;
14
+ };
4
15
  /**
5
16
  * The main interop API bridge between the JS host environment and a WebAssembly
6
17
  * module. This class provides a small core API with various typed accessors and
@@ -17,7 +28,7 @@ import type { BigIntArray, CoreAPI, IWasmAPI, WasmExports } from "./api.js";
17
28
  * 64bit integers are handled via JS `BigInt` and hence require the host env to
18
29
  * support it. No polyfill is provided.
19
30
  */
20
- export declare class WasmBridge<T extends WasmExports = WasmExports> {
31
+ export declare class WasmBridge<T extends WasmExports = WasmExports> implements WasmMemViews {
21
32
  modules: Record<string, IWasmAPI<T>>;
22
33
  logger: ILogger;
23
34
  i8: Int8Array;
@@ -34,7 +45,7 @@ export declare class WasmBridge<T extends WasmExports = WasmExports> {
34
45
  utf8Encoder: TextEncoder;
35
46
  imports: WebAssembly.Imports;
36
47
  exports: T;
37
- core: CoreAPI;
48
+ api: CoreAPI;
38
49
  constructor(modules?: Record<string, IWasmAPI<T>>, logger?: ILogger);
39
50
  /**
40
51
  * Instantiates WASM module from given `src` (and optional provided extra
@@ -58,6 +69,11 @@ export declare class WasmBridge<T extends WasmExports = WasmExports> {
58
69
  * @param exports
59
70
  */
60
71
  init(exports: T): Promise<boolean>;
72
+ /**
73
+ * Called automatically. Initializes and/or updates the various typed WASM
74
+ * memory views (e.g. after growing the WASM memory).
75
+ */
76
+ ensureMemory(): void;
61
77
  /**
62
78
  * Required use for WASM module instantiation to provide JS imports to the
63
79
  * module. Returns an object of all WASM imports declared by the bridge core
@@ -65,8 +81,9 @@ export declare class WasmBridge<T extends WasmExports = WasmExports> {
65
81
  *
66
82
  * @remarks
67
83
  * Since v0.4.0 each API module's imports will be in their own WASM import
68
- * table, named using the same key which was assigned to the module when
69
- * creating the WASM bridge.
84
+ * object, named using the same key which was assigned to the module when
85
+ * creating the WASM bridge. The bridge's core API will be named `core` and
86
+ * is reserved.
70
87
  *
71
88
  * @example
72
89
  * The following creates a bridge with a fictional `custom` API module:
@@ -78,7 +95,7 @@ export declare class WasmBridge<T extends WasmExports = WasmExports> {
78
95
  * bridge.getImports();
79
96
  * {
80
97
  * // imports defined by the core API of the bridge itself
81
- * core: { ... },
98
+ * wasmapi: { ... },
82
99
  * // imports defined by the CustomAPI module
83
100
  * custom: { ... }
84
101
  * }
@@ -92,6 +109,38 @@ export declare class WasmBridge<T extends WasmExports = WasmExports> {
92
109
  * ```
93
110
  */
94
111
  getImports(): WebAssembly.Imports;
112
+ /**
113
+ * Attempts to grow the WASM memory by an additional `numPages` (64KB/page)
114
+ * and if successful updates all typed memory views to use the new
115
+ * underlying buffer.
116
+ *
117
+ * @param numPages
118
+ */
119
+ growMemory(numPages: number): void;
120
+ /**
121
+ * Attempts to allocate `numBytes` using the exported WASM core API function
122
+ * {@link WasmExports._wasm_allocate} (implementation specific) and returns
123
+ * start address of the new memory block. If unsuccessful, throws an
124
+ * {@link OutOfMemoryError}. If `clear` is true, the allocated region will
125
+ * be zero-filled.
126
+ *
127
+ * @remarks
128
+ * See {@link WasmExports._wasm_allocate} docs for further details.
129
+ *
130
+ * @param numBytes
131
+ * @param clear
132
+ */
133
+ allocate(numBytes: number, clear?: boolean): number;
134
+ /**
135
+ * Frees a previous allocated memory region using the exported WASM core API
136
+ * function {@link WasmExports._wasm_free} (implementation specific). The
137
+ * `numBytes` value must be the same as previously given to
138
+ * {@link WasmBridge.allocate}.
139
+ *
140
+ * @param addr
141
+ * @param numBytes
142
+ */
143
+ free(addr: number, numBytes: number): void;
95
144
  getI8(addr: number): number;
96
145
  getU8(addr: number): number;
97
146
  getI16(addr: number): number;
@@ -132,7 +181,30 @@ export declare class WasmBridge<T extends WasmExports = WasmExports> {
132
181
  setU64Array(addr: number, buf: BigIntArray): this;
133
182
  setF32Array(addr: number, buf: NumericArray): this;
134
183
  setF64Array(addr: number, buf: NumericArray): this;
184
+ /**
185
+ * Reads UTF-8 encoded string from given address and optional byte length.
186
+ * The default length is 0, which will be interpreted as a zero-terminated
187
+ * string. Returns string.
188
+ *
189
+ * @param addr
190
+ * @param len
191
+ */
135
192
  getString(addr: number, len?: number): string;
193
+ /**
194
+ * Encodes given string as UTF-8 and writes it to WASM memory starting at
195
+ * `addr`. By default the string will be zero-terminated and only `maxBytes`
196
+ * will be written. Returns the number of bytes written.
197
+ *
198
+ * @remarks
199
+ * An error will be thrown if the encoded string doesn't fully fit into the
200
+ * designated memory region (also note that there might need to be space for
201
+ * the additional sentinel/termination byte).
202
+ *
203
+ * @param str
204
+ * @param addr
205
+ * @param maxBytes
206
+ * @param terminate
207
+ */
136
208
  setString(str: string, addr: number, maxBytes: number, terminate?: boolean): number;
137
209
  getElementById(addr: number, len?: number): HTMLElement;
138
210
  }
package/bridge.js CHANGED
@@ -1,7 +1,9 @@
1
+ import { defError } from "@thi.ng/errors/deferror";
1
2
  import { illegalArgs } from "@thi.ng/errors/illegal-arguments";
2
3
  import { U16, U32, U64HL, U8 } from "@thi.ng/hex";
3
4
  import { ConsoleLogger } from "@thi.ng/logger/console";
4
5
  const B32 = BigInt(32);
6
+ export const OutOfMemoryError = defError(() => "Out of memory");
5
7
  /**
6
8
  * The main interop API bridge between the JS host environment and a WebAssembly
7
9
  * module. This class provides a small core API with various typed accessors and
@@ -26,7 +28,7 @@ export class WasmBridge {
26
28
  this.utf8Encoder = new TextEncoder();
27
29
  const logN = (x) => this.logger.debug(x);
28
30
  const logA = (method) => (addr, len) => this.logger.debug(method(addr, len).join(", "));
29
- this.core = {
31
+ this.api = {
30
32
  printI8: logN,
31
33
  printU8: logN,
32
34
  printU8Hex: (x) => this.logger.debug(`0x${U8(x)}`),
@@ -85,7 +87,23 @@ export class WasmBridge {
85
87
  */
86
88
  async init(exports) {
87
89
  this.exports = exports;
88
- const buf = exports.memory.buffer;
90
+ this.ensureMemory();
91
+ for (let id in this.modules) {
92
+ this.logger.debug(`initializing API module: ${id}`);
93
+ const status = await this.modules[id].init(this);
94
+ if (!status)
95
+ return false;
96
+ }
97
+ return true;
98
+ }
99
+ /**
100
+ * Called automatically. Initializes and/or updates the various typed WASM
101
+ * memory views (e.g. after growing the WASM memory).
102
+ */
103
+ ensureMemory() {
104
+ const buf = this.exports.memory.buffer;
105
+ if (this.u8 && this.u8.buffer === buf)
106
+ return;
89
107
  this.i8 = new Int8Array(buf);
90
108
  this.u8 = new Uint8Array(buf);
91
109
  this.i16 = new Int16Array(buf);
@@ -96,13 +114,6 @@ export class WasmBridge {
96
114
  this.u64 = new BigUint64Array(buf);
97
115
  this.f32 = new Float32Array(buf);
98
116
  this.f64 = new Float64Array(buf);
99
- for (let id in this.modules) {
100
- this.logger.debug(`initializing API module: ${id}`);
101
- const status = await this.modules[id].init(this);
102
- if (!status)
103
- return false;
104
- }
105
- return true;
106
117
  }
107
118
  /**
108
119
  * Required use for WASM module instantiation to provide JS imports to the
@@ -111,8 +122,9 @@ export class WasmBridge {
111
122
  *
112
123
  * @remarks
113
124
  * Since v0.4.0 each API module's imports will be in their own WASM import
114
- * table, named using the same key which was assigned to the module when
115
- * creating the WASM bridge.
125
+ * object, named using the same key which was assigned to the module when
126
+ * creating the WASM bridge. The bridge's core API will be named `core` and
127
+ * is reserved.
116
128
  *
117
129
  * @example
118
130
  * The following creates a bridge with a fictional `custom` API module:
@@ -124,7 +136,7 @@ export class WasmBridge {
124
136
  * bridge.getImports();
125
137
  * {
126
138
  * // imports defined by the core API of the bridge itself
127
- * core: { ... },
139
+ * wasmapi: { ... },
128
140
  * // imports defined by the CustomAPI module
129
141
  * custom: { ... }
130
142
  * }
@@ -139,7 +151,7 @@ export class WasmBridge {
139
151
  */
140
152
  getImports() {
141
153
  if (!this.imports) {
142
- this.imports = { core: this.core };
154
+ this.imports = { wasmapi: this.api };
143
155
  for (let id in this.modules) {
144
156
  if (this.imports[id] !== undefined) {
145
157
  illegalArgs(`attempt to redeclare API module ${id}`);
@@ -149,6 +161,52 @@ export class WasmBridge {
149
161
  }
150
162
  return this.imports;
151
163
  }
164
+ /**
165
+ * Attempts to grow the WASM memory by an additional `numPages` (64KB/page)
166
+ * and if successful updates all typed memory views to use the new
167
+ * underlying buffer.
168
+ *
169
+ * @param numPages
170
+ */
171
+ growMemory(numPages) {
172
+ this.exports.memory.grow(numPages);
173
+ this.ensureMemory();
174
+ }
175
+ /**
176
+ * Attempts to allocate `numBytes` using the exported WASM core API function
177
+ * {@link WasmExports._wasm_allocate} (implementation specific) and returns
178
+ * start address of the new memory block. If unsuccessful, throws an
179
+ * {@link OutOfMemoryError}. If `clear` is true, the allocated region will
180
+ * be zero-filled.
181
+ *
182
+ * @remarks
183
+ * See {@link WasmExports._wasm_allocate} docs for further details.
184
+ *
185
+ * @param numBytes
186
+ * @param clear
187
+ */
188
+ allocate(numBytes, clear = false) {
189
+ const addr = this.exports._wasm_allocate(numBytes);
190
+ if (!addr)
191
+ throw new OutOfMemoryError(`unable to allocate: ${numBytes}`);
192
+ this.logger.debug(`allocated ${numBytes} bytes @ 0x${U32(addr)}`);
193
+ this.ensureMemory();
194
+ clear && this.u8.fill(0, addr, addr + numBytes);
195
+ return addr;
196
+ }
197
+ /**
198
+ * Frees a previous allocated memory region using the exported WASM core API
199
+ * function {@link WasmExports._wasm_free} (implementation specific). The
200
+ * `numBytes` value must be the same as previously given to
201
+ * {@link WasmBridge.allocate}.
202
+ *
203
+ * @param addr
204
+ * @param numBytes
205
+ */
206
+ free(addr, numBytes) {
207
+ this.logger.debug(`freeing memory @ 0x${U32(addr)} .. 0x${U32(addr + numBytes - 1)}`);
208
+ this.exports._wasm_free(addr, numBytes);
209
+ }
152
210
  getI8(addr) {
153
211
  return this.i8[addr];
154
212
  }
@@ -297,13 +355,37 @@ export class WasmBridge {
297
355
  this.f64.set(buf, addr >> 3);
298
356
  return this;
299
357
  }
358
+ /**
359
+ * Reads UTF-8 encoded string from given address and optional byte length.
360
+ * The default length is 0, which will be interpreted as a zero-terminated
361
+ * string. Returns string.
362
+ *
363
+ * @param addr
364
+ * @param len
365
+ */
300
366
  getString(addr, len = 0) {
367
+ this.ensureMemory();
301
368
  return this.utf8Decoder.decode(this.u8.subarray(addr, len > 0 ? addr + len : this.u8.indexOf(0, addr)));
302
369
  }
370
+ /**
371
+ * Encodes given string as UTF-8 and writes it to WASM memory starting at
372
+ * `addr`. By default the string will be zero-terminated and only `maxBytes`
373
+ * will be written. Returns the number of bytes written.
374
+ *
375
+ * @remarks
376
+ * An error will be thrown if the encoded string doesn't fully fit into the
377
+ * designated memory region (also note that there might need to be space for
378
+ * the additional sentinel/termination byte).
379
+ *
380
+ * @param str
381
+ * @param addr
382
+ * @param maxBytes
383
+ * @param terminate
384
+ */
303
385
  setString(str, addr, maxBytes, terminate = true) {
304
386
  maxBytes = Math.min(maxBytes, this.u8.length - addr);
305
387
  const len = this.utf8Encoder.encodeInto(str, this.u8.subarray(addr, addr + maxBytes)).written;
306
- if (len != null && len < maxBytes + (terminate ? 0 : 1)) {
388
+ if (len == null || len >= maxBytes + (terminate ? 0 : 1)) {
307
389
  illegalArgs(`error writing string to 0x${U32(addr)}`);
308
390
  }
309
391
  if (terminate) {
package/cli.d.ts ADDED
@@ -0,0 +1,5 @@
1
+ export declare const INSTALL_DIR: string;
2
+ export declare const PKG: any;
3
+ export declare const APP_NAME: any;
4
+ export declare const HEADER: string;
5
+ //# sourceMappingURL=cli.d.ts.map