WebAssembly: implement data section
[WebKit-https.git] / JSTests / wasm / js-api / test_Data.js
1 import * as assert from '../assert.js';
2 import Builder from '../Builder.js';
3
4 const memSizeInPages = 1;
5 const pageSizeInBytes = 64 * 1024;
6 const memoryDescription = { initial: memSizeInPages, maximum: memSizeInPages };
7
8 // FIXME Some corner cases are ill-specified: https://github.com/WebAssembly/design/issues/897
9
10 (function DataSection() {
11     const builder = (new Builder())
12         .Type().End()
13         .Import().Memory("imp", "memory", memoryDescription).End()
14         .Data()
15           .Segment([0xff, 0x2a]).Offset(4).End()
16           .Segment([0xde, 0xad, 0xbe, 0xef]).Offset(24).End()
17           .Segment([0xca, 0xfe]).Offset(25).End() // Overwrite.
18           .Segment([]).Offset(4).End() // Empty.
19         .End();
20     const bin = builder.WebAssembly().get();
21     const module = new WebAssembly.Module(bin);
22     const memory = new WebAssembly.Memory(memoryDescription);
23     const instance = new WebAssembly.Instance(module, { imp: { memory: memory } });
24     const buffer = new Uint8Array(memory.buffer);
25     for (let idx = 0; idx < memSizeInPages * pageSizeInBytes; ++idx) {
26         const value = buffer[idx];
27         switch (idx) {
28         case 4: assert.eq(value, 0xff); break;
29         case 5: assert.eq(value, 0x2a); break;
30         case 24: assert.eq(value, 0xde); break;
31         case 25: assert.eq(value, 0xca); break;
32         case 26: assert.eq(value, 0xfe); break;
33         case 27: assert.eq(value, 0xef); break;
34         default: assert.eq(value, 0x00); break;
35         }
36     }
37 })();
38
39 (function DataSectionOffTheEnd() {
40     const builder = (new Builder())
41         .Type().End()
42         .Import().Memory("imp", "memory", memoryDescription).End()
43         .Data()
44           .Segment([0xff]).Offset(memSizeInPages * pageSizeInBytes).End()
45         .End();
46     const bin = builder.WebAssembly().get();
47     const module = new WebAssembly.Module(bin);
48     const memory = new WebAssembly.Memory(memoryDescription);
49     assert.throws(() => new WebAssembly.Instance(module, { imp: { memory: memory } }), RangeError, `Data segment initializes memory out of range`);
50     const buffer = new Uint8Array(memory.buffer);
51     for (let idx = 0; idx < memSizeInPages * pageSizeInBytes; ++idx) {
52         const value = buffer[idx];
53         assert.eq(value, 0x00);
54     }
55 })();
56
57 (function DataSectionPartlyOffTheEnd() {
58     const builder = (new Builder())
59         .Type().End()
60         .Import().Memory("imp", "memory", memoryDescription).End()
61         .Data()
62           .Segment([0xff, 0xff]).Offset(memSizeInPages * pageSizeInBytes - 1).End()
63         .End();
64     const bin = builder.WebAssembly().get();
65     const module = new WebAssembly.Module(bin);
66     const memory = new WebAssembly.Memory(memoryDescription);
67     assert.throws(() => new WebAssembly.Instance(module, { imp: { memory: memory } }), RangeError, `Data segment initializes memory out of range`);
68     const buffer = new Uint8Array(memory.buffer);
69     for (let idx = 0; idx < memSizeInPages * pageSizeInBytes; ++idx) {
70         const value = buffer[idx];
71         assert.eq(value, 0x00);
72     }
73 })();
74
75 (function DataSectionEmptyOffTheEnd() {
76     const builder = (new Builder())
77         .Type().End()
78         .Import().Memory("imp", "memory", memoryDescription).End()
79         .Data()
80           .Segment([]).Offset(memSizeInPages * pageSizeInBytes).End()
81         .End();
82     const bin = builder.WebAssembly().get();
83     const module = new WebAssembly.Module(bin);
84     const memory = new WebAssembly.Memory(memoryDescription);
85     const instance = new WebAssembly.Instance(module, { imp: { memory: memory } });
86     const buffer = new Uint8Array(memory.buffer);
87     for (let idx = 0; idx < memSizeInPages * pageSizeInBytes; ++idx) {
88         const value = buffer[idx];
89         assert.eq(value, 0x00);
90     }
91 })();
92
93 (function DataSectionSeenByStart() {
94     const offset = 1024;
95     const builder = (new Builder())
96         .Type().End()
97         .Import()
98             .Memory("imp", "memory", memoryDescription)
99             .Function("imp", "func", { params: ["i32"] })
100         .End()
101         .Function().End()
102         .Start("foo").End()
103         .Code()
104             .Function("foo", { params: [] })
105                 .I32Const(offset)
106                 .I32Load8U(2, 0)
107                 .Call(0) // Calls func((i8.load(offset), align=2, offset=0). This should observe 0xff as set by the data section.
108             .End()
109         .End()
110         .Data()
111           .Segment([0xff]).Offset(offset).End()
112         .End();
113     const bin = builder.WebAssembly().get();
114     const module = new WebAssembly.Module(bin);
115     const memory = new WebAssembly.Memory(memoryDescription);
116     let value = 0;
117     const setter = v => value = v;
118     const instance = new WebAssembly.Instance(
119         module,
120         {
121             imp: {
122                 memory: memory,
123                 func: setter
124             }
125         });
126     assert.eq(value, 0xff);
127     const buffer = new Uint8Array(memory.buffer);
128     for (let idx = 0; idx < memSizeInPages * pageSizeInBytes; ++idx) {
129         const value = buffer[idx];
130         if (idx == offset)
131             assert.eq(value, 0xff);
132         else
133             assert.eq(value, 0x00);
134     }
135 })();