@thi.ng/wasm-api 1.1.0 → 1.2.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 +7 -1
- package/README.md +43 -20
- package/package.json +10 -10
- package/zig/build.zig +135 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Change Log
|
|
2
2
|
|
|
3
|
-
- **Last updated**: 2022-
|
|
3
|
+
- **Last updated**: 2022-12-01T18:02:30Z
|
|
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,12 @@ 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
|
+
## [1.2.0](https://github.com/thi-ng/umbrella/tree/@thi.ng/wasm-api@1.2.0) (2022-12-01)
|
|
13
|
+
|
|
14
|
+
#### 🚀 Features
|
|
15
|
+
|
|
16
|
+
- add build script for user projects ([7164f5e](https://github.com/thi-ng/umbrella/commit/7164f5e))
|
|
17
|
+
|
|
12
18
|
## [1.1.0](https://github.com/thi-ng/umbrella/tree/@thi.ng/wasm-api@1.1.0) (2022-11-28)
|
|
13
19
|
|
|
14
20
|
#### 🚀 Features
|
package/README.md
CHANGED
|
@@ -11,11 +11,12 @@ This project is part of the
|
|
|
11
11
|
|
|
12
12
|
- [About](#about)
|
|
13
13
|
- [Custom API modules](#custom-api-modules)
|
|
14
|
-
- [Building Zig projects with these hybrid API modules](#building-zig-projects-with-these-hybrid-api-modules)
|
|
15
14
|
- [String handling](#string-handling)
|
|
16
15
|
- [Memory allocations](#memory-allocations)
|
|
17
16
|
- [API module auto-initialization](#api-module-auto-initialization)
|
|
18
17
|
- [Object indices & handles](#object-indices--handles)
|
|
18
|
+
- [Using the Zig build system](#using-the-zig-build-system)
|
|
19
|
+
- [Naming & structural conventions](#naming--structural-conventions)
|
|
19
20
|
- [Status](#status)
|
|
20
21
|
- [Support packages](#support-packages)
|
|
21
22
|
- [Installation](#installation)
|
|
@@ -55,13 +56,15 @@ WebGL, WebGPU, WebAudio etc. is being actively worked on.
|
|
|
55
56
|
defining glue code for the TypeScript [core
|
|
56
57
|
API](https://docs.thi.ng/umbrella/wasm-api/interfaces/CoreAPI.html) defined
|
|
57
58
|
by this package
|
|
58
|
-
7.
|
|
59
|
+
7. [Zig build files]() to simplify using hybrid TS/Zig packages with the
|
|
60
|
+
built-in build system
|
|
61
|
+
8. Extensible shared [datatype code generator
|
|
59
62
|
infrastructure](https://github.com/thi-ng/umbrella/tree/develop/packages/wasm-api-bindgen/)
|
|
60
63
|
for (currently) Zig & TypeScript and C11. For TS fully type checked and
|
|
61
64
|
memory-mapped (zero-copy) accessors of WASM-side data are generated. In
|
|
62
65
|
principle, all languages with a WASM target are supported, however currently
|
|
63
66
|
only bindings for these mentioned langs are included.
|
|
64
|
-
|
|
67
|
+
9. [CLI
|
|
65
68
|
frontend/utility](https://github.com/thi-ng/umbrella/blob/develop/packages/wasm-api-bindgen/README.md#cli-generator)
|
|
66
69
|
for the code generator(s)
|
|
67
70
|
|
|
@@ -148,7 +151,7 @@ Main Zig file:
|
|
|
148
151
|
|
|
149
152
|
```zig
|
|
150
153
|
// Import JS core API
|
|
151
|
-
const js = @import("
|
|
154
|
+
const js = @import("wasm-api");
|
|
152
155
|
const custom = @import("custom.zig");
|
|
153
156
|
|
|
154
157
|
export fn test_randomVec4() void {
|
|
@@ -165,19 +168,6 @@ export fn test_randomVec4() void {
|
|
|
165
168
|
}
|
|
166
169
|
```
|
|
167
170
|
|
|
168
|
-
### Building Zig projects with these hybrid API modules
|
|
169
|
-
|
|
170
|
-
Some example projects (see [list below](#usage-examples)) provide custom
|
|
171
|
-
[`build.zig`](https://github.com/thi-ng/umbrella/blob/develop/examples/zig-canvas/build.zig)
|
|
172
|
-
&
|
|
173
|
-
[`npm.zig`](https://github.com/thi-ng/umbrella/blob/develop/examples/zig-canvas/npm.zig)
|
|
174
|
-
build scripts to easily integrate these hybrid TS/Zig packages into users'
|
|
175
|
-
development processes.
|
|
176
|
-
|
|
177
|
-
To avoid guesswork about the internals of these API modules, all of them are
|
|
178
|
-
using an overall uniform structure, with the main Zig entry point in
|
|
179
|
-
`/zig/lib.zig`...
|
|
180
|
-
|
|
181
171
|
## String handling
|
|
182
172
|
|
|
183
173
|
Most low-level languages deal with strings very differently and alas there's no
|
|
@@ -313,6 +303,38 @@ in the
|
|
|
313
303
|
[@thi.ng/wasm-api-schedule](https://github.com/thi-ng/umbrella/blob/develop/packages/wasm-api-schedule/)
|
|
314
304
|
packages this is used to manage Zig-side event listeners.
|
|
315
305
|
|
|
306
|
+
## Using the Zig build system
|
|
307
|
+
|
|
308
|
+
This package provides utilities to simplify using hybrid TS/Zig WASM API modules which are distributed as NPM packages. Using these utils, a build file for Zig's built-in build system is as simple as:
|
|
309
|
+
|
|
310
|
+
```zig
|
|
311
|
+
const std = @import("std");
|
|
312
|
+
|
|
313
|
+
pub fn build(b: *std.build.Builder) void {
|
|
314
|
+
@import("node_modules/@thi.ng/wasm-api/zig/build.zig").wasmLib(b, .{
|
|
315
|
+
// Declare extra WASM API packages to use
|
|
316
|
+
// Each package can also declare its dependencies
|
|
317
|
+
.packages = &.{
|
|
318
|
+
.{ .id = "wasm-api-dom", .path = "@thi.ng/wasm-api-dom/zig/lib.zig" },
|
|
319
|
+
.{ .id = "wasm-api-schedule", .path = "@thi.ng/wasm-api-schedule/zig/lib.zig" },
|
|
320
|
+
},
|
|
321
|
+
// (optional) build mode override
|
|
322
|
+
.mode = .ReleaseSmall,
|
|
323
|
+
}).install();
|
|
324
|
+
}
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
All bundled example projects (see [list below](#usage-examples)) are being built
|
|
328
|
+
via this script. **Please find more details/options in the commented source
|
|
329
|
+
code:**
|
|
330
|
+
[`/zig/build.zig`](https://github.com/thi-ng/umbrella/blob/develop/packages/wasm-api/zig/build.zig)
|
|
331
|
+
|
|
332
|
+
## Naming & structural conventions
|
|
333
|
+
|
|
334
|
+
To avoid guesswork about the internals of any of the supplied WASM API modules,
|
|
335
|
+
please also consult the information in
|
|
336
|
+
[#368](https://github.com/thi-ng/umbrella/issues/368).
|
|
337
|
+
|
|
316
338
|
## Status
|
|
317
339
|
|
|
318
340
|
**ALPHA** - bleeding edge / work-in-progress
|
|
@@ -348,7 +370,7 @@ node --experimental-repl-await
|
|
|
348
370
|
> const wasmApi = await import("@thi.ng/wasm-api");
|
|
349
371
|
```
|
|
350
372
|
|
|
351
|
-
Package sizes (
|
|
373
|
+
Package sizes (brotli'd, pre-treeshake): ESM: 2.47 KB
|
|
352
374
|
|
|
353
375
|
## Dependencies
|
|
354
376
|
|
|
@@ -371,6 +393,7 @@ A selection:
|
|
|
371
393
|
| Screenshot | Description | Live demo | Source |
|
|
372
394
|
|:---------------------------------------------------------------------------------------------------------------------|:-------------------------------------------------------------------|:----------------------------------------------------|:---------------------------------------------------------------------------------|
|
|
373
395
|
| <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) |
|
|
396
|
+
| <img src="https://raw.githubusercontent.com/thi-ng/umbrella/develop/assets/examples/zig-cellular.jpg" width="240"/> | Zig-based 2D multi-behavior cellular automata | [Demo](https://demo.thi.ng/umbrella/zig-cellular/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/zig-cellular) |
|
|
374
397
|
| <img src="https://raw.githubusercontent.com/thi-ng/umbrella/develop/assets/examples/zig-counter.png" width="240"/> | Simple Zig/WASM click counter DOM component | [Demo](https://demo.thi.ng/umbrella/zig-counter/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/zig-counter) |
|
|
375
398
|
| <img src="https://raw.githubusercontent.com/thi-ng/umbrella/develop/assets/examples/zig-todo-list.png" width="240"/> | Zig-based To-Do list, DOM creation, local storage task persistence | [Demo](https://demo.thi.ng/umbrella/zig-todo-list/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/zig-todo-list) |
|
|
376
399
|
|
|
@@ -413,7 +436,7 @@ Requires [Zig](https://ziglang.org) to be installed:
|
|
|
413
436
|
|
|
414
437
|
/// import externals
|
|
415
438
|
/// see build command for configuration
|
|
416
|
-
const js = @import("
|
|
439
|
+
const js = @import("wasm-api");
|
|
417
440
|
|
|
418
441
|
export fn start() void {
|
|
419
442
|
js.printStr("hello world!");
|
|
@@ -427,7 +450,7 @@ folder):
|
|
|
427
450
|
```bash
|
|
428
451
|
# compile WASM binary
|
|
429
452
|
zig build-lib \
|
|
430
|
-
--pkg-begin
|
|
453
|
+
--pkg-begin wasm-api node_modules/@thi.ng/wasm-api/zig/lib.zig --pkg-end \
|
|
431
454
|
-target wasm32-freestanding \
|
|
432
455
|
-O ReleaseSmall -dynamic \
|
|
433
456
|
hello.zig
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@thi.ng/wasm-api",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.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",
|
|
@@ -35,17 +35,17 @@
|
|
|
35
35
|
"test:build-zig": "zig build-lib -O ReleaseSmall -target wasm32-freestanding -dynamic --strip --pkg-begin wasmapi zig/lib.zig --pkg-end test/custom.zig && wasm-dis -o custom.wast custom.wasm && cp custom.wasm test"
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@thi.ng/api": "^8.5.
|
|
39
|
-
"@thi.ng/arrays": "^2.4.
|
|
40
|
-
"@thi.ng/checks": "^3.3.
|
|
41
|
-
"@thi.ng/errors": "^2.2.
|
|
42
|
-
"@thi.ng/hex": "^2.3.
|
|
43
|
-
"@thi.ng/idgen": "^2.1.
|
|
44
|
-
"@thi.ng/logger": "^1.4.
|
|
38
|
+
"@thi.ng/api": "^8.5.1",
|
|
39
|
+
"@thi.ng/arrays": "^2.4.4",
|
|
40
|
+
"@thi.ng/checks": "^3.3.4",
|
|
41
|
+
"@thi.ng/errors": "^2.2.5",
|
|
42
|
+
"@thi.ng/hex": "^2.3.1",
|
|
43
|
+
"@thi.ng/idgen": "^2.1.20",
|
|
44
|
+
"@thi.ng/logger": "^1.4.4"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
47
|
"@microsoft/api-extractor": "^7.33.5",
|
|
48
|
-
"@thi.ng/testament": "^0.3.
|
|
48
|
+
"@thi.ng/testament": "^0.3.6",
|
|
49
49
|
"rimraf": "^3.0.2",
|
|
50
50
|
"tools": "^0.0.1",
|
|
51
51
|
"typedoc": "^0.23.20",
|
|
@@ -110,5 +110,5 @@
|
|
|
110
110
|
"status": "alpha",
|
|
111
111
|
"year": 2022
|
|
112
112
|
},
|
|
113
|
-
"gitHead": "
|
|
113
|
+
"gitHead": "199dcde33bf3d0b0bbd205d3b870dff43b735b22\n"
|
|
114
114
|
}
|
package/zig/build.zig
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
const std = @import("std");
|
|
2
|
+
|
|
3
|
+
/// Definition for a (usually hybrid) Zig package which will be distributed via NPM
|
|
4
|
+
pub const Pkg = struct {
|
|
5
|
+
/// Package ID used for @import
|
|
6
|
+
id: []const u8,
|
|
7
|
+
/// Package sub path (appended to base path)
|
|
8
|
+
path: []const u8,
|
|
9
|
+
/// Package dependencies aka other package IDs.
|
|
10
|
+
/// All of them must already have been registered
|
|
11
|
+
deps: ?[]const []const u8 = null,
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
pub const PkgOpts = struct {
|
|
15
|
+
/// Base path to common node_modules directory under which
|
|
16
|
+
/// all to be imported packages are located
|
|
17
|
+
base: []const u8 = "node_modules",
|
|
18
|
+
/// Additional WASM API support packages.
|
|
19
|
+
/// We don't need to specify core wasmapi, only custom/extra ones
|
|
20
|
+
/// `wasm-api` and `wasm-api-bindgen` are also auto-added
|
|
21
|
+
/// as dependency for each of these...
|
|
22
|
+
packages: ?[]const Pkg = null,
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
/// Dependency graph for WASM API packages
|
|
26
|
+
/// Expands & resolves the more compact/convenient/human friendly format of PkgOpts
|
|
27
|
+
/// into the data structures used by Zig's build system
|
|
28
|
+
/// Provides a `addAllTo()` function to add all declared packages to a build step
|
|
29
|
+
pub const PkgGraph = struct {
|
|
30
|
+
arena: std.heap.ArenaAllocator,
|
|
31
|
+
basePath: []const u8,
|
|
32
|
+
packages: std.StringArrayHashMap(std.build.Pkg),
|
|
33
|
+
|
|
34
|
+
const Self = @This();
|
|
35
|
+
|
|
36
|
+
pub fn init(opts: PkgOpts) Self {
|
|
37
|
+
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
|
|
38
|
+
var self = Self{
|
|
39
|
+
.arena = arena,
|
|
40
|
+
.basePath = opts.base,
|
|
41
|
+
.packages = std.StringArrayHashMap(std.build.Pkg).init(arena.allocator()),
|
|
42
|
+
};
|
|
43
|
+
const api = "wasm-api";
|
|
44
|
+
self.packages.put(api, .{
|
|
45
|
+
.name = api,
|
|
46
|
+
.source = .{ .path = self.modulePath("@thi.ng/wasm-api/zig/lib.zig") },
|
|
47
|
+
}) catch unreachable;
|
|
48
|
+
const apiTypes = "wasm-api-bindgen";
|
|
49
|
+
self.packages.put(apiTypes, .{
|
|
50
|
+
.name = apiTypes,
|
|
51
|
+
.source = .{ .path = self.modulePath("@thi.ng/wasm-api-bindgen/zig/lib.zig") },
|
|
52
|
+
}) catch unreachable;
|
|
53
|
+
if (opts.packages) |pkgs| {
|
|
54
|
+
for (pkgs) |pkg| {
|
|
55
|
+
self.register(pkg.id, pkg.path, pkg.deps);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return self;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
pub fn deinit(self: *const Self) void {
|
|
62
|
+
self.arena.deinit();
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/// Registers a single package and its deps (also injects core wasm-api deps)
|
|
66
|
+
pub fn register(
|
|
67
|
+
self: *Self,
|
|
68
|
+
name: []const u8,
|
|
69
|
+
path: []const u8,
|
|
70
|
+
dependencies: ?[]const []const u8,
|
|
71
|
+
) void {
|
|
72
|
+
var pkg = std.build.Pkg{
|
|
73
|
+
.name = name,
|
|
74
|
+
.source = .{ .path = self.modulePath(path) },
|
|
75
|
+
};
|
|
76
|
+
const num = if (dependencies) |deps| deps.len else 0;
|
|
77
|
+
var dpkgs = self.arena.allocator().alloc(std.build.Pkg, num + 2) catch unreachable;
|
|
78
|
+
dpkgs[0] = if (self.packages.get("wasm-api")) |p| p else unreachable;
|
|
79
|
+
dpkgs[1] = if (self.packages.get("wasm-api-bindgen")) |p| p else unreachable;
|
|
80
|
+
if (dependencies) |deps| {
|
|
81
|
+
var i: usize = 0;
|
|
82
|
+
while (i < deps.len) : (i += 1) {
|
|
83
|
+
if (self.packages.get(deps[i])) |p| {
|
|
84
|
+
dpkgs[i + 1] = p;
|
|
85
|
+
} else @panic("unknown dependency");
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
pkg.dependencies = dpkgs;
|
|
89
|
+
self.packages.put(name, pkg) catch unreachable;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/// Adds all registered packages to the given build step
|
|
93
|
+
pub fn addAllTo(self: *const Self, step: *std.build.LibExeObjStep) void {
|
|
94
|
+
for (self.packages.values()) |pkg| step.addPackage(pkg);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
fn modulePath(self: *Self, path: []const u8) []const u8 {
|
|
98
|
+
return std.fs.path.join(self.arena.allocator(), &.{ self.basePath, path }) catch unreachable;
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
/// Config options
|
|
103
|
+
pub const WasmLibOpts = struct {
|
|
104
|
+
/// Relative path to base directory for WASM API packages
|
|
105
|
+
base: []const u8 = "node_modules",
|
|
106
|
+
/// Relative path to root source file
|
|
107
|
+
root: []const u8 = "zig/main.zig",
|
|
108
|
+
/// Relative path to output directory
|
|
109
|
+
out: []const u8 = "src",
|
|
110
|
+
/// Package definitions for additional WASM API modules
|
|
111
|
+
packages: ?[]const Pkg = null,
|
|
112
|
+
/// Build mode override (else allows config via CLI args)
|
|
113
|
+
mode: ?std.builtin.Mode = null,
|
|
114
|
+
/// Additional WASM target features, e.g. `.simd128` to enable SIMD
|
|
115
|
+
features: ?[]const std.Target.wasm.Feature = null,
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
/// Creates and returns a build step to build a dynamic WASM library, configured
|
|
119
|
+
/// with given options and package declarations. The given package specs will be inserted
|
|
120
|
+
pub fn wasmLib(b: *std.build.Builder, opts: WasmLibOpts) *std.build.LibExeObjStep {
|
|
121
|
+
const lib = b.addSharedLibrary("main", opts.root, .unversioned);
|
|
122
|
+
lib.setTarget(.{
|
|
123
|
+
.cpu_arch = .wasm32,
|
|
124
|
+
.os_tag = .freestanding,
|
|
125
|
+
.cpu_features_add = if (opts.features) |features| std.Target.wasm.featureSet(features) else std.Target.Cpu.Feature.Set.empty,
|
|
126
|
+
});
|
|
127
|
+
const mode = if (opts.mode) |m| m else b.standardReleaseOptions();
|
|
128
|
+
lib.setBuildMode(mode);
|
|
129
|
+
if (mode == .ReleaseSmall or mode == .ReleaseFast) lib.strip = true;
|
|
130
|
+
const pkgs = PkgGraph.init(.{ .base = opts.base, .packages = opts.packages });
|
|
131
|
+
defer pkgs.deinit();
|
|
132
|
+
pkgs.addAllTo(lib);
|
|
133
|
+
lib.setOutputDir(opts.out);
|
|
134
|
+
return lib;
|
|
135
|
+
}
|