// Copyright 2019 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 --experimental-wasm-anyref --expose-gc

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

(function testAnyFuncIdentityFunction() {
  print(arguments.callee.name);
  const builder = new WasmModuleBuilder();
  builder.addFunction('main', kSig_a_a)
      .addBody([kExprGetLocal, 0])
      .exportFunc();

  const instance = builder.instantiate();

  assertThrows(() => instance.exports.main(print), TypeError);
  assertThrows(() => instance.exports.main({'hello': 'world'}), TypeError);
  assertSame(
      instance.exports.main, instance.exports.main(instance.exports.main));
})();

(function testPassAnyFuncToImportedFunction() {
  print(arguments.callee.name);
  const builder = new WasmModuleBuilder();
  const sig_index = builder.addType(kSig_v_a);
  const imp_index = builder.addImport('q', 'func', sig_index);
  builder.addFunction('main', sig_index)
      .addBody([kExprGetLocal, 0, kExprCallFunction, imp_index])
      .exportFunc();

  const main = builder.instantiate({q: {func: checkFunction}}).exports.main;

  function checkFunction(value) {
    assertSame(main, value);
  }

  main(main);
})();

(function testPassAnyFuncWithGCWithLocals() {
  print(arguments.callee.name);
  const builder = new WasmModuleBuilder();
  const ref_sig = builder.addType(kSig_v_a);
  const void_sig = builder.addType(kSig_v_v);
  const imp_index = builder.addImport('q', 'func', ref_sig);
  const gc_index = builder.addImport('q', 'gc', void_sig);
  // First call the gc, then check if the object still exists.
  builder.addFunction('main', ref_sig)
      .addLocals({anyfunc_count: 10})
      .addBody([
        kExprGetLocal,     0,
        kExprSetLocal,     1,  // Set local
        kExprGetLocal,     0,
        kExprSetLocal,     2,  // Set local
        kExprGetLocal,     0,
        kExprSetLocal,     3,  // Set local
        kExprGetLocal,     0,
        kExprSetLocal,     4,  // Set local
        kExprGetLocal,     0,
        kExprSetLocal,     5,  // Set local
        kExprGetLocal,     0,
        kExprSetLocal,     6,  // Set local
        kExprGetLocal,     0,
        kExprSetLocal,     7,  // Set local
        kExprGetLocal,     0,
        kExprSetLocal,     8,  // Set local
        kExprGetLocal,     0,
        kExprSetLocal,     9,  // Set local
        kExprGetLocal,     0,
        kExprSetLocal,     10,        // Set local
        kExprCallFunction, gc_index,  // call gc
        kExprGetLocal,     9,
        kExprCallFunction, imp_index  // call import
      ])
      .exportFunc();

  const main =
      builder.instantiate({q: {func: checkFunction, gc: gc}}).exports.main;

  function checkFunction(value) {
    assertSame(main, value);
  }

  main(main);
})();

(function testPassAnyFuncWithGC() {
  print(arguments.callee.name);
  const builder = new WasmModuleBuilder();
  const ref_sig = builder.addType(kSig_v_a);
  const void_sig = builder.addType(kSig_v_v);
  const imp_index = builder.addImport('q', 'func', ref_sig);
  const gc_index = builder.addImport('q', 'gc', void_sig);
  // First call the gc, then check if the object still exists.
  builder.addFunction('main', ref_sig)
      .addBody([
        kExprCallFunction, gc_index,                    // call gc
        kExprGetLocal, 0, kExprCallFunction, imp_index  // call import
      ])
      .exportFunc();

  function checkFunction(value) {
    assertSame(main, value);
  }

  const main =
      builder.instantiate({q: {func: checkFunction, gc: gc}}).exports.main;

  main(main);
})();

(function testPassAnyFuncWithGCInWrapper() {
  print(arguments.callee.name);
  const builder = new WasmModuleBuilder();
  const kSig_a_iai =
      makeSig([kWasmI32, kWasmAnyFunc, kWasmI32], [kWasmAnyFunc]);
  const sig_index = builder.addType(kSig_a_iai);
  builder.addFunction('main', sig_index)
      .addBody([kExprGetLocal, 1])
      .exportFunc();

  const main = builder.instantiate().exports.main;

  const triggerGCParam = {
    valueOf: () => {
      gc();
      return 17;
    }
  };

  const result = main(triggerGCParam, main, triggerGCParam);
  assertSame(main, result);
})();

(function testAnyFuncDefaultValue() {
  print(arguments.callee.name);
  const builder = new WasmModuleBuilder();
  const sig_index = builder.addType(kSig_a_v);
  builder.addFunction('main', sig_index)
      .addLocals({anyfunc_count: 1})
      .addBody([kExprGetLocal, 0])
      .exportFunc();

  const main = builder.instantiate().exports.main;
  assertEquals(null, main());
})();

(function testAssignNullRefToAnyFuncLocal() {
  print(arguments.callee.name);
  const builder = new WasmModuleBuilder();
  const sig_index = builder.addType(kSig_a_a);
  builder.addFunction('main', sig_index)
      .addBody([kExprRefNull, kExprSetLocal, 0, kExprGetLocal, 0])
      .exportFunc();

  const main = builder.instantiate().exports.main;
  assertEquals(null, main(main));
})();

(function testImplicitReturnNullRefAsAnyFunc() {
  print(arguments.callee.name);
  const builder = new WasmModuleBuilder();
  const sig_index = builder.addType(kSig_a_v);
  builder.addFunction('main', sig_index).addBody([kExprRefNull]).exportFunc();

  const main = builder.instantiate().exports.main;
  assertEquals(null, main());
})();

(function testExplicitReturnNullRefAsAnyFunc() {
  print(arguments.callee.name);
  const builder = new WasmModuleBuilder();
  const sig_index = builder.addType(kSig_a_v);
  builder.addFunction('main', sig_index)
      .addBody([kExprRefNull, kExprReturn])
      .exportFunc();

  const main = builder.instantiate().exports.main;
  assertEquals(null, main());
})();

(function testImplicitReturnAnyFuncAsAnyRef() {
  print(arguments.callee.name);
  const builder = new WasmModuleBuilder();
  const sig_index = builder.addType(kSig_r_v);
  builder.addFunction('main', sig_index)
      .addLocals({anyfunc_count: 1})
      .addBody([kExprGetLocal, 0])
      .exportFunc();

  const main = builder.instantiate().exports.main;
  assertEquals(null, main());
})();

(function testExplicitReturnAnyFuncAsAnyRef() {
  print(arguments.callee.name);
  const builder = new WasmModuleBuilder();
  const sig_index = builder.addType(kSig_r_v);
  builder.addFunction('main', sig_index)
      .addLocals({anyfunc_count: 1})
      .addBody([kExprGetLocal, 0, kExprReturn])
      .exportFunc();

  const main = builder.instantiate().exports.main;
  assertEquals(null, main());
})();

(function testRefFuncOutOfBounds() {
  print(arguments.callee.name);
  const builder = new WasmModuleBuilder();
  builder.addFunction('main', kSig_a_v).addBody([kExprRefFunc, 10]);

  assertThrows(() => builder.toModule(), WebAssembly.CompileError);
})();

(function testRefFuncIsCallable() {
  print(arguments.callee.name);
  const expected = 54;
  const builder = new WasmModuleBuilder();
  const function_index = builder.addFunction('hidden', kSig_i_v)
                             .addBody([kExprI32Const, expected])
                             .index;
  builder.addFunction('main', kSig_a_v)
      .addBody([kExprRefFunc, function_index])
      .exportFunc();

  const instance = builder.instantiate();
  assertEquals(expected, instance.exports.main()());
})();

(function testRefFuncPreservesIdentity() {
  print(arguments.callee.name);
  const expected = 54;
  const builder = new WasmModuleBuilder();
  const foo = builder.addFunction('foo', kSig_i_v)
                  .addBody([kExprI32Const, expected])
                  .exportFunc();
  builder.addFunction('main', kSig_a_v)
      .addBody([kExprRefFunc, foo.index])
      .exportFunc();

  const instance = builder.instantiate();
  assertSame(instance.exports.foo, instance.exports.main());
})();
