Expose the content of Sets and WeakSets through SetMirror.
authoryangguo@chromium.org <yangguo@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 23 Jul 2014 07:33:47 +0000 (07:33 +0000)
committeryangguo@chromium.org <yangguo@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 23 Jul 2014 07:33:47 +0000 (07:33 +0000)
BUG=v8:3093
LOG=Y
R=aandrey@chromium.org, arv@chromium.org, yangguo@chromium.org

Review URL: https://codereview.chromium.org/402423003

Patch from Alexandra Mikhaylova <amikhaylova@google.com>.

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@22541 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/mirror-debugger.js
src/runtime.cc
src/runtime.h
test/mjsunit/harmony/mirror-collections.js
test/mjsunit/runtime-gen/getweaksetvalues.js [new file with mode: 0644]
tools/generate-runtime-tests.py

index e717f6e..35f34a9 100644 (file)
@@ -83,6 +83,8 @@ function MakeMirror(value, opt_transient) {
     mirror = new ScriptMirror(value);
   } else if (IS_MAP(value) || IS_WEAKMAP(value)) {
     mirror = new MapMirror(value);
+  } else if (IS_SET(value) || IS_WEAKSET(value)) {
+    mirror = new SetMirror(value);
   } else if (ObjectIsPromise(value)) {
     mirror = new PromiseMirror(value);
   } else {
@@ -158,6 +160,7 @@ var CONTEXT_TYPE = 'context';
 var SCOPE_TYPE = 'scope';
 var PROMISE_TYPE = 'promise';
 var MAP_TYPE = 'map';
+var SET_TYPE = 'set';
 
 // Maximum length when sending strings through the JSON protocol.
 var kMaxProtocolStringLength = 80;
@@ -214,6 +217,7 @@ var ScopeType = { Global: 0,
 //         - ErrorMirror
 //         - PromiseMirror
 //         - MapMirror
+//         - SetMirror
 //     - PropertyMirror
 //     - InternalPropertyMirror
 //     - FrameMirror
@@ -434,6 +438,15 @@ Mirror.prototype.isMap = function() {
 
 
 /**
+ * Check whether the mirror reflects a set.
+ * @returns {boolean} True if the mirror reflects a set
+ */
+Mirror.prototype.isSet = function() {
+  return this instanceof SetMirror;
+};
+
+
+/**
  * Allocate a handle id for this object.
  */
 Mirror.prototype.allocateHandle_ = function() {
@@ -1304,6 +1317,33 @@ MapMirror.prototype.entries = function() {
 };
 
 
+function SetMirror(value) {
+  %_CallFunction(this, value, SET_TYPE, ObjectMirror);
+}
+inherits(SetMirror, ObjectMirror);
+
+
+/**
+ * Returns an array of elements of a set.
+ * This will keep elements alive for WeakSets.
+ *
+ * @returns {Array.<Object>} Array of elements of a set.
+ */
+SetMirror.prototype.values = function() {
+  if (IS_WEAKSET(this.value_)) {
+    return %GetWeakSetValues(this.value_);
+  }
+
+  var result = [];
+  var iter = %_CallFunction(this.value_, builtins.SetValues);
+  var next;
+  while (!(next = iter.next()).done) {
+    result.push(next.value);
+  }
+  return result;
+};
+
+
 /**
  * Base mirror object for properties.
  * @param {ObjectMirror} mirror The mirror object having this property
index abf9c4e..61e1069 100644 (file)
@@ -1798,6 +1798,28 @@ RUNTIME_FUNCTION(Runtime_WeakCollectionSet) {
 }
 
 
+RUNTIME_FUNCTION(Runtime_GetWeakSetValues) {
+  HandleScope scope(isolate);
+  ASSERT(args.length() == 1);
+  CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, holder, 0);
+  Handle<ObjectHashTable> table(ObjectHashTable::cast(holder->table()));
+  Handle<FixedArray> values =
+      isolate->factory()->NewFixedArray(table->NumberOfElements());
+  {
+    DisallowHeapAllocation no_gc;
+    int number_of_non_hole_elements = 0;
+    for (int i = 0; i < table->Capacity(); i++) {
+      Handle<Object> key(table->KeyAt(i), isolate);
+      if (table->IsKey(*key)) {
+        values->set(number_of_non_hole_elements++, *key);
+      }
+    }
+    ASSERT_EQ(table->NumberOfElements(), number_of_non_hole_elements);
+  }
+  return *isolate->factory()->NewJSArrayWithElements(values);
+}
+
+
 RUNTIME_FUNCTION(Runtime_ClassOf) {
   SealHandleScope shs(isolate);
   ASSERT(args.length() == 1);
index 791fdba..e6bdd15 100644 (file)
@@ -298,6 +298,7 @@ namespace internal {
   F(WeakCollectionSet, 3, 1)                           \
                                                        \
   F(GetWeakMapEntries, 1, 1)                           \
+  F(GetWeakSetValues, 1, 1)                            \
                                                        \
   /* Harmony events */                                 \
   F(EnqueueMicrotask, 1, 1)                            \
index 9df5b68..271cf91 100644 (file)
@@ -22,6 +22,24 @@ function testMapMirror(mirror) {
   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();
@@ -50,6 +68,19 @@ assertSame(o2, entries[1].value);
 assertEquals(undefined, entries[2].key);
 assertEquals(44, entries[2].value);
 
+// 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);
+assertSame(o2, values[0]);
+assertEquals(undefined, values[1]);
+
 // Test the mirror object for WeakMaps
 var weakMap = new WeakMap();
 weakMap.set(o1, 11);
@@ -80,3 +111,34 @@ function testWeakMapEntries(weakMapMirror) {
 }
 
 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);
+  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);
diff --git a/test/mjsunit/runtime-gen/getweaksetvalues.js b/test/mjsunit/runtime-gen/getweaksetvalues.js
new file mode 100644 (file)
index 0000000..e344723
--- /dev/null
@@ -0,0 +1,5 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// AUTO-GENERATED BY tools/generate-runtime-tests.py, DO NOT MODIFY
+// Flags: --allow-natives-syntax --harmony
+var _holder = new WeakMap();
+%GetWeakSetValues(_holder);
index 6b99a47..dd32213 100755 (executable)
@@ -47,11 +47,11 @@ EXPAND_MACROS = [
 # that the parser doesn't bit-rot. Change the values as needed when you add,
 # remove or change runtime functions, but make sure we don't lose our ability
 # to parse them!
-EXPECTED_FUNCTION_COUNT = 419
-EXPECTED_FUZZABLE_COUNT = 334
+EXPECTED_FUNCTION_COUNT = 420
+EXPECTED_FUZZABLE_COUNT = 335
 EXPECTED_CCTEST_COUNT = 8
 EXPECTED_UNKNOWN_COUNT = 4
-EXPECTED_BUILTINS_COUNT = 812
+EXPECTED_BUILTINS_COUNT = 813
 
 
 # Don't call these at all.