Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@thi.ng/wasm-api-bindgen

Package Overview
Dependencies
Maintainers
0
Versions
119
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@thi.ng/wasm-api-bindgen - npm Package Compare versions

Comparing version 0.5.13 to 0.6.0

20

api.d.ts

@@ -202,2 +202,20 @@ import type { BigType, FloatType, Fn, Fn2, IObjectOf, NumOrString } from "@thi.ng/api";

skip?: boolean;
/**
* If false, omits getter for languages which would usually define one (e.g.
* for TypeScript). Useful to avoid obsolete code and reduce file size.
*
* @defaultValue true
*/
getter?: boolean;
/**
* If false, omits setter for languages which would usually define one (e.g.
* for TypeScript). Useful to avoid obsolete code and reduce file size.
*
* @remarks
* If a field has its setter disabled, the generated TypeScript interface
* will declare this field as `readonly`.
*
* @defaultValue true
*/
setter?: boolean;
}

@@ -358,3 +376,5 @@ export interface Enum extends TopLevelType {

usize: "u32" | "u64";
bits: number;
sizeBytes: number;
shift: number;
}

@@ -361,0 +381,0 @@ /**

8

api.js

@@ -5,3 +5,5 @@ const PKG_NAME = "@thi.ng/wasm-api-bindgen";

usize: "u32",
sizeBytes: 4
bits: 32,
sizeBytes: 4,
shift: 2
};

@@ -11,3 +13,5 @@ const WASM64 = {

usize: "u64",
sizeBytes: 8
bits: 64,
sizeBytes: 8,
shift: 3
};

@@ -14,0 +18,0 @@ export {

# Change Log
- **Last updated**: 2024-08-10T15:03:07Z
- **Last updated**: 2024-08-18T14:11:34Z
- **Generator**: [thi.ng/monopub](https://thi.ng/monopub)

@@ -12,2 +12,21 @@

## [0.6.0](https://github.com/thi-ng/umbrella/tree/@thi.ng/wasm-api-bindgen@0.6.0) (2024-08-18)
#### 🚀 Features
- update TS codegen to produce more compact results ([ee5e283](https://github.com/thi-ng/umbrella/commit/ee5e283))
- update array & slice handling to re-use new helpers in [@thi.ng/wasm-api](https://github.com/thi-ng/umbrella/tree/main/packages/wasm-api)
- update test snapshots
- add getter/setter field flags ([6e87558](https://github.com/thi-ng/umbrella/commit/6e87558))
- update JSON schema
- update TS codegen to handle optional getters/setters
- add doc strings
#### 🩹 Bug fixes
- fix TS codegen address divisor for prim slices ([dfd66ba](https://github.com/thi-ng/umbrella/commit/dfd66ba))
- update __primSlice()
- address needs to be divided based on type size
- update test snapshots
### [0.5.5](https://github.com/thi-ng/umbrella/tree/@thi.ng/wasm-api-bindgen@0.5.5) (2024-06-21)

@@ -14,0 +33,0 @@

{
"name": "@thi.ng/wasm-api-bindgen",
"version": "0.5.13",
"version": "0.6.0",
"description": "Polyglot bindings code generators (TS/JS, Zig, C11) for hybrid WebAssembly projects",

@@ -41,15 +41,15 @@ "type": "module",

"dependencies": {
"@thi.ng/api": "^8.11.8",
"@thi.ng/args": "^2.3.41",
"@thi.ng/arrays": "^2.9.14",
"@thi.ng/binary": "^3.4.31",
"@thi.ng/checks": "^3.6.10",
"@thi.ng/compare": "^2.4.0",
"@thi.ng/defmulti": "^3.0.46",
"@thi.ng/errors": "^2.5.14",
"@thi.ng/file-io": "^2.1.10",
"@thi.ng/logger": "^3.0.18",
"@thi.ng/paths": "^5.1.88",
"@thi.ng/strings": "^3.8.3",
"@thi.ng/wasm-api": "^1.6.7"
"@thi.ng/api": "^8.11.9",
"@thi.ng/args": "^2.3.42",
"@thi.ng/arrays": "^2.10.0",
"@thi.ng/binary": "^3.4.32",
"@thi.ng/checks": "^3.6.11",
"@thi.ng/compare": "^2.4.1",
"@thi.ng/defmulti": "^3.0.47",
"@thi.ng/errors": "^2.5.15",
"@thi.ng/file-io": "^2.1.11",
"@thi.ng/logger": "^3.0.19",
"@thi.ng/paths": "^5.1.89",
"@thi.ng/strings": "^3.8.4",
"@thi.ng/wasm-api": "^2.0.0"
},

@@ -121,6 +121,11 @@ "devDependencies": {

"parent": "@thi.ng/wasm-api",
"status": "alpha",
"related": [
"wasm-api-canvas",
"wasm-api-dom",
"wasm-api-schedule",
"wasm-api-webgl"
],
"year": 2022
},
"gitHead": "e914ebbd81c56783c39cf746548c547cbacadc96\n"
"gitHead": "f6e26ea1142525171de5d36b9c3119f2782bb437\n"
}

@@ -10,3 +10,3 @@ <!-- This file is generated - DO NOT EDIT! -->

> [!NOTE]
> This is one of 198 standalone projects, maintained as part
> This is one of 199 standalone projects, maintained as part
> of the [@thi.ng/umbrella](https://github.com/thi-ng/umbrella/) monorepo

@@ -32,2 +32,3 @@ > and anti-framework.

- [Padding](#padding)
- [Omitting getters & setters](#omitting-getters--setters)
- [JSON schema for type definitions](#json-schema-for-type-definitions)

@@ -42,4 +43,6 @@ - [CLI generator](#cli-generator)

- [Status](#status)
- [Related packages](#related-packages)
- [Installation](#installation)
- [Dependencies](#dependencies)
- [Usage examples](#usage-examples)
- [API](#api)

@@ -303,2 +306,143 @@ - [Authors](#authors)

### Omitting getters & setters
Depending on the amount and size of the data structures defined, generated code
for JS/TS can grow quite quickly (even though since v0.6.0 the TS codegen has
been much more optimized and the resulting file sizes gone down noticeably).
One of the largest contributing factors to code size is the amount of field
getters and setters. However, in many use cases only getters, setters or neither
of them are required on the TS/JS side and omitting them where possible can lead
to drastic file size savings.
Use the `getter`, `setter` field options to control if relevant code should be
generated for a single field. E.g. If you only intend to read a field on the JS
side, we can omit generating its setter. In general, if a field has no setter
defined, the generated TypeScript interface will mark this field as `readonly`.
Furthermore, the `skip` option can be used to omit code generation of an entire
struct, union or enum for specific languages.
The following example illustrates these concepts:
```json tangle:export/readme-omit.json
[
{
"name": "TestOpts",
"type": "struct",
"doc": [
"Apart from the first field (`a`), all others in this struct ",
"will only be partially generated in TypeScript..."
],
"fields": [
{ "name": "a", "type": "i32" },
{ "name": "b", "type": "i32", "getter": false },
{ "name": "c", "type": "i32", "setter": false },
{ "name": "d", "type": "TestType", "getter": false, "setter": false }
]
},
{
"name": "TestType",
"type": "enum",
"doc": "This enum will not be generated at all for TypeScript",
"values": ["a", "b", "c"],
"skip": ["ts"]
}
]
```
<details><summary>Generated TypeScript source code</summary>
```ts
/**
* Generated by @thi.ng/wasm-api-bindgen at 2024-08-18T11:18:16.006Z
* DO NOT EDIT!
*/
// @ts-ignore possibly includes unused imports
import { Pointer, WasmStringPtr, type IWasmMemoryAccess, type MemorySlice, type MemoryView, type WasmType, type WasmTypeBase, type WasmTypeConstructor } from "@thi.ng/wasm-api";
// @ts-ignore
import { __array, __instanceArray, __slice32, __primslice32 } from "@thi.ng/wasm-api/memory";
/**
* Apart from the first field (`a`), all others in this struct
* will only be partially generated in TypeScript...
*/
export interface TestOpts extends WasmTypeBase {
/**
* Zig type: `i32`
*/
a: number;
/**
* Zig type: `i32`
*/
b: number;
/**
* Zig type: `i32`
*/
readonly c: number;
}
export const $TestOpts: WasmTypeConstructor<TestOpts> = (mem) => ({
get align() {
return 4;
},
get size() {
return 16;
},
instanceArray(base, num) {
return __instanceArray<TestOpts>(this, base, num);
},
instance: (base) => {
return {
get __base() {
return base;
},
get __bytes() {
return mem.u8.subarray(base, base + 16);
},
get a(): number {
return mem.i32[base >>> 2];
},
set a(x: number) {
mem.i32[base >>> 2] = x;
},
set b(x: number) {
mem.i32[(base + 4) >>> 2] = x;
},
get c(): number {
return mem.i32[(base + 8) >>> 2];
},
};
}
});
```
</details>
<details><summary>Generated Zig source code</summary>
```zig
//! Generated by @thi.ng/wasm-api-bindgen at 2024-08-18T11:18:12.197Z
//! DO NOT EDIT!
const std = @import("std");
const bindgen = @import("wasm-api-bindgen");
/// Apart from the first field (`a`), all others in this struct
/// will only be partially generated in TypeScript...
pub const TestOpts = extern struct {
a: i32,
b: i32,
c: i32,
d: TestType,
};
/// This enum will not be generated at all for TypeScript
pub const TestType = enum(i32) {
a,
b,
c,
};
```
</details>
## JSON schema for type definitions

@@ -336,3 +480,3 @@

██ █ │
█ █ █ █ █ █ █ █ │ @thi.ng/wasm-api-bindgen 0.1.0
█ █ █ █ █ █ █ █ │ @thi.ng/wasm-api-bindgen 0.6.0
█ █ █ █ █ █ █ █ █ │ Multi-language data bindings code generator

@@ -466,3 +610,3 @@ █ │

/**
* Generated by @thi.ng/wasm-api-bindgen at 2022-11-24T10:54:36.733Z
* Generated by @thi.ng/wasm-api-bindgen at 2024-08-18T11:20:15.332Z
* DO NOT EDIT!

@@ -472,3 +616,5 @@ */

// @ts-ignore possibly includes unused imports
import { MemorySlice, Pointer, WasmStringPtr, WasmTypeBase, WasmTypeConstructor } from "@thi.ng/wasm-api";
import { Pointer, WasmStringPtr, type IWasmMemoryAccess, type MemorySlice, type MemoryView, type WasmType, type WasmTypeBase, type WasmTypeConstructor } from "@thi.ng/wasm-api";
// @ts-ignore
import { __array, __instanceArray, __slice32, __primslice32 } from "@thi.ng/wasm-api/memory";

@@ -498,3 +644,3 @@ /**

*/
pos: Uint16Array;
readonly pos: Uint16Array;
}

@@ -509,2 +655,5 @@

},
instanceArray(base, num) {
return __instanceArray<MouseEvent>(this, base, num);
},
instance: (base) => {

@@ -540,3 +689,3 @@ return {

*/
key: WasmStringPtr;
readonly key: WasmStringPtr;
/**

@@ -558,2 +707,5 @@ * Bitmask of active modifier keys

},
instanceArray(base, num) {
return __instanceArray<KeyEvent>(this, base, num);
},
instance: (base) => {

@@ -599,2 +751,5 @@ let $key: WasmStringPtr | null = null;

},
instanceArray(base, num) {
return __instanceArray<Event>(this, base, num);
},
instance: (base) => {

@@ -631,3 +786,3 @@ return {

```zig
//! Generated by @thi.ng/wasm-api-bindgen at 2022-11-24T10:54:36.735Z
//! Generated by @thi.ng/wasm-api-bindgen at 2024-08-18T11:20:28.120Z
//! DO NOT EDIT!

@@ -727,10 +882,18 @@

value (mem copy). Currently, array, multi-pointers and slices do not provide
write access (from the JS side)...
write access (from the JS side). Also see [omitting
getters/setters](#omitting-getters--setters)...
## Status
**ALPHA** - bleeding edge / work-in-progress
**STABLE** - used in production
[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=%5Bwasm-api-bindgen%5D+in%3Atitle)
## Related packages
- [@thi.ng/wasm-api-canvas](https://github.com/thi-ng/umbrella/tree/develop/packages/wasm-api-canvas) - HTML Canvas2D bridge API for hybrid TypeScript & WASM (Zig) applications
- [@thi.ng/wasm-api-dom](https://github.com/thi-ng/umbrella/tree/develop/packages/wasm-api-dom) - Browser DOM bridge API for hybrid TypeScript & WASM (Zig) applications
- [@thi.ng/wasm-api-schedule](https://github.com/thi-ng/umbrella/tree/develop/packages/wasm-api-schedule) - Delayed & scheduled function execution (via setTimeout() etc.) for hybrid WASM apps
- [@thi.ng/wasm-api-webgl](https://github.com/thi-ng/umbrella/tree/develop/packages/wasm-api-webgl) - WebGL bridge API for hybrid TypeScript & WASM (Zig) applications
## Installation

@@ -762,3 +925,3 @@

Package sizes (brotli'd, pre-treeshake): ESM: 6.01 KB
Package sizes (brotli'd, pre-treeshake): ESM: 6.07 KB

@@ -783,2 +946,12 @@ ## Dependencies

## Usage examples
One project in this repo's
[/examples](https://github.com/thi-ng/umbrella/tree/develop/examples)
directory is using this package:
| Screenshot | Description | Live demo | Source |
|:---------------------------------------------------------------------------------------------------------------------|:-------------------------------------------------------------------|:----------------------------------------------------|:---------------------------------------------------------------------------------|
| <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) |
## API

@@ -785,0 +958,0 @@

@@ -204,2 +204,12 @@ {

"description": "If true, code generation of this field will be skipped for WASM host environment languages (e.g. TypeScript)"
},
"getter": {
"type": "boolean",
"default": true,
"description": "If false, omits getter for languages which would usually define one (e.g. TypeScript)"
},
"setter": {
"type": "boolean",
"default": true,
"description": "If false, omits setter for languages which would usually define one (e.g. TypeScript)"
}

@@ -206,0 +216,0 @@ },

@@ -31,3 +31,3 @@ import {

id: "ts",
pre: (_, globalOpts) => {
pre: (coll, globalOpts) => {
const res = [

@@ -37,4 +37,13 @@ "// @ts-ignore possibly includes unused imports",

globalOpts
)}, type MemorySlice, type WasmTypeBase, type WasmTypeConstructor } from "@thi.ng/wasm-api";`
)}, type IWasmMemoryAccess, type MemorySlice, type MemoryView, type WasmType, type WasmTypeBase, type WasmTypeConstructor } from "@thi.ng/wasm-api";`
];
if (Object.values(coll).some(
(t) => t.type === "struct" || t.type === "union"
)) {
const bits = globalOpts.target.bits;
res.push(
"// @ts-ignore",
`import { __array, __instanceArray, __slice${bits}, __primslice${bits} } from "@thi.ng/wasm-api/memory";`
);
}
if (opts.pre) res.push("", ...ensureStringArray(opts.pre));

@@ -66,3 +75,3 @@ return res.join("\n");

const strType = __stringImpl(opts2);
const fields = struct.fields.map((f) => __generateField(f, coll, opts2)).filter((f) => !!f);
const fields = struct.fields.map((f) => __generateField(f, coll, opts2)).filter((f) => !!f && (f.getter || f.setter));
const lines = [];

@@ -75,3 +84,4 @@ lines.push(

doc && gen.doc(doc, lines, opts2);
lines.push(`${f.field.name}: ${f.type};`);
const decl = `${f.field.name}: ${f.type};`;
lines.push((!f.setter ? `readonly ` : "") + decl);
}

@@ -95,5 +105,3 @@ injectBody(lines, struct.body?.ts, "decl");

`instanceArray(base, num) {`,
`const items: ${struct.name}[] = [];`,
`for (; num --> 0; base += ${struct.__size}) items.push(this.instance(base));`,
`return items;`,
`return __instanceArray<${struct.name}>(this, base, num);`,
`},`,

@@ -113,7 +121,9 @@ `instance: (base) => {`,

if (!f) continue;
lines.push(
`get ${f.field.name}(): ${f.type} {`,
...f.getter,
"},"
);
if (f.getter) {
lines.push(
`get ${f.field.name}(): ${f.type} {`,
...f.getter,
"},"
);
}
if (f.setter) {

@@ -154,8 +164,2 @@ lines.push(

const __mem = (type, offset) => `mem.${type}[${__addrShift(offset, type)}]`;
const __mapArray = (f, coll, len = "len") => [
`const inst = $${f.type}(mem);`,
`const buf: ${f.type}[] = [];`,
`for(let i = 0; i < ${len}; i++) buf.push(inst.instance(addr + i * ${coll[f.type].__size}));`,
`return buf;`
];
const __mapStringArray = (target, name, type, len, isConst, isLocal = false) => [

@@ -166,6 +170,2 @@ isLocal ? `const $${name}: ${type}[] = [];` : `$${name} = [];`,

];
const __primSlice = (type, _, __) => [
// `const addr = ${__ptrShift(opts.target, offset, type)};`,
`return mem.${type}.subarray(addr, addr + len);`
];
const __primArray = (type, len, offset) => [

@@ -205,3 +205,3 @@ `const addr = ${__addrShift(offset, type)};`,

let decl;
let getter = [];
let getter;
let setter;

@@ -304,5 +304,3 @@ let ptrType;

getter = __ptrBody(ptrType, name, offset, [
`(addr) => {`,
...__mapArray(field, coll, field.len),
"}"
`(addr) => __array(mem, $${field.type}, addr, ${field.len})`
]);

@@ -327,4 +325,3 @@ }

getter = [
`const addr = ${__addr(offset)};`,
...__mapArray(field, coll, field.len)
`return __array(mem, $${field.type}, ${__addr(offset)}, ${field.len});`
];

@@ -340,19 +337,18 @@ }

case "enumSlice":
getter = [
`const addr = ${__ptr(opts.target, offset)};`,
`const len = ${__ptr(
opts.target,
offset + opts.target.sizeBytes
)};`
];
if (isPrim) {
getter.push(...__primSlice(type, offset, opts));
getter = [
`return __primslice${opts.target.bits}(mem, mem.${type}, ${__addr(offset)}, ${__shift(type)});`
];
type = __arrayType(type);
} else if ($isEnum) {
tag = coll[type].tag;
getter.push(...__primSlice(tag, offset, opts));
getter = [
`return __primslice${opts.target.bits}(mem, mem.${tag}, ${__addr(offset)}, ${__shift(tag)});`
];
type = __arrayType(tag);
} else {
type += "[]";
getter.push(...__mapArray(field, coll));
getter = [
`return __slice${opts.target.bits}(mem, $${field.type}, ${__addr(offset)});`
];
}

@@ -387,3 +383,9 @@ break;

}
return { field, type, decl, getter, setter };
return {
field,
type,
decl,
getter: field.getter !== false ? getter : void 0,
setter: field.setter !== false ? setter : void 0
};
};

@@ -390,0 +392,0 @@ export {

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc