Revision: 25100
Author:   [email protected]
Date:     Tue Nov  4 10:02:25 2014 UTC
Log:      Add debug mirror support for ES6 Map/Set iterators.

This is to show values preview of an iterator in DevTools console.

API=v8::Value::IsMapIterator, v8::Value::IsSetIterator
BUG=chromium:427868
[email protected], [email protected], [email protected]
LOG=Y

Review URL: https://codereview.chromium.org/693813002
https://code.google.com/p/v8/source/detail?r=25100

Added:
 /branches/bleeding_edge/test/mjsunit/es6/mirror-iterators.js
Modified:
 /branches/bleeding_edge/include/v8.h
 /branches/bleeding_edge/src/api.cc
 /branches/bleeding_edge/src/factory.cc
 /branches/bleeding_edge/src/factory.h
 /branches/bleeding_edge/src/mirror-debugger.js
 /branches/bleeding_edge/src/runtime/runtime-collections.cc
 /branches/bleeding_edge/src/runtime/runtime.h

=======================================
--- /dev/null
+++ /branches/bleeding_edge/test/mjsunit/es6/mirror-iterators.js Tue Nov 4 10:02:25 2014 UTC
@@ -0,0 +1,62 @@
+// 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
+// Test the mirror object for collection iterators.
+
+function testIteratorMirror(iter, offset, expected) {
+  while (offset-- > 0) iter.next();
+
+  var mirror = debug.MakeMirror(iter);
+  assertTrue(mirror.isIterator());
+
+  var preview = mirror.preview();
+  assertArrayEquals(expected, preview);
+
+  // Check that iterator has not changed after taking preview.
+  var values = [];
+  for (var i of iter) values.push(i);
+  assertArrayEquals(expected, values);
+}
+
+var o1 = { foo: 1 };
+var o2 = { foo: 2 };
+
+var map = new Map();
+map.set(41, 42);
+map.set(o1, o2);
+
+testIteratorMirror(map.keys(), 0, [41, o1]);
+testIteratorMirror(map.values(), 0, [42, o2]);
+testIteratorMirror(map.entries(), 0, [[41, 42], [o1, o2]]);
+
+testIteratorMirror(map.keys(), 1, [o1]);
+testIteratorMirror(map.values(), 1, [o2]);
+testIteratorMirror(map.entries(), 1, [[o1, o2]]);
+
+testIteratorMirror(map.keys(), 2, []);
+testIteratorMirror(map.values(), 2, []);
+testIteratorMirror(map.entries(), 2, []);
+
+var set = new Set();
+set.add(41);
+set.add(42);
+set.add(o1);
+set.add(o2);
+
+testIteratorMirror(set.keys(), 0, [41, 42, o1, o2]);
+testIteratorMirror(set.values(), 0, [41, 42, o1, o2]);
+testIteratorMirror(set.entries(), 0, [[41, 41], [42, 42], [o1, o1], [o2, o2]]);
+
+testIteratorMirror(set.keys(), 1, [42, o1, o2]);
+testIteratorMirror(set.values(), 1, [42, o1, o2]);
+testIteratorMirror(set.entries(), 1, [[42, 42], [o1, o1], [o2, o2]]);
+
+testIteratorMirror(set.keys(), 3, [o2]);
+testIteratorMirror(set.values(), 3, [o2]);
+testIteratorMirror(set.entries(), 3, [[o2, o2]]);
+
+testIteratorMirror(set.keys(), 5, []);
+testIteratorMirror(set.values(), 5, []);
+testIteratorMirror(set.entries(), 5, []);
=======================================
--- /branches/bleeding_edge/include/v8.h        Mon Nov  3 17:23:55 2014 UTC
+++ /branches/bleeding_edge/include/v8.h        Tue Nov  4 10:02:25 2014 UTC
@@ -1625,6 +1625,18 @@
    */
   bool IsSet() const;

+  /**
+   * Returns true if this value is a Map Iterator.
+   * This is an experimental feature.
+   */
+  bool IsMapIterator() const;
+
+  /**
+   * Returns true if this value is a Set Iterator.
+   * This is an experimental feature.
+   */
+  bool IsSetIterator() const;
+
   /**
    * Returns true if this value is a WeakMap.
    * This is an experimental feature.
=======================================
--- /branches/bleeding_edge/src/api.cc  Mon Nov  3 17:23:55 2014 UTC
+++ /branches/bleeding_edge/src/api.cc  Tue Nov  4 10:02:25 2014 UTC
@@ -2569,6 +2569,16 @@
 bool Value::IsGeneratorObject() const {
   return Utils::OpenHandle(this)->IsJSGeneratorObject();
 }
+
+
+bool Value::IsMapIterator() const {
+  return Utils::OpenHandle(this)->IsJSMapIterator();
+}
+
+
+bool Value::IsSetIterator() const {
+  return Utils::OpenHandle(this)->IsJSSetIterator();
+}


 Local<String> Value::ToString(Isolate* v8_isolate) const {
=======================================
--- /branches/bleeding_edge/src/factory.cc      Mon Oct 20 11:42:56 2014 UTC
+++ /branches/bleeding_edge/src/factory.cc      Tue Nov  4 10:02:25 2014 UTC
@@ -1720,6 +1720,22 @@
       isolate()->heap()->AllocateJSObject(*data_view_fun),
       JSDataView);
 }
+
+
+Handle<JSMapIterator> Factory::NewJSMapIterator() {
+  Handle<Map> map(isolate()->native_context()->map_iterator_map());
+  CALL_HEAP_FUNCTION(isolate(),
+                     isolate()->heap()->AllocateJSObjectFromMap(*map),
+                     JSMapIterator);
+}
+
+
+Handle<JSSetIterator> Factory::NewJSSetIterator() {
+  Handle<Map> map(isolate()->native_context()->set_iterator_map());
+  CALL_HEAP_FUNCTION(isolate(),
+                     isolate()->heap()->AllocateJSObjectFromMap(*map),
+                     JSSetIterator);
+}


 namespace {
=======================================
--- /branches/bleeding_edge/src/factory.h       Mon Oct 20 11:42:56 2014 UTC
+++ /branches/bleeding_edge/src/factory.h       Tue Nov  4 10:02:25 2014 UTC
@@ -445,6 +445,10 @@
   Handle<JSDataView> NewJSDataView(Handle<JSArrayBuffer> buffer,
                                    size_t byte_offset, size_t byte_length);

+ // TODO(aandrey): Maybe these should take table, index and kind arguments.
+  Handle<JSMapIterator> NewJSMapIterator();
+  Handle<JSSetIterator> NewJSSetIterator();
+
   // Allocates a Harmony proxy.
Handle<JSProxy> NewJSProxy(Handle<Object> handler, Handle<Object> prototype);

=======================================
--- /branches/bleeding_edge/src/mirror-debugger.js Thu Sep 18 13:30:15 2014 UTC +++ /branches/bleeding_edge/src/mirror-debugger.js Tue Nov 4 10:02:25 2014 UTC
@@ -85,6 +85,8 @@
     mirror = new MapMirror(value);
   } else if (IS_SET(value) || IS_WEAKSET(value)) {
     mirror = new SetMirror(value);
+  } else if (IS_MAP_ITERATOR(value) || IS_SET_ITERATOR(value)) {
+    mirror = new IteratorMirror(value);
   } else if (ObjectIsPromise(value)) {
     mirror = new PromiseMirror(value);
   } else if (IS_GENERATOR(value)) {
@@ -163,6 +165,7 @@
 var PROMISE_TYPE = 'promise';
 var MAP_TYPE = 'map';
 var SET_TYPE = 'set';
+var ITERATOR_TYPE = 'iterator';
 var GENERATOR_TYPE = 'generator';

 // Maximum length when sending strings through the JSON protocol.
@@ -217,6 +220,7 @@
 //         - PromiseMirror
 //         - MapMirror
 //         - SetMirror
+//         - IteratorMirror
 //         - GeneratorMirror
 //     - PropertyMirror
 //     - InternalPropertyMirror
@@ -455,6 +459,15 @@
 };


+/**
+ * Check whether the mirror reflects an iterator.
+ * @returns {boolean} True if the mirror reflects an iterator
+ */
+Mirror.prototype.isIterator = function() {
+  return this instanceof IteratorMirror;
+};
+
+
 /**
  * Allocate a handle id for this object.
  */
@@ -1343,6 +1356,16 @@
 inherits(SetMirror, ObjectMirror);


+function IteratorGetValues_(iter, next_function) {
+  var result = [];
+  var next;
+  while (!(next = %_CallFunction(iter, next_function)).done) {
+    result.push(next.value);
+  }
+  return result;
+}
+
+
 /**
  * Returns an array of elements of a set.
  * This will keep elements alive for WeakSets.
@@ -1354,13 +1377,31 @@
     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 IteratorGetValues_(iter, builtins.SetIteratorNextJS);
+};
+
+
+function IteratorMirror(value) {
+  %_CallFunction(this, value, ITERATOR_TYPE, ObjectMirror);
+}
+inherits(IteratorMirror, ObjectMirror);
+
+
+/**
+ * Returns a preview of elements of an iterator.
+ * Does not change the backing iterator state.
+ *
+ * @returns {Array.<Object>} Array of elements of an iterator.
+ */
+IteratorMirror.prototype.preview = function() {
+  if (IS_MAP_ITERATOR(this.value_)) {
+    return IteratorGetValues_(%MapIteratorClone(this.value_),
+                              builtins.MapIteratorNextJS);
+  } else if (IS_SET_ITERATOR(this.value_)) {
+    return IteratorGetValues_(%SetIteratorClone(this.value_),
+                              builtins.SetIteratorNextJS);
   }
-  return result;
 };


=======================================
--- /branches/bleeding_edge/src/runtime/runtime-collections.cc Fri Oct 31 13:11:30 2014 UTC +++ /branches/bleeding_edge/src/runtime/runtime-collections.cc Tue Nov 4 10:02:25 2014 UTC
@@ -90,6 +90,20 @@
   holder->set_kind(Smi::FromInt(kind));
   return isolate->heap()->undefined_value();
 }
+
+
+RUNTIME_FUNCTION(Runtime_SetIteratorClone) {
+  HandleScope scope(isolate);
+  DCHECK(args.length() == 1);
+  CONVERT_ARG_HANDLE_CHECKED(JSSetIterator, holder, 0);
+
+  Handle<JSSetIterator> result = isolate->factory()->NewJSSetIterator();
+  result->set_table(holder->table());
+  result->set_index(Smi::FromInt(Smi::cast(holder->index())->value()));
+  result->set_kind(Smi::FromInt(Smi::cast(holder->kind())->value()));
+
+  return *result;
+}


 RUNTIME_FUNCTION(Runtime_SetIteratorNext) {
@@ -195,6 +209,20 @@
   holder->set_kind(Smi::FromInt(kind));
   return isolate->heap()->undefined_value();
 }
+
+
+RUNTIME_FUNCTION(Runtime_MapIteratorClone) {
+  HandleScope scope(isolate);
+  DCHECK(args.length() == 1);
+  CONVERT_ARG_HANDLE_CHECKED(JSMapIterator, holder, 0);
+
+  Handle<JSMapIterator> result = isolate->factory()->NewJSMapIterator();
+  result->set_table(holder->table());
+  result->set_index(Smi::FromInt(Smi::cast(holder->index())->value()));
+  result->set_kind(Smi::FromInt(Smi::cast(holder->kind())->value()));
+
+  return *result;
+}


 RUNTIME_FUNCTION(Runtime_GetWeakMapEntries) {
=======================================
--- /branches/bleeding_edge/src/runtime/runtime.h Wed Oct 29 11:45:57 2014 UTC +++ /branches/bleeding_edge/src/runtime/runtime.h Tue Nov 4 10:02:25 2014 UTC
@@ -310,6 +310,7 @@
   F(SetGetSize, 1, 1)                                  \
                                                        \
   F(SetIteratorInitialize, 3, 1)                       \
+  F(SetIteratorClone, 1, 1)                            \
   F(SetIteratorNext, 2, 1)                             \
                                                        \
   /* Harmony maps */                                   \
@@ -322,6 +323,7 @@
   F(MapGetSize, 1, 1)                                  \
                                                        \
   F(MapIteratorInitialize, 3, 1)                       \
+  F(MapIteratorClone, 1, 1)                            \
   F(MapIteratorNext, 2, 1)                             \
                                                        \
   /* Harmony weak maps and sets */                     \

--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to