// Copyright 2017 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Flags: --expose-wasm --allow-natives-syntax

load("test/mjsunit/wasm/wasm-constants.js");
load("test/mjsunit/wasm/wasm-module-builder.js");

function assertCompiles(buffer) {
  return assertPromiseResult(
      WebAssembly.compile(buffer),
      module => assertTrue(module instanceof WebAssembly.Module),
      ex => assertUnreachable);
}

function assertCompileError(buffer) {
  return assertPromiseResult(
      WebAssembly.compile(buffer), module => assertUnreachable,
      ex => assertTrue(ex instanceof WebAssembly.CompileError));
}

assertPromiseResult(async function basicCompile() {
  let ok_buffer = (() => {
    var builder = new WasmModuleBuilder();
    builder.addFunction('f', kSig_i_v)
        .addBody([kExprI32Const, 42])
        .exportAs('f');
    return builder.toBuffer();
  })();

  // The OK buffer validates and can be made into a module.
  assertTrue(WebAssembly.validate(ok_buffer));
  let ok_module = new WebAssembly.Module(ok_buffer);
  assertTrue(ok_module instanceof WebAssembly.Module);

  // The bad buffer does not validate and cannot be made into a module.
  let bad_buffer = new ArrayBuffer(0);
  assertFalse(WebAssembly.validate(bad_buffer));
  assertThrows(
      () => new WebAssembly.Module(bad_buffer), WebAssembly.CompileError);

  let kNumCompiles = 3;

  // Three compilations of the OK module should succeed.
  for (var i = 0; i < kNumCompiles; i++) {
    await assertCompiles(ok_buffer);
  }

  // Three compilations of the bad module should fail.
  for (var i = 0; i < kNumCompiles; i++) {
    await assertCompileError(bad_buffer);
  }
}());

assertPromiseResult(async function badFunctionInTheMiddle() {
  // We had an error where an exception was generated by a background task and
  // later thrown in a foreground task. The handle to the exception died
  // inbetween, since the HandleScope was left.
  // This test reproduced that error.
  let builder = new WasmModuleBuilder();
  let sig = builder.addType(kSig_i_v);
  for (var i = 0; i < 10; ++i) {
    builder.addFunction('a' + i, sig).addBody([kExprI32Const, 42]);
  }
  builder.addFunction('bad', sig).addBody([]);
  for (var i = 0; i < 10; ++i) {
    builder.addFunction('b' + i, sig).addBody([kExprI32Const, 42]);
  }
  let buffer = builder.toBuffer();
  await assertCompileError(buffer);
}());