// 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.

Debug = debug.Debug

var exception = null;
var date = new Date();
var map = new Map().set("a", "b").set("c", "d");
var set = new Set([1, 2]);
var weak_key = [];
var weak_map = new WeakMap().set(weak_key, "a").set({}, "b");
var weak_set = new WeakSet([weak_key, {}]);
var add = function (a, b) { return a + b; };
var number_value = 13;
function get_number() {
  return typeof(number_value);
};

function listener(event, exec_state, event_data, data) {
  if (event != Debug.DebugEvent.Break) return;
  try {
    function success(expectation, source) {
      var result = exec_state.frame(0).evaluate(source, true).value();
      if (expectation !== undefined) assertEquals(expectation, result);
    }
    function fail(source) {
      assertThrows(() => exec_state.frame(0).evaluate(source, true),
                   EvalError);
    }

    // Test Function-related functions.
    success("func", `(function func(){}).prototype.constructor.name`);
    success("[object Object]", `(function func(){}).prototype.toString()`);
    success(12, `add.bind(null, 10)(2)`);
    success(3, `add.call(null, 1, 2)`);
    success(3, `add.apply(null, [1, 2])`);

    // Test Date.prototype functions.
    success(undefined, `Date()`);
    success(undefined, `new Date()`);
    success(undefined, `Date.now()`);
    success(undefined, `Date.parse(1)`);
    for (f of Object.getOwnPropertyNames(Date.prototype)) {
      if (typeof Date.prototype[f] === "function") {
        if (f.startsWith("set")) {
          fail(`date.${f}(5);`, true);
        } else if (f.startsWith("toLocale") && typeof Intl === "undefined") {
          continue;
        } else {
          success(undefined, `date.${f}();`);
        }
      }
    }

    // Test Boolean.
    success(true, `Boolean(1)`);
    success(new Boolean(true), `new Boolean(1)`);
    success("true", `true.toString()`);
    success(true, `true.valueOf()`);

    // Test global functions.
    success(1, `parseInt("1")`);
    success(1.3, `parseFloat("1.3")`);
    success("abc", `decodeURI("abc")`);
    success("abc", `encodeURI("abc")`);
    success("abc", `decodeURIComponent("abc")`);
    success("abc", `encodeURIComponent("abc")`);
    success("abc", `escape("abc")`);
    success("abc", `unescape("abc")`);
    success(true, `isFinite(0)`);
    success(true, `isNaN(0/0)`);
    success("object", `typeof date`);
    success("number", `get_number()`);

    // Test Map functions.
    success(undefined, `new Map()`);
    success("[object Map]", `map.toString()`);
    success("b", `map.get("a")`);
    success(true, `map.get("x") === undefined`);
    success(undefined, `map.entries()`);
    success(undefined, `map.keys()`);
    success(undefined, `map.values()`);
    success(undefined, `map.forEach(()=>1)`);
    success(true, `map.has("c")`);
    success(2, `map.size`);
    success(undefined, `new Map([[1, 2]])`);
    fail(`map.delete("a")`);
    fail(`map.clear()`);
    fail(`map.set("x", "y")`);

    // Test Set functions.
    success(undefined, `new Set()`);
    success("[object Set]", `set.toString()`);
    success(undefined, `set.entries()`);
    success(undefined, `set.keys()`);
    success(undefined, `set.values()`);
    success(undefined, `set.forEach(()=>1)`);
    success(true, `set.has(1)`);
    success(2, `set.size`);
    success(1, `new Set([1]).size`);
    fail(`set.add(2)`);
    fail(`set.delete(1)`);
    fail(`set.clear()`);

    // Test WeakMap functions.
    success(undefined, `new WeakMap()`);
    success("[object WeakMap]", `weak_map.toString()`);
    success("a", `weak_map.get(weak_key)`);
    success(true, `weak_map.get([]) === undefined`);
    success(true, `weak_map.has(weak_key)`);
    fail(`new WeakMap([[[], {}]])`);
    fail(`weak_map.delete("a")`);
    fail(`weak_map.set("x", "y")`);

    // Test WeakSet functions.
    success(undefined, `new WeakSet()`);
    success("[object WeakSet]", `weak_set.toString()`);
    success(true, `weak_set.has(weak_key)`);
    fail(`new WeakSet([[], {}])`);
    fail(`weak_set.add([])`);
    fail(`weak_set.delete("a")`);

    // Test BigInt functions.
    success(10n, `BigInt('10')`);
    success(10n, `BigInt.asIntN(10, 10n)`);
    success(10n, `BigInt.asUintN(10, 10n)`);
    success("10", `10n.toString()`);
    success(10n, `10n.valueOf()`);
  } catch (e) {
    exception = e;
    print(e, e.stack);
  };
};

// Add the debug event listener.
Debug.setListener(listener);

function f() {
  debugger;
};

f();

assertNull(exception);
