Revision: 21994
Author:   [email protected]
Date:     Wed Jun 25 07:43:14 2014 UTC
Log:      Add @@iterator support for strings

[email protected]
BUG=

Review URL: https://codereview.chromium.org/335423002
http://code.google.com/p/v8/source/detail?r=21994

Added:
 /branches/bleeding_edge/src/string-iterator.js
 /branches/bleeding_edge/test/mjsunit/harmony/string-iterator.js
Modified:
 /branches/bleeding_edge/src/bootstrapper.cc
 /branches/bleeding_edge/test/mjsunit/harmony/iteration-semantics.js
 /branches/bleeding_edge/tools/generate-runtime-tests.py
 /branches/bleeding_edge/tools/gyp/v8.gyp

=======================================
--- /dev/null
+++ /branches/bleeding_edge/src/string-iterator.js Wed Jun 25 07:43:14 2014 UTC
@@ -0,0 +1,106 @@
+// 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.
+
+'use strict';
+
+
+// This file relies on the fact that the following declaration has been made
+// in runtime.js:
+// var $String = global.String;
+
+
+var stringIteratorIteratedStringSymbol =
+    GLOBAL_PRIVATE("StringIterator#iteratedString");
+var stringIteratorNextIndexSymbol = GLOBAL_PRIVATE("StringIterator#next");
+
+
+function StringIterator() {}
+
+
+// 21.1.5.1 CreateStringIterator Abstract Operation
+function CreateStringIterator(string) {
+  var s = TO_STRING_INLINE(string);
+  var iterator = new StringIterator;
+  SET_PRIVATE(iterator, stringIteratorIteratedStringSymbol, s);
+  SET_PRIVATE(iterator, stringIteratorNextIndexSymbol, 0);
+  return iterator;
+}
+
+
+// 21.1.5.2.2 %StringIteratorPrototype%[@@iterator]
+function StringIteratorIterator() {
+  return this;
+}
+
+
+// 21.1.5.2.1 %StringIteratorPrototype%.next( )
+function StringIteratorNext() {
+  var iterator = ToObject(this);
+
+  if (!HAS_PRIVATE(iterator, stringIteratorIteratedStringSymbol)) {
+    throw MakeTypeError('incompatible_method_receiver',
+                        ['String Iterator.prototype.next']);
+  }
+
+  var s = GET_PRIVATE(iterator, stringIteratorIteratedStringSymbol);
+  if (IS_UNDEFINED(s)) {
+    return CreateIteratorResultObject(UNDEFINED, true);
+  }
+
+  var position = GET_PRIVATE(iterator, stringIteratorNextIndexSymbol);
+  var length = TO_UINT32(s.length);
+
+  if (position >= length) {
+    SET_PRIVATE(iterator, stringIteratorIteratedStringSymbol, UNDEFINED);
+    return CreateIteratorResultObject(UNDEFINED, true);
+  }
+
+  var first = %_StringCharCodeAt(s, position);
+  var resultString = %_StringCharFromCode(first);
+  position++;
+
+  if (first >= 0xD800 && first <= 0xDBFF && position < length) {
+    var second = %_StringCharCodeAt(s, position);
+    if (second >= 0xDC00 && second <= 0xDFFF) {
+      resultString += %_StringCharFromCode(second);
+      position++;
+    }
+  }
+
+  SET_PRIVATE(iterator, stringIteratorNextIndexSymbol, position);
+
+  return CreateIteratorResultObject(resultString, false);
+}
+
+
+function SetUpStringIterator() {
+  %CheckIsBootstrapping();
+
+  %FunctionSetPrototype(StringIterator, new $Object());
+  %FunctionSetInstanceClassName(StringIterator, 'String Iterator');
+
+  InstallFunctions(StringIterator.prototype, DONT_ENUM, $Array(
+    'next', StringIteratorNext
+  ));
+  %FunctionSetName(StringIteratorIterator, '[Symbol.iterator]');
+ %SetProperty(StringIterator.prototype, symbolIterator, StringIteratorIterator,
+      DONT_ENUM);
+}
+SetUpStringIterator();
+
+
+// 21.1.3.27 String.prototype [ @@iterator ]( )
+function StringPrototypeIterator() {
+  return CreateStringIterator(this);
+}
+
+
+function ExtendStringPrototypeWithIterator() {
+  %CheckIsBootstrapping();
+
+  %FunctionSetName(StringPrototypeIterator, '[Symbol.iterator]');
+  %SetProperty($String.prototype, symbolIterator, StringPrototypeIterator,
+      DONT_ENUM);
+}
+ExtendStringPrototypeWithIterator();
=======================================
--- /dev/null
+++ /branches/bleeding_edge/test/mjsunit/harmony/string-iterator.js Wed Jun 25 07:43:14 2014 UTC
@@ -0,0 +1,91 @@
+// 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: --harmony-iteration
+
+
+function TestStringPrototypeIterator() {
+  assertTrue(String.prototype.hasOwnProperty(Symbol.iterator));
+  assertFalse("".hasOwnProperty(Symbol.iterator));
+  assertFalse("".propertyIsEnumerable(Symbol.iterator));
+}
+TestStringPrototypeIterator();
+
+
+function assertIteratorResult(value, done, result) {
+  assertEquals({value: value, done: done}, result);
+}
+
+
+function TestManualIteration() {
+  var string = "abc";
+  var iterator = string[Symbol.iterator]();
+  assertIteratorResult('a', false, iterator.next());
+  assertIteratorResult('b', false, iterator.next());
+  assertIteratorResult('c', false, iterator.next());
+  assertIteratorResult(void 0, true, iterator.next());
+  assertIteratorResult(void 0, true, iterator.next());
+}
+TestManualIteration();
+
+
+function TestSurrogatePairs() {
+  var lo = "\uD834";
+  var hi = "\uDF06";
+  var pair = lo + hi;
+  var string = "abc" + pair + "def" + lo + pair + hi + lo;
+  var iterator = string[Symbol.iterator]();
+  assertIteratorResult('a', false, iterator.next());
+  assertIteratorResult('b', false, iterator.next());
+  assertIteratorResult('c', false, iterator.next());
+  assertIteratorResult(pair, false, iterator.next());
+  assertIteratorResult('d', false, iterator.next());
+  assertIteratorResult('e', false, iterator.next());
+  assertIteratorResult('f', false, iterator.next());
+  assertIteratorResult(lo, false, iterator.next());
+  assertIteratorResult(pair, false, iterator.next());
+  assertIteratorResult(hi, false, iterator.next());
+  assertIteratorResult(lo, false, iterator.next());
+  assertIteratorResult(void 0, true, iterator.next());
+  assertIteratorResult(void 0, true, iterator.next());
+}
+TestSurrogatePairs();
+
+
+function TestStringIteratorPrototype() {
+  var iterator = ""[Symbol.iterator]();
+  var StringIteratorPrototype = iterator.__proto__;
+  assertFalse(StringIteratorPrototype.hasOwnProperty('constructor'));
+  assertEquals(StringIteratorPrototype.__proto__, Object.prototype);
+  assertArrayEquals(['next'],
+      Object.getOwnPropertyNames(StringIteratorPrototype));
+  assertEquals('[object String Iterator]', "" + iterator);
+}
+TestStringIteratorPrototype();
+
+
+function TestForOf() {
+  var lo = "\uD834";
+  var hi = "\uDF06";
+  var pair = lo + hi;
+  var string = "abc" + pair + "def" + lo + pair + hi + lo;
+  var expected = ['a', 'b', 'c', pair, 'd', 'e', 'f', lo, pair, hi, lo];
+
+  var i = 0;
+  for (var char of string) {
+    assertEquals(expected[i++], char);
+  }
+
+  assertEquals(expected.length, i);
+}
+TestForOf();
+
+
+function TestNonOwnSlots() {
+  var iterator = ""[Symbol.iterator]();
+  var object = {__proto__: iterator};
+
+  assertThrows(function() { object.next(); }, TypeError);
+}
+TestNonOwnSlots();
=======================================
--- /branches/bleeding_edge/src/bootstrapper.cc Tue Jun 24 14:53:48 2014 UTC
+++ /branches/bleeding_edge/src/bootstrapper.cc Wed Jun 25 07:43:14 2014 UTC
@@ -2052,6 +2052,7 @@
     INSTALL_EXPERIMENTAL_NATIVE(i, collections, "collection-iterator.js")
     INSTALL_EXPERIMENTAL_NATIVE(i, generators, "generator.js")
     INSTALL_EXPERIMENTAL_NATIVE(i, iteration, "array-iterator.js")
+    INSTALL_EXPERIMENTAL_NATIVE(i, iteration, "string-iterator.js")
     INSTALL_EXPERIMENTAL_NATIVE(i, strings, "harmony-string.js")
     INSTALL_EXPERIMENTAL_NATIVE(i, arrays, "harmony-array.js")
     INSTALL_EXPERIMENTAL_NATIVE(i, maths, "harmony-math.js")
=======================================
--- /branches/bleeding_edge/test/mjsunit/harmony/iteration-semantics.js Thu Jun 12 17:31:54 2014 UTC +++ /branches/bleeding_edge/test/mjsunit/harmony/iteration-semantics.js Wed Jun 25 07:43:14 2014 UTC
@@ -219,7 +219,7 @@

 // Other non-iterators do cause an error.
 assertThrows('fold(sum, 0, unreachable({}))', TypeError);
-assertThrows('fold(sum, 0, unreachable("foo"))', TypeError);
+assertThrows('fold(sum, 0, unreachable(false))', TypeError);
 assertThrows('fold(sum, 0, unreachable(37))', TypeError);

 // "next" is looked up each time.
=======================================
--- /branches/bleeding_edge/tools/generate-runtime-tests.py Mon Jun 23 18:05:57 2014 UTC +++ /branches/bleeding_edge/tools/generate-runtime-tests.py Wed Jun 25 07:43:14 2014 UTC
@@ -51,7 +51,7 @@
 EXPECTED_FUZZABLE_COUNT = 326
 EXPECTED_CCTEST_COUNT = 6
 EXPECTED_UNKNOWN_COUNT = 4
-EXPECTED_BUILTINS_COUNT = 800
+EXPECTED_BUILTINS_COUNT = 807


 # Don't call these at all.
=======================================
--- /branches/bleeding_edge/tools/gyp/v8.gyp    Tue Jun 24 14:03:24 2014 UTC
+++ /branches/bleeding_edge/tools/gyp/v8.gyp    Wed Jun 25 07:43:14 2014 UTC
@@ -1261,6 +1261,7 @@
           '../../src/collection-iterator.js',
           '../../src/generator.js',
           '../../src/array-iterator.js',
+          '../../src/string-iterator.js',
           '../../src/harmony-string.js',
           '../../src/harmony-array.js',
           '../../src/harmony-math.js'

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