Reviewers: rossberg,
Description:
yield* calls @@iterator on iterable
[email protected]
BUG=v8:3422
LOG=N
Please review this at https://codereview.chromium.org/430693003/
SVN Base: https://v8.googlecode.com/svn/branches/bleeding_edge
Affected files (+61, -20 lines):
M src/parser.h
M src/parser.cc
M src/preparser.h
M test/mjsunit/harmony/generators-iteration.js
Index: src/parser.cc
diff --git a/src/parser.cc b/src/parser.cc
index
ead37b0a2cf155e32b1bf590a22e3f4c48339ce9..a3970db20640bca0515556ec0bc31b2724807340
100644
--- a/src/parser.cc
+++ b/src/parser.cc
@@ -665,6 +665,19 @@ Expression* ParserTraits::ExpressionFromString(
}
+Expression* ParserTraits::GetIterator(
+ Expression* iterable, AstNodeFactory<AstConstructionVisitor>* factory)
{
+ Expression* iterator_symbol_literal =
+ factory->NewSymbolLiteral("symbolIterator", RelocInfo::kNoPosition);
+ int pos = iterable->position();
+ Expression* prop =
+ factory->NewProperty(iterable, iterator_symbol_literal, pos);
+ Zone* zone = parser_->zone();
+ ZoneList<Expression*>* args = new (zone) ZoneList<Expression*>(0, zone);
+ return factory->NewCall(prop, args, pos);
+}
+
+
Literal* ParserTraits::GetLiteralTheHole(
int position, AstNodeFactory<AstConstructionVisitor>* factory) {
return factory->NewTheHoleLiteral(RelocInfo::kNoPosition);
@@ -2773,23 +2786,9 @@ void
Parser::InitializeForEachStatement(ForEachStatement* stmt,
Expression* assign_each;
// var iterator = subject[Symbol.iterator]();
- {
- Expression* iterator_symbol_literal =
- factory()->NewSymbolLiteral("symbolIterator",
RelocInfo::kNoPosition);
- // FIXME(wingo): Unhappily, it will be a common error that the RHS
of a
- // for-of doesn't have a Symbol.iterator property. We should do
better
- // than informing the user that "undefined is not a function".
- int pos = subject->position();
- Expression* iterator_property =
- factory()->NewProperty(subject, iterator_symbol_literal, pos);
- ZoneList<Expression*>* iterator_arguments =
- new(zone()) ZoneList<Expression*>(0, zone());
- Expression* iterator_call = factory()->NewCall(
- iterator_property, iterator_arguments, pos);
- Expression* iterator_proxy = factory()->NewVariableProxy(iterator);
- assign_iterator = factory()->NewAssignment(
- Token::ASSIGN, iterator_proxy, iterator_call,
RelocInfo::kNoPosition);
- }
+ assign_iterator = factory()->NewAssignment(
+ Token::ASSIGN, factory()->NewVariableProxy(iterator),
+ GetIterator(subject, factory()), RelocInfo::kNoPosition);
// var result = iterator.next();
{
Index: src/parser.h
diff --git a/src/parser.h b/src/parser.h
index
2d5ce2f3760bc929fa04eb967c54ef39db691e63..fd24e8d4e952b4d33408f3fc03c0fcb83ec3bf43
100644
--- a/src/parser.h
+++ b/src/parser.h
@@ -543,6 +543,8 @@ class ParserTraits {
Expression* ExpressionFromString(
int pos, Scanner* scanner,
AstNodeFactory<AstConstructionVisitor>* factory);
+ Expression* GetIterator(Expression* iterable,
+ AstNodeFactory<AstConstructionVisitor>* factory);
ZoneList<v8::internal::Expression*>* NewExpressionList(int size, Zone*
zone) {
return new(zone) ZoneList<v8::internal::Expression*>(size, zone);
}
Index: src/preparser.h
diff --git a/src/preparser.h b/src/preparser.h
index
d1d1c53e0b16979d91c4d233b1dd0e3096e1f1f1..6058f89cc025d29f35bd09046ea9d4956cb6a081
100644
--- a/src/preparser.h
+++ b/src/preparser.h
@@ -1232,6 +1232,11 @@ class PreParserTraits {
Scanner* scanner,
PreParserFactory* factory =
NULL);
+ PreParserExpression GetIterator(PreParserExpression iterable,
+ PreParserFactory* factory) {
+ return PreParserExpression::Default();
+ }
+
static PreParserExpressionList NewExpressionList(int size, void* zone) {
return PreParserExpressionList();
}
@@ -2094,6 +2099,10 @@ ParserBase<Traits>::ParseYieldExpression(bool* ok) {
break;
}
}
+ if (kind == Yield::DELEGATING) {
+ // var iterator = subject[Symbol.iterator]();
+ expression = this->GetIterator(expression, factory());
+ }
typename Traits::Type::YieldExpression yield =
factory()->NewYield(generator_object, expression, kind, pos);
if (kind == Yield::DELEGATING) {
Index: test/mjsunit/harmony/generators-iteration.js
diff --git a/test/mjsunit/harmony/generators-iteration.js
b/test/mjsunit/harmony/generators-iteration.js
index
e54aeabd75cb2e9f3e93951a5ffd95358840c942..fdbc8d6bb001686a762424bcaa1a782876228b2c
100644
--- a/test/mjsunit/harmony/generators-iteration.js
+++ b/test/mjsunit/harmony/generators-iteration.js
@@ -25,7 +25,8 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-// Flags: --harmony-generators --expose-gc
+// Flags: --harmony-generators --expose-gc --harmony-symbols
+// Flags: --harmony-iteration
// Test generator iteration.
@@ -355,6 +356,32 @@ TestGenerator(
"foo",
[undefined, undefined]);
+// TODO(wingo): We should use TestGenerator for these, except that
+// currently yield* will unconditionally propagate a throw() to the
+// delegate iterator, which fails for these iterators that don't have
+// throw(). See http://code.google.com/p/v8/issues/detail?id=3484.
+(function() {
+ function* g28() {
+ yield* [1, 2, 3];
+ }
+ var iter = g28();
+ assertIteratorResult(1, false, iter.next());
+ assertIteratorResult(2, false, iter.next());
+ assertIteratorResult(3, false, iter.next());
+ assertIteratorResult(undefined, true, iter.next());
+})();
+
+(function() {
+ function* g29() {
+ yield* "abc";
+ }
+ var iter = g29();
+ assertIteratorResult("a", false, iter.next());
+ assertIteratorResult("b", false, iter.next());
+ assertIteratorResult("c", false, iter.next());
+ assertIteratorResult(undefined, true, iter.next());
+})();
+
// Generator function instances.
TestGenerator(GeneratorFunction(),
[undefined],
@@ -393,12 +420,16 @@ function TestDelegatingYield() {
function next() {
return results[i++];
}
- return { next: next }
+ var iter = { next: next };
+ var ret = {};
+ ret[Symbol.iterator] = function() { return iter; };
+ return ret;
}
function* yield_results(expected) {
return yield* results(expected);
}
- function collect_results(iter) {
+ function collect_results(iterable) {
+ var iter = iterable[Symbol.iterator]();
var ret = [];
var result;
do {
--
--
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.