@wasmgroundup/emit 1.0.1 → 2.0.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/index.d.ts ADDED
@@ -0,0 +1,452 @@
1
+ export type Byte = number;
2
+ export type Bytes = readonly Byte[];
3
+
4
+ export type Fragment = readonly (Byte | Bytes | Fragment)[];
5
+
6
+ export type SectionId =
7
+ | typeof SECTION_ID_CUSTOM
8
+ | typeof SECTION_ID_TYPE
9
+ | typeof SECTION_ID_IMPORT
10
+ | typeof SECTION_ID_FUNCTION
11
+ | typeof SECTION_ID_TABLE
12
+ | typeof SECTION_ID_MEMORY
13
+ | typeof SECTION_ID_GLOBAL
14
+ | typeof SECTION_ID_EXPORT
15
+ | typeof SECTION_ID_START
16
+ | typeof SECTION_ID_ELEMENT
17
+ | typeof SECTION_ID_CODE
18
+ | typeof SECTION_ID_DATA;
19
+
20
+ declare const brand: unique symbol;
21
+ type Brand<T, B extends string> = T & {readonly [brand]: B};
22
+
23
+ export type typeidx = Brand<Bytes, 'typeidx'>;
24
+ export type funcidx = Brand<Bytes, 'funcidx'>;
25
+ export type localidx = Brand<Bytes, 'localidx'>;
26
+ export type globalidx = Brand<Bytes, 'globalidx'>;
27
+ export type tableidx = Brand<Bytes, 'tableidx'>;
28
+ export type labelidx = Brand<Bytes, 'labelidx'>;
29
+ export type memidx = Brand<Bytes, 'memidx'>;
30
+ export type idx =
31
+ | typeidx
32
+ | funcidx
33
+ | localidx
34
+ | globalidx
35
+ | tableidx
36
+ | labelidx
37
+ | memidx;
38
+
39
+ export function stringToBytes(s: string): Bytes;
40
+
41
+ export function magic(): Bytes;
42
+ export function version(): Bytes;
43
+
44
+ export function u32(v: number): Bytes;
45
+ export function i32(v: number): Bytes;
46
+
47
+ export function section(id: SectionId, contents: Fragment): Fragment;
48
+ export function vec(elements: Fragment): Fragment;
49
+
50
+ // Type section
51
+ // ------------
52
+
53
+ export const SECTION_ID_TYPE: 1;
54
+
55
+ export type valtype = Brand<number, 'valtype'>;
56
+
57
+ export const valtype: {
58
+ i32: valtype;
59
+ i64: valtype;
60
+ f32: valtype;
61
+ f64: valtype;
62
+ };
63
+
64
+ export function functype(
65
+ paramTypes: readonly valtype[],
66
+ resultTypes: readonly valtype[],
67
+ ): Fragment;
68
+
69
+ export function typesec(functypes: readonly Fragment[]): Fragment;
70
+
71
+ // Function section and indices
72
+ // ----------------------------
73
+
74
+ export const SECTION_ID_FUNCTION: 3;
75
+
76
+ export function typeidx(x: number): typeidx;
77
+ export function funcidx(x: number): funcidx;
78
+ export function localidx(x: number): localidx;
79
+ export function labelidx(x: number): labelidx;
80
+ export function tableidx(x: number): tableidx;
81
+ export function globalidx(x: number): globalidx;
82
+ export function memidx(x: number): memidx;
83
+
84
+ export function funcsec(typeidxs: readonly typeidx[]): Fragment;
85
+
86
+ // Code section
87
+ // ------------
88
+
89
+ export const SECTION_ID_CODE: 10;
90
+
91
+ export function code(func: Fragment): Fragment;
92
+
93
+ export function func(locals: readonly Fragment[], body: Fragment): Fragment;
94
+
95
+ export function expr(instrs: readonly Fragment[]): Fragment;
96
+
97
+ export function codesec(codes: readonly Fragment[]): Fragment;
98
+
99
+ // Instructions etc.
100
+ // -----------------
101
+
102
+ // Autogenerated by scripts/gen_instr_type.js. Do not edit manually.
103
+ export const instr: {
104
+ readonly end: 0x0b;
105
+ i32: {
106
+ readonly const: 0x41;
107
+ readonly add: 0x6a;
108
+ readonly sub: 0x6b;
109
+ readonly mul: 0x6c;
110
+ readonly div_s: 0x6d;
111
+ readonly eq: 0x46;
112
+ readonly ne: 0x47;
113
+ readonly lt_s: 0x48;
114
+ readonly lt_u: 0x49;
115
+ readonly gt_s: 0x4a;
116
+ readonly gt_u: 0x4b;
117
+ readonly le_s: 0x4c;
118
+ readonly le_u: 0x4d;
119
+ readonly ge_s: 0x4e;
120
+ readonly ge_u: 0x4f;
121
+ readonly eqz: 0x45;
122
+ readonly and: 0x71;
123
+ readonly or: 0x72;
124
+ readonly load: 0x28;
125
+ readonly store: 0x36;
126
+ readonly load8_s: 0x2c;
127
+ readonly load8_u: 0x2d;
128
+ readonly load16_s: 0x2e;
129
+ readonly load16_u: 0x2f;
130
+ readonly store8: 0x3a;
131
+ readonly store16: 0x3b;
132
+ readonly clz: 0x67;
133
+ readonly ctz: 0x68;
134
+ readonly popcnt: 0x69;
135
+ readonly div_u: 0x6e;
136
+ readonly rem_s: 0x6f;
137
+ readonly rem_u: 0x70;
138
+ readonly xor: 0x73;
139
+ readonly shl: 0x74;
140
+ readonly shr_s: 0x75;
141
+ readonly shr_u: 0x76;
142
+ readonly rotl: 0x77;
143
+ readonly rotr: 0x78;
144
+ readonly wrap_i64: 0xa7;
145
+ readonly trunc_f32_s: 0xa8;
146
+ readonly trunc_f32_u: 0xa9;
147
+ readonly trunc_f64_s: 0xaa;
148
+ readonly trunc_f64_u: 0xab;
149
+ readonly reinterpret_f32: 0xbc;
150
+ };
151
+ i64: {
152
+ readonly const: 0x42;
153
+ readonly load: 0x29;
154
+ readonly load8_s: 0x30;
155
+ readonly load8_u: 0x31;
156
+ readonly load16_s: 0x32;
157
+ readonly load16_u: 0x33;
158
+ readonly load32_s: 0x34;
159
+ readonly load32_u: 0x35;
160
+ readonly store: 0x37;
161
+ readonly store8: 0x3c;
162
+ readonly store16: 0x3d;
163
+ readonly store32: 0x3e;
164
+ readonly eqz: 0x50;
165
+ readonly eq: 0x51;
166
+ readonly ne: 0x52;
167
+ readonly lt_s: 0x53;
168
+ readonly lt_u: 0x54;
169
+ readonly gt_s: 0x55;
170
+ readonly gt_u: 0x56;
171
+ readonly le_s: 0x57;
172
+ readonly le_u: 0x58;
173
+ readonly ge_s: 0x59;
174
+ readonly ge_u: 0x5a;
175
+ readonly clz: 0x79;
176
+ readonly ctz: 0x7a;
177
+ readonly popcnt: 0x7b;
178
+ readonly add: 0x7c;
179
+ readonly sub: 0x7d;
180
+ readonly mul: 0x7e;
181
+ readonly div_s: 0x7f;
182
+ readonly div_u: 0x80;
183
+ readonly rem_s: 0x81;
184
+ readonly rem_u: 0x82;
185
+ readonly and: 0x83;
186
+ readonly or: 0x84;
187
+ readonly xor: 0x85;
188
+ readonly shl: 0x86;
189
+ readonly shr_s: 0x87;
190
+ readonly shr_u: 0x88;
191
+ readonly rotl: 0x89;
192
+ readonly rotr: 0x8a;
193
+ readonly extend_i32_s: 0xac;
194
+ readonly extend_i32_u: 0xad;
195
+ readonly trunc_f32_s: 0xae;
196
+ readonly trunc_f32_u: 0xaf;
197
+ readonly trunc_f64_s: 0xb0;
198
+ readonly trunc_f64_u: 0xb1;
199
+ readonly reinterpret_f64: 0xbd;
200
+ };
201
+ f32: {
202
+ readonly const: 0x43;
203
+ readonly load: 0x2a;
204
+ readonly store: 0x38;
205
+ readonly eq: 0x5b;
206
+ readonly ne: 0x5c;
207
+ readonly lt: 0x5d;
208
+ readonly gt: 0x5e;
209
+ readonly le: 0x5f;
210
+ readonly ge: 0x60;
211
+ readonly abs: 0x8b;
212
+ readonly neg: 0x8c;
213
+ readonly ceil: 0x8d;
214
+ readonly floor: 0x8e;
215
+ readonly trunc: 0x8f;
216
+ readonly nearest: 0x90;
217
+ readonly sqrt: 0x91;
218
+ readonly add: 0x92;
219
+ readonly sub: 0x93;
220
+ readonly mul: 0x94;
221
+ readonly div: 0x95;
222
+ readonly min: 0x96;
223
+ readonly max: 0x97;
224
+ readonly copysign: 0x98;
225
+ readonly convert_i32_s: 0xb2;
226
+ readonly convert_i32_u: 0xb3;
227
+ readonly convert_i64_s: 0xb4;
228
+ readonly convert_i64_u: 0xb5;
229
+ readonly demote_f64: 0xb6;
230
+ readonly reinterpret_i32: 0xbe;
231
+ };
232
+ f64: {
233
+ readonly const: 0x44;
234
+ readonly load: 0x2b;
235
+ readonly store: 0x39;
236
+ readonly eq: 0x61;
237
+ readonly ne: 0x62;
238
+ readonly lt: 0x63;
239
+ readonly gt: 0x64;
240
+ readonly le: 0x65;
241
+ readonly ge: 0x66;
242
+ readonly abs: 0x99;
243
+ readonly neg: 0x9a;
244
+ readonly ceil: 0x9b;
245
+ readonly floor: 0x9c;
246
+ readonly trunc: 0x9d;
247
+ readonly nearest: 0x9e;
248
+ readonly sqrt: 0x9f;
249
+ readonly add: 0xa0;
250
+ readonly sub: 0xa1;
251
+ readonly mul: 0xa2;
252
+ readonly div: 0xa3;
253
+ readonly min: 0xa4;
254
+ readonly max: 0xa5;
255
+ readonly copysign: 0xa6;
256
+ readonly convert_i32_s: 0xb7;
257
+ readonly convert_i32_u: 0xb8;
258
+ readonly convert_i64_s: 0xb9;
259
+ readonly convert_i64_u: 0xba;
260
+ readonly promote_f32: 0xbb;
261
+ readonly reinterpret_i64: 0xbf;
262
+ };
263
+ local: {
264
+ readonly get: 0x20;
265
+ readonly set: 0x21;
266
+ readonly tee: 0x22;
267
+ };
268
+ readonly drop: 0x1a;
269
+ readonly call: 0x10;
270
+ readonly if: 0x04;
271
+ readonly else: 0x05;
272
+ readonly block: 0x02;
273
+ readonly loop: 0x03;
274
+ readonly br: 0x0c;
275
+ readonly br_if: 0x0d;
276
+ memory: {
277
+ readonly size: 0x3f;
278
+ readonly grow: 0x40;
279
+ };
280
+ readonly unreachable: 0x00;
281
+ global: {
282
+ readonly get: 0x23;
283
+ readonly set: 0x24;
284
+ };
285
+ readonly call_indirect: 0x11;
286
+ readonly nop: 0x01;
287
+ readonly br_table: 0x0e;
288
+ readonly return: 0x0f;
289
+ readonly select: 0x1b;
290
+ };
291
+ // End of autogenerated instruction types.
292
+
293
+ export const blocktype: {readonly empty: 0x40} & typeof valtype;
294
+
295
+ // Export section
296
+ // --------------
297
+
298
+ export const SECTION_ID_EXPORT: 7;
299
+
300
+ export function name(s: string): Fragment;
301
+
302
+ export function export_(nm: string, exportdesc: Fragment): Fragment;
303
+
304
+ export function exportsec(exports: readonly Fragment[]): Fragment;
305
+
306
+ export const exportdesc: {
307
+ func(idx: funcidx): Fragment;
308
+ mem(idx: memidx): Fragment;
309
+ };
310
+
311
+ // Module
312
+ // ------
313
+
314
+ export type WasmModule = Fragment;
315
+
316
+ export function module(sections: readonly Fragment[]): WasmModule;
317
+
318
+ // Locals
319
+ // ------
320
+
321
+ export function locals(n: number, type: valtype): Fragment;
322
+
323
+ // Imports
324
+ // -------
325
+
326
+ export const SECTION_ID_IMPORT: 2;
327
+
328
+ export function import_(mod: string, nm: string, d: Fragment): Fragment;
329
+
330
+ export function importsec(ims: readonly Fragment[]): Fragment;
331
+
332
+ export const importdesc: {
333
+ func(x: typeidx): Fragment;
334
+ };
335
+
336
+ // Memory
337
+ // ------
338
+
339
+ export const SECTION_ID_MEMORY: 5;
340
+
341
+ export function memsec(mems: readonly Fragment[]): Fragment;
342
+
343
+ export function mem(memtype: Fragment): Fragment;
344
+
345
+ export function memtype(limits: Fragment): Fragment;
346
+
347
+ export const limits: {
348
+ min(n: number): Fragment;
349
+ minmax(n: number, m: number): Fragment;
350
+ };
351
+
352
+ export function memarg(align: number, offset: number): Fragment;
353
+
354
+ // Data / custom / names
355
+ // ---------------------
356
+
357
+ export const SECTION_ID_DATA: 11;
358
+
359
+ export function data(x: memidx, e: Fragment, bs: Bytes): Fragment;
360
+
361
+ export function datasec(segs: readonly Fragment[]): Fragment;
362
+
363
+ export const SECTION_ID_CUSTOM: 0;
364
+
365
+ export function custom(nameBytes: Fragment, payload: Fragment): Fragment;
366
+ export function customsec(custom: Fragment): Fragment;
367
+
368
+ export function namesec(namedata: Fragment): Fragment;
369
+
370
+ export function namedata(
371
+ modulenamesubsec: Fragment,
372
+ funcnamesubsec: Fragment,
373
+ localnamesubsec: Fragment,
374
+ ): Fragment;
375
+
376
+ export type NameSubsectionId =
377
+ | typeof CUSTOM_NAME_SUB_SEC_MODULE
378
+ | typeof CUSTOM_NAME_SUB_SEC_FUNC
379
+ | typeof CUSTOM_NAME_SUB_SEC_LOCAL;
380
+
381
+ export const CUSTOM_NAME_SUB_SEC_MODULE: 0;
382
+ export function modulenamesubsec(n: string): Fragment;
383
+
384
+ export const CUSTOM_NAME_SUB_SEC_FUNC: 1;
385
+ export function funcnamesubsec(namemap: Fragment): Fragment;
386
+
387
+ export function namesubsection(N: NameSubsectionId, B: Fragment): Fragment;
388
+
389
+ export function namemap(nameassocs: readonly Fragment[]): Fragment;
390
+
391
+ export function nameassoc(idx: idx, n: string): Fragment;
392
+
393
+ export const CUSTOM_NAME_SUB_SEC_LOCAL: 2;
394
+ export function localnamesubsec(indirectnamemap: Fragment): Fragment;
395
+
396
+ export function indirectnamemap(
397
+ indirectnameassocs: readonly Fragment[],
398
+ ): Fragment;
399
+
400
+ export function indirectnameassoc(idx: funcidx, namemap: Fragment): Fragment;
401
+
402
+ // Start section
403
+ // -------------
404
+
405
+ export const SECTION_ID_START: 8;
406
+
407
+ export function start(x: number): funcidx;
408
+
409
+ export function startsec(st: funcidx): Fragment;
410
+
411
+ // Globals
412
+ // -------
413
+
414
+ export const SECTION_ID_GLOBAL: 6;
415
+
416
+ export type mut = Brand<number, 'mut'>;
417
+
418
+ export const mut: {
419
+ const: mut;
420
+ var: mut;
421
+ };
422
+
423
+ export function globaltype(t: valtype, m: mut): Fragment;
424
+
425
+ export function global(gt: Fragment, e: Fragment): Fragment;
426
+
427
+ export function globalsec(globs: readonly Fragment[]): Fragment;
428
+
429
+ // Tables / elements
430
+ // -----------------
431
+
432
+ export const SECTION_ID_TABLE: 4;
433
+
434
+ export const elemtype: {
435
+ readonly funcref: 0x70;
436
+ };
437
+
438
+ export function tabletype(et: typeof elemtype.funcref, lim: Fragment): Fragment;
439
+
440
+ export function table(tt: Fragment): Fragment;
441
+
442
+ export function tablesec(tables: readonly Fragment[]): Fragment;
443
+
444
+ export const SECTION_ID_ELEMENT: 9;
445
+
446
+ export function elem(
447
+ x: tableidx,
448
+ e: Fragment,
449
+ ys: readonly funcidx[],
450
+ ): Fragment;
451
+
452
+ export function elemsec(segs: readonly Fragment[]): Fragment;
package/index.js CHANGED
@@ -119,8 +119,12 @@ export function code(func) {
119
119
  return [u32(sizeInBytes), func];
120
120
  }
121
121
 
122
- export function func(locals, body) {
123
- return [vec(locals), body];
122
+ export function func(locals, e) {
123
+ return [vec(locals), e];
124
+ }
125
+
126
+ export function expr(instrs) {
127
+ return [...instrs, instr.end];
124
128
  }
125
129
 
126
130
  export function codesec(codes) {
@@ -149,7 +153,7 @@ export const funcidx = (x) => u32(x);
149
153
 
150
154
  export const exportdesc = {
151
155
  func(idx) {
152
- return [0x00, funcidx(idx)];
156
+ return [0x00, idx];
153
157
  },
154
158
  };
155
159
 
@@ -226,7 +230,7 @@ export function importsec(ims) {
226
230
  export const importdesc = {
227
231
  // x:typeidx
228
232
  func(x) {
229
- return [0x00, typeidx(x)];
233
+ return [0x00, x];
230
234
  },
231
235
  };
232
236
  export const SECTION_ID_MEMORY = 5;
@@ -256,7 +260,7 @@ export const limits = {
256
260
 
257
261
  export const memidx = u32;
258
262
 
259
- exportdesc.mem = (idx) => [0x02, memidx(idx)];
263
+ exportdesc.mem = (idx) => [0x02, idx];
260
264
 
261
265
  instr.memory = {
262
266
  size: 0x3f, // [] -> [i32]
@@ -412,34 +416,10 @@ export function elemsec(segs) {
412
416
  return section(SECTION_ID_ELEMENT, vec(segs));
413
417
  }
414
418
 
415
- instr.local ??= {};
416
- instr.global ??= {};
417
- instr.memory ??= {};
418
- instr.i32 ??= {};
419
- instr.i64 ??= {};
420
- instr.f32 ??= {};
421
- instr.f64 ??= {};
422
- instr.unreachable = 0x0;
423
419
  instr.nop = 0x1;
424
- instr.block = 0x2;
425
- instr.loop = 0x3;
426
- instr.if = 0x4;
427
- instr.else = 0x5;
428
- instr.end = 0xb;
429
- instr.br = 0xc;
430
- instr.br_if = 0xd;
431
420
  instr.br_table = 0xe;
432
421
  instr.return = 0xf;
433
- instr.call = 0x10;
434
- instr.call_indirect = 0x11;
435
- instr.drop = 0x1a;
436
422
  instr.select = 0x1b;
437
- instr.local.get = 0x20;
438
- instr.local.set = 0x21;
439
- instr.local.tee = 0x22;
440
- instr.global.get = 0x23;
441
- instr.global.set = 0x24;
442
- instr.i32.load = 0x28;
443
423
  instr.i64.load = 0x29;
444
424
  instr.f32.load = 0x2a;
445
425
  instr.f64.load = 0x2b;
@@ -453,7 +433,6 @@ instr.i64.load16_s = 0x32;
453
433
  instr.i64.load16_u = 0x33;
454
434
  instr.i64.load32_s = 0x34;
455
435
  instr.i64.load32_u = 0x35;
456
- instr.i32.store = 0x36;
457
436
  instr.i64.store = 0x37;
458
437
  instr.f32.store = 0x38;
459
438
  instr.f64.store = 0x39;
@@ -462,23 +441,6 @@ instr.i32.store16 = 0x3b;
462
441
  instr.i64.store8 = 0x3c;
463
442
  instr.i64.store16 = 0x3d;
464
443
  instr.i64.store32 = 0x3e;
465
- instr.memory.size = 0x3f;
466
- instr.memory.grow = 0x40;
467
- instr.i32.const = 0x41;
468
- instr.i64.const = 0x42;
469
- instr.f32.const = 0x43;
470
- instr.f64.const = 0x44;
471
- instr.i32.eqz = 0x45;
472
- instr.i32.eq = 0x46;
473
- instr.i32.ne = 0x47;
474
- instr.i32.lt_s = 0x48;
475
- instr.i32.lt_u = 0x49;
476
- instr.i32.gt_s = 0x4a;
477
- instr.i32.gt_u = 0x4b;
478
- instr.i32.le_s = 0x4c;
479
- instr.i32.le_u = 0x4d;
480
- instr.i32.ge_s = 0x4e;
481
- instr.i32.ge_u = 0x4f;
482
444
  instr.i64.eqz = 0x50;
483
445
  instr.i64.eq = 0x51;
484
446
  instr.i64.ne = 0x52;
@@ -505,15 +467,9 @@ instr.f64.ge = 0x66;
505
467
  instr.i32.clz = 0x67;
506
468
  instr.i32.ctz = 0x68;
507
469
  instr.i32.popcnt = 0x69;
508
- instr.i32.add = 0x6a;
509
- instr.i32.sub = 0x6b;
510
- instr.i32.mul = 0x6c;
511
- instr.i32.div_s = 0x6d;
512
470
  instr.i32.div_u = 0x6e;
513
471
  instr.i32.rem_s = 0x6f;
514
472
  instr.i32.rem_u = 0x70;
515
- instr.i32.and = 0x71;
516
- instr.i32.or = 0x72;
517
473
  instr.i32.xor = 0x73;
518
474
  instr.i32.shl = 0x74;
519
475
  instr.i32.shr_s = 0x75;
package/package.json CHANGED
@@ -1,9 +1,20 @@
1
1
  {
2
2
  "name": "@wasmgroundup/emit",
3
3
  "description": "A library for creating binary-encoded WebAssembly modules",
4
- "version": "1.0.1",
4
+ "version": "2.0.0",
5
5
  "type": "module",
6
6
  "main": "index.js",
7
+ "types": "index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./index.d.ts",
11
+ "default": "./index.js"
12
+ }
13
+ },
14
+ "files": [
15
+ "index.js",
16
+ "index.d.ts"
17
+ ],
7
18
  "repository": {
8
19
  "type": "git",
9
20
  "url": "git+https://github.com/wasmgroundup/emit.git"
@@ -17,5 +28,16 @@
17
28
  "bugs": {
18
29
  "url": "https://github.com/wasmgroundup/emit/issues"
19
30
  },
20
- "homepage": "https://github.com/wasmgroundup/emit#readme"
21
- }
31
+ "homepage": "https://github.com/wasmgroundup/emit#readme",
32
+ "devDependencies": {
33
+ "@types/node": "^24.10.1",
34
+ "prettier": "^3.6.2",
35
+ "typescript": "^5.9.3"
36
+ },
37
+ "scripts": {
38
+ "build": "tsc",
39
+ "format": "npx prettier '**/*.{ts,js,json}' --write",
40
+ "test": "node --test",
41
+ "test:watch": "node --test --watch"
42
+ }
43
+ }
package/index.test.ts DELETED
@@ -1,229 +0,0 @@
1
- import { expect, test } from "bun:test";
2
-
3
- import {
4
- blocktype,
5
- code,
6
- codesec,
7
- export_,
8
- exportdesc,
9
- exportsec,
10
- func,
11
- funcidx,
12
- funcsec,
13
- functype,
14
- global,
15
- globalsec,
16
- globaltype,
17
- i32,
18
- import_,
19
- importdesc,
20
- importsec,
21
- instr,
22
- module,
23
- mut,
24
- typeidx,
25
- typesec,
26
- u32,
27
- valtype,
28
- } from "./index.js";
29
-
30
- function blocktype(t?: valtype): number {
31
- return t ?? 0x40;
32
- }
33
-
34
- function f64(v: number): number[] {
35
- var buf = new ArrayBuffer(8);
36
- new Float64Array(buf)[0] = v;
37
- return Array.from(new Uint8Array(buf));
38
- }
39
-
40
- const PI = 3.141592653589793115997963468544185161590576171875;
41
-
42
- function fragmentToUInt8Array(frag): Uint8Array {
43
- return Uint8Array.from((frag as any).flat(Infinity));
44
- }
45
-
46
- test("u32", () => {
47
- expect(u32(32768)).toEqual([128, 128, 2]);
48
- expect(u32(2 ** 32 - 1)).toEqual([255, 255, 255, 255, 15]);
49
- });
50
-
51
- test("i32", () => {
52
- expect(i32(32768)).toEqual([128, 128, 2]);
53
- expect(i32(2 ** 31 - 1)).toEqual([255, 255, 255, 255, 7]);
54
- expect(i32(-(2 ** 31 - 1))).toEqual([129, 128, 128, 128, 120]);
55
- });
56
-
57
- test("simple modules", async () => {
58
- const makeModule = (paramTypes, resultTypes, body) => {
59
- const mod = module([
60
- typesec([functype(paramTypes, resultTypes)]),
61
- funcsec([typeidx(0)]),
62
- exportsec([export_("main", exportdesc.func(0))]),
63
- codesec([code(func([], body))]),
64
- ]);
65
- return fragmentToUInt8Array(mod);
66
- };
67
- const runMain = async (bytes, args) => {
68
- const { instance } = await WebAssembly.instantiate(bytes);
69
- return instance.exports.main(...args);
70
- };
71
-
72
- // () => ()
73
- expect(await runMain(makeModule([], [], [instr.end]), [])).toBe(undefined);
74
-
75
- // () => i32
76
- expect(
77
- await runMain(
78
- makeModule([], [valtype.i32], [instr.i32.const, 1, instr.end]),
79
- [],
80
- ),
81
- ).toBe(1);
82
-
83
- // (i32) => i32
84
- expect(
85
- await runMain(
86
- makeModule([valtype.i32], [valtype.i32], [instr.local.get, 0, instr.end]),
87
- [1],
88
- ),
89
- ).toBe(1);
90
- expect(
91
- await runMain(
92
- makeModule([valtype.i32], [valtype.i32], [instr.local.get, 0, instr.end]),
93
- [99],
94
- ),
95
- ).toBe(99);
96
- });
97
-
98
- test("imports", async () => {
99
- const makeModule = () => {
100
- const mod = module([
101
- typesec([functype([valtype.i32], [valtype.i32])]),
102
- importsec([import_("builtins", "addOne", importdesc.func(0))]),
103
- funcsec([typeidx(0)]),
104
- exportsec([export_("main", exportdesc.func(1))]),
105
- codesec([
106
- code(func([], [instr.local.get, 0, instr.call, funcidx(0), instr.end])),
107
- ]),
108
- ]);
109
- return fragmentToUInt8Array(mod);
110
- };
111
-
112
- const { instance } = await WebAssembly.instantiate(makeModule(), {
113
- builtins: {
114
- addOne(x) {
115
- return x + 1;
116
- },
117
- },
118
- });
119
-
120
- expect(instance.exports.main(1)).toBe(2);
121
- expect(instance.exports.main(2)).toBe(3);
122
- });
123
-
124
- test("f64", async () => {
125
- const makeModule = () => {
126
- const mod = module([
127
- typesec([functype([], [valtype.f64])]),
128
- funcsec([typeidx(0), typeidx(0), typeidx(0)]),
129
- exportsec([
130
- export_("pi", exportdesc.func(0)),
131
- export_("nan", exportdesc.func(1)),
132
- export_("one", exportdesc.func(2)),
133
- ]),
134
- codesec([
135
- code(func([], [instr.f64.const, f64(PI), instr.end])),
136
- code(func([], [instr.f64.const, f64(Number.NaN), instr.end])),
137
- code(func([], [instr.f64.const, f64(1), instr.end])),
138
- ]),
139
- ]);
140
- return fragmentToUInt8Array(mod);
141
- };
142
- const { instance } = await WebAssembly.instantiate(makeModule());
143
- expect(instance.exports.pi()).toBe(PI);
144
- expect(instance.exports.nan()).toBe(Number.NaN);
145
- expect(instance.exports.one()).toBe(1);
146
- });
147
-
148
- test("globals", async () => {
149
- const makeModule = () => {
150
- const mod = module([
151
- typesec([
152
- functype([], [valtype.f64]), // pi
153
- functype([], [valtype.i32]), // getVar
154
- functype([], []), // incVar
155
- ]),
156
- funcsec([typeidx(0), typeidx(1), typeidx(2)]),
157
- globalsec([
158
- global(globaltype(valtype.f64, mut.const), [
159
- instr.f64.const,
160
- f64(PI),
161
- instr.end,
162
- ]),
163
- global(globaltype(valtype.i32, mut.var), [
164
- instr.i32.const,
165
- i32(0),
166
- instr.end,
167
- ]),
168
- ]),
169
- exportsec([
170
- export_("pi", exportdesc.func(0)),
171
- export_("getVar", exportdesc.func(1)),
172
- export_("incVar", exportdesc.func(2)),
173
- ]),
174
- codesec([
175
- code(func([], [instr.global.get, 0, instr.end])), // pi
176
- code(func([], [instr.global.get, 1, instr.end])), // getVar
177
- code(
178
- // prettier-ignore
179
- func([], [
180
- instr.global.get, 1,
181
- instr.i32.const, 1,
182
- instr.i32.add,
183
- instr.global.set, 1,
184
- instr.end,
185
- ],
186
- ),
187
- ), // incVar
188
- ]),
189
- ]);
190
- return fragmentToUInt8Array(mod);
191
- };
192
-
193
- const { exports } = (await WebAssembly.instantiate(makeModule())).instance;
194
- expect(exports.pi()).toBe(PI);
195
- expect(exports.getVar()).toBe(0);
196
- exports.incVar();
197
- expect(exports.getVar()).toBe(1);
198
- });
199
-
200
- test("if", async () => {
201
- const makeModule = () => {
202
- const mod = module([
203
- typesec([functype([valtype.i32], [valtype.f64])]),
204
- funcsec([typeidx(0)]),
205
- exportsec([export_("maybePi", exportdesc.func(0))]),
206
- codesec([
207
- code(
208
- func(
209
- [],
210
- // prettier-ignore
211
- [
212
- instr.local.get, 0,
213
- instr.if, blocktype(valtype.f64),
214
- instr.f64.const, f64(PI),
215
- instr.else,
216
- instr.f64.const, f64(0),
217
- instr.end,
218
- instr.end,
219
- ],
220
- ),
221
- ),
222
- ]),
223
- ]);
224
- return fragmentToUInt8Array(mod);
225
- };
226
- const { exports } = (await WebAssembly.instantiate(makeModule())).instance;
227
- expect(exports.maybePi(1)).toBe(PI);
228
- expect(exports.maybePi(0)).toBe(0);
229
- });