WebAssembly: implement data section
[WebKit-https.git] / JSTests / wasm / self-test / test_BuilderJSON.js
1 import * as assert from '../assert.js';
2 import Builder from '../Builder.js';
3
4 const assertOpThrows = (opFn, message) => {
5     let f = (new Builder()).Type().End().Code().Function();
6     assert.throws(opFn, Error, message, f);
7 };
8
9 (function EmptyModule() {
10     const b = new Builder();
11     const j = JSON.parse(b.json());
12     assert.isNotUndef(j.preamble);
13     assert.isNotUndef(j.preamble["magic number"]);
14     assert.isNotUndef(j.preamble.version);
15     assert.isNotUndef(j.section);
16     assert.eq(j.section.length, 0);
17 })();
18
19 (function CustomMagicNumber() {
20     const b = (new Builder()).setPreamble({ "magic number": 1337 });
21     const j = JSON.parse(b.json());
22     assert.eq(j.preamble["magic number"], 1337);
23     assert.isNotUndef(j.preamble.version);
24 })();
25
26 (function CustomVersion() {
27     const b = (new Builder()).setPreamble({ "version": 1337 });
28     const j = JSON.parse(b.json());
29     assert.eq(j.preamble["version"], 1337);
30     assert.isNotUndef(j.preamble.version);
31 })();
32
33 (function CustomSection() {
34     const b = new Builder();
35     b.Unknown("custom section")
36         .Byte(0x00)
37         .Byte(0x42)
38         .Byte(0xFF);
39     const j = JSON.parse(b.json());
40     assert.eq(j.section.length, 1);
41     assert.eq(j.section[0].name, "custom section");
42     assert.eq(j.section[0].data.length, 3);
43     assert.eq(j.section[0].data[0], 0x00);
44     assert.eq(j.section[0].data[1], 0x42);
45     assert.eq(j.section[0].data[2], 0xFF);
46 })();
47
48 (function CustomSectionAllBytes() {
49     const b = new Builder();
50     let u = b.Unknown("custom section");
51     for (let i = 0; i !== 0xFF + 1; ++i)
52         u.Byte(i);
53     const j = JSON.parse(b.json());
54     assert.eq(j.section[0].data.length, 256);
55     for (let i = 0; i !== 0xFF + 1; ++i)
56         assert.eq(j.section[0].data[i], i);
57 })();
58
59 (function CustomSectionInvalidByte() {
60     const u = (new Builder()).Unknown("custom section");
61     assert.throws(() => u.Byte(0xFF + 1), Error, `Not the same: "0" and "256": Unknown section expected byte, got: "256"`);
62 })();
63
64 (function TwoCustomSections() {
65     const b = new Builder();
66     b.Unknown("custom section")
67         .Byte(0x00)
68         .Byte(0x42)
69         .Byte(0xFF)
70     .End()
71     .Unknown("☃")
72         .Byte(0x11);
73     const j = JSON.parse(b.json());
74     assert.eq(j.section.length, 2);
75     assert.eq(j.section[0].name, "custom section");
76     assert.eq(j.section[0].data.length, 3);
77     assert.eq(j.section[1].name, "☃");
78     assert.eq(j.section[1].data.length, 1);
79     assert.eq(j.section[1].data[0], 0x11);
80 })();
81
82 (function SectionsWithSameCustomName() {
83     const b = (new Builder()).Unknown("foo").End();
84     assert.throws(() => b.Unknown("foo"), Error, `Expected falsy: Cannot have two sections with the same name "foo" and ID 0`);
85 })();
86
87 (function EmptyTypeSection() {
88     const b = (new Builder()).Type().End();
89     const j = JSON.parse(b.json());
90     assert.eq(j.section.length, 1);
91     assert.eq(j.section[0].name, "Type");
92     assert.eq(j.section[0].data.length, 0);
93 })();
94
95 (function TwoTypeSections() {
96     const b = (new Builder()).Type().End();
97     assert.throws(() => b.Type(), Error, `Expected falsy: Cannot have two sections with the same name "Type" and ID 1`);
98 })();
99
100 (function SimpleTypeSection() {
101     const b = (new Builder()).Type()
102             .Func([])
103             .Func([], "void")
104             .Func([], "i32")
105             .Func([], "i64")
106             .Func([], "f32")
107             .Func([], "f64")
108             .Func(["i32", "i64", "f32", "f64"])
109         .End();
110     const j = JSON.parse(b.json());
111     assert.eq(j.section[0].data.length, 7);
112     assert.eq(j.section[0].data[0].params, []);
113     assert.eq(j.section[0].data[0].ret, "void");
114     assert.eq(j.section[0].data[1].params, []);
115     assert.eq(j.section[0].data[1].ret, "void");
116     assert.eq(j.section[0].data[2].params, []);
117     assert.eq(j.section[0].data[2].ret, "i32");
118     assert.eq(j.section[0].data[3].params, []);
119     assert.eq(j.section[0].data[3].ret, "i64");
120     assert.eq(j.section[0].data[4].params, []);
121     assert.eq(j.section[0].data[4].ret, "f32");
122     assert.eq(j.section[0].data[5].params, []);
123     assert.eq(j.section[0].data[5].ret, "f64");
124     assert.eq(j.section[0].data[6].params, ["i32", "i64", "f32", "f64"]);
125     assert.eq(j.section[0].data[6].ret, "void");
126 })();
127
128 (function EmptyImportSection() {
129     const b = (new Builder()).Import().End();
130     const j = JSON.parse(b.json());
131     assert.eq(j.section.length, 1);
132     assert.eq(j.section[0].name, "Import");
133     assert.eq(j.section[0].data.length, 0);
134 })();
135
136 (function ImportBeforeTypeSections() {
137     const b = (new Builder()).Import().End();
138     assert.throws(() => b.Type(), Error, `Expected: "2" > "1": Bad section ordering: "Import" cannot precede "Type"`);
139 })();
140
141 (function ImportFunctionWithoutTypeSection() {
142     const i = (new Builder()).Import();
143     assert.throws(() => i.Function("foo", "bar", 0), Error, `Shouldn't be undefined: Can not use type 0 if a type section is not present`);
144 })();
145
146 (function ImportFunctionWithInvalidType() {
147     const i = (new Builder()).Type().End().Import();
148     assert.throws(() => i.Function("foo", "bar", 0), Error, `Shouldn't be undefined: Type 0 does not exist in type section`);
149 })();
150
151 (function ImportFunction() {
152     const b = (new Builder())
153         .Type().Func([]).End()
154         .Import()
155             .Function("foo", "bar", 0)
156         .End();
157     const j = JSON.parse(b.json());
158     assert.eq(j.section[1].data.length, 1);
159     assert.eq(j.section[1].data[0].module, "foo");
160     assert.eq(j.section[1].data[0].field, "bar");
161     assert.eq(j.section[1].data[0].type, 0);
162     assert.eq(j.section[1].data[0].kind, "Function");
163 })();
164
165 (function ImportFunctionsWithExistingTypes() {
166     const b = (new Builder())
167         .Type()
168             .Func([])
169             .Func([], "i32")
170             .Func(["i64", "i32"])
171             .Func(["i64", "i64"])
172         .End()
173         .Import()
174             .Function("foo", "bar", { params: [] })
175             .Function("foo", "baz", { params: [], ret: "i32" })
176             .Function("foo", "boo", { params: ["i64", "i64"] })
177         .End();
178     const j = JSON.parse(b.json());
179     assert.eq(j.section[0].data.length, 4);
180     assert.eq(j.section[1].data.length, 3);
181     assert.eq(j.section[1].data[0].type, 0);
182     assert.eq(j.section[1].data[1].type, 1);
183     assert.eq(j.section[1].data[2].type, 3);
184 })();
185
186 (function ImportFunctionWithNewType() {
187     const b = (new Builder())
188         .Type().End()
189         .Import()
190             .Function("foo", "bar", { params: [] })
191             .Function("foo", "baz", { params: [], ret: "i32" })
192             .Function("foo", "boo", { params: ["i64", "i64"] })
193         .End();
194     const j = JSON.parse(b.json());
195     assert.eq(j.section[0].data.length, 3);
196     assert.eq(j.section[0].data[0].ret, "void");
197     assert.eq(j.section[0].data[0].params, []);
198     assert.eq(j.section[0].data[1].ret, "i32");
199     assert.eq(j.section[0].data[1].params, []);
200     assert.eq(j.section[0].data[2].ret, "void");
201     assert.eq(j.section[0].data[2].params, ["i64", "i64"]);
202 })();
203
204 (function EmptyExportSection() {
205     const b = (new Builder()).Export().End();
206     const j = JSON.parse(b.json());
207     assert.eq(j.section.length, 1);
208     assert.eq(j.section[0].name, "Export");
209     assert.eq(j.section[0].data.length, 0);
210 })();
211
212 (function ExportFunctionWithoutTypeSection() {
213     const e = (new Builder()).Export();
214     assert.throws(() => e.Function("foo", 0, 0), Error, `Shouldn't be undefined: Can not use type 0 if a type section is not present`);
215 })();
216
217 (function ExportFunctionWithInvalidType() {
218     const e = (new Builder()).Type().End().Export();
219     assert.throws(() => e.Function("foo", 0, 0), Error, `Shouldn't be undefined: Type 0 does not exist in type section`);
220 })();
221
222 (function ExportAnImport() {
223     const b = (new Builder())
224         .Type().End()
225         .Import().Function("foo", "bar", { params: [] }).End()
226         .Export().Function("ExportAnImport", { module: "foo", field: "bar" }).End();
227     const j = JSON.parse(b.json());
228     assert.eq(j.section[2].name, "Export");
229     assert.eq(j.section[2].data.length, 1);
230     assert.eq(j.section[2].data[0].field, "ExportAnImport");
231     assert.eq(j.section[2].data[0].type, 0);
232     assert.eq(j.section[2].data[0].index, 0);
233     assert.eq(j.section[2].data[0].kind, "Function");
234 })();
235
236 (function ExportMismatchedImport() {
237     const e = (new Builder())
238         .Type().End()
239         .Import().Function("foo", "bar", { params: [] }).End()
240         .Export();
241     assert.throws(() => e.Function("foo", 0, { params: ["i32"] }), Error, `Not the same: "1" and "0": Re-exporting import "bar" as "foo" has mismatching type`);
242 })();
243
244 (function StartInvalidNumberedFunction() {
245     const b = (new Builder())
246         .Type().End()
247         .Function().End()
248         .Start(0).End()
249     assert.throws(() => b.Code().End(), Error, `Start section refers to non-existant function '0'`);
250 })();
251
252 (function StartInvalidNamedFunction() {
253     const b = (new Builder())
254         .Type().End()
255         .Function().End()
256         .Start("foo").End();
257     assert.throws(() => b.Code().End(), Error, `Start section refers to non-existant function 'foo'`);
258 })();
259
260 (function StartNamedFunction() {
261     const b = (new Builder())
262         .Type().End()
263         .Function().End()
264         .Start("foo").End()
265         .Code()
266             .Function("foo", { params: [] }).End()
267         .End();
268     const j = JSON.parse(b.json());
269     assert.eq(j.section.length, 4);
270     assert.eq(j.section[2].name, "Start");
271     assert.eq(j.section[2].data.length, 1);
272     assert.eq(j.section[2].data[0], 0);
273 })();
274
275 /* FIXME implement checking of signature https://bugs.webkit.org/show_bug.cgi?id=165658
276 (function StartInvalidTypeArg() {
277     const b = (new Builder())
278         .Type().End()
279         .Function().End()
280         .Start("foo").End()
281     assert.throws(() => b.Code().Function("foo", { params: ["i32"] }).End(), Error, `???`);
282 })();
283
284 (function StartInvalidTypeReturn() {
285     const b = (new Builder())
286         .Type().End()
287         .Function().End()
288         .Start("foo").End()
289     assert.throws(() => b.Code().Function("foo", { params: [], ret: "i32" }).I32Const(42).Ret().End(), Error, `???`);
290 })();
291 */
292
293 // FIXME test start of import or table. https://bugs.webkit.org/show_bug.cgi?id=165658
294
295 (function EmptyCodeSection() {
296     const b = new Builder();
297     b.Code();
298     const j = JSON.parse(b.json());
299     assert.eq(j.section.length, 1);
300     assert.eq(j.section[0].name, "Code");
301     assert.eq(j.section[0].data.length, 0);
302 })();
303
304 (function CodeSectionWithEmptyFunction() {
305     const b = new Builder();
306     b.Type().End()
307         .Code()
308             .Function();
309     const j = JSON.parse(b.json());
310     assert.eq(j.section.length, 2);
311     assert.eq(j.section[0].name, "Type");
312     assert.eq(j.section[0].data.length, 1);
313     assert.eq(j.section[0].data[0].params, []);
314     assert.eq(j.section[0].data[0].ret, "void");
315     assert.eq(j.section[1].name, "Code");
316     assert.eq(j.section[1].data.length, 1);
317     assert.eq(j.section[1].data[0].name, undefined);
318     assert.eq(j.section[1].data[0].type, 0);
319     assert.eq(j.section[1].data[0].parameterCount, 0);
320     assert.eq(j.section[1].data[0].locals.length, 0);
321     assert.eq(j.section[1].data[0].code.length, 0);
322 })();
323
324 (function CodeSectionWithEmptyFunctionWithParameters() {
325     const b = new Builder();
326     b.Type().End()
327         .Code()
328             .Function({ params: ["i32", "i64", "f32", "f64"] });
329     const j = JSON.parse(b.json());
330     assert.eq(j.section.length, 2);
331     assert.eq(j.section[0].data.length, 1);
332     assert.eq(j.section[0].data[0].params, ["i32", "i64", "f32", "f64"]);
333     assert.eq(j.section[0].data[0].ret, "void");
334     assert.eq(j.section[1].data.length, 1);
335     assert.eq(j.section[1].data[0].type, 0);
336     assert.eq(j.section[1].data[0].parameterCount, 4);
337     assert.eq(j.section[1].data[0].locals[0], "i32");
338     assert.eq(j.section[1].data[0].locals[1], "i64");
339     assert.eq(j.section[1].data[0].locals[2], "f32");
340     assert.eq(j.section[1].data[0].locals[3], "f64");
341     assert.eq(j.section[1].data[0].code.length, 0);
342 })();
343
344 (function InvalidFunctionParameters() {
345     for (let invalid of ["", "void", "bool", "any", "struct", 0, 3.14, undefined, [], {}]) {
346         const c = (new Builder()).Code();
347         assert.throws(() => c.Function({ params: [invalid] }), Error, `Expected truthy: Type parameter ${invalid} needs a valid value type`);
348     }
349 })();
350
351 (function SimpleFunction() {
352     const b = new Builder();
353     b.Type().End()
354         .Code()
355             .Function()
356                 .Nop()
357                 .Nop()
358             .End();
359     const j = JSON.parse(b.json());
360     assert.eq(j.section[1].data.length, 1);
361     assert.eq(j.section[1].data[0].locals.length, 0);
362     assert.eq(j.section[1].data[0].code.length, 3);
363     assert.eq(j.section[1].data[0].code[0].name, "nop");
364     assert.eq(j.section[1].data[0].code[1].name, "nop");
365     assert.eq(j.section[1].data[0].code[2].name, "end");
366 })();
367
368 (function TwoSimpleFunctions() {
369     const b = new Builder();
370     b.Type().End()
371         .Code()
372             .Function()
373                 .Nop()
374                 .Nop()
375             .End()
376             .Function()
377                 .Return()
378             .End();
379     const j = JSON.parse(b.json());
380     assert.eq(j.section[1].data.length, 2);
381     assert.eq(j.section[1].data[0].locals.length, 0);
382     assert.eq(j.section[1].data[0].code.length, 3);
383     assert.eq(j.section[1].data[0].code[0].name, "nop");
384     assert.eq(j.section[1].data[0].code[1].name, "nop");
385     assert.eq(j.section[1].data[0].code[2].name, "end");
386     assert.eq(j.section[1].data[1].locals.length, 0);
387     assert.eq(j.section[1].data[1].code.length, 2);
388     assert.eq(j.section[1].data[1].code[0].name, "return");
389     assert.eq(j.section[1].data[1].code[1].name, "end");
390 })();
391
392 (function NamedFunctions() {
393     const b = new Builder().Type().End().Code()
394         .Function("hello").End()
395         .Function("world", { params: ["i32"] }).End()
396     .End();
397     const j = JSON.parse(b.json());
398     assert.eq(j.section[1].data[0].name, "hello");
399     assert.eq(j.section[1].data[0].parameterCount, 0);
400     assert.eq(j.section[1].data[1].name, "world");
401     assert.eq(j.section[1].data[1].parameterCount, 1);
402 })();
403
404 (function ExportSimpleFunctions() {
405     const b = (new Builder())
406         .Type().End()
407         .Export()
408             .Function("foo", 0, { params: [] })
409             .Function("bar")
410             .Function("betterNameForBar", "bar")
411         .End()
412         .Code()
413             .Function({ params: [] }).Nop().End()
414             .Function("bar", { params: [] }).Nop().End()
415         .End();
416     const j = JSON.parse(b.json());
417     assert.eq(j.section[0].data.length, 1);
418     assert.eq(j.section[0].data[0].ret, "void");
419     assert.eq(j.section[0].data[0].params, []);
420     assert.eq(j.section[1].data.length, 3);
421     assert.eq(j.section[1].data[0].field, "foo");
422     assert.eq(j.section[1].data[0].type, 0);
423     assert.eq(j.section[1].data[0].index, 0);
424     assert.eq(j.section[1].data[0].kind, "Function");
425     assert.eq(j.section[1].data[1].field, "bar");
426     assert.eq(j.section[1].data[1].type, 0);
427     assert.eq(j.section[1].data[1].index, 1);
428     assert.eq(j.section[1].data[1].kind, "Function");
429     assert.eq(j.section[1].data[2].field, "betterNameForBar");
430     assert.eq(j.section[1].data[2].type, 0);
431     assert.eq(j.section[1].data[2].index, 1);
432     assert.eq(j.section[1].data[2].kind, "Function");
433 })();
434
435 (function ExportUndefinedFunction() {
436     const c = (new Builder()).Type().End().Export().Function("foo").End().Code();
437     assert.throws(() => c.End(), Error, `Should be number, got undefined: Export section contains undefined function "foo"`);
438 })();
439
440 (function TwoBuildersAtTheSameTime() {
441     const b = [new Builder(), new Builder()];
442     const f = b.map(builder => builder.Type().End().Code().Function());
443     f[0].Nop();
444     f[1].Return().End().End();
445     f[0].Nop().End().End();
446     const j = b.map(builder => JSON.parse(builder.json()));
447     assert.eq(j[0].section[1].data[0].code.length, 3);
448     assert.eq(j[0].section[1].data[0].code[0].name, "nop");
449     assert.eq(j[0].section[1].data[0].code[1].name, "nop");
450     assert.eq(j[0].section[1].data[0].code[2].name, "end");
451     assert.eq(j[1].section[1].data[0].code.length, 2);
452     assert.eq(j[1].section[1].data[0].code[0].name, "return");
453     assert.eq(j[1].section[1].data[0].code[1].name, "end");
454 })();
455
456 (function CheckedOpcodeArgumentsTooMany() {
457     assertOpThrows(f => f.Nop("uh-oh!"), `Not the same: "1" and "0": "nop" expects exactly 0 immediates, got 1`);
458 })();
459
460 (function UncheckedOpcodeArgumentsTooMany() {
461     (new Builder()).setChecked(false).Type().End().Code().Function().Nop("This is fine.", "I'm OK with the events that are unfolding currently.");
462 })();
463
464 (function CheckedOpcodeArgumentsNotEnough() {
465     assertOpThrows(f => f.I32Const(), `Not the same: "0" and "1": "i32.const" expects exactly 1 immediate, got 0`);
466 })();
467
468 (function UncheckedOpcodeArgumentsNotEnough() {
469     (new Builder()).setChecked(false).Type().End().Code().Function().I32Const();
470 })();
471
472 (function CallNoArguments() {
473     const b = (new Builder()).Type().End().Code().Function().Call(0).End().End();
474     const j = JSON.parse(b.json());
475     assert.eq(j.section[1].data[0].code.length, 2);
476     assert.eq(j.section[1].data[0].code[0].name, "call");
477     assert.eq(j.section[1].data[0].code[0].arguments.length, 0);
478     assert.eq(j.section[1].data[0].code[0].immediates.length, 1);
479     assert.eq(j.section[1].data[0].code[0].immediates[0], 0);
480     assert.eq(j.section[1].data[0].code[1].name, "end");
481 })();
482
483 (function CallInvalid() {
484     for (let c of [-1, 0x100000000, "0", {}, Infinity, -Infinity, NaN, -NaN, null])
485         assertOpThrows(f => f.Call(c), `Expected truthy: Invalid value on call: got "${c}", expected i32`);
486 })();
487
488 (function I32ConstValid() {
489     for (let c of [0, 1, 2, 42, 1337, 0xFF, 0xFFFF, 0x7FFFFFFF, 0xFFFFFFFE, 0xFFFFFFFF]) {
490         const b = (new Builder()).Type().End().Code().Function().I32Const(c).Return().End().End();
491         const j = JSON.parse(b.json());
492         assert.eq(j.section[1].data[0].code[0].name, "i32.const");
493         assert.eq(j.section[1].data[0].code[0].arguments.length, 0);
494         assert.eq(j.section[1].data[0].code[0].immediates.length, 1);
495         assert.eq(j.section[1].data[0].code[0].immediates[0], c);
496     }
497 })();
498
499 (function I32ConstInvalid() {
500     for (let c of [-1, 0x100000000, 0.1, -0.1, "0", {}, Infinity, null])
501         assertOpThrows(f => f.I32Const(c), `Expected truthy: Invalid value on i32.const: got "${c}", expected i32`);
502 })();
503
504 // FIXME: test i64. https://bugs.webkit.org/show_bug.cgi?id=163420
505
506 (function F32ConstValid() {
507     for (let c of [0, -0., 0.2, Math.PI, 0x100000000]) {
508         const b = (new Builder()).Type().End().Code().Function().F32Const(c).Return().End().End();
509         const j = JSON.parse(b.json());
510         assert.eq(j.section[1].data[0].code[0].name, "f32.const");
511         assert.eq(j.section[1].data[0].code[0].arguments.length, 0);
512         assert.eq(j.section[1].data[0].code[0].immediates.length, 1);
513         assert.eq(j.section[1].data[0].code[0].immediates[0], c);
514     }
515 })();
516
517 (function F32ConstInvalid() {
518     for (let c of ["0", {}, Infinity, -Infinity, NaN, -NaN, null])
519         assertOpThrows(f => f.F32Const(c), `Expected truthy: Invalid value on f32.const: got "${c}", expected f32`);
520 })();
521
522 (function F64ConstValid() {
523     for (let c of [0, -0., 0.2, Math.PI, 0x100000000]) {
524         const b = (new Builder()).Type().End().Code().Function().F64Const(c).Return().End().End();
525         const j = JSON.parse(b.json());
526         assert.eq(j.section[1].data[0].code[0].name, "f64.const");
527         assert.eq(j.section[1].data[0].code[0].arguments.length, 0);
528         assert.eq(j.section[1].data[0].code[0].immediates.length, 1);
529         assert.eq(j.section[1].data[0].code[0].immediates[0], c);
530     }
531 })();
532
533 (function F64ConstInvalid() {
534     for (let c of ["0", {}, Infinity, -Infinity, NaN, -NaN, null])
535         assertOpThrows(f => f.F64Const(c), `Expected truthy: Invalid value on f64.const: got "${c}", expected f64`);
536 })();
537
538 (function CallOneFromStack() {
539     const b = (new Builder()).Type().End().Code()
540         .Function({ params: ["i32"] })
541             .I32Const(42)
542             .Call(0)
543         .End()
544     .End();
545     const j = JSON.parse(b.json());
546     assert.eq(j.section[1].data[0].code.length, 3);
547     assert.eq(j.section[1].data[0].code[0].name, "i32.const");
548     assert.eq(j.section[1].data[0].code[0].immediates[0], 42);
549     assert.eq(j.section[1].data[0].code[1].name, "call");
550     // FIXME: assert.eq(j.section[1].data[0].code[1].arguments.length, 1); https://bugs.webkit.org/show_bug.cgi?id=163267
551     assert.eq(j.section[1].data[0].code[1].immediates.length, 1);
552     assert.eq(j.section[1].data[0].code[1].immediates[0], 0);
553     assert.eq(j.section[1].data[0].code[2].name, "end");
554 })();
555
556 // FIXME https://bugs.webkit.org/show_bug.cgi?id=163267 all of these:
557 //  test too many pops.
558 //  test not enough pops (function has non-empty stack at the end).
559 //  test mismatched pop types.
560 //  test mismatched function signature (calling with wrong arg types).
561 //  test invalid function index.
562 //  test function names (both setting and calling them).
563
564 (function CallManyFromStack() {
565     const b = (new Builder()).Type().End().Code()
566         .Function({ params: ["i32", "i32", "i32", "i32"] })
567               .I32Const(42).I32Const(1337).I32Const(0xBEEF).I32Const(0xFFFF)
568               .Call(0)
569         .End()
570     .End();
571     const j = JSON.parse(b.json());
572     assert.eq(j.section[1].data[0].code.length, 6);
573     assert.eq(j.section[1].data[0].code[4].name, "call");
574     // FIXME: assert.eq(j.section[1].data[0].code[4].arguments.length, 4); https://bugs.webkit.org/show_bug.cgi?id=163267
575     assert.eq(j.section[1].data[0].code[4].immediates.length, 1);
576     assert.eq(j.section[1].data[0].code[4].immediates[0], 0);
577 })();
578
579 (function OpcodeAdd() {
580     const b = (new Builder()).Type().End().Code()
581           .Function()
582               .I32Const(42).I32Const(1337)
583               .I32Add()
584               .Return()
585         .End()
586     .End();
587     const j = JSON.parse(b.json());
588     assert.eq(j.section[1].data[0].code.length, 5);
589     assert.eq(j.section[1].data[0].code[2].name, "i32.add");
590     // FIXME: assert.eq(j.section[1].data[0].code[2].arguments.length, 2); https://bugs.webkit.org/show_bug.cgi?id=163267
591     assert.eq(j.section[1].data[0].code[3].name, "return");
592     // FIXME check return. https://bugs.webkit.org/show_bug.cgi?id=163267
593 })();
594
595 (function OpcodeUnreachable() {
596     const b = (new Builder()).Type().End().Code().Function().Unreachable().End().End();
597     const j = JSON.parse(b.json());
598     assert.eq(j.section[1].data[0].code.length, 2);
599     assert.eq(j.section[1].data[0].code[0].name, "unreachable");
600 })();
601
602 (function OpcodeUnreachableCombinations() {
603     (new Builder()).Type().End().Code().Function().Nop().Unreachable().End().End().json();
604     (new Builder()).Type().End().Code().Function().Unreachable().Nop().End().End().json();
605     (new Builder()).Type().End().Code().Function().Return().Unreachable().End().End().json();
606     (new Builder()).Type().End().Code().Function().Unreachable().Return().End().End().json();
607     (new Builder()).Type().End().Code().Function().Call(0).Unreachable().End().End().json();
608     (new Builder()).Type().End().Code().Function().Unreachable().Call(0).End().End().json();
609 })();
610
611 (function OpcodeSelect() {
612     const b = (new Builder()).Type().End().Code().Function()
613         .I32Const(1).I32Const(2).I32Const(0)
614         .Select()
615         .Return()
616       .End()
617     .End();
618     const j = JSON.parse(b.json());
619     assert.eq(j.section[1].data[0].code.length, 6);
620     assert.eq(j.section[1].data[0].code[3].name, "select");
621 })();
622 // FIXME test type mismatch with select. https://bugs.webkit.org/show_bug.cgi?id=163267
623
624 (function MemoryImport() {
625     const builder = (new Builder())
626         .Type().End()
627         .Import()
628             .Memory("__module__", "__field__", {initial: 30, maximum: 31})
629         .End()
630         .Code().End();
631
632     const json = JSON.parse(builder.json());
633     assert.eq(json.section.length, 3);
634     assert.eq(json.section[1].name, "Import");
635     assert.eq(json.section[1].data.length, 1);
636     assert.eq(json.section[1].data[0].module, "__module__");
637     assert.eq(json.section[1].data[0].field, "__field__");
638     assert.eq(json.section[1].data[0].kind, "Memory");
639     assert.eq(json.section[1].data[0].memoryDescription.initial, 30);
640     assert.eq(json.section[1].data[0].memoryDescription.maximum, 31);
641 })();
642
643 (function DataSection() {
644     const builder = (new Builder())
645         .Memory().InitialMaxPages(64, 64).End()
646         .Data()
647           .Segment([0xff, 0x2a]).Offset(4).End()
648           .Segment([0xde, 0xad, 0xbe, 0xef]).Index(0).Offset(24).End()
649         .End();
650     const json = JSON.parse(builder.json());
651     assert.eq(json.section.length, 2);
652     assert.eq(json.section[1].name, "Data");
653     assert.eq(json.section[1].data.length, 2);
654     assert.eq(json.section[1].data[0].index, 0);
655     assert.eq(json.section[1].data[0].offset, 4);
656     assert.eq(json.section[1].data[0].data.length, 2);
657     assert.eq(json.section[1].data[0].data[0], 0xff);
658     assert.eq(json.section[1].data[0].data[1], 0x2a);
659     assert.eq(json.section[1].data[1].index, 0);
660     assert.eq(json.section[1].data[1].offset, 24);
661     assert.eq(json.section[1].data[1].data.length, 4);
662     assert.eq(json.section[1].data[1].data[0], 0xde);
663     assert.eq(json.section[1].data[1].data[1], 0xad);
664     assert.eq(json.section[1].data[1].data[2], 0xbe);
665     assert.eq(json.section[1].data[1].data[3], 0xef);
666 })();