// Copyright 2016 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: --harmony-object-own-property-descriptors
// Flags: --allow-natives-syntax

function DataDescriptor(value) {
  return { "enumerable": true, "configurable": true, "writable": true, value };
}


function TestMeta() {
  assertEquals(1, Object.getOwnPropertyDescriptors.length);
  assertEquals(Function.prototype,
               Object.getPrototypeOf(Object.getOwnPropertyDescriptors));
  assertEquals(
      'getOwnPropertyDescriptors', Object.getOwnPropertyDescriptors.name);
  var desc = Reflect.getOwnPropertyDescriptor(
      Object, 'getOwnPropertyDescriptors');
  assertFalse(desc.enumerable);
  assertTrue(desc.writable);
  assertTrue(desc.configurable);
}
TestMeta();


function TestToObject() {
  assertThrows(function() {
    Object.getOwnPropertyDescriptors(null);
  }, TypeError);

  assertThrows(function() {
    Object.getOwnPropertyDescriptors(undefined);
  }, TypeError);

  assertThrows(function() {
    Object.getOwnPropertyDescriptors();
  }, TypeError);
}
TestToObject();


function TestPrototypeProperties() {
  function F() {};
  F.prototype.a = "A";
  F.prototype.b = "B";

  var F2 = new F();
  Object.defineProperties(F2, {
    "b": {
      enumerable: false,
      configurable: true,
      writable: false,
      value: "Shadowed 'B'"
    },
    "c": {
      enumerable: false,
      configurable: true,
      writable: false,
      value: "C"
    }
  });

  assertEquals({
    "b": {
      enumerable: false,
      configurable: true,
      writable: false,
      value: "Shadowed 'B'"
    },
    "c": {
      enumerable: false,
      configurable: true,
      writable: false,
      value: "C"
    }
  }, Object.getOwnPropertyDescriptors(F2));
}
TestPrototypeProperties();


function TestPrototypeProperties() {
  function F() {};
  F.prototype.a = "A";
  F.prototype.b = "B";

  var F2 = new F();
  Object.defineProperties(F2, {
    "b": {
      enumerable: false,
      configurable: true,
      writable: false,
      value: "Shadowed 'B'"
    },
    "c": {
      enumerable: false,
      configurable: true,
      writable: false,
      value: "C"
    }
  });

  assertEquals({
    "b": {
      enumerable: false,
      configurable: true,
      writable: false,
      value: "Shadowed 'B'"
    },
    "c": {
      enumerable: false,
      configurable: true,
      writable: false,
      value: "C"
    }
  }, Object.getOwnPropertyDescriptors(F2));
}
TestPrototypeProperties();


function TestTypeFilteringAndOrder() {
  var log = [];
  var sym = Symbol("foo");
  var psym = %CreatePrivateSymbol("private");
  var O = {
    0: 0,
    [sym]: 3,
    "a": 2,
    [psym]: 4,
    1: 1,
  };
  var P = new Proxy(O, {
    ownKeys(target) {
      log.push("ownKeys()");
      return Reflect.ownKeys(target);
    },
    getOwnPropertyDescriptor(target, name) {
      log.push(`getOwnPropertyDescriptor(${String(name)})`);
      return Reflect.getOwnPropertyDescriptor(target, name);
    },
    get(target, name) { assertUnreachable(); },
    set(target, name, value) { assertUnreachable(); },
    deleteProperty(target, name) { assertUnreachable(); },
    defineProperty(target, name, desc) { assertUnreachable(); }
  });

  var result1 = Object.getOwnPropertyDescriptors(O);
  assertEquals({
    0: DataDescriptor(0),
    1: DataDescriptor(1),
    "a": DataDescriptor(2),
    [sym]: DataDescriptor(3)
  }, result1);

  var result2 = Object.getOwnPropertyDescriptors(P);
  assertEquals([
    "ownKeys()",
    "getOwnPropertyDescriptor(0)",
    "getOwnPropertyDescriptor(1)",
    "getOwnPropertyDescriptor(a)",
    "getOwnPropertyDescriptor(Symbol(foo))"
  ], log);
  assertEquals({
    0: DataDescriptor(0),
    1: DataDescriptor(1),
    "a": DataDescriptor(2),
    [sym]: DataDescriptor(3)
  }, result2);
}
TestTypeFilteringAndOrder();


function TestDuplicateKeys() {
  var i = 0;
  var log = [];
  var P = new Proxy({}, {
    ownKeys() {
      log.push(`ownKeys()`);
      return ["A", "A"];
    },
    getOwnPropertyDescriptor(t, name) {
      log.push(`getOwnPropertyDescriptor(${name})`);
      if (i++) return;
      return {
        configurable: true,
        writable: false,
        value: "VALUE"
      };
    },
    get(target, name) { assertUnreachable(); },
    set(target, name, value) { assertUnreachable(); },
    deleteProperty(target, name) { assertUnreachable(); },
    defineProperty(target, name, desc) { assertUnreachable(); }
  });

  var result = Object.getOwnPropertyDescriptors(P);
  assertEquals({ "A": undefined }, result);
  assertTrue(result.hasOwnProperty("A"));
  assertEquals([
    "ownKeys()",
    "getOwnPropertyDescriptor(A)",
    "getOwnPropertyDescriptor(A)"
  ], log);
}
TestDuplicateKeys();
