yield* calls @@iterator on iterable
R=rossberg@chromium.org BUG=v8:3422 LOG=N Review URL: https://codereview.chromium.org/430693003 git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@22872 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
ee52dffb37
commit
6b7f9dba84
@ -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();
|
||||
{
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -25,7 +25,7 @@
|
||||
// (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-iteration
|
||||
|
||||
// Test generator iteration.
|
||||
|
||||
@ -355,6 +355,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 +419,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 {
|
||||
|
Loading…
Reference in New Issue
Block a user