Merge pull request #1228 from anba/destructuring-order-return

Change destructuring tests to not rely on exact evaluation order for property references
This commit is contained in:
Leo Balter 2017-09-19 14:38:08 -04:00 committed by GitHub
commit 134bfcd2b3
19 changed files with 380 additions and 71 deletions

View File

@ -4,12 +4,6 @@
desc: >
IteratorClose throws a TypeError when `return` returns a non-Object value
info: |
AssignmentElement : DestructuringAssignmentTarget Initializer
1. If DestructuringAssignmentTarget is neither an ObjectLiteral nor an ArrayLiteral, then
a. Let lref be the result of evaluating DestructuringAssignmentTarget.
b. ReturnIfAbrupt(lref).
[...]
ArrayAssignmentPattern : [ AssignmentElementList ]
[...]
@ -32,8 +26,15 @@ esid: sec-runtime-semantics-destructuringassignmentevaluation
//- setup
let unreachable = 0;
let nextCount = 0;
let returnCount = 0;
let iterator = {
next() {
nextCount += 1;
return {done: false, value: undefined};
},
return() {
returnCount += 1;
return null;
}
};
@ -43,17 +44,21 @@ let iterable = {
}
};
//- elems
[ {}[yield] ]
[ {} = yield ]
//- vals
iterable
//- body
unreachable += 1;
//- teardown
iter.next().then(result => {
assert.sameValue(nextCount, 1);
assert.sameValue(returnCount, 0);
assert.sameValue(result.value, undefined);
assert.sameValue(result.done, false);
iter.return().then(() => $DONE('Promise incorrectly fulfilled.'), ({ constructor }) => {
assert.sameValue(nextCount, 1);
assert.sameValue(returnCount, 1);
assert.sameValue(unreachable, 0);
assert.sameValue(constructor, TypeError);
}).then($DONE, $DONE);

View File

@ -26,19 +26,26 @@ esid: sec-runtime-semantics-destructuringassignmentevaluation
---*/
//- setup
var iterable = {};
var nextCount = 0;
var returnCount = 0;
var unreachable = 0;
var iterator = {
next: function() {
nextCount += 1;
return {done: false, value: undefined};
},
return: function() {
returnCount += 1;
return null;
}
};
var iter;
var iterable = {};
iterable[Symbol.iterator] = function() {
return iterator;
};
function* g() {
//- elems
[ {}[yield] ]
[ {} = yield ]
//- vals
iterable
//- body
@ -46,9 +53,14 @@ iterable
//- teardown
}
iter = g();
var iter = g();
iter.next();
assert.sameValue(nextCount, 1);
assert.sameValue(returnCount, 0);
assert.throws(TypeError, function() {
iter.return();
});
assert.sameValue(nextCount, 1);
assert.sameValue(returnCount, 1);
assert.sameValue(unreachable, 0, 'Unreachable statement was not executed');

View File

@ -25,12 +25,16 @@ esid: sec-runtime-semantics-destructuringassignmentevaluation
---*/
//- setup
var nextCount = 0;
var returnCount = 0;
var unreachable = 0;
var thisValue = null;
var args = null;
var iterable = {};
var iterator = {
next: function() {
nextCount += 1;
return {done: false, value: undefined};
},
return: function() {
returnCount += 1;
thisValue = this;
@ -38,24 +42,29 @@ var iterator = {
return {};
}
};
var iter, result;
var iterable = {};
iterable[Symbol.iterator] = function() {
return iterator;
};
function* g() {
//- elems
[ {}[yield] ]
[ {} = yield ]
//- vals
iterable
//- body
unreachable += 1;
//- teardown
}
iter = g();
var iter = g();
iter.next();
result = iter.return(777);
assert.sameValue(nextCount, 1);
assert.sameValue(returnCount, 0);
var result = iter.return(777);
assert.sameValue(nextCount, 1);
assert.sameValue(returnCount, 1);
assert.sameValue(unreachable, 0, 'Unreachable statement was not executed');
assert.sameValue(result.value, 777);

View File

@ -30,24 +30,28 @@ esid: sec-runtime-semantics-destructuringassignmentevaluation
---*/
//- setup
var nextCount = 0;
var returnCount = 0;
var unreachable = 0;
var iterable = {};
var iterator = {
next: function() {
nextCount += 1;
return {done: false, value: undefined};
},
return: function() {
returnCount += 1;
throw new Test262Error();
}
};
var iter;
var iterable = {};
iterable[Symbol.iterator] = function() {
return iterator;
};
function* g() {
//- elems
[ {}[yield] , ]
[ {} = yield , ]
//- vals
iterable
//- body
@ -55,11 +59,14 @@ unreachable += 1;
//- teardown
}
iter = g();
var iter = g();
iter.next();
assert.sameValue(nextCount, 1);
assert.sameValue(returnCount, 0);
assert.throws(Test262Error, function() {
iter.return();
});
assert.sameValue(nextCount, 1);
assert.sameValue(returnCount, 1);
assert.sameValue(unreachable, 0, 'Unreachable statement was not executed');

View File

@ -32,28 +32,38 @@ esid: sec-runtime-semantics-destructuringassignmentevaluation
---*/
//- setup
var iterable = {};
var nextCount = 0;
var returnCount = 0;
var iterator = {
next: function() {
nextCount += 1;
return {done: false, value: undefined};
},
return: function() {
returnCount += 1;
return null;
}
};
var iter;
var iterable = {};
iterable[Symbol.iterator] = function() {
return iterator;
};
function* g() {
//- elems
[ {}[yield] , ]
[ {} = yield , ]
//- vals
iterable
//- teardown
}
iter = g();
var iter = g();
iter.next();
assert.sameValue(nextCount, 1);
assert.sameValue(returnCount, 0);
assert.throws(TypeError, function() {
iter.return();
});
assert.sameValue(nextCount, 1);
assert.sameValue(returnCount, 1);

View File

@ -31,12 +31,17 @@ esid: sec-runtime-semantics-destructuringassignmentevaluation
---*/
//- setup
var nextCount = 0;
var returnCount = 0;
var unreachable = 0;
var thisValue = null;
var args = null;
var iterable = {};
var iterator = {
next: function() {
nextCount += 1;
return {done: false, value: undefined};
},
return: function() {
returnCount += 1;
thisValue = this;
@ -52,7 +57,7 @@ iterable[Symbol.iterator] = function() {
function* g() {
//- elems
[ {}[yield] , ]
[ {} = yield , ]
//- vals
iterable
//- body
@ -62,8 +67,13 @@ iterable
iter = g();
iter.next();
assert.sameValue(nextCount, 1);
assert.sameValue(returnCount, 0);
result = iter.return(888);
assert.sameValue(nextCount, 1);
assert.sameValue(returnCount, 1);
assert.sameValue(unreachable, 0, 'Unreachable statement was not executed');
assert.sameValue(result.value, 888);

View File

@ -0,0 +1,80 @@
// Copyright (C) 2017 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-runtime-semantics-iteratordestructuringassignmentevaluation
description: >
Ensure correct evaluation order when destructuring target is property reference.
info: |
12.15.5.3 Runtime Semantics: IteratorDestructuringAssignmentEvaluation
AssignmentElement : DestructuringAssignmentTarget Initializer
1. If DestructuringAssignmentTarget is neither an ObjectLiteral nor an ArrayLiteral, then
a. Let lref be the result of evaluating DestructuringAssignmentTarget.
b. ReturnIfAbrupt(lref).
2. If iteratorRecord.[[Done]] is false, then
a. Let next be IteratorStep(iteratorRecord.[[Iterator]]).
...
3. If iteratorRecord.[[Done]] is true, let value be undefined.
...
5. Else, let v be value.
...
8. Return ? PutValue(lref, v).
features: [Symbol.iterator]
includes: [compareArray.js]
---*/
var log = [];
function source() {
log.push("source");
var iterator = {
next: function() {
log.push("iterator-step");
return {
get done() {
log.push("iterator-done");
return true;
},
get value() {
// Note: This getter shouldn't be called.
log.push("iterator-value");
}
};
}
};
var source = {};
source[Symbol.iterator] = function() {
log.push("iterator");
return iterator;
};
return source;
}
function target() {
log.push("target");
return target = {
set q(v) {
log.push("set");
}
};
}
function targetKey() {
log.push("target-key");
return {
toString: function() {
log.push("target-key-tostring");
return "q";
}
};
}
([target()[targetKey()]] = source());
assert.compareArray(log, [
"source", "iterator",
"target", "target-key", "target-key-tostring",
"iterator-step", "iterator-done",
"set",
]);

View File

@ -0,0 +1,75 @@
// Copyright (C) 2017 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-runtime-semantics-keyeddestructuringassignmentevaluation
description: >
Ensure correct evaluation order when destructuring target is property reference.
info: |
12.15.5.2 Runtime Semantics: DestructuringAssignmentEvaluation
AssignmentProperty : PropertyName : AssignmentElement
1. Let name be the result of evaluating PropertyName.
2. ReturnIfAbrupt(name).
3. Return the result of performing KeyedDestructuringAssignmentEvaluation of
AssignmentElement with value and name as the arguments.
12.15.5.4 Runtime Semantics: KeyedDestructuringAssignmentEvaluation
1. If DestructuringAssignmentTarget is neither an ObjectLiteral nor an ArrayLiteral, then
a. Let lref be the result of evaluating DestructuringAssignmentTarget.
b. ReturnIfAbrupt(lref).
2. Let v be ? GetV(value, propertyName).
...
4. Else, let rhsValue be v.
...
7. Return ? PutValue(lref, rhsValue).
includes: [compareArray.js]
---*/
var log = [];
function source() {
log.push("source");
return {
get p() {
log.push("get");
}
};
}
function target() {
log.push("target");
return {
set q(v) {
log.push("set");
}
};
}
function sourceKey() {
log.push("source-key");
return {
toString: function() {
log.push("source-key-tostring");
return "p";
}
};
}
function targetKey() {
log.push("target-key");
return {
toString: function() {
log.push("target-key-tostring");
return "q";
}
};
}
({[sourceKey()]: target()[targetKey()]} = source());
assert.compareArray(log, [
"source", "source-key", "source-key-tostring",
"target", "target-key", "target-key-tostring",
"get", "set",
]);

View File

@ -33,13 +33,20 @@ info: |
exception.
---*/
var iterable = {};
var nextCount = 0;
var returnCount = 0;
var unreachable = 0;
var iterator = {
next: function() {
nextCount += 1;
return {done: false, value: undefined};
},
return: function() {
returnCount += 1;
return null;
}
};
var iter;
var iterable = {};
iterable[Symbol.iterator] = function() {
return iterator;
};
@ -48,7 +55,7 @@ function* g() {
var result;
var vals = iterable;
result = [ {}[yield] ] = vals;
result = [ {} = yield ] = vals;
unreachable += 1;
@ -56,9 +63,14 @@ assert.sameValue(result, vals);
}
iter = g();
var iter = g();
iter.next();
assert.sameValue(nextCount, 1);
assert.sameValue(returnCount, 0);
assert.throws(TypeError, function() {
iter.return();
});
assert.sameValue(nextCount, 1);
assert.sameValue(returnCount, 1);
assert.sameValue(unreachable, 0, 'Unreachable statement was not executed');

View File

@ -31,12 +31,16 @@ info: |
8. If innerResult.[[type]] is throw, return Completion(innerResult).
---*/
var nextCount = 0;
var returnCount = 0;
var unreachable = 0;
var thisValue = null;
var args = null;
var iterable = {};
var iterator = {
next: function() {
nextCount += 1;
return {done: false, value: undefined};
},
return: function() {
returnCount += 1;
thisValue = this;
@ -44,7 +48,7 @@ var iterator = {
return {};
}
};
var iter, result;
var iterable = {};
iterable[Symbol.iterator] = function() {
return iterator;
};
@ -54,17 +58,22 @@ function* g() {
var result;
var vals = iterable;
result = [ {}[yield] ] = vals;
result = [ {} = yield ] = vals;
unreachable += 1;
assert.sameValue(result, vals);
}
iter = g();
var iter = g();
iter.next();
result = iter.return(777);
assert.sameValue(nextCount, 1);
assert.sameValue(returnCount, 0);
var result = iter.return(777);
assert.sameValue(nextCount, 1);
assert.sameValue(returnCount, 1);
assert.sameValue(unreachable, 0, 'Unreachable statement was not executed');
assert.sameValue(result.value, 777);

View File

@ -36,17 +36,21 @@ info: |
8. If innerResult.[[type]] is throw, return Completion(innerResult).
---*/
var nextCount = 0;
var returnCount = 0;
var unreachable = 0;
var iterable = {};
var iterator = {
next: function() {
nextCount += 1;
return {done: false, value: undefined};
},
return: function() {
returnCount += 1;
throw new Test262Error();
}
};
var iter;
var iterable = {};
iterable[Symbol.iterator] = function() {
return iterator;
};
@ -56,7 +60,7 @@ function* g() {
var result;
var vals = iterable;
result = [ {}[yield] , ] = vals;
result = [ {} = yield , ] = vals;
unreachable += 1;
@ -64,11 +68,14 @@ assert.sameValue(result, vals);
}
iter = g();
var iter = g();
iter.next();
assert.sameValue(nextCount, 1);
assert.sameValue(returnCount, 0);
assert.throws(Test262Error, function() {
iter.return();
});
assert.sameValue(nextCount, 1);
assert.sameValue(returnCount, 1);
assert.sameValue(unreachable, 0, 'Unreachable statement was not executed');

View File

@ -39,13 +39,19 @@ info: |
exception.
---*/
var iterable = {};
var nextCount = 0;
var returnCount = 0;
var iterator = {
next: function() {
nextCount += 1;
return {done: false, value: undefined};
},
return: function() {
returnCount += 1;
return null;
}
};
var iter;
var iterable = {};
iterable[Symbol.iterator] = function() {
return iterator;
};
@ -55,7 +61,7 @@ function* g() {
var result;
var vals = iterable;
result = [ {}[yield] , ] = vals;
result = [ {} = yield , ] = vals;
@ -63,9 +69,13 @@ assert.sameValue(result, vals);
}
iter = g();
var iter = g();
iter.next();
assert.sameValue(nextCount, 1);
assert.sameValue(returnCount, 0);
assert.throws(TypeError, function() {
iter.return();
});
assert.sameValue(nextCount, 1);
assert.sameValue(returnCount, 1);

View File

@ -37,12 +37,17 @@ info: |
8. If innerResult.[[type]] is throw, return Completion(innerResult).
---*/
var nextCount = 0;
var returnCount = 0;
var unreachable = 0;
var thisValue = null;
var args = null;
var iterable = {};
var iterator = {
next: function() {
nextCount += 1;
return {done: false, value: undefined};
},
return: function() {
returnCount += 1;
thisValue = this;
@ -61,7 +66,7 @@ function* g() {
var result;
var vals = iterable;
result = [ {}[yield] , ] = vals;
result = [ {} = yield , ] = vals;
unreachable += 1;
@ -71,8 +76,13 @@ assert.sameValue(result, vals);
iter = g();
iter.next();
assert.sameValue(nextCount, 1);
assert.sameValue(returnCount, 0);
result = iter.return(888);
assert.sameValue(nextCount, 1);
assert.sameValue(returnCount, 1);
assert.sameValue(unreachable, 0, 'Unreachable statement was not executed');
assert.sameValue(result.value, 888);

View File

@ -24,12 +24,6 @@ info: |
lhs using AssignmentPattern as the goal symbol.
[...]
AssignmentElement : DestructuringAssignmentTarget Initializer
1. If DestructuringAssignmentTarget is neither an ObjectLiteral nor an ArrayLiteral, then
a. Let lref be the result of evaluating DestructuringAssignmentTarget.
b. ReturnIfAbrupt(lref).
[...]
ArrayAssignmentPattern : [ AssignmentElementList ]
[...]
@ -46,8 +40,15 @@ info: |
---*/
let unreachable = 0;
let nextCount = 0;
let returnCount = 0;
let iterator = {
next() {
nextCount += 1;
return {done: false, value: undefined};
},
return() {
returnCount += 1;
return null;
}
};
@ -59,7 +60,7 @@ let iterable = {
let iterCount = 0;
async function * fn() {
for await ([ {}[yield] ] of [iterable]) {
for await ([ {} = yield ] of [iterable]) {
unreachable += 1;
iterCount += 1;
}
@ -68,10 +69,14 @@ async function * fn() {
let iter = fn();
iter.next().then(result => {
assert.sameValue(nextCount, 1);
assert.sameValue(returnCount, 0);
assert.sameValue(result.value, undefined);
assert.sameValue(result.done, false);
iter.return().then(() => $DONE('Promise incorrectly fulfilled.'), ({ constructor }) => {
assert.sameValue(nextCount, 1);
assert.sameValue(returnCount, 1);
assert.sameValue(unreachable, 0);
assert.sameValue(constructor, TypeError);
}).then($DONE, $DONE);

View File

@ -42,13 +42,20 @@ info: |
exception.
---*/
var iterable = {};
var nextCount = 0;
var returnCount = 0;
var unreachable = 0;
var iterator = {
next: function() {
nextCount += 1;
return {done: false, value: undefined};
},
return: function() {
returnCount += 1;
return null;
}
};
var iter;
var iterable = {};
iterable[Symbol.iterator] = function() {
return iterator;
};
@ -56,7 +63,7 @@ function* g() {
var counter = 0;
for ([ {}[yield] ] of [iterable]) {
for ([ {} = yield ] of [iterable]) {
unreachable += 1;
counter += 1;
}
@ -65,9 +72,14 @@ assert.sameValue(counter, 1);
}
iter = g();
var iter = g();
iter.next();
assert.sameValue(nextCount, 1);
assert.sameValue(returnCount, 0);
assert.throws(TypeError, function() {
iter.return();
});
assert.sameValue(nextCount, 1);
assert.sameValue(returnCount, 1);
assert.sameValue(unreachable, 0, 'Unreachable statement was not executed');

View File

@ -40,12 +40,16 @@ info: |
8. If innerResult.[[type]] is throw, return Completion(innerResult).
---*/
var nextCount = 0;
var returnCount = 0;
var unreachable = 0;
var thisValue = null;
var args = null;
var iterable = {};
var iterator = {
next: function() {
nextCount += 1;
return {done: false, value: undefined};
},
return: function() {
returnCount += 1;
thisValue = this;
@ -53,7 +57,7 @@ var iterator = {
return {};
}
};
var iter, result;
var iterable = {};
iterable[Symbol.iterator] = function() {
return iterator;
};
@ -62,7 +66,7 @@ function* g() {
var counter = 0;
for ([ {}[yield] ] of [iterable]) {
for ([ {} = yield ] of [iterable]) {
unreachable += 1;
counter += 1;
}
@ -70,10 +74,15 @@ for ([ {}[yield] ] of [iterable]) {
assert.sameValue(counter, 1);
}
iter = g();
var iter = g();
iter.next();
result = iter.return(777);
assert.sameValue(nextCount, 1);
assert.sameValue(returnCount, 0);
var result = iter.return(777);
assert.sameValue(nextCount, 1);
assert.sameValue(returnCount, 1);
assert.sameValue(unreachable, 0, 'Unreachable statement was not executed');
assert.sameValue(result.value, 777);

View File

@ -45,17 +45,21 @@ info: |
8. If innerResult.[[type]] is throw, return Completion(innerResult).
---*/
var nextCount = 0;
var returnCount = 0;
var unreachable = 0;
var iterable = {};
var iterator = {
next: function() {
nextCount += 1;
return {done: false, value: undefined};
},
return: function() {
returnCount += 1;
throw new Test262Error();
}
};
var iter;
var iterable = {};
iterable[Symbol.iterator] = function() {
return iterator;
};
@ -64,7 +68,7 @@ function* g() {
var counter = 0;
for ([ {}[yield] , ] of [iterable]) {
for ([ {} = yield , ] of [iterable]) {
unreachable += 1;
counter += 1;
}
@ -73,11 +77,14 @@ assert.sameValue(counter, 1);
}
iter = g();
var iter = g();
iter.next();
assert.sameValue(nextCount, 1);
assert.sameValue(returnCount, 0);
assert.throws(Test262Error, function() {
iter.return();
});
assert.sameValue(nextCount, 1);
assert.sameValue(returnCount, 1);
assert.sameValue(unreachable, 0, 'Unreachable statement was not executed');

View File

@ -48,13 +48,19 @@ info: |
exception.
---*/
var iterable = {};
var nextCount = 0;
var returnCount = 0;
var iterator = {
next: function() {
nextCount += 1;
return {done: false, value: undefined};
},
return: function() {
returnCount += 1;
return null;
}
};
var iter;
var iterable = {};
iterable[Symbol.iterator] = function() {
return iterator;
};
@ -63,7 +69,7 @@ function* g() {
var counter = 0;
for ([ {}[yield] , ] of [iterable]) {
for ([ {} = yield , ] of [iterable]) {
counter += 1;
}
@ -72,9 +78,13 @@ assert.sameValue(counter, 1);
}
iter = g();
var iter = g();
iter.next();
assert.sameValue(nextCount, 1);
assert.sameValue(returnCount, 0);
assert.throws(TypeError, function() {
iter.return();
});
assert.sameValue(nextCount, 1);
assert.sameValue(returnCount, 1);

View File

@ -46,12 +46,17 @@ info: |
8. If innerResult.[[type]] is throw, return Completion(innerResult).
---*/
var nextCount = 0;
var returnCount = 0;
var unreachable = 0;
var thisValue = null;
var args = null;
var iterable = {};
var iterator = {
next: function() {
nextCount += 1;
return {done: false, value: undefined};
},
return: function() {
returnCount += 1;
thisValue = this;
@ -69,7 +74,7 @@ function* g() {
var counter = 0;
for ([ {}[yield] , ] of [iterable]) {
for ([ {} = yield , ] of [iterable]) {
unreachable += 1;
counter += 1;
}
@ -80,8 +85,13 @@ assert.sameValue(counter, 1);
iter = g();
iter.next();
assert.sameValue(nextCount, 1);
assert.sameValue(returnCount, 0);
result = iter.return(888);
assert.sameValue(nextCount, 1);
assert.sameValue(returnCount, 1);
assert.sameValue(unreachable, 0, 'Unreachable statement was not executed');
assert.sameValue(result.value, 888);