// Copyright 2014 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-debug-as debug --expose-gc

function testMapMirror(mirror) {
  // Create JSON representation.
  var serializer = debug.MakeMirrorSerializer();
  var json = JSON.stringify(serializer.serializeValue(mirror));

  // Check the mirror hierachy.
  assertTrue(mirror instanceof debug.Mirror);
  assertTrue(mirror instanceof debug.ValueMirror);
  assertTrue(mirror instanceof debug.ObjectMirror);
  assertTrue(mirror instanceof debug.MapMirror);

  assertTrue(mirror.isMap());

  // Parse JSON representation and check.
  var fromJSON = eval('(' + json + ')');
  assertEquals('map', fromJSON.type);
}

function testSetMirror(mirror) {
  // Create JSON representation.
  var serializer = debug.MakeMirrorSerializer();
  var json = JSON.stringify(serializer.serializeValue(mirror));

  // Check the mirror hierachy.
  assertTrue(mirror instanceof debug.Mirror);
  assertTrue(mirror instanceof debug.ValueMirror);
  assertTrue(mirror instanceof debug.ObjectMirror);
  assertTrue(mirror instanceof debug.SetMirror);

  assertTrue(mirror.isSet());

  // Parse JSON representation and check.
  var fromJSON = eval('(' + json + ')');
  assertEquals('set', fromJSON.type);
}

var o1 = new Object();
var o2 = new Object();
var o3 = new Object();

// Test the mirror object for Maps
var map = new Map();
map.set(o1, 11);
map.set(o2, 22);
map.delete(o1);
var mapMirror = debug.MakeMirror(map);
testMapMirror(mapMirror);

var entries = mapMirror.entries();
assertEquals(1, entries.length);
assertSame(o2, entries[0].key);
assertEquals(22, entries[0].value);
map.set(o1, 33);
map.set(o3, o2);
map.delete(o2);
map.set(undefined, 44);

entries = mapMirror.entries();
assertEquals(3, entries.length);
assertSame(o1, entries[0].key);
assertEquals(33, entries[0].value);
assertSame(o3, entries[1].key);
assertSame(o2, entries[1].value);
assertEquals(undefined, entries[2].key);
assertEquals(44, entries[2].value);

assertEquals(3, mapMirror.entries(0).length);
assertEquals(1, mapMirror.entries(1).length);
assertEquals(2, mapMirror.entries(2).length);

// Test the mirror object for Sets
var set = new Set();
set.add(o1);
set.add(o2);
set.delete(o1);
set.add(undefined);
var setMirror = debug.MakeMirror(set);
testSetMirror(setMirror);
var values = setMirror.values();
assertEquals(2, values.length);
assertEquals(1, setMirror.values(1).length);
assertSame(o2, values[0]);
assertEquals(undefined, values[1]);

// Test the mirror object for WeakMaps
var weakMap = new WeakMap();
weakMap.set(o1, 11);
weakMap.set(new Object(), 22);
weakMap.set(o3, 33);
weakMap.set(new Object(), 44);
var weakMapMirror = debug.MakeMirror(weakMap);
testMapMirror(weakMapMirror);
weakMap.set(new Object(), 55);
assertTrue(weakMapMirror.entries().length <= 5);
gc();

function testWeakMapEntries(weakMapMirror) {
  var entries = weakMapMirror.entries();
  assertEquals(2, entries.length);
  assertEquals(2, weakMapMirror.entries(0).length);
  assertEquals(1, weakMapMirror.entries(1).length);
  var found = 0;
  for (var i = 0; i < entries.length; i++) {
    if (Object.is(entries[i].key, o1)) {
      assertEquals(11, entries[i].value);
      found++;
    }
    if (Object.is(entries[i].key, o3)) {
      assertEquals(33, entries[i].value);
      found++;
    }
  }
  assertEquals(2, found);
}

testWeakMapEntries(weakMapMirror);

// Test the mirror object for WeakSets
var weakSet = new WeakSet();
weakSet.add(o1);
weakSet.add(new Object());
weakSet.add(o2);
weakSet.add(new Object());
weakSet.add(new Object());
weakSet.add(o3);
weakSet.delete(o2);
var weakSetMirror = debug.MakeMirror(weakSet);
testSetMirror(weakSetMirror);
assertTrue(weakSetMirror.values().length <= 5);
gc();

function testWeakSetValues(weakSetMirror) {
  var values = weakSetMirror.values();
  assertEquals(2, values.length);
  assertEquals(2, weakSetMirror.values(0).length);
  assertEquals(1, weakSetMirror.values(1).length);
  var found = 0;
  for (var i = 0; i < values.length; i++) {
    if (Object.is(values[i], o1)) {
      found++;
    }
    if (Object.is(values[i], o3)) {
      found++;
    }
  }
  assertEquals(2, found);
}

testWeakSetValues(weakSetMirror);