import * as assert from '../assert.js';
import Builder from '../Builder.js';

const memoryInfo = { initial: 2 };
const tableInfo = { element: "funcref", initial: 8 };

async function StartTrapsAsync() {
    const builder = (new Builder())
        .Type().End()
        .Import()
            .Memory("imp", "memory", memoryInfo)
            .Table("imp", "table", tableInfo)
            .Function("imp", "func", { params: ["i32"] })
        .End()
        .Function().End()
        .Start("startMeUp").End()
        .Element()
          .Element({ offset: 4, functionIndices: [0, 1] })
        .End()
        .Code()
            .Function("startMeUp", { params: [] })
                .I32Const(0).I32Load(2, 0).I32Const(0xfeedface).I32Store(2, 0)
                .I32Const(4).I32Load(2, 0).I32Const(0xc0fec0fe).I32Store(2, 0) // This will trap.
                // This is unreachable:
                .I32Const(42).Call(0) // Calls func(42).
            .End()
        .End()
        .Data()
          .Segment([0xef, 0xbe, 0xad, 0xde]).Offset(1024).End()
        .End();

    const memory = new WebAssembly.Memory(memoryInfo);
    const buffer = new Uint32Array(memory.buffer);

    const table = new WebAssembly.Table(tableInfo);

    // The instance will use these as addresses for stores.
    buffer[0] = 128;
    buffer[1] = 0xc0defefe; // This is out of bounds.

    // This function shouldn't get called because the trap occurs before the call.
    let value = 0;
    const func = v => value = v;

    const module = new WebAssembly.Module(builder.WebAssembly().get());
    const imp = { imp: { memory, table, func } };

    const promise = WebAssembly.instantiate(module, imp);
    await assert.throwsAsync(promise, WebAssembly.RuntimeError, `Out of bounds memory access`);

    assert.eq(value, 0);

    for (let i = 0; i < buffer.length; ++i) {
        switch (i) {
        case   0: assert.eq(buffer[i], 128);        break; // Initial ArrayBuffer store.
        case   1: assert.eq(buffer[i], 0xc0defefe); break; // Initial ArrayBuffer store.
        case  32: assert.eq(buffer[i], 0xfeedface); break; // First store from start function.
        case 256: assert.eq(buffer[i], 0xdeadbeef); break; // Data segment.
        default:  assert.eq(buffer[i], 0);          break; // The rest.
        }
    }

    for (let i = 0; i < table.length; ++i) {
        switch (i) {
        case 4:  assert.isFunction(table.get(i)); break;
        case 5:  assert.isFunction(table.get(i)); break;
        default: assert.eq(table.get(i), null); break;
        }
    }

    // Call the imported `func`.
    table.get(4)(0xf00f);
    assert.eq(value, 0xf00f);
    value = 0;

    // Call the start function again on the instance. The instance is otherwise inaccessible!
    buffer[32] = 0; // Reset the location which will be set by the first store.
    assert.throws(() => table.get(5)(), WebAssembly.RuntimeError, `Out of bounds memory access`);
    assert.eq(buffer[32], 0xfeedface); // The first store should still succeed.
    assert.eq(value, 0);
}

assert.asyncTest(StartTrapsAsync());
