@wasmgroundup/emit 2.0.0 → 2.1.1

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/README.md CHANGED
@@ -10,6 +10,36 @@ A JavaScript library to emit WebAssembly 1.0 binary modules.
10
10
  npm i @wasmgroundup/emit
11
11
  ```
12
12
 
13
+ ## Example
14
+
15
+ Build a WebAssembly module with an exported `add` function:
16
+
17
+ ```typescript
18
+ import * as w from "@wasmgroundup/emit";
19
+
20
+ const mod = w.module([
21
+ w.typesec([w.functype([w.valtype.i32, w.valtype.i32], [w.valtype.i32])]),
22
+ w.funcsec([w.typeidx(0)]),
23
+ w.exportsec([w.export_("add", w.exportdesc.func(w.funcidx(0)))]),
24
+ w.codesec([
25
+ w.code(
26
+ w.func(
27
+ [],
28
+ w.expr([
29
+ [w.instr.local.get, ...w.i32(0)],
30
+ [w.instr.local.get, ...w.i32(1)],
31
+ w.instr.i32.add,
32
+ ]),
33
+ ),
34
+ ),
35
+ ]),
36
+ ]);
37
+
38
+ const { instance } = await WebAssembly.instantiate(w.flatten(mod));
39
+ const { add } = instance.exports as { add: (a: number, b: number) => number };
40
+ console.log(add(1, 2)); // 3
41
+ ```
42
+
13
43
  ## Features
14
44
 
15
45
  - Simple API following the [spec](https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/)'s naming conventions
package/index.d.ts CHANGED
@@ -92,7 +92,7 @@ export function code(func: Fragment): Fragment;
92
92
 
93
93
  export function func(locals: readonly Fragment[], body: Fragment): Fragment;
94
94
 
95
- export function expr(instrs: readonly Fragment[]): Fragment;
95
+ export function expr(instrs: Fragment): Fragment;
96
96
 
97
97
  export function codesec(codes: readonly Fragment[]): Fragment;
98
98
 
@@ -292,6 +292,8 @@ export const instr: {
292
292
 
293
293
  export const blocktype: {readonly empty: 0x40} & typeof valtype;
294
294
 
295
+ export type blocktype = typeof blocktype.empty | valtype | Fragment;
296
+
295
297
  // Export section
296
298
  // --------------
297
299
 
@@ -315,6 +317,8 @@ export type WasmModule = Fragment;
315
317
 
316
318
  export function module(sections: readonly Fragment[]): WasmModule;
317
319
 
320
+ export function flatten(fragment: Fragment): Uint8Array<ArrayBuffer>;
321
+
318
322
  // Locals
319
323
  // ------
320
324
 
package/index.js CHANGED
@@ -1,5 +1,26 @@
1
1
  // WebAssembly 1.0 Module Builder
2
2
  // https://wasmgroundup.com/
3
+
4
+ function byteLength(fragment) {
5
+ let n = 0;
6
+ for (const item of fragment) {
7
+ if (Array.isArray(item)) n += byteLength(item);
8
+ else n += 1;
9
+ }
10
+ return n;
11
+ }
12
+
13
+ function writeInto(fragment, out, offset) {
14
+ for (const item of fragment) {
15
+ if (Array.isArray(item)) {
16
+ offset = writeInto(item, out, offset);
17
+ } else {
18
+ out[offset++] = item;
19
+ }
20
+ }
21
+ return offset;
22
+ }
23
+
3
24
  export function stringToBytes(s) {
4
25
  const bytes = new TextEncoder().encode(s);
5
26
  return Array.from(bytes);
@@ -86,7 +107,7 @@ export function i32(v) {
86
107
  }
87
108
 
88
109
  export function section(id, contents) {
89
- const sizeInBytes = contents.flat(Infinity).length;
110
+ const sizeInBytes = byteLength(contents);
90
111
  return [id, u32(sizeInBytes), contents];
91
112
  }
92
113
 
@@ -115,7 +136,7 @@ export function funcsec(typeidxs) {
115
136
  export const SECTION_ID_CODE = 10;
116
137
 
117
138
  export function code(func) {
118
- const sizeInBytes = func.flat(Infinity).length;
139
+ const sizeInBytes = byteLength(func);
119
140
  return [u32(sizeInBytes), func];
120
141
  }
121
142
 
@@ -160,6 +181,12 @@ export const exportdesc = {
160
181
  export function module(sections) {
161
182
  return [magic(), version(), sections];
162
183
  }
184
+
185
+ export function flatten(fragment) {
186
+ const out = new Uint8Array(byteLength(fragment));
187
+ writeInto(fragment, out, 0);
188
+ return out;
189
+ }
163
190
  export const valtype = {
164
191
  i32: 0x7f,
165
192
  i64: 0x7e,
@@ -321,9 +348,8 @@ export function funcnamesubsec(namemap) {
321
348
 
322
349
  // N:byte
323
350
  export function namesubsection(N, B) {
324
- const flatB = B.flat(Infinity);
325
- const size = u32(flatB.length);
326
- return [N, size, flatB];
351
+ const size = u32(byteLength(B));
352
+ return [N, size, B];
327
353
  }
328
354
 
329
355
  export function namemap(nameassocs) {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@wasmgroundup/emit",
3
3
  "description": "A library for creating binary-encoded WebAssembly modules",
4
- "version": "2.0.0",
4
+ "version": "2.1.1",
5
5
  "type": "module",
6
6
  "main": "index.js",
7
7
  "types": "index.d.ts",
@@ -30,13 +30,17 @@
30
30
  },
31
31
  "homepage": "https://github.com/wasmgroundup/emit#readme",
32
32
  "devDependencies": {
33
+ "@arethetypeswrong/cli": "^0.18.2",
33
34
  "@types/node": "^24.10.1",
34
35
  "prettier": "^3.6.2",
36
+ "publint": "^0.3.17",
35
37
  "typescript": "^5.9.3"
36
38
  },
37
39
  "scripts": {
38
40
  "build": "tsc",
39
41
  "format": "npx prettier '**/*.{ts,js,json}' --write",
42
+ "lint": "publint && attw --pack . --ignore-rules cjs-resolves-to-esm",
43
+ "pretest": "node scripts/extract-readme-example.js",
40
44
  "test": "node --test",
41
45
  "test:watch": "node --test --watch"
42
46
  }