@thi.ng/wasm-api 0.11.0 → 0.12.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 +30 -1
- package/README.md +109 -57
- package/api.d.ts +24 -5
- package/bin/wasm-api.mjs_ +17 -0
- package/bridge.js +2 -2
- package/cli.js +28 -7
- package/codegen/c11.js +4 -4
- package/codegen/typescript.js +4 -9
- package/codegen/utils.d.ts +5 -3
- package/codegen/utils.js +8 -5
- package/codegen/zig.js +27 -8
- package/codegen.js +6 -2
- package/include/wasmapi.zig +1 -1
- package/package.json +16 -15
- package/string.d.ts +3 -4
- package/doc/assets/main.js +0 -52
- package/doc/assets/search.js +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Change Log
|
|
2
2
|
|
|
3
|
-
- **Last updated**: 2022-
|
|
3
|
+
- **Last updated**: 2022-10-03T16:07:55Z
|
|
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,35 @@ 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
|
+
## [0.12.0](https://github.com/thi-ng/umbrella/tree/@thi.ng/wasm-api@0.12.0) (2022-10-03)
|
|
13
|
+
|
|
14
|
+
#### 🚀 Features
|
|
15
|
+
|
|
16
|
+
- update CLI ([98d2414](https://github.com/thi-ng/umbrella/commit/98d2414))
|
|
17
|
+
- add optional type analytics JSON output
|
|
18
|
+
- add support for including user code via `@`-file references
|
|
19
|
+
- update config `@`-file refs to resolve relative to config file
|
|
20
|
+
- add support for sentinels & user type body injection ([d240046](https://github.com/thi-ng/umbrella/commit/d240046))
|
|
21
|
+
- update sizeOf() to include sentinels
|
|
22
|
+
- add TopLevelType.body for extra user code
|
|
23
|
+
- update Zig codegen to:
|
|
24
|
+
- support array/slice sentinels
|
|
25
|
+
- add optional user code injection
|
|
26
|
+
- add `std` import header
|
|
27
|
+
- add ReadonlyWasmString, update impls ([240a148](https://github.com/thi-ng/umbrella/commit/240a148))
|
|
28
|
+
- add default value support for Zig codegen ([3c37ae7](https://github.com/thi-ng/umbrella/commit/3c37ae7))
|
|
29
|
+
- add doc string word wrapping ([c0b8e15](https://github.com/thi-ng/umbrella/commit/c0b8e15))
|
|
30
|
+
- update prefixLines(), add target line width arg
|
|
31
|
+
- update ICodeGen & CodeGenOpts
|
|
32
|
+
- update all codegens
|
|
33
|
+
- update deps
|
|
34
|
+
|
|
35
|
+
#### 🩹 Bug fixes
|
|
36
|
+
|
|
37
|
+
- update zig panic handler sig for latest zig master version ([cb51bf6](https://github.com/thi-ng/umbrella/commit/cb51bf6))
|
|
38
|
+
- see https://github.com/ziglang/zig/commit/694fab484805088030fa36efe3e6b6e7ee385852
|
|
39
|
+
- minor fix word wrap line width ([053ba0f](https://github.com/thi-ng/umbrella/commit/053ba0f))
|
|
40
|
+
|
|
12
41
|
## [0.11.0](https://github.com/thi-ng/umbrella/tree/@thi.ng/wasm-api@0.11.0) (2022-09-21)
|
|
13
42
|
|
|
14
43
|
#### 🚀 Features
|
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<!-- This file is generated - DO NOT EDIT! -->
|
|
2
2
|
|
|
3
|
-
# 
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/@thi.ng/wasm-api)
|
|
6
6
|

|
|
@@ -19,8 +19,10 @@ This project is part of the
|
|
|
19
19
|
- [Custom API modules](#custom-api-modules)
|
|
20
20
|
- [Object indices & handles](#object-indices--handles)
|
|
21
21
|
- [Status](#status)
|
|
22
|
+
- [Support packages](#support-packages)
|
|
22
23
|
- [Installation](#installation)
|
|
23
24
|
- [Dependencies](#dependencies)
|
|
25
|
+
- [Usage examples](#usage-examples)
|
|
24
26
|
- [API](#api)
|
|
25
27
|
- [Basic usage example](#basic-usage-example)
|
|
26
28
|
- [Zig version](#zig-version)
|
|
@@ -39,9 +41,10 @@ This package provides a the following:
|
|
|
39
41
|
class as interop basis and much reduced boilerplate for hybrid JS/WebAssembly
|
|
40
42
|
applications.
|
|
41
43
|
2. A minimal core API for debug output, string/pointer/typedarray accessors for
|
|
42
|
-
8/16/32/64 bit (u)ints and 32/64 bit floats, memory allocation (optional).
|
|
43
|
-
|
|
44
|
-
|
|
44
|
+
8/16/32/64 bit (u)ints and 32/64 bit floats, memory allocation (optional).
|
|
45
|
+
Additionally, a number of support modules for [DOM
|
|
46
|
+
manipulation](https://github.com/thi-ng/umbrella/tree/develop/packages/wasm-api-dom/),
|
|
47
|
+
WebGL, WebGPU, WebAudio etc. is being actively worked on.
|
|
45
48
|
3. [Include files for C11/C++ and
|
|
46
49
|
Zig](https://github.com/thi-ng/umbrella/tree/develop/packages/wasm-api/include),
|
|
47
50
|
defining WASM imports of the extern JS [core
|
|
@@ -51,7 +54,7 @@ WebGPU, WebAudio etc.
|
|
|
51
54
|
[Zig](https://ziglang.org). The latter also generates fully type checked
|
|
52
55
|
memory-mapped (zero-copy) accessors of WASM-side data. In general, all
|
|
53
56
|
languages with a WebAssembly target are supported, however currently only
|
|
54
|
-
bindings for these
|
|
57
|
+
bindings for these mentioned langs are included.
|
|
55
58
|
5. [CLI frontend/utility](#cli-generator) to invoke the code generator(s)
|
|
56
59
|
|
|
57
60
|
### Data bindings & code generators
|
|
@@ -59,7 +62,9 @@ bindings for these few langs are included.
|
|
|
59
62
|
The package provides an extensible codegeneration framework to simplify the
|
|
60
63
|
bilateral design & exchange of data structures shared between the WASM & JS host
|
|
61
64
|
env. Currently, code generators for TypeScript & Zig are supplied (more are
|
|
62
|
-
planned). A CLI wrapper is available too.
|
|
65
|
+
planned). A CLI wrapper is available too. See the
|
|
66
|
+
[@thi.ng/wasm-api-dom](https://github.com/thi-ng/umbrella/tree/develop/packages/wasm-api-dom/)
|
|
67
|
+
support package for a more thorough realworld example...
|
|
63
68
|
|
|
64
69
|
#### CLI generator
|
|
65
70
|
|
|
@@ -73,7 +78,7 @@ $ npx @thi.ng/wasm-api
|
|
|
73
78
|
|
|
74
79
|
█ █ █ │
|
|
75
80
|
██ █ │
|
|
76
|
-
█ █ █ █ █ █ █ █ │ @thi.ng/wasm-api 0.
|
|
81
|
+
█ █ █ █ █ █ █ █ │ @thi.ng/wasm-api 0.12.0
|
|
77
82
|
█ █ █ █ █ █ █ █ █ │ Multi-language data bindings code generator
|
|
78
83
|
█ │
|
|
79
84
|
█ █ │
|
|
@@ -88,6 +93,7 @@ Flags:
|
|
|
88
93
|
|
|
89
94
|
Main:
|
|
90
95
|
|
|
96
|
+
-a FILE, --analytics FILE output file path for raw codegen analytics
|
|
91
97
|
-c FILE, --config FILE JSON config file with codegen options
|
|
92
98
|
-l ID[,..], --lang ID[,..] [multiple] target language: "c11", "ts", "zig" (default: ["ts","zig"])
|
|
93
99
|
-o FILE, --out FILE [multiple] output file path
|
|
@@ -195,42 +201,59 @@ codes:
|
|
|
195
201
|
<details><summary>generated.ts (generated TypeScript source)</summary>
|
|
196
202
|
|
|
197
203
|
```ts
|
|
198
|
-
/**
|
|
204
|
+
/**
|
|
205
|
+
* Generated by @thi.ng/wasm-api at 2022-10-03T15:32:12.339Z - DO NOT EDIT!
|
|
206
|
+
*/
|
|
199
207
|
|
|
200
|
-
|
|
208
|
+
// @ts-ignore possibly includes unused imports
|
|
209
|
+
import { Pointer, WasmStringSlice, WasmTypeBase, WasmTypeConstructor } from "@thi.ng/wasm-api";
|
|
201
210
|
|
|
202
|
-
/**
|
|
211
|
+
/**
|
|
212
|
+
* Example struct
|
|
213
|
+
*/
|
|
203
214
|
export interface Foo extends WasmTypeBase {
|
|
204
215
|
color: Float32Array;
|
|
205
216
|
bars: Bar[];
|
|
206
|
-
/**
|
|
217
|
+
/**
|
|
218
|
+
* Unique ID
|
|
219
|
+
*/
|
|
207
220
|
id: number;
|
|
208
221
|
}
|
|
209
222
|
|
|
210
223
|
export const $Foo: WasmTypeConstructor<Foo> = (mem) => ({
|
|
211
|
-
get align() {
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
224
|
+
get align() {
|
|
225
|
+
return 16;
|
|
226
|
+
},
|
|
227
|
+
get size() {
|
|
228
|
+
return 48;
|
|
229
|
+
},
|
|
230
|
+
instance: (base) => {
|
|
231
|
+
return {
|
|
232
|
+
get __base() {
|
|
233
|
+
return base;
|
|
234
|
+
},
|
|
235
|
+
get __bytes() {
|
|
236
|
+
return mem.u8.subarray(base, base + 48);
|
|
237
|
+
},
|
|
238
|
+
get color(): Float32Array {
|
|
239
|
+
const addr = base >>> 2;
|
|
240
|
+
return mem.f32.subarray(addr, addr + 4);
|
|
241
|
+
},
|
|
242
|
+
get bars(): Bar[] {
|
|
243
|
+
const addr = (base + 16);
|
|
244
|
+
const inst = $Bar(mem);
|
|
245
|
+
const slice: Bar[] = [];
|
|
246
|
+
for(let i = 0; i < 3; i++) slice.push(inst.instance(addr + i * 24));
|
|
247
|
+
return slice;
|
|
248
|
+
},
|
|
249
|
+
get id(): number {
|
|
250
|
+
return mem.u8[(base + 40)];
|
|
251
|
+
},
|
|
252
|
+
set id(x: number) {
|
|
253
|
+
mem.u8[(base + 40)] = x;
|
|
254
|
+
},
|
|
255
|
+
};
|
|
256
|
+
}
|
|
234
257
|
});
|
|
235
258
|
|
|
236
259
|
export interface Bar extends WasmTypeBase {
|
|
@@ -239,24 +262,34 @@ export interface Bar extends WasmTypeBase {
|
|
|
239
262
|
}
|
|
240
263
|
|
|
241
264
|
export const $Bar: WasmTypeConstructor<Bar> = (mem) => ({
|
|
242
|
-
get align() {
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
265
|
+
get align() {
|
|
266
|
+
return 4;
|
|
267
|
+
},
|
|
268
|
+
get size() {
|
|
269
|
+
return 8;
|
|
270
|
+
},
|
|
271
|
+
instance: (base) => {
|
|
272
|
+
return {
|
|
273
|
+
get __base() {
|
|
274
|
+
return base;
|
|
275
|
+
},
|
|
276
|
+
get __bytes() {
|
|
277
|
+
return mem.u8.subarray(base, base + 8);
|
|
278
|
+
},
|
|
279
|
+
get kind(): Kind {
|
|
280
|
+
return mem.u16[base >>> 1];
|
|
281
|
+
},
|
|
282
|
+
set kind(x: Kind) {
|
|
283
|
+
mem.u16[base >>> 1] = x;
|
|
284
|
+
},
|
|
285
|
+
get flags(): number {
|
|
286
|
+
return mem.u32[(base + 4) >>> 2];
|
|
287
|
+
},
|
|
288
|
+
set flags(x: number) {
|
|
289
|
+
mem.u32[(base + 4) >>> 2] = x;
|
|
290
|
+
},
|
|
291
|
+
};
|
|
292
|
+
}
|
|
260
293
|
});
|
|
261
294
|
|
|
262
295
|
export enum Kind {
|
|
@@ -270,7 +303,9 @@ export enum Kind {
|
|
|
270
303
|
<details><summary>generated.zig (generated Zig source)</summary>
|
|
271
304
|
|
|
272
305
|
```zig
|
|
273
|
-
//! Generated by @thi.ng/wasm-api at 2022-
|
|
306
|
+
//! Generated by @thi.ng/wasm-api at 2022-10-03T15:32:12.341Z - DO NOT EDIT!
|
|
307
|
+
|
|
308
|
+
const std = @import("std");
|
|
274
309
|
|
|
275
310
|
/// Example struct
|
|
276
311
|
pub const Foo = struct {
|
|
@@ -286,9 +321,9 @@ pub const Bar = struct {
|
|
|
286
321
|
};
|
|
287
322
|
|
|
288
323
|
pub const Kind = enum(u16) {
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
324
|
+
UNKNOWN,
|
|
325
|
+
GOOD = 100,
|
|
326
|
+
BEST = 1000,
|
|
292
327
|
};
|
|
293
328
|
```
|
|
294
329
|
</details>
|
|
@@ -538,6 +573,10 @@ canvases.delete(0);
|
|
|
538
573
|
|
|
539
574
|
[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=%5Bwasm-api%5D+in%3Atitle)
|
|
540
575
|
|
|
576
|
+
## Support packages
|
|
577
|
+
|
|
578
|
+
- [@thi.ng/wasm-api-dom](https://github.com/thi-ng/umbrella/tree/develop/packages/wasm-api-dom) - Browser DOM bridge API for hybrid TypeScript & Zig applications
|
|
579
|
+
|
|
541
580
|
## Installation
|
|
542
581
|
|
|
543
582
|
```bash
|
|
@@ -561,7 +600,7 @@ node --experimental-repl-await
|
|
|
561
600
|
> const wasmApi = await import("@thi.ng/wasm-api");
|
|
562
601
|
```
|
|
563
602
|
|
|
564
|
-
Package sizes (gzipped, pre-treeshake): ESM: 6.
|
|
603
|
+
Package sizes (gzipped, pre-treeshake): ESM: 6.29 KB
|
|
565
604
|
|
|
566
605
|
**IMPORTANT:** The package includes code generators for various languages which
|
|
567
606
|
are **not** required for just using the API bridge. Hence, the usual package
|
|
@@ -581,6 +620,19 @@ size in production will be MUCH smaller than what's stated here!
|
|
|
581
620
|
- [@thi.ng/idgen](https://github.com/thi-ng/umbrella/tree/develop/packages/idgen)
|
|
582
621
|
- [@thi.ng/logger](https://github.com/thi-ng/umbrella/tree/develop/packages/logger)
|
|
583
622
|
- [@thi.ng/paths](https://github.com/thi-ng/umbrella/tree/develop/packages/paths)
|
|
623
|
+
- [@thi.ng/strings](https://github.com/thi-ng/umbrella/tree/develop/packages/strings)
|
|
624
|
+
|
|
625
|
+
## Usage examples
|
|
626
|
+
|
|
627
|
+
Several demos in this repo's
|
|
628
|
+
[/examples](https://github.com/thi-ng/umbrella/tree/develop/examples)
|
|
629
|
+
directory are using this package.
|
|
630
|
+
|
|
631
|
+
A selection:
|
|
632
|
+
|
|
633
|
+
| Screenshot | Description | Live demo | Source |
|
|
634
|
+
|:------------------------------------------------------------------------------------------------------------------|:--------------------------------------------|:-------------------------------------------------|:------------------------------------------------------------------------------|
|
|
635
|
+
| <img src="https://raw.githubusercontent.com/thi-ng/umbrella/develop/assets/examples/zig-canvas.png" width="240"/> | Zig-based DOM creation & canvas drawing app | [Demo](https://demo.thi.ng/umbrella/zig-canvas/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/zig-canvas) |
|
|
584
636
|
|
|
585
637
|
## API
|
|
586
638
|
|
package/api.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { BigType, FloatType, Fn } from "@thi.ng/api";
|
|
1
|
+
import type { BigType, FloatType, Fn, IDeref, ILength, IObjectOf } from "@thi.ng/api";
|
|
2
2
|
import type { WasmBridge } from "./bridge.js";
|
|
3
3
|
export declare const PKG_NAME = "@thi.ng/wasm-api";
|
|
4
4
|
export declare const EVENT_MEMORY_CHANGED = "memory-changed";
|
|
@@ -175,6 +175,9 @@ export declare type WasmUint = "u8" | "u16" | "u32" | "u64";
|
|
|
175
175
|
export declare type WasmFloat = FloatType;
|
|
176
176
|
export declare type WasmPrim = WasmInt | WasmUint | WasmFloat;
|
|
177
177
|
export declare type WasmPrim32 = Exclude<WasmPrim, BigType>;
|
|
178
|
+
export declare type ReadonlyWasmString = IDeref<string> & ILength & {
|
|
179
|
+
readonly addr: number;
|
|
180
|
+
};
|
|
178
181
|
export declare type TypeColl = Record<string, TopLevelType>;
|
|
179
182
|
export interface TypeInfo {
|
|
180
183
|
/**
|
|
@@ -209,6 +212,14 @@ export interface TopLevelType extends TypeInfo {
|
|
|
209
212
|
* Type / kind
|
|
210
213
|
*/
|
|
211
214
|
type: "struct" | "enum";
|
|
215
|
+
/**
|
|
216
|
+
* Optional object of user provided source codes to be injected into the
|
|
217
|
+
* generated type. Keys are language IDs (same name as respective codegen).
|
|
218
|
+
*
|
|
219
|
+
* @remarks
|
|
220
|
+
* Currently only supported by the {@link ZIG} codegen, ignored otherwise.
|
|
221
|
+
*/
|
|
222
|
+
body?: IObjectOf<string>;
|
|
212
223
|
}
|
|
213
224
|
export interface Struct extends TopLevelType {
|
|
214
225
|
type: "struct";
|
|
@@ -276,7 +287,8 @@ export interface StructField extends TypeInfo {
|
|
|
276
287
|
*/
|
|
277
288
|
const?: boolean;
|
|
278
289
|
/**
|
|
279
|
-
*
|
|
290
|
+
* Currently only supported for {@link ZIG} arrays & slices, otherwise
|
|
291
|
+
* ignored!
|
|
280
292
|
*/
|
|
281
293
|
sentinel?: number;
|
|
282
294
|
/**
|
|
@@ -284,9 +296,10 @@ export interface StructField extends TypeInfo {
|
|
|
284
296
|
*/
|
|
285
297
|
len?: number;
|
|
286
298
|
/**
|
|
287
|
-
*
|
|
299
|
+
* Currently only supported for {@link ZIG} scalar & string values,
|
|
300
|
+
* otherwise ignored!
|
|
288
301
|
*/
|
|
289
|
-
default?:
|
|
302
|
+
default?: number;
|
|
290
303
|
/**
|
|
291
304
|
* If defined and > 0, the field will be considered for padding purposes only and
|
|
292
305
|
* the value provided is the number of bytes used.
|
|
@@ -363,6 +376,12 @@ export interface CodeGenOpts extends CodeGenOptsBase {
|
|
|
363
376
|
* @defaultValue false
|
|
364
377
|
*/
|
|
365
378
|
debug: boolean;
|
|
379
|
+
/**
|
|
380
|
+
* Target line width for word wrapping doc strings
|
|
381
|
+
*
|
|
382
|
+
* @defaultValue 80
|
|
383
|
+
*/
|
|
384
|
+
lineWidth: number;
|
|
366
385
|
}
|
|
367
386
|
export interface ICodeGen {
|
|
368
387
|
/**
|
|
@@ -376,7 +395,7 @@ export interface ICodeGen {
|
|
|
376
395
|
/**
|
|
377
396
|
* Docstring codegen
|
|
378
397
|
*/
|
|
379
|
-
doc: (doc: string, acc: string[], topLevel?: boolean) => void;
|
|
398
|
+
doc: (doc: string, acc: string[], opts: CodeGenOpts, topLevel?: boolean) => void;
|
|
380
399
|
/**
|
|
381
400
|
* Codegen for enum types.
|
|
382
401
|
*/
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { spawn } from "child_process";
|
|
4
|
+
import { realpathSync } from "fs";
|
|
5
|
+
import { join } from "path";
|
|
6
|
+
const [node, toolsDir, ...args] = process.argv;
|
|
7
|
+
|
|
8
|
+
const cli = join(realpathSync(toolsDir), "..", "..", "cli.js");
|
|
9
|
+
|
|
10
|
+
const child = spawn(node, ["--loader", "ts-node/esm", cli, ...args]);
|
|
11
|
+
|
|
12
|
+
child.stderr.on("data", (d) => {
|
|
13
|
+
const dStr = d.toString().trim();
|
|
14
|
+
!dStr.includes("ExperimentalWarning") ? console.log(dStr) : "";
|
|
15
|
+
});
|
|
16
|
+
child.on("exit", (err) => process.exit(err));
|
|
17
|
+
child.stdout.pipe(process.stdout);
|
package/bridge.js
CHANGED
|
@@ -215,7 +215,7 @@ let WasmBridge = class WasmBridge {
|
|
|
215
215
|
const addr = this.exports._wasm_allocate(numBytes);
|
|
216
216
|
if (!addr)
|
|
217
217
|
throw new OutOfMemoryError(`unable to allocate: ${numBytes}`);
|
|
218
|
-
this.logger.
|
|
218
|
+
this.logger.fine(`allocated ${numBytes} bytes @ 0x${U32(addr)} .. 0x${U32(addr + numBytes - 1)}`);
|
|
219
219
|
this.ensureMemory();
|
|
220
220
|
clear && this.u8.fill(0, addr, addr + numBytes);
|
|
221
221
|
return addr;
|
|
@@ -234,7 +234,7 @@ let WasmBridge = class WasmBridge {
|
|
|
234
234
|
* @param numBytes
|
|
235
235
|
*/
|
|
236
236
|
free(addr, numBytes) {
|
|
237
|
-
this.logger.
|
|
237
|
+
this.logger.fine(`freeing memory @ 0x${U32(addr)} .. 0x${U32(addr + numBytes - 1)}`);
|
|
238
238
|
this.exports._wasm_free(addr, numBytes);
|
|
239
239
|
}
|
|
240
240
|
getI8(addr) {
|
package/cli.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { flag, oneOf, oneOfMulti, parse, ParseError, string, strings, usage, } from "@thi.ng/args";
|
|
2
2
|
import { isArray, isPlainObject } from "@thi.ng/checks";
|
|
3
3
|
import { illegalArgs } from "@thi.ng/errors";
|
|
4
|
-
import {
|
|
5
|
-
import { readJSON, readText, writeText } from "@thi.ng/file-io";
|
|
4
|
+
import { readJSON, readText, writeJSON, writeText } from "@thi.ng/file-io";
|
|
6
5
|
import { ConsoleLogger } from "@thi.ng/logger";
|
|
7
|
-
import {
|
|
6
|
+
import { mutIn } from "@thi.ng/paths";
|
|
7
|
+
import { dirname, resolve } from "path";
|
|
8
8
|
import { generateTypes } from "./codegen.js";
|
|
9
9
|
import { C11 } from "./codegen/c11.js";
|
|
10
10
|
import { TYPESCRIPT } from "./codegen/typescript.js";
|
|
@@ -12,6 +12,11 @@ import { isPadding, isWasmPrim, isWasmString } from "./codegen/utils.js";
|
|
|
12
12
|
import { ZIG } from "./codegen/zig.js";
|
|
13
13
|
const GENERATORS = { c11: C11, ts: TYPESCRIPT, zig: ZIG };
|
|
14
14
|
const argOpts = {
|
|
15
|
+
analytics: string({
|
|
16
|
+
alias: "a",
|
|
17
|
+
hint: "FILE",
|
|
18
|
+
desc: "output file path for raw codegen analytics",
|
|
19
|
+
}),
|
|
15
20
|
config: string({
|
|
16
21
|
alias: "c",
|
|
17
22
|
hint: "FILE",
|
|
@@ -70,6 +75,16 @@ const addTypeSpec = (ctx, path, coll, spec) => {
|
|
|
70
75
|
invalidSpec(path, `${spec.name} type: ${spec.type}`);
|
|
71
76
|
if (coll[spec.name])
|
|
72
77
|
invalidSpec(path, `duplicate name: ${spec.name}`);
|
|
78
|
+
if (spec.body) {
|
|
79
|
+
if (!isPlainObject(spec.body))
|
|
80
|
+
invalidSpec(path, `${spec.name}.body must be an object`);
|
|
81
|
+
for (let lang in spec.body) {
|
|
82
|
+
const src = spec.body[lang];
|
|
83
|
+
if (src[0] === "@") {
|
|
84
|
+
spec.body[lang] = readText(src.substring(1), ctx.logger);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
73
88
|
ctx.logger.debug(`registering ${spec.type}: ${spec.name}`);
|
|
74
89
|
coll[spec.name] = spec;
|
|
75
90
|
spec.__path = path;
|
|
@@ -141,20 +156,26 @@ try {
|
|
|
141
156
|
opts,
|
|
142
157
|
};
|
|
143
158
|
if (opts.config) {
|
|
144
|
-
|
|
159
|
+
opts.config = resolve(opts.config);
|
|
160
|
+
ctx.config = readJSON(opts.config, ctx.logger);
|
|
145
161
|
for (let id in ctx.config) {
|
|
146
162
|
const conf = ctx.config[id];
|
|
147
163
|
if (conf.pre && conf.pre[0] === "@") {
|
|
148
|
-
conf.pre = readText(conf.pre.substring(1), ctx.logger);
|
|
164
|
+
conf.pre = readText(resolve(dirname(opts.config), conf.pre.substring(1)), ctx.logger);
|
|
149
165
|
}
|
|
150
166
|
if (conf.post && conf.post[0] === "@") {
|
|
151
|
-
conf.post = readText(conf.post.substring(1), ctx.logger);
|
|
167
|
+
conf.post = readText(resolve(dirname(opts.config), conf.post.substring(1)), ctx.logger);
|
|
152
168
|
}
|
|
153
169
|
}
|
|
154
170
|
}
|
|
155
171
|
opts.debug && mutIn(ctx, ["config", "global", "debug"], true);
|
|
156
172
|
opts.string && mutIn(ctx, ["config", "global", "stringType"], opts.string);
|
|
157
|
-
|
|
173
|
+
const types = parseTypeSpecs(ctx, rest);
|
|
174
|
+
generateOutputs(ctx, types);
|
|
175
|
+
if (ctx.opts.analytics) {
|
|
176
|
+
// always write analytics, even if dry run
|
|
177
|
+
writeJSON(resolve(ctx.opts.analytics), types, undefined, "\t", ctx.logger);
|
|
178
|
+
}
|
|
158
179
|
}
|
|
159
180
|
catch (e) {
|
|
160
181
|
if (!(e instanceof ParseError))
|
package/codegen/c11.js
CHANGED
|
@@ -36,8 +36,8 @@ ${opts.debug ? "\n#include <stdalign.h>" : ""}
|
|
|
36
36
|
#include <stddef.h>
|
|
37
37
|
#include <stdint.h>${opts.pre ? `\n${opts.pre}` : ""}`,
|
|
38
38
|
post: () => opts.post || "",
|
|
39
|
-
doc: (doc, acc) => {
|
|
40
|
-
acc.push(prefixLines("// ", doc));
|
|
39
|
+
doc: (doc, acc, opts) => {
|
|
40
|
+
acc.push(...prefixLines("// ", doc, opts.lineWidth));
|
|
41
41
|
},
|
|
42
42
|
enum: (e, _, acc, opts) => {
|
|
43
43
|
if (!(e.tag === "i32" || e.tag === "u32")) {
|
|
@@ -49,7 +49,7 @@ ${opts.debug ? "\n#include <stdalign.h>" : ""}
|
|
|
49
49
|
for (let v of e.values) {
|
|
50
50
|
let line;
|
|
51
51
|
if (!isString(v)) {
|
|
52
|
-
v.doc && gen.doc(v.doc, lines);
|
|
52
|
+
v.doc && gen.doc(v.doc, lines, opts);
|
|
53
53
|
line = enumName(opts, v.name);
|
|
54
54
|
if (v.value != null)
|
|
55
55
|
line += ` = ${v.value}`;
|
|
@@ -74,7 +74,7 @@ ${opts.debug ? "\n#include <stdalign.h>" : ""}
|
|
|
74
74
|
res.push(`uint8_t __pad${padID++}[${f.pad}];`);
|
|
75
75
|
continue;
|
|
76
76
|
}
|
|
77
|
-
f.doc && gen.doc(f.doc, res);
|
|
77
|
+
f.doc && gen.doc(f.doc, res, opts);
|
|
78
78
|
const fconst = f.const ? "const " : "";
|
|
79
79
|
let ftype = f.type === "string"
|
|
80
80
|
? isStringSlice(opts.stringType)
|
package/codegen/typescript.js
CHANGED
|
@@ -24,13 +24,8 @@ export const TYPESCRIPT = (opts = {}) => {
|
|
|
24
24
|
pre: (opts) => `// @ts-ignore possibly includes unused imports
|
|
25
25
|
import { Pointer, ${__stringImpl(opts)}, WasmTypeBase, WasmTypeConstructor } from "${PKG_NAME}";${opts.pre ? `\n${opts.pre}` : ""}`,
|
|
26
26
|
post: () => opts.post || "",
|
|
27
|
-
doc: (doc, acc) => {
|
|
28
|
-
|
|
29
|
-
acc.push("/**", prefixLines(indent + " * ", doc), " */");
|
|
30
|
-
}
|
|
31
|
-
else {
|
|
32
|
-
acc.push(`/** ${doc} */`);
|
|
33
|
-
}
|
|
27
|
+
doc: (doc, acc, opts) => {
|
|
28
|
+
acc.push("/**", ...prefixLines(" * ", doc, opts.lineWidth), " */");
|
|
34
29
|
},
|
|
35
30
|
enum: (e, _, acc, opts) => {
|
|
36
31
|
const res = [];
|
|
@@ -38,7 +33,7 @@ import { Pointer, ${__stringImpl(opts)}, WasmTypeBase, WasmTypeConstructor } fro
|
|
|
38
33
|
for (let v of e.values) {
|
|
39
34
|
let line;
|
|
40
35
|
if (!isString(v)) {
|
|
41
|
-
v.doc && gen.doc(v.doc, res);
|
|
36
|
+
v.doc && gen.doc(v.doc, res, opts);
|
|
42
37
|
line = enumName(opts, v.name);
|
|
43
38
|
if (v.value != null)
|
|
44
39
|
line += ` = ${v.value}`;
|
|
@@ -60,7 +55,7 @@ import { Pointer, ${__stringImpl(opts)}, WasmTypeBase, WasmTypeConstructor } fro
|
|
|
60
55
|
for (let f of struct.fields) {
|
|
61
56
|
if (isPadding(f))
|
|
62
57
|
continue;
|
|
63
|
-
f.doc && gen.doc(f.doc, lines);
|
|
58
|
+
f.doc && gen.doc(f.doc, lines, opts);
|
|
64
59
|
const ftype = __fieldType(f, opts);
|
|
65
60
|
fieldTypes[f.name] = ftype;
|
|
66
61
|
lines.push(`${f.name}: ${ftype};`);
|
package/codegen/utils.d.ts
CHANGED
|
@@ -21,13 +21,15 @@ export declare const isWasmPrim: (x: string) => x is WasmPrim;
|
|
|
21
21
|
export declare const isWasmString: (x: string) => x is "string";
|
|
22
22
|
export declare const isPadding: (f: StructField) => boolean;
|
|
23
23
|
/**
|
|
24
|
-
* Takes an array of strings or splits given string into lines,
|
|
25
|
-
* line with given `
|
|
24
|
+
* Takes an array of strings or splits given string into lines, word wraps and
|
|
25
|
+
* then prefixes each line with given `width` and `prefix`. Returns array of new
|
|
26
|
+
* lines.
|
|
26
27
|
*
|
|
27
28
|
* @param prefix
|
|
28
29
|
* @param str
|
|
30
|
+
* @param width
|
|
29
31
|
*/
|
|
30
|
-
export declare const prefixLines: (prefix: string, str: string | string[]) => string;
|
|
32
|
+
export declare const prefixLines: (prefix: string, str: string | string[], width: number) => string[];
|
|
31
33
|
/**
|
|
32
34
|
* Returns true if `type` is "slice".
|
|
33
35
|
*
|
package/codegen/utils.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { isString } from "@thi.ng/checks/is-string";
|
|
2
|
+
import { wordWrapLine, wordWrapLines } from "@thi.ng/strings/word-wrap";
|
|
2
3
|
/**
|
|
3
4
|
* Returns true iff `x` is a {@link WasmPrim32}.
|
|
4
5
|
*
|
|
@@ -20,15 +21,17 @@ export const isWasmPrim = (x) => isNumeric(x) || isBigNumeric(x);
|
|
|
20
21
|
export const isWasmString = (x) => x === "string";
|
|
21
22
|
export const isPadding = (f) => f.pad != null && f.pad > 0;
|
|
22
23
|
/**
|
|
23
|
-
* Takes an array of strings or splits given string into lines,
|
|
24
|
-
* line with given `
|
|
24
|
+
* Takes an array of strings or splits given string into lines, word wraps and
|
|
25
|
+
* then prefixes each line with given `width` and `prefix`. Returns array of new
|
|
26
|
+
* lines.
|
|
25
27
|
*
|
|
26
28
|
* @param prefix
|
|
27
29
|
* @param str
|
|
30
|
+
* @param width
|
|
28
31
|
*/
|
|
29
|
-
export const prefixLines = (prefix, str) => (isString(str)
|
|
30
|
-
|
|
31
|
-
.
|
|
32
|
+
export const prefixLines = (prefix, str, width) => (isString(str)
|
|
33
|
+
? wordWrapLines(str, { width: width - prefix.length })
|
|
34
|
+
: str.flatMap((x) => wordWrapLine(x, { width: width - prefix.length }))).map((line) => prefix + line);
|
|
32
35
|
/**
|
|
33
36
|
* Returns true if `type` is "slice".
|
|
34
37
|
*
|