Merge pull request #288 from bocoup/for-of-additions

for..of additions
This commit is contained in:
Brian Terlson 2015-06-08 12:18:34 -07:00
commit a47916e6ec
21 changed files with 539 additions and 3 deletions

View File

@ -0,0 +1,39 @@
// Copyright (C) 2015 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
es6id: 13.6.4.13 S5.i.i
description: >
If the left-hand side requires a DestructuringAssignment operation and that
operation produces an error, the iterator should be closed and the error
forwarded to the runtime.
features: [Symbol.iterator]
---*/
var callCount = 0;
var iterationCount = 0;
var iterable = {};
var x = {
set attr(_) {
throw new Test262Error();
}
};
iterable[Symbol.iterator] = function() {
return {
next: function() {
return { done: false, value: [0] };
},
return: function() {
callCount += 1;
}
}
};
assert.throws(Test262Error, function() {
for ([x.attr] of iterable) {
iterationCount += 1;
}
});
assert.sameValue(iterationCount, 0, 'The loop body is not evaluated');
assert.sameValue(callCount, 1, 'Iterator is closed');

View File

@ -0,0 +1,17 @@
// Copyright (C) 2015 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
es6id: 13.6.4.13 S5.i.i
description: >
The left-hand side may take the form of a DestructuringAssignment.
---*/
var iterationCount = 0;
var x;
for ([x] of [[0]]) {
assert.sameValue(x, 0);
iterationCount += 1;
}
assert.sameValue(iterationCount, 1);

View File

@ -0,0 +1,39 @@
// Copyright (C) 2015 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
es6id: 13.6.4.13 S5.h.ii
description: >
If the left-hand side is not a lexical binding and the assignment produces
an error, the iterator should be closed and the error forwarded to the
runtime.
features: [Symbol.iterator]
---*/
var callCount = 0;
var iterationCount = 0;
var iterable = {};
var x = {
set attr(_) {
throw new Test262Error();
}
};
iterable[Symbol.iterator] = function() {
return {
next: function() {
return { done: false, value: 0 };
},
return: function() {
callCount += 1;
}
}
};
assert.throws(Test262Error, function() {
for (x.attr of iterable) {
iterationCount += 1;
}
});
assert.sameValue(iterationCount, 0, 'The loop body is not evaluated');
assert.sameValue(callCount, 1, 'Iterator is closed');

View File

@ -0,0 +1,47 @@
// Copyright (C) 2015 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
es6id: 13.6.4.13
description: >
Generators should be closed via their `return` method when iteration is
interrupted via a `break` statement.
features: [generators]
---*/
var startedCount = 0;
var finallyCount = 0;
var iterationCount = 0;
function* values() {
startedCount += 1;
try {
yield;
$ERROR('This code is unreachable (within `try` block)');
} finally {
finallyCount += 1;
}
$ERROR('This code is unreachable (following `try` statement)');
}
var iterable = values();
assert.sameValue(
startedCount, 0, 'Generator is initialized in suspended state'
);
for (var x of iterable) {
assert.sameValue(
startedCount, 1, 'Generator executes prior to first iteration'
);
assert.sameValue(
finallyCount, 0, 'Generator is paused during first iteration'
);
iterationCount += 1;
break;
}
assert.sameValue(
startedCount, 1, 'Generator does not restart following interruption'
);
assert.sameValue(iterationCount, 1, 'A single iteration occurs');
assert.sameValue(
finallyCount, 1, 'Generator is closed after `break` statement'
);

View File

@ -0,0 +1,49 @@
// Copyright (C) 2015 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
es6id: 13.6.4.13
description: >
Generators should be closed via their `return` method when iteration is
interrupted via a `return` statement.
features: [generators]
---*/
var startedCount = 0;
var finallyCount = 0;
var iterationCount = 0;
function* values() {
startedCount += 1;
try {
yield;
$ERROR('This code is unreachable (within `try` block)');
} finally {
finallyCount += 1;
}
$ERROR('This code is unreachable (following `try` statement)');
}
var iterable = values();
assert.sameValue(
startedCount, 0, 'Generator is initialized in suspended state'
);
(function() {
for (var x of iterable) {
assert.sameValue(
startedCount, 1, 'Generator executes prior to first iteration'
);
assert.sameValue(
finallyCount, 0, 'Generator is paused during first iteration'
);
iterationCount += 1;
return;
}
}());
assert.sameValue(
startedCount, 1, 'Generator does not restart following interruption'
);
assert.sameValue(iterationCount, 1, 'A single iteration occurs');
assert.sameValue(
finallyCount, 1, 'Generator is closed after `return` statement'
);

View File

@ -0,0 +1,49 @@
// Copyright (C) 2015 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
es6id: 13.6.4.13
description: >
Generators should be closed via their `return` method when iteration is
interrupted via a `throw` statement.
features: [generators]
---*/
var startedCount = 0;
var finallyCount = 0;
var iterationCount = 0;
function* values() {
startedCount += 1;
try {
yield;
$ERROR('This code is unreachable (within `try` block)');
} finally {
finallyCount += 1;
}
$ERROR('This code is unreachable (following `try` statement)');
}
var iterable = values();
assert.sameValue(
startedCount, 0, 'Generator is initialized in suspended state'
);
try {
for (var x of iterable) {
assert.sameValue(
startedCount, 1, 'Generator executes prior to first iteration'
);
assert.sameValue(
finallyCount, 0, 'Generator is paused during first iteration'
);
iterationCount += 1;
throw 0;
}
} catch(err) {}
assert.sameValue(
startedCount, 1, 'Generator does not restart following interruption'
);
assert.sameValue(iterationCount, 1, 'A single iteration occurs');
assert.sameValue(
finallyCount, 1, 'Generator is closed after `throw` statement'
);

View File

@ -0,0 +1,22 @@
// Copyright (C) 2015 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
es6id: 13.6.4.13 S5.g
description: >
If `nextResult` is an abrupt completion as per IteratorStep (ES6 7.4.5),
return the completion.
features: [generators]
---*/
var iterable = (function*() {
throw new Test262Error();
}());
var iterationCount = 0;
assert.throws(Test262Error, function() {
for (var x of iterable) {
iterationCount += 1;
}
});
assert.sameValue(iterationCount, 0, 'The loop body is not evaluated');

View File

@ -4,6 +4,7 @@
es6id: 13.6.4.13
description: >
Generator function should return valid iterable objects.
features: [generators]
---*/
function* values() {

View File

@ -4,6 +4,7 @@
es6id: 13.6.4.13
description: >
Generic objects with `@@iterator` protocols should function as iterables.
features: [Symbol.iterator]
---*/
var iterable = {};

View File

@ -5,6 +5,7 @@ es6id: 13.6.4.13
description: >
Iterators that are implemented as proxies should behave identically to
non-proxy versions.
features: [Proxy, Symbol.iterator]
---*/
var iterable = {};

View File

@ -0,0 +1,32 @@
// Copyright (C) 2015 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
es6id: 13.6.4.13
description: >
If retrieving an iterator's `return` method generates an error while
closing the iterator, the error should be forwarded to the runtime.
features: [Symbol.iterator]
---*/
var iterable = {};
var iterationCount = 0;
iterable[Symbol.iterator] = function() {
return {
next: function() {
return { done: false, value: null };
},
get return() {
throw new Test262Error();
}
};
};
assert.throws(Test262Error, function() {
for (var x of iterable) {
iterationCount += 1;
break;
}
});
assert.sameValue(iterationCount, 1, 'The loop body is evaluated');

View File

@ -0,0 +1,32 @@
// Copyright (C) 2015 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
es6id: 13.6.4.13
description: >
If an iterator's `return` method returns a non-Object value, a TypeError
should be thrown.
features: [Symbol.iterator]
---*/
var iterable = {};
var iterationCount = 0;
iterable[Symbol.iterator] = function() {
return {
next: function() {
return { done: false, value: null };
},
return: function() {
return 0;
}
};
};
assert.throws(TypeError, function() {
for (var x of iterable) {
iterationCount += 1;
break;
}
});
assert.sameValue(iterationCount, 1, 'The loop body is evaluated');

View File

@ -0,0 +1,46 @@
// Copyright (C) 2015 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
es6id: 13.6.4.13
description: >
Iterators should be closed via their `return` method when iteration is
interrupted via a `break` statement.
features: [Symbol.iterator]
---*/
var startedCount = 0;
var returnCount = 0;
var iterationCount = 0;
var iterable = {};
iterable[Symbol.iterator] = function() {
return {
next: function() {
startedCount += 1;
return { done: false, value: null };
},
return: function() {
returnCount += 1;
return {};
}
};
};
for (var x of iterable) {
assert.sameValue(
startedCount, 1, 'Value is retrieved'
);
assert.sameValue(
returnCount, 0, 'Iterator is not closed'
);
iterationCount += 1;
break;
}
assert.sameValue(
startedCount, 1, 'Iterator does not restart following interruption'
);
assert.sameValue(iterationCount, 1, 'A single iteration occurs');
assert.sameValue(
returnCount, 1, 'Iterator is closed after `break` statement'
);

View File

@ -0,0 +1,48 @@
// Copyright (C) 2015 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
es6id: 13.6.4.13
description: >
Iterators should be closed via their `return` method when iteration is
interrupted via a `return` statement.
features: [Symbol.iterator]
---*/
var startedCount = 0;
var returnCount = 0;
var iterationCount = 0;
var iterable = {};
iterable[Symbol.iterator] = function() {
return {
next: function() {
startedCount += 1;
return { done: false, value: null };
},
return: function() {
returnCount += 1;
return {};
}
};
};
(function() {
for (var x of iterable) {
assert.sameValue(
startedCount, 1, 'Value is retrieved'
);
assert.sameValue(
returnCount, 0, 'Iterator is not closed'
);
iterationCount += 1;
return;
}
}());
assert.sameValue(
startedCount, 1, 'Iterator does not restart following interruption'
);
assert.sameValue(iterationCount, 1, 'A single iteration occurs');
assert.sameValue(
returnCount, 1, 'Iterator is closed after `return` statement'
);

View File

@ -0,0 +1,48 @@
// Copyright (C) 2015 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
es6id: 13.6.4.13
description: >
Iterators should be closed via their `return` method when iteration is
interrupted via a `throw` statement.
features: [Symbol.iterator]
---*/
var startedCount = 0;
var returnCount = 0;
var iterationCount = 0;
var iterable = {};
iterable[Symbol.iterator] = function() {
return {
next: function() {
startedCount += 1;
return { done: false, value: null };
},
return: function() {
returnCount += 1;
return {};
}
};
};
try {
for (var x of iterable) {
assert.sameValue(
startedCount, 1, 'Value is retrieved'
);
assert.sameValue(
returnCount, 0, 'Iterator is not closed'
);
iterationCount += 1;
throw 0;
}
} catch (err) {}
assert.sameValue(
startedCount, 1, 'Iterator does not restart following interruption'
);
assert.sameValue(iterationCount, 1, 'A single iteration occurs');
assert.sameValue(
returnCount, 1, 'Iterator is closed after `throw` statement'
);

View File

@ -0,0 +1,28 @@
// Copyright (C) 2015 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
es6id: 13.6.4.13 S5.d
description: >
If `nextResult` is an abrupt completion as per IteratorStep (ES6 7.4.5),
return the completion.
features: [Symbol.iterator]
---*/
var iterable = {};
var iterationCount = 0;
iterable[Symbol.iterator] = function() {
return {
next: function() {
throw new Test262Error();
}
};
};
assert.throws(Test262Error, function() {
for (var x of iterable) {
iterationCount += 1;
}
});
assert.sameValue(iterationCount, 0, 'The loop body is not evaluated');

View File

@ -5,6 +5,7 @@ es6id: 13.6.4.13 S5.c
description: >
The iterator's `next` method should be accessed with each iteration as per
the `IteratorStep` abstract operation (7.4.5).
features: [Symbol.iterator]
---*/
var iterable = {};

View File

@ -5,6 +5,7 @@ es6id: 7.4.3
description: >
The `done` value of iteration result objects should be interpreted as
incomplete as per `ToBoolean` (7.1.2).
features: [Symbol.iterator]
---*/
var iterable = {};

View File

@ -5,6 +5,7 @@ es6id: 13.6.4.13 S5.c
description: >
If Type(result) is not Object, throw a TypeError exception as per
`IteratorNext` (7.4.2 S4)
features: [Symbol.iterator]
---*/
var iterable = {};

View File

@ -0,0 +1,33 @@
// Copyright (C) 2015 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
es6id: 13.6.4.13 S5.g
description: >
If `nextValue` is an abrupt completion as per IteratorValue (ES6 7.4.4),
return the completion.
features: [Symbol.iterator]
---*/
var iterable = {};
var iterationCount = 0;
iterable[Symbol.iterator] = function() {
return {
next: function() {
return {
done: false,
get value() {
throw new Test262Error();
}
};
}
};
};
assert.throws(Test262Error, function() {
for (var x of iterable) {
iterationCount += 1;
}
});
assert.sameValue(iterationCount, 0, 'The loop body is not evaluated');

View File

@ -1,10 +1,11 @@
// Copyright (C) 2013 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
es6id: 13.6.4.13 S5.c
es6id: 13.6.4.13 S5.f
description: >
The `done` value of iteration result objects should be interpreted as
incomplete as per `ToBoolean` (7.1.2).
The `value` of iteration result objects should be retrieved using the Get
abstract operation.
features: [Symbol.iterator]
---*/
var iterable = {};