[WASM-References] Rename anyfunc to funcref
[WebKit-https.git] / JSTests / wasm / function-tests / trap-from-start-async.js
1 import * as assert from '../assert.js';
2 import Builder from '../Builder.js';
3
4 const memoryInfo = { initial: 2 };
5 const tableInfo = { element: "funcref", initial: 8 };
6
7 async function StartTrapsAsync() {
8     const builder = (new Builder())
9         .Type().End()
10         .Import()
11             .Memory("imp", "memory", memoryInfo)
12             .Table("imp", "table", tableInfo)
13             .Function("imp", "func", { params: ["i32"] })
14         .End()
15         .Function().End()
16         .Start("startMeUp").End()
17         .Element()
18           .Element({ offset: 4, functionIndices: [0, 1] })
19         .End()
20         .Code()
21             .Function("startMeUp", { params: [] })
22                 .I32Const(0).I32Load(2, 0).I32Const(0xfeedface).I32Store(2, 0)
23                 .I32Const(4).I32Load(2, 0).I32Const(0xc0fec0fe).I32Store(2, 0) // This will trap.
24                 // This is unreachable:
25                 .I32Const(42).Call(0) // Calls func(42).
26             .End()
27         .End()
28         .Data()
29           .Segment([0xef, 0xbe, 0xad, 0xde]).Offset(1024).End()
30         .End();
31
32     const memory = new WebAssembly.Memory(memoryInfo);
33     const buffer = new Uint32Array(memory.buffer);
34
35     const table = new WebAssembly.Table(tableInfo);
36
37     // The instance will use these as addresses for stores.
38     buffer[0] = 128;
39     buffer[1] = 0xc0defefe; // This is out of bounds.
40
41     // This function shouldn't get called because the trap occurs before the call.
42     let value = 0;
43     const func = v => value = v;
44
45     const module = new WebAssembly.Module(builder.WebAssembly().get());
46     const imp = { imp: { memory, table, func } };
47
48     const promise = WebAssembly.instantiate(module, imp);
49     await assert.throwsAsync(promise, WebAssembly.RuntimeError, `Out of bounds memory access`);
50
51     assert.eq(value, 0);
52
53     for (let i = 0; i < buffer.length; ++i) {
54         switch (i) {
55         case   0: assert.eq(buffer[i], 128);        break; // Initial ArrayBuffer store.
56         case   1: assert.eq(buffer[i], 0xc0defefe); break; // Initial ArrayBuffer store.
57         case  32: assert.eq(buffer[i], 0xfeedface); break; // First store from start function.
58         case 256: assert.eq(buffer[i], 0xdeadbeef); break; // Data segment.
59         default:  assert.eq(buffer[i], 0);          break; // The rest.
60         }
61     }
62
63     for (let i = 0; i < table.length; ++i) {
64         switch (i) {
65         case 4:  assert.isFunction(table.get(i)); break;
66         case 5:  assert.isFunction(table.get(i)); break;
67         default: assert.eq(table.get(i), null); break;
68         }
69     }
70
71     // Call the imported `func`.
72     table.get(4)(0xf00f);
73     assert.eq(value, 0xf00f);
74     value = 0;
75
76     // Call the start function again on the instance. The instance is otherwise inaccessible!
77     buffer[32] = 0; // Reset the location which will be set by the first store.
78     assert.throws(() => table.get(5)(), WebAssembly.RuntimeError, `Out of bounds memory access`);
79     assert.eq(buffer[32], 0xfeedface); // The first store should still succeed.
80     assert.eq(value, 0);
81 }
82
83 assert.asyncTest(StartTrapsAsync());