@thi.ng/wasm-api 1.5.3 → 1.6.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 CHANGED
@@ -1,6 +1,6 @@
1
1
  # Change Log
2
2
 
3
- - **Last updated**: 2024-04-25T19:44:55Z
3
+ - **Last updated**: 2024-06-21T19:34:38Z
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.6.0](https://github.com/thi-ng/umbrella/tree/@thi.ng/wasm-api@1.6.0) (2024-06-21)
13
+
14
+ #### 🚀 Features
15
+
16
+ - update build script & readme for Zig v0.13.0 ([cd401b2](https://github.com/thi-ng/umbrella/commit/cd401b2))
17
+
12
18
  ## [1.5.0](https://github.com/thi-ng/umbrella/tree/@thi.ng/wasm-api@1.5.0) (2024-04-22)
13
19
 
14
20
  #### 🚀 Features
package/README.md CHANGED
@@ -7,7 +7,7 @@
7
7
  [![Mastodon Follow](https://img.shields.io/mastodon/follow/109331703950160316?domain=https%3A%2F%2Fmastodon.thi.ng&style=social)](https://mastodon.thi.ng/@toxi)
8
8
 
9
9
  > [!NOTE]
10
- > This is one of 192 standalone projects, maintained as part
10
+ > This is one of 193 standalone projects, maintained as part
11
11
  > of the [@thi.ng/umbrella](https://github.com/thi-ng/umbrella/) monorepo
12
12
  > and anti-framework.
13
13
  >
@@ -21,7 +21,7 @@
21
21
  - [API module auto-initialization](#api-module-auto-initialization)
22
22
  - [Object indices & handles](#object-indices--handles)
23
23
  - [Using the Zig build system](#using-the-zig-build-system)
24
- - [Zig v0.12 or newer](#zig-v012-or-newer)
24
+ - [Zig v0.13 or newer](#zig-v013-or-newer)
25
25
  - [Example projects](#example-projects)
26
26
  - [Naming & structural conventions](#naming--structural-conventions)
27
27
  - [Status](#status)
@@ -40,6 +40,12 @@
40
40
 
41
41
  Generic, modular, extensible API bridge and infrastructure for hybrid JS & WebAssembly projects.
42
42
 
43
+ | Quasiflock | Danza | S-TRACE | Voxelscape |
44
+ |---------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------|
45
+ | <a href="https://www.fxhash.xyz/generative/6671"><img src="https://github.com/thi-ng/umbrella/raw/develop/assets/fxhash/quasiflock-240.jpg"/></a> | <a href="https://mastodon.thi.ng/@toxi/tagged/DANZA"><img src="https://github.com/thi-ng/umbrella/raw/develop/assets/fxhash/danza-240.jpg"/></a> | <a href="https://mastodon.thi.ng/@toxi/tagged/STRACE"><img src="https://github.com/thi-ng/umbrella/raw/develop/assets/fxhash/s-trace-240.jpg"/></a> | <a href="https://twitter.com/search?q=from%3A%40toxi+voxel+ziglang"><img src="https://github.com/thi-ng/umbrella/raw/develop/assets/fxhash/voxelscape-240.jpg"/></a> |
46
+
47
+ (Screenshots of selected projects made with Zig & TypeScript using the interop features provided by this package. Images link to respective project info)
48
+
43
49
  This package provides the following:
44
50
 
45
51
  1. A small
@@ -315,12 +321,14 @@ This package provides utilities to simplify using hybrid TS/Zig WASM API modules
315
321
  which are distributed as NPM packages. Using these utils, a build file for Zig's
316
322
  built-in build system is as simple as:
317
323
 
318
- ### Zig v0.12 or newer
324
+ ### Zig v0.13 or newer
319
325
 
320
- **IMPORTANT:** Due to recent [syntax & build system changes in Zig
321
- v0.12.0](https://ziglang.org/download/0.12.0/release-notes.html), older Zig
322
- versions are not actively unsupported (however build files for v0.10 and v0.11
323
- are still included)
326
+ **IMPORTANT:** Due to recent syntax & build system changes in Zig
327
+ [v0.12.0](https://ziglang.org/download/0.12.0/release-notes.html) &
328
+ [v0.13.0](https://ziglang.org/download/0.13.0/release-notes.html), older Zig
329
+ versions are not actively supported (however, [build files for older versions
330
+ are still
331
+ included](https://github.com/thi-ng/umbrella/blob/develop/packages/wasm-api/zig))
324
332
 
325
333
  ```zig
326
334
  const std = @import("std");
package/bridge.d.ts CHANGED
@@ -1,4 +1,3 @@
1
- /// <reference types="node" />
2
1
  import type { Event, INotify, IObjectOf, Listener, NumericArray } from "@thi.ng/api";
3
2
  import type { ILogger } from "@thi.ng/logger";
4
3
  import { type BigIntArray, type BridgeEventType, type CoreAPI, type IWasmAPI, type IWasmMemoryAccess, type MemorySlice, type WasmExports } from "./api.js";
@@ -7,10 +6,10 @@ export declare const Panic: {
7
6
  origMessage: string;
8
7
  name: string;
9
8
  message: string;
10
- stack?: string | undefined;
9
+ stack?: string;
11
10
  cause?: unknown;
12
11
  };
13
- captureStackTrace(targetObject: object, constructorOpt?: Function | undefined): void;
12
+ captureStackTrace(targetObject: object, constructorOpt?: Function): void;
14
13
  prepareStackTrace?: ((err: Error, stackTraces: NodeJS.CallSite[]) => any) | undefined;
15
14
  stackTraceLimit: number;
16
15
  };
@@ -19,10 +18,10 @@ export declare const OutOfMemoryError: {
19
18
  origMessage: string;
20
19
  name: string;
21
20
  message: string;
22
- stack?: string | undefined;
21
+ stack?: string;
23
22
  cause?: unknown;
24
23
  };
25
- captureStackTrace(targetObject: object, constructorOpt?: Function | undefined): void;
24
+ captureStackTrace(targetObject: object, constructorOpt?: Function): void;
26
25
  prepareStackTrace?: ((err: Error, stackTraces: NodeJS.CallSite[]) => any) | undefined;
27
26
  stackTraceLimit: number;
28
27
  };
package/bridge.js CHANGED
@@ -5,8 +5,7 @@ var __decorateClass = (decorators, target, key, kind) => {
5
5
  for (var i = decorators.length - 1, decorator; i >= 0; i--)
6
6
  if (decorator = decorators[i])
7
7
  result = (kind ? decorator(target, key, result) : decorator(result)) || result;
8
- if (kind && result)
9
- __defProp(target, key, result);
8
+ if (kind && result) __defProp(target, key, result);
10
9
  return result;
11
10
  };
12
11
  import { INotifyMixin } from "@thi.ng/api/mixins/inotify";
@@ -138,8 +137,7 @@ let WasmBridge = class {
138
137
  assert(!!this.modules[id], `missing API module: ${id}`);
139
138
  this.logger.debug(`initializing API module: ${id}`);
140
139
  const status = await this.modules[id].init(this);
141
- if (!status)
142
- return false;
140
+ if (!status) return false;
143
141
  }
144
142
  this.notify({ id: EVENT_MEMORY_CHANGED, value: this.exports.memory });
145
143
  return true;
@@ -155,8 +153,7 @@ let WasmBridge = class {
155
153
  */
156
154
  ensureMemory(notify = true) {
157
155
  const buf = this.exports.memory.buffer;
158
- if (this.u8 && this.u8.buffer === buf)
159
- return;
156
+ if (this.u8 && this.u8.buffer === buf) return;
160
157
  this.i8 = new Int8Array(buf);
161
158
  this.u8 = new Uint8Array(buf);
162
159
  this.i16 = new Int16Array(buf);
package/object-index.js CHANGED
@@ -70,8 +70,7 @@ class ObjectIndex {
70
70
  */
71
71
  find(pred, ensure = true) {
72
72
  for (let id of this.idgen) {
73
- if (pred(this.items[id]))
74
- return id;
73
+ if (pred(this.items[id])) return id;
75
74
  }
76
75
  assert(!ensure, `given predicate matched no ${this.name}`);
77
76
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thi.ng/wasm-api",
3
- "version": "1.5.3",
3
+ "version": "1.6.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",
@@ -10,7 +10,7 @@
10
10
  "type": "git",
11
11
  "url": "https://github.com/thi-ng/umbrella.git"
12
12
  },
13
- "homepage": "https://github.com/thi-ng/umbrella/tree/develop/packages/wasm-api#readme",
13
+ "homepage": "https://thi.ng/wasm-api",
14
14
  "funding": [
15
15
  {
16
16
  "type": "github",
@@ -32,24 +32,24 @@
32
32
  "doc:ae": "mkdir -p .ae/doc .ae/temp && api-extractor run --local --verbose",
33
33
  "doc:readme": "bun ../../tools/src/module-stats.ts && bun ../../tools/src/readme.ts",
34
34
  "pub": "yarn npm publish --access public",
35
- "test": "zig test zig/managed-index.zig && bun test",
35
+ "test": "zig test zig/tests.zig && bun test",
36
36
  "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",
37
37
  "tool:tangle": "../../node_modules/.bin/tangle src/**/*.ts"
38
38
  },
39
39
  "dependencies": {
40
- "@thi.ng/api": "^8.11.1",
41
- "@thi.ng/arrays": "^2.9.5",
42
- "@thi.ng/checks": "^3.6.3",
43
- "@thi.ng/errors": "^2.5.6",
44
- "@thi.ng/hex": "^2.3.45",
45
- "@thi.ng/idgen": "^2.2.40",
46
- "@thi.ng/logger": "^3.0.11"
40
+ "@thi.ng/api": "^8.11.3",
41
+ "@thi.ng/arrays": "^2.9.7",
42
+ "@thi.ng/checks": "^3.6.5",
43
+ "@thi.ng/errors": "^2.5.8",
44
+ "@thi.ng/hex": "^2.3.47",
45
+ "@thi.ng/idgen": "^2.2.42",
46
+ "@thi.ng/logger": "^3.0.13"
47
47
  },
48
48
  "devDependencies": {
49
- "@microsoft/api-extractor": "^7.43.0",
50
- "esbuild": "^0.20.2",
51
- "typedoc": "^0.25.12",
52
- "typescript": "^5.4.3"
49
+ "@microsoft/api-extractor": "^7.47.0",
50
+ "esbuild": "^0.21.5",
51
+ "typedoc": "^0.25.13",
52
+ "typescript": "^5.5.2"
53
53
  },
54
54
  "keywords": [
55
55
  "allocator",
@@ -115,5 +115,5 @@
115
115
  "status": "alpha",
116
116
  "year": 2022
117
117
  },
118
- "gitHead": "aed3421c21044c005fbcb7cc37965ccf85a870d2\n"
118
+ "gitHead": "154c95cf9d6bab32174498ec3b5b5d87e42be7f9\n"
119
119
  }
package/string.js CHANGED
@@ -50,8 +50,7 @@ class WasmStringSlice {
50
50
  set(str) {
51
51
  this.mem.ensureMemory();
52
52
  if (typeof str === "string") {
53
- if (this.isConst)
54
- unsupported("can't mutate const string");
53
+ if (this.isConst) unsupported("can't mutate const string");
55
54
  this.mem.u32[this.base + 4 >>> 2] = this.mem.setString(
56
55
  str,
57
56
  this.addr,
@@ -158,8 +157,7 @@ class WasmStringPtr {
158
157
  set(str) {
159
158
  const addr = this.addr;
160
159
  if (typeof str === "string") {
161
- if (this.isConst)
162
- unsupported("can't mutate const string");
160
+ if (this.isConst) unsupported("can't mutate const string");
163
161
  this.mem.ensureMemory();
164
162
  this.mem.setString(str, addr, this.mem.u8.byteLength - addr, true);
165
163
  } else {
File without changes
@@ -0,0 +1,2 @@
1
+ pub const packages = struct {};
2
+ pub const root_deps: []const struct { []const u8, []const u8 } = &.{};
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -0,0 +1,130 @@
1
+ //! Build helpers for using modules/packages distributed via NPM
2
+ //! Intended for use with https://thi.ng/wasm-api and support packages
3
+ //!
4
+ //! This version of the script is only compatible with:
5
+ //! Zig v0.12.0
6
+ //!
7
+ //! Use other build.zig files in this same directory for older Zig versions
8
+
9
+ const std = @import("std");
10
+ const Build = std.Build;
11
+
12
+ /// Config options
13
+ pub const WasmLibOpts = struct {
14
+ /// Base path to common node_modules directory under which
15
+ /// all to be imported modules are located
16
+ base: []const u8 = "node_modules",
17
+ /// Relative path to root source file
18
+ root: []const u8 = "zig/main.zig",
19
+ /// Additional WASM API support modules.
20
+ /// Only need to specify custom/extra modules
21
+ /// `wasm-api` and `wasm-api-bindgen` are auto-added as dependency for all...
22
+ modules: ?[]const ModuleSpec = null,
23
+ /// Build mode override (else allows config via CLI args)
24
+ optimize: ?std.builtin.Mode = null,
25
+ /// Additional WASM target features, e.g. `.simd128` to enable SIMD
26
+ features: ?[]const std.Target.wasm.Feature = null,
27
+ /// Initial memory (in bytes, MUST be multiple of 0x10000)
28
+ initialMemory: ?u64 = null,
29
+ /// Max memory (in bytes, MUST be multiple of 0x10000)
30
+ maxMemory: ?u64 = null,
31
+ // If true, build will also generate docs
32
+ // docs: bool = false,
33
+ };
34
+
35
+ /// WASM API sub-module declaration
36
+ pub const ModuleSpec = struct {
37
+ /// module import name/ID
38
+ name: []const u8,
39
+ /// Relative path to configured base path
40
+ path: []const u8,
41
+ /// Module IDs of other modules this module depends on
42
+ /// Only need to specify custom/extra modules
43
+ /// `wasm-api` and `wasm-api-bindgen` are auto-added as dependency for all...
44
+ dependencies: ?[]const []const u8 = null,
45
+ };
46
+
47
+ const wasmapi = "wasm-api";
48
+ const wasmbind = "wasm-api-bindgen";
49
+
50
+ /// Creates and returns a build step to build a dynamic WASM library, configured
51
+ /// with given options and package declarations. The given package specs will be inserted
52
+ pub fn wasmLib(b: *Build, opts: WasmLibOpts) *Build.Step.Compile {
53
+ const optimize = if (opts.optimize) |m| m else b.standardOptimizeOption(.{});
54
+ const lib = b.addExecutable(.{
55
+ .name = "main",
56
+ .root_source_file = .{ .path = opts.root },
57
+ .target = b.resolveTargetQuery(
58
+ .{
59
+ .cpu_arch = .wasm32,
60
+ .os_tag = .freestanding,
61
+ .cpu_features_add = if (opts.features) |features| std.Target.wasm.featureSet(features) else std.Target.Cpu.Feature.Set.empty,
62
+ },
63
+ ),
64
+ .optimize = optimize,
65
+ .strip = (optimize == .ReleaseSmall or optimize == .ReleaseFast),
66
+ });
67
+
68
+ // build flags
69
+ // https://github.com/ziglang/zig/pull/17815
70
+ lib.entry = .disabled;
71
+ lib.rdynamic = true;
72
+ lib.import_symbols = true;
73
+ lib.initial_memory = opts.initialMemory;
74
+ lib.max_memory = opts.maxMemory;
75
+
76
+ // add default dependencies
77
+ // https://ziggit.dev/t/what-happened-to-addmodule/2908/3
78
+ _ = lib.root_module.addImport(
79
+ wasmapi,
80
+ b.createModule(.{
81
+ .root_source_file = modulePath(b.allocator, opts.base, "@thi.ng/wasm-api/zig/lib.zig"),
82
+ }),
83
+ );
84
+ _ = lib.root_module.addImport(
85
+ wasmbind,
86
+ b.createModule(.{
87
+ .root_source_file = modulePath(b.allocator, opts.base, "@thi.ng/wasm-api-bindgen/zig/lib.zig"),
88
+ }),
89
+ );
90
+ if (opts.modules) |modules| {
91
+ for (modules) |mod| register(lib, mod, opts);
92
+ }
93
+ return lib;
94
+ }
95
+
96
+ /// Registers a single package and its deps (also injects core wasm-api deps)
97
+ pub fn register(lib: *Build.Step.Compile, mod: ModuleSpec, opts: WasmLibOpts) void {
98
+ const num = if (mod.dependencies) |ids| ids.len else 0;
99
+ var dpkgs = lib.step.owner.allocator.alloc(Build.Module.Import, num + 2) catch unreachable;
100
+ dpkgs[0] = if (lib.root_module.import_table.get(wasmapi)) |m| .{ .name = wasmapi, .module = m } else unreachable;
101
+ dpkgs[1] = if (lib.root_module.import_table.get(wasmbind)) |m| .{ .name = wasmbind, .module = m } else unreachable;
102
+ var i: usize = 2;
103
+ if (mod.dependencies) |ids| {
104
+ for (ids) |id| {
105
+ if (lib.root_module.import_table.get(id)) |m| {
106
+ if (isDuplicateId(dpkgs[0..i], id)) {
107
+ std.log.info("ignoring duplicate dependency: {s}", .{id});
108
+ continue;
109
+ }
110
+ dpkgs[i] = .{ .name = id, .module = m };
111
+ i += 1;
112
+ } else @panic("unknown dependency");
113
+ }
114
+ }
115
+ _ = lib.root_module.addImport(mod.name, lib.step.owner.createModule(.{
116
+ .root_source_file = modulePath(lib.step.owner.allocator, opts.base, mod.path),
117
+ .imports = dpkgs[0..i],
118
+ }));
119
+ }
120
+
121
+ fn isDuplicateId(deps: []Build.Module.Import, name: []const u8) bool {
122
+ for (deps) |d| {
123
+ if (std.mem.eql(u8, d.name, name)) return true;
124
+ }
125
+ return false;
126
+ }
127
+
128
+ fn modulePath(allocator: std.mem.Allocator, base: []const u8, path: []const u8) Build.LazyPath {
129
+ return .{ .path = std.fs.path.join(allocator, &.{ base, path }) catch unreachable };
130
+ }
package/zig/build.zig CHANGED
@@ -2,7 +2,7 @@
2
2
  //! Intended for use with https://thi.ng/wasm-api and support packages
3
3
  //!
4
4
  //! This version of the script is only compatible with:
5
- //! Zig v0.12.0 or newer
5
+ //! Zig v0.13.0
6
6
  //!
7
7
  //! Use other build.zig files in this same directory for older Zig versions
8
8
 
@@ -53,7 +53,7 @@ pub fn wasmLib(b: *Build, opts: WasmLibOpts) *Build.Step.Compile {
53
53
  const optimize = if (opts.optimize) |m| m else b.standardOptimizeOption(.{});
54
54
  const lib = b.addExecutable(.{
55
55
  .name = "main",
56
- .root_source_file = .{ .path = opts.root },
56
+ .root_source_file = b.path(opts.root),
57
57
  .target = b.resolveTargetQuery(
58
58
  .{
59
59
  .cpu_arch = .wasm32,
@@ -78,13 +78,13 @@ pub fn wasmLib(b: *Build, opts: WasmLibOpts) *Build.Step.Compile {
78
78
  _ = lib.root_module.addImport(
79
79
  wasmapi,
80
80
  b.createModule(.{
81
- .root_source_file = modulePath(b.allocator, opts.base, "@thi.ng/wasm-api/zig/lib.zig"),
81
+ .root_source_file = b.path(modulePath(b.allocator, opts.base, "@thi.ng/wasm-api/zig/lib.zig")),
82
82
  }),
83
83
  );
84
84
  _ = lib.root_module.addImport(
85
85
  wasmbind,
86
86
  b.createModule(.{
87
- .root_source_file = modulePath(b.allocator, opts.base, "@thi.ng/wasm-api-bindgen/zig/lib.zig"),
87
+ .root_source_file = b.path(modulePath(b.allocator, opts.base, "@thi.ng/wasm-api-bindgen/zig/lib.zig")),
88
88
  }),
89
89
  );
90
90
  if (opts.modules) |modules| {
@@ -113,7 +113,7 @@ pub fn register(lib: *Build.Step.Compile, mod: ModuleSpec, opts: WasmLibOpts) vo
113
113
  }
114
114
  }
115
115
  _ = lib.root_module.addImport(mod.name, lib.step.owner.createModule(.{
116
- .root_source_file = modulePath(lib.step.owner.allocator, opts.base, mod.path),
116
+ .root_source_file = lib.step.owner.path(modulePath(lib.step.owner.allocator, opts.base, mod.path)),
117
117
  .imports = dpkgs[0..i],
118
118
  }));
119
119
  }
@@ -125,6 +125,6 @@ fn isDuplicateId(deps: []Build.Module.Import, name: []const u8) bool {
125
125
  return false;
126
126
  }
127
127
 
128
- fn modulePath(allocator: std.mem.Allocator, base: []const u8, path: []const u8) Build.LazyPath {
129
- return .{ .path = std.fs.path.join(allocator, &.{ base, path }) catch unreachable };
128
+ fn modulePath(allocator: std.mem.Allocator, base: []const u8, path: []const u8) []u8 {
129
+ return std.fs.path.join(allocator, &.{ base, path }) catch unreachable;
130
130
  }
package/zig/tests.zig ADDED
@@ -0,0 +1,4 @@
1
+ test {
2
+ _ = @import("managed-index.zig");
3
+ _ = @import("lib.zig");
4
+ }
File without changes