For-of on null or undefined is an error

The latest ES6 draft changed the behavior of for-of on null / undefined,
which for once is a simplification.

R=rossberg@chromium.org
BUG=

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

Patch from Andy Wingo <wingo@igalia.com>.

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@22602 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
yangguo@chromium.org 2014-07-24 13:40:08 +00:00
parent b5a5148260
commit 029b8a2379
11 changed files with 7 additions and 94 deletions

View File

@ -1276,15 +1276,6 @@ void FullCodeGenerator::VisitForOfStatement(ForOfStatement* stmt) {
Iteration loop_statement(this, stmt);
increment_loop_depth();
// var iterable = subject
VisitForAccumulatorValue(stmt->assign_iterable());
// As with for-in, skip the loop if the iterator is null or undefined.
__ CompareRoot(r0, Heap::kUndefinedValueRootIndex);
__ b(eq, loop_statement.break_label());
__ CompareRoot(r0, Heap::kNullValueRootIndex);
__ b(eq, loop_statement.break_label());
// var iterator = iterable[Symbol.iterator]();
VisitForEffect(stmt->assign_iterator());

View File

@ -1271,16 +1271,6 @@ void FullCodeGenerator::VisitForOfStatement(ForOfStatement* stmt) {
Iteration loop_statement(this, stmt);
increment_loop_depth();
// var iterable = subject
VisitForAccumulatorValue(stmt->assign_iterable());
// As with for-in, skip the loop if the iterator is null or undefined.
Register iterator = x0;
__ JumpIfRoot(iterator, Heap::kUndefinedValueRootIndex,
loop_statement.break_label());
__ JumpIfRoot(iterator, Heap::kNullValueRootIndex,
loop_statement.break_label());
// var iterator = iterable[Symbol.iterator]();
VisitForEffect(stmt->assign_iterator());

View File

@ -243,7 +243,6 @@ class AstValue : public ZoneObject {
F(dot_for, ".for") \
F(dot_generator, ".generator") \
F(dot_generator_object, ".generator_object") \
F(dot_iterable, ".iterable") \
F(dot_iterator, ".iterator") \
F(dot_module, ".module") \
F(dot_result, ".result") \

View File

@ -961,13 +961,11 @@ class ForOfStatement V8_FINAL : public ForEachStatement {
void Initialize(Expression* each,
Expression* subject,
Statement* body,
Expression* assign_iterable,
Expression* assign_iterator,
Expression* next_result,
Expression* result_done,
Expression* assign_each) {
ForEachStatement::Initialize(each, subject, body);
assign_iterable_ = assign_iterable;
assign_iterator_ = assign_iterator;
next_result_ = next_result;
result_done_ = result_done;
@ -978,12 +976,7 @@ class ForOfStatement V8_FINAL : public ForEachStatement {
return subject();
}
// var iterable = subject;
Expression* assign_iterable() const {
return assign_iterable_;
}
// var iterator = iterable[Symbol.iterator]();
// var iterator = subject[Symbol.iterator]();
Expression* assign_iterator() const {
return assign_iterator_;
}
@ -1018,7 +1011,6 @@ class ForOfStatement V8_FINAL : public ForEachStatement {
back_edge_id_(GetNextId(zone)) {
}
Expression* assign_iterable_;
Expression* assign_iterator_;
Expression* next_result_;
Expression* result_done_;

View File

@ -1207,15 +1207,6 @@ void FullCodeGenerator::VisitForOfStatement(ForOfStatement* stmt) {
Iteration loop_statement(this, stmt);
increment_loop_depth();
// var iterable = subject
VisitForAccumulatorValue(stmt->assign_iterable());
// As with for-in, skip the loop if the iterator is null or undefined.
__ CompareRoot(eax, Heap::kUndefinedValueRootIndex);
__ j(equal, loop_statement.break_label());
__ CompareRoot(eax, Heap::kNullValueRootIndex);
__ j(equal, loop_statement.break_label());
// var iterator = iterable[Symbol.iterator]();
VisitForEffect(stmt->assign_iterator());

View File

@ -1272,16 +1272,6 @@ void FullCodeGenerator::VisitForOfStatement(ForOfStatement* stmt) {
Iteration loop_statement(this, stmt);
increment_loop_depth();
// var iterable = subject
VisitForAccumulatorValue(stmt->assign_iterable());
__ mov(a0, v0);
// As with for-in, skip the loop if the iterator is null or undefined.
__ LoadRoot(at, Heap::kUndefinedValueRootIndex);
__ Branch(loop_statement.break_label(), eq, a0, Operand(at));
__ LoadRoot(at, Heap::kNullValueRootIndex);
__ Branch(loop_statement.break_label(), eq, a0, Operand(at));
// var iterator = iterable[Symbol.iterator]();
VisitForEffect(stmt->assign_iterator());

View File

@ -1267,16 +1267,6 @@ void FullCodeGenerator::VisitForOfStatement(ForOfStatement* stmt) {
Iteration loop_statement(this, stmt);
increment_loop_depth();
// var iterable = subject
VisitForAccumulatorValue(stmt->assign_iterable());
__ mov(a0, v0);
// As with for-in, skip the loop if the iterator is null or undefined.
__ LoadRoot(at, Heap::kUndefinedValueRootIndex);
__ Branch(loop_statement.break_label(), eq, a0, Operand(at));
__ LoadRoot(at, Heap::kNullValueRootIndex);
__ Branch(loop_statement.break_label(), eq, a0, Operand(at));
// var iterator = iterable[Symbol.iterator]();
VisitForEffect(stmt->assign_iterator());

View File

@ -2749,37 +2749,26 @@ void Parser::InitializeForEachStatement(ForEachStatement* stmt,
ForOfStatement* for_of = stmt->AsForOfStatement();
if (for_of != NULL) {
Variable* iterable = scope_->DeclarationScope()->NewTemporary(
ast_value_factory_->dot_iterable_string());
Variable* iterator = scope_->DeclarationScope()->NewTemporary(
ast_value_factory_->dot_iterator_string());
Variable* result = scope_->DeclarationScope()->NewTemporary(
ast_value_factory_->dot_result_string());
Expression* assign_iterable;
Expression* assign_iterator;
Expression* next_result;
Expression* result_done;
Expression* assign_each;
// var iterable = subject;
// var iterator = subject[Symbol.iterator]();
{
Expression* iterable_proxy = factory()->NewVariableProxy(iterable);
assign_iterable = factory()->NewAssignment(
Token::ASSIGN, iterable_proxy, subject, subject->position());
}
// var iterator = iterable[Symbol.iterator]();
{
Expression* iterable_proxy = factory()->NewVariableProxy(iterable);
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(
iterable_proxy, iterator_symbol_literal, pos);
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(
@ -2826,7 +2815,6 @@ void Parser::InitializeForEachStatement(ForEachStatement* stmt,
}
for_of->Initialize(each, subject, body,
assign_iterable,
assign_iterator,
next_result,
result_done,

View File

@ -1241,15 +1241,6 @@ void FullCodeGenerator::VisitForOfStatement(ForOfStatement* stmt) {
Iteration loop_statement(this, stmt);
increment_loop_depth();
// var iterable = subject
VisitForAccumulatorValue(stmt->assign_iterable());
// As with for-in, skip the loop if the iterable is null or undefined.
__ CompareRoot(rax, Heap::kUndefinedValueRootIndex);
__ j(equal, loop_statement.break_label());
__ CompareRoot(rax, Heap::kNullValueRootIndex);
__ j(equal, loop_statement.break_label());
// var iterator = iterable[Symbol.iterator]();
VisitForEffect(stmt->assign_iterator());

View File

@ -1204,15 +1204,6 @@ void FullCodeGenerator::VisitForOfStatement(ForOfStatement* stmt) {
Iteration loop_statement(this, stmt);
increment_loop_depth();
// var iterable = subject
VisitForAccumulatorValue(stmt->assign_iterable());
// As with for-in, skip the loop if the iterator is null or undefined.
__ CompareRoot(eax, Heap::kUndefinedValueRootIndex);
__ j(equal, loop_statement.break_label());
__ CompareRoot(eax, Heap::kNullValueRootIndex);
__ j(equal, loop_statement.break_label());
// var iterator = iterable[Symbol.iterator]();
VisitForEffect(stmt->assign_iterator());

View File

@ -213,9 +213,9 @@ assertEquals([1, 2],
{ value: 37, done: true },
never_getter(never_getter({}, 'done'), 'value')])));
// Null and undefined do not cause an error.
assertEquals(0, fold(sum, 0, unreachable(null)));
assertEquals(0, fold(sum, 0, unreachable(undefined)));
// Unlike the case with for-in, null and undefined cause an error.
assertThrows('fold(sum, 0, unreachable(null))', TypeError);
assertThrows('fold(sum, 0, unreachable(undefined))', TypeError);
// Other non-iterators do cause an error.
assertThrows('fold(sum, 0, unreachable({}))', TypeError);