Skip to content
Snippets Groups Projects
Unverified Commit a010c9cf authored by Leo Balter's avatar Leo Balter
Browse files

Add cases for yield stars flow

parent 882b3cc0
No related branches found
No related tags found
No related merge requests found
// Copyright 2017 Tooru Fujisawa. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
desc: Execution order for yield* with async iterator and next()
template: default
info: |
YieldExpression: yield * AssignmentExpression
...
2. Let value be ? GetValue(exprRef).
3. Let generatorKind be ! GetGeneratorKind().
4. Let iterator be ? GetIterator(value, generatorKind).
5. Let received be NormalCompletion(undefined).
6. Repeat
a. If received.[[Type]] is normal, then
i. Let innerResult be ? IteratorNext(iterator, received.[[Value]]).
ii. Let innerResult be ? Invoke(iterator, "next",
« received.[[Value]] »).
iii. If generatorKind is async, then set innerResult to
? Await(innerResult).
...
v. Let done be ? IteratorComplete(innerResult).
vi. If done is true, then
1. Return ? IteratorValue(innerResult).
vii. Let received be GeneratorYield(innerResult).
...
GetIterator ( obj [ , hint ] )
...
3. If hint is async,
a. Set method to ? GetMethod(obj, @@asyncIterator).
b. If method is undefined,
i. Let syncMethod be ? GetMethod(obj, @@iterator).
ii. Let syncIterator be ? Call(syncMethod, obj).
iii. Return ? CreateAsyncFromSyncIterator(syncIterator).
...
GeneratorYield ( iterNextObj )
...
10. If generatorKind is async,
a. Let value be IteratorValue(iterNextObj).
b. Let done be IteratorComplete(iterNextObj).
c. Return ! AsyncGeneratorResolve(generator, value, done).
...
flags: [async]
features: [async-iteration, Symbol.asyncIterator]
---*/
//- setup
var log = [];
var obj = {
get [Symbol.iterator]() {
log.push({ name: "get [Symbol.iterator]" });
},
get [Symbol.asyncIterator]() {
log.push({
name: "get [Symbol.asyncIterator]",
thisValue: this
});
return function() {
log.push({
name: "call [Symbol.asyncIterator]",
thisValue: this,
args: [...arguments]
});
var nextCount = 0;
return {
name: "asyncIterator",
get next() {
log.push({
name: "get next",
thisValue: this
});
return function() {
log.push({
name: "call next",
thisValue: this,
args: [...arguments]
});
nextCount++;
if (nextCount == 1) {
return {
name: "next-promise-1",
get then() {
log.push({
name: "get next then (1)",
thisValue: this
});
return function(resolve) {
log.push({
name: "call next then (1)",
thisValue: this,
args: [...arguments]
});
resolve({
name: "next-result-1",
get value() {
log.push({
name: "get next value (1)",
thisValue: this
});
return "next-value-1";
},
get done() {
log.push({
name: "get next done (1)",
thisValue: this
});
return false;
}
});
};
}
};
}
return {
name: "next-promise-2",
get then() {
log.push({
name: "get next then (2)",
thisValue: this
});
return function(resolve) {
log.push({
name: "call next then (2)",
thisValue: this,
args: [...arguments]
});
resolve({
name: "next-result-2",
get value() {
log.push({
name: "get next value (2)",
thisValue: this
});
return "next-value-2";
},
get done() {
log.push({
name: "get next done (2)",
thisValue: this
});
return true;
}
});
};
}
};
};
}
};
};
}
};
//- body
log.push({ name: "before yield*" });
var v = yield* obj;
log.push({
name: "after yield*",
value: v
});
return "return-value";
//- assertions
assert.sameValue(log.length, 0, "log.length");
iter.next("next-arg-1").then(v => {
assert.sameValue(log[0].name, "before yield*");
assert.sameValue(log[1].name, "get [Symbol.asyncIterator]");
assert.sameValue(log[1].thisValue, obj, "get [Symbol.asyncIterator] thisValue");
assert.sameValue(log[2].name, "call [Symbol.asyncIterator]");
assert.sameValue(log[2].thisValue, obj, "[Symbol.asyncIterator] thisValue");
assert.sameValue(log[2].args.length, 0, "[Symbol.asyncIterator] args.length");
assert.sameValue(log[3].name, "get next");
assert.sameValue(log[3].thisValue.name, "asyncIterator", "get next thisValue");
assert.sameValue(log[4].name, "call next");
assert.sameValue(log[4].thisValue.name, "asyncIterator", "next thisValue");
assert.sameValue(log[4].args.length, 1, "next args.length");
assert.sameValue(log[4].args[0], undefined, "next args[0]");
assert.sameValue(log[5].name, "get next then (1)");
assert.sameValue(log[5].thisValue.name, "next-promise-1", "get next then thisValue");
assert.sameValue(log[6].name, "call next then (1)");
assert.sameValue(log[6].thisValue.name, "next-promise-1", "next then thisValue");
assert.sameValue(log[6].args.length, 2, "next then args.length");
assert.sameValue(typeof log[6].args[0], "function", "next then args[0]");
assert.sameValue(typeof log[6].args[1], "function", "next then args[1]");
assert.sameValue(log[7].name, "get next done (1)");
assert.sameValue(log[7].thisValue.name, "next-result-1", "get next done thisValue");
assert.sameValue(log[8].name, "get next value (1)");
assert.sameValue(log[8].thisValue.name, "next-result-1", "get next value thisValue");
assert.sameValue(log[9].name, "get next done (1)");
assert.sameValue(log[9].thisValue.name, "next-result-1", "get next done thisValue");
assert.sameValue(v.value, "next-value-1");
assert.sameValue(v.done, false);
assert.sameValue(log.length, 10, "log.length");
iter.next("next-arg-2").then(v => {
assert.sameValue(log[10].name, "get next");
assert.sameValue(log[10].thisValue.name, "asyncIterator", "get next thisValue");
assert.sameValue(log[11].name, "call next");
assert.sameValue(log[11].thisValue.name, "asyncIterator", "next thisValue");
assert.sameValue(log[11].args.length, 1, "next args.length");
assert.sameValue(log[11].args[0], "next-arg-2", "next args[0]");
assert.sameValue(log[12].name, "get next then (2)");
assert.sameValue(log[12].thisValue.name, "next-promise-2", "get next then thisValue");
assert.sameValue(log[13].name, "call next then (2)");
assert.sameValue(log[13].thisValue.name, "next-promise-2", "next then thisValue");
assert.sameValue(log[13].args.length, 2, "next then args.length");
assert.sameValue(typeof log[13].args[0], "function", "next then args[0]");
assert.sameValue(typeof log[13].args[1], "function", "next then args[1]");
assert.sameValue(log[14].name, "get next done (2)");
assert.sameValue(log[14].thisValue.name, "next-result-2", "get next done thisValue");
assert.sameValue(log[15].name, "get next value (2)");
assert.sameValue(log[15].thisValue.name, "next-result-2", "get next value thisValue");
assert.sameValue(log[16].name, "after yield*");
assert.sameValue(log[16].value, "next-value-2");
assert.sameValue(v.value, "return-value");
assert.sameValue(v.done, true);
assert.sameValue(log.length, 17, "log.length");
}).then($DONE, $DONE);
}).catch($DONE);
// Copyright 2017 Tooru Fujisawa. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
template: default
desc: execution order for yield* with async iterator and return()
info: |
YieldExpression: yield * AssignmentExpression
...
6. Repeat
...
c. Else,
i. Assert: received.[[Type]] is return.
ii. Let return be ? GetMethod(iterator, "return").
iii. If return is undefined, return Completion(received).
iv. Let innerReturnResult be ? Call(return, iterator,
« received.[[Value]] »).
v. If generatorKind is async, then set innerReturnResult to
? Await(innerReturnResult).
...
vii. Let done be ? IteratorComplete(innerReturnResult).
viii. If done is true, then
1. Let value be ? IteratorValue(innerReturnResult).
2. Return Completion{[[Type]]: return, [[Value]]: value,
[[Target]]: empty}.
ix. Let received be GeneratorYield(innerResult).
GeneratorYield ( iterNextObj )
...
10. If generatorKind is async,
a. Let value be IteratorValue(iterNextObj).
b. Let done be IteratorComplete(iterNextObj).
c. Return ! AsyncGeneratorResolve(generator, value, done).
...
flags: [async]
features: [async-iteration, Symbol.asyncIterator]
---*/
//- setup
var log = [];
var obj = {
[Symbol.asyncIterator]() {
var returnCount = 0;
return {
name: 'asyncIterator',
get next() {
log.push({ name: "get next" });
return function() {
return {
value: "next-value-1",
done: false
};
};
},
get return() {
log.push({
name: "get return",
thisValue: this
});
return function() {
log.push({
name: "call return",
thisValue: this,
args: [...arguments]
});
returnCount++;
if (returnCount == 1) {
return {
name: "return-promise-1",
get then() {
log.push({
name: "get return then (1)",
thisValue: this
});
return function(resolve) {
log.push({
name: "call return then (1)",
thisValue: this,
args: [...arguments]
});
resolve({
name: "return-result-1",
get value() {
log.push({
name: "get return value (1)",
thisValue: this
});
return "return-value-1";
},
get done() {
log.push({
name: "get return done (1)",
thisValue: this
});
return false;
}
});
};
}
};
}
return {
name: "return-promise-2",
get then() {
log.push({
name: "get return then (2)",
thisValue: this
});
return function(resolve) {
log.push({
name: "call return then (2)",
thisValue: this,
args: [...arguments]
});
resolve({
name: "return-result-2",
get value() {
log.push({
name: "get return value (2)",
thisValue: this
});
return "return-value-2";
},
get done() {
log.push({
name: "get return done (2)",
thisValue: this
});
return true;
}
});
};
}
};
};
}
};
}
};
//- body
log.push({ name: "before yield*" });
yield* obj;
//- assertions
assert.sameValue(log.length, 0, "log.length");
iter.next().then(v => {
assert.sameValue(log[0].name, "before yield*");
assert.sameValue(log[1].name, "get next");
assert.sameValue(v.value, "next-value-1");
assert.sameValue(v.done, false);
assert.sameValue(log.length, 2, "log.length");
iter.return("return-arg-1").then(v => {
assert.sameValue(log[2].name, "get return");
assert.sameValue(log[2].thisValue.name, "asyncIterator", "get return thisValue");
assert.sameValue(log[3].name, "call return");
assert.sameValue(log[3].thisValue.name, "asyncIterator", "return thisValue");
assert.sameValue(log[3].args.length, 1, "return args.length");
assert.sameValue(log[3].args[0], "return-arg-1", "return args[0]");
assert.sameValue(log[4].name, "get return then (1)");
assert.sameValue(log[4].thisValue.name, "return-promise-1", "get return then thisValue");
assert.sameValue(log[5].name, "call return then (1)");
assert.sameValue(log[5].thisValue.name, "return-promise-1", "return then thisValue");
assert.sameValue(log[5].args.length, 2, "return then args.length");
assert.sameValue(typeof log[5].args[0], "function", "return then args[0]");
assert.sameValue(typeof log[5].args[1], "function", "return then args[1]");
assert.sameValue(log[6].name, "get return done (1)");
assert.sameValue(log[6].thisValue.name, "return-result-1", "get return done thisValue");
assert.sameValue(log[7].name, "get return value (1)");
assert.sameValue(log[7].thisValue.name, "return-result-1", "get return value thisValue");
assert.sameValue(log[8].name, "get return done (1)");
assert.sameValue(log[8].thisValue.name, "return-result-1", "get return done thisValue");
assert.sameValue(v.value, "return-value-1");
assert.sameValue(v.done, false);
assert.sameValue(log.length, 9, "log.length");
iter.return("return-arg-2").then(v => {
assert.sameValue(log[9].name, "get return");
assert.sameValue(log[9].thisValue.name, "asyncIterator", "get return thisValue");
assert.sameValue(log[10].name, "call return");
assert.sameValue(log[10].thisValue.name, "asyncIterator", "return thisValue");
assert.sameValue(log[10].args.length, 1, "return args.length");
assert.sameValue(log[10].args[0], "return-arg-2", "return args[0]");
assert.sameValue(log[11].name, "get return then (2)");
assert.sameValue(log[11].thisValue.name, "return-promise-2", "get return then thisValue");
assert.sameValue(log[12].name, "call return then (2)");
assert.sameValue(log[12].thisValue.name, "return-promise-2", "return then thisValue");
assert.sameValue(log[12].args.length, 2, "return then args.length");
assert.sameValue(typeof log[12].args[0], "function", "return then args[0]");
assert.sameValue(typeof log[12].args[1], "function", "return then args[1]");
assert.sameValue(log[13].name, "get return done (2)");
assert.sameValue(log[13].thisValue.name, "return-result-2", "get return done thisValue");
assert.sameValue(log[14].name, "get return value (2)");
assert.sameValue(log[14].thisValue.name, "return-result-2", "get return value thisValue");
assert.sameValue(v.value, "return-value-2");
assert.sameValue(v.done, true);
assert.sameValue(log.length, 15, "log.length");
}).then($DONE, $DONE);
}).catch($DONE);
}).catch($DONE);
// Copyright 2017 Tooru Fujisawa. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
template: default
desc: execution order for yield* with async iterator and throw()
info: |
YieldExpression: yield * AssignmentExpression
...
6. Repeat
...
b. Else if received.[[Type]] is throw, then
i. Let throw be ? GetMethod(iterator, "throw").
ii. If throw is not undefined, then
1. Let innerResult be ? Call(throw, iterator, « received.[[Value]] »).
2. If generatorKind is async, then set innerResult to
? Await(innerResult).
...
5. Let done be ? IteratorComplete(innerResult).
6. If done is true, then
a. Return ? IteratorValue(innerResult).
7. Let received be GeneratorYield(innerResult).
...
GeneratorYield ( iterNextObj )
...
10. If generatorKind is async,
a. Let value be IteratorValue(iterNextObj).
b. Let done be IteratorComplete(iterNextObj).
c. Return ! AsyncGeneratorResolve(generator, value, done).
...
flags: [async]
features: [async-iteration, Symbol.asyncIterator]
---*/
//- setup
var log = [];
var obj = {
[Symbol.asyncIterator]() {
var throwCount = 0;
return {
name: "asyncIterator",
get next() {
log.push({ name: "get next" });
return function() {
return {
value: "next-value-1",
done: false
};
};
},
get throw() {
log.push({
name: "get throw",
thisValue: this
});
return function() {
log.push({
name: "call throw",
thisValue: this,
args: [...arguments]
});
throwCount++;
if (throwCount == 1) {
return {
name: "throw-promise-1",
get then() {
log.push({
name: "get throw then (1)",
thisValue: this
});
return function(resolve) {
log.push({
name: "call throw then (1)",
thisValue: this,
args: [...arguments]
});
resolve({
name: "throw-result-1",
get value() {
log.push({
name: "get throw value (1)",
thisValue: this
});
return "throw-value-1";
},
get done() {
log.push({
name: "get throw done (1)",
thisValue: this
});
return false;
}
});
};
}
};
}
return {
name: "throw-promise-2",
get then() {
log.push({
name: "get throw then (2)",
thisValue: this
});
return function(resolve) {
log.push({
name: "call throw then (2)",
thisValue: this,
args: [...arguments]
});
resolve({
name: "throw-result-2",
get value() {
log.push({
name: "get throw value (2)",
thisValue: this
});
return "throw-value-2";
},
get done() {
log.push({
name: "get throw done (2)",
thisValue: this
});
return true;
}
});
};
}
};
};
}
};
}
};
//- body
log.push({ name: "before yield*" });
var v = yield* obj;
log.push({
name: "after yield*",
value: v
});
return "return-value";
//- assertions
assert.sameValue(log.length, 0, "log.length");
iter.next().then(v => {
assert.sameValue(log[0].name, "before yield*");
assert.sameValue(log[1].name, "get next");
assert.sameValue(v.value, "next-value-1");
assert.sameValue(v.done, false);
assert.sameValue(log.length, 2, "log.length");
iter.throw("throw-arg-1").then(v => {
assert.sameValue(log[2].name, "get throw");
assert.sameValue(log[2].thisValue.name, "asyncIterator", "get throw thisValue");
assert.sameValue(log[3].name, "call throw");
assert.sameValue(log[3].thisValue.name, "asyncIterator", "throw thisValue");
assert.sameValue(log[3].args.length, 1, "throw args.length");
assert.sameValue(log[3].args[0], "throw-arg-1", "throw args[0]");
assert.sameValue(log[4].name, "get throw then (1)");
assert.sameValue(log[4].thisValue.name, "throw-promise-1", "get throw thisValue");
assert.sameValue(log[5].name, "call throw then (1)");
assert.sameValue(log[5].thisValue.name, "throw-promise-1", "throw thisValue");
assert.sameValue(log[5].args.length, 2, "throw then args.length");
assert.sameValue(typeof log[5].args[0], "function", "throw then args[0]");
assert.sameValue(typeof log[5].args[1], "function", "throw then args[1]");
assert.sameValue(log[6].name, "get throw done (1)");
assert.sameValue(log[6].thisValue.name, "throw-result-1", "get throw done thisValue");
assert.sameValue(log[7].name, "get throw value (1)");
assert.sameValue(log[7].thisValue.name, "throw-result-1", "get throw value thisValue");
assert.sameValue(log[8].name, "get throw done (1)");
assert.sameValue(log[8].thisValue.name, "throw-result-1", "get throw done thisValue");
assert.sameValue(v.value, "throw-value-1");
assert.sameValue(v.done, false);
assert.sameValue(log.length, 9, "log.length");
iter.throw("throw-arg-2").then(v => {
assert.sameValue(log[9].name, "get throw");
assert.sameValue(log[9].thisValue.name, "asyncIterator", "get throw thisValue");
assert.sameValue(log[10].name, "call throw");
assert.sameValue(log[10].thisValue.name, "asyncIterator", "throw thisValue");
assert.sameValue(log[10].args.length, 1, "throw args.length");
assert.sameValue(log[10].args[0], "throw-arg-2", "throw args[0]");
assert.sameValue(log[11].name, "get throw then (2)");
assert.sameValue(log[11].thisValue.name, "throw-promise-2", "get throw thisValue");
assert.sameValue(log[12].name, "call throw then (2)");
assert.sameValue(log[12].thisValue.name, "throw-promise-2", "throw thisValue");
assert.sameValue(log[12].args.length, 2, "throw then args.length");
assert.sameValue(typeof log[12].args[0], "function", "throw then args[0]");
assert.sameValue(typeof log[12].args[1], "function", "throw then args[1]");
assert.sameValue(log[13].name, "get throw done (2)");
assert.sameValue(log[13].thisValue.name, "throw-result-2", "get throw done thisValue");
assert.sameValue(log[14].name, "get throw value (2)");
assert.sameValue(log[14].thisValue.name, "throw-result-2", "get throw value thisValue");
assert.sameValue(log[15].name, "after yield*");
assert.sameValue(log[15].value, "throw-value-2");
assert.sameValue(v.value, "return-value");
assert.sameValue(v.done, true);
assert.sameValue(log.length, 16, "log.length");
}).then($DONE, $DONE);
}).catch($DONE);
}).catch($DONE);
// Copyright 2017 Tooru Fujisawa. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
template: default
desc: execution order for yield* with sync iterator and next()
info: |
YieldExpression: yield * AssignmentExpression
...
2. Let value be ? GetValue(exprRef).
3. Let generatorKind be ! GetGeneratorKind().
4. Let iterator be ? GetIterator(value, generatorKind).
5. Let received be NormalCompletion(undefined).
6. Repeat
a. If received.[[Type]] is normal, then
i. Let innerResult be ? IteratorNext(iterator, received.[[Value]]).
ii. Let innerResult be ? Invoke(iterator, "next",
« received.[[Value]] »).
iii. If generatorKind is async, then set innerResult to
? Await(innerResult).
...
v. Let done be ? IteratorComplete(innerResult).
vi. If done is true, then
1. Return ? IteratorValue(innerResult).
vii. Let received be GeneratorYield(innerResult).
...
GetIterator ( obj [ , hint ] )
...
3. If hint is async,
a. Set method to ? GetMethod(obj, @@asyncIterator).
b. If method is undefined,
i. Let syncMethod be ? GetMethod(obj, @@iterator).
ii. Let syncIterator be ? Call(syncMethod, obj).
iii. Return ? CreateAsyncFromSyncIterator(syncIterator).
...
%AsyncFromSyncIteratorPrototype%.next ( value )
...
5. Let nextResult be IteratorNext(syncIterator, value).
...
7. Let nextValue be IteratorValue(nextResult).
...
9. Let nextDone be IteratorComplete(nextResult).
...
12. Perform ! Call(valueWrapperCapability.[[Resolve]], undefined,
« nextValue »).
...
14. Set onFulfilled.[[Done]] to nextDone.
15. Perform ! PerformPromiseThen(valueWrapperCapability.[[Promise]],
onFulfilled, undefined, promiseCapability).
...
Async Iterator Value Unwrap Functions
1. Return ! CreateIterResultObject(value, F.[[Done]]).
flags: [async]
features: [async-iteration, Symbol.asyncIterator]
---*/
//- setup
var log = [];
var obj = {
get [Symbol.iterator]() {
log.push({
name: "get [Symbol.iterator]",
thisValue: this
});
return function() {
log.push({
name: "call [Symbol.iterator]",
thisValue: this,
args: [...arguments]
});
var nextCount = 0;
return {
name: "syncIterator",
get next() {
log.push({
name: "get next",
thisValue: this
});
return function() {
log.push({
name: "call next",
thisValue: this,
args: [...arguments]
});
nextCount++;
if (nextCount == 1) {
return {
name: "next-result-1",
get value() {
log.push({
name: "get next value (1)",
thisValue: this
});
return "next-value-1";
},
get done() {
log.push({
name: "get next done (1)",
thisValue: this
});
return false;
}
};
}
return {
name: "next-result-2",
get value() {
log.push({
name: "get next value (2)",
thisValue: this
});
return "next-value-2";
},
get done() {
log.push({
name: "get next done (2)",
thisValue: this
});
return true;
}
};
};
}
};
};
},
get [Symbol.asyncIterator]() {
log.push({ name: "get [Symbol.asyncIterator]" });
return null;
}
};
//- body
log.push({ name: "before yield*" });
var v = yield* obj;
log.push({
name: "after yield*",
value: v
});
return "return-value";
//- assertions
assert.sameValue(log.length, 0, "log.length");
iter.next("next-arg-1").then(v => {
assert.sameValue(log[0].name, "before yield*");
assert.sameValue(log[1].name, "get [Symbol.asyncIterator]");
assert.sameValue(log[2].name, "get [Symbol.iterator]");
assert.sameValue(log[2].thisValue, obj, "get [Symbol.iterator] thisValue");
assert.sameValue(log[3].name, "call [Symbol.iterator]");
assert.sameValue(log[3].thisValue, obj, "[Symbol.iterator] thisValue");
assert.sameValue(log[3].args.length, 0, "[Symbol.iterator] args.length");
assert.sameValue(log[4].name, "get next");
assert.sameValue(log[4].thisValue.name, "syncIterator", "get next thisValue");
assert.sameValue(log[5].name, "call next");
assert.sameValue(log[5].thisValue.name, "syncIterator", "next thisValue");
assert.sameValue(log[5].args.length, 1, "next args.length");
assert.sameValue(log[5].args[0], undefined, "next args[0]");
assert.sameValue(log[6].name, "get next value (1)");
assert.sameValue(log[6].thisValue.name, "next-result-1", "get next value thisValue");
assert.sameValue(log[7].name, "get next done (1)");
assert.sameValue(log[7].thisValue.name, "next-result-1", "get next done thisValue");
assert.sameValue(v.value, "next-value-1");
assert.sameValue(v.done, false);
assert.sameValue(log.length, 8, "log.length");
iter.next("next-arg-2").then(v => {
assert.sameValue(log[8].name, "get next");
assert.sameValue(log[8].thisValue.name, "syncIterator", "get next thisValue");
assert.sameValue(log[9].name, "call next");
assert.sameValue(log[9].thisValue.name, "syncIterator", "next thisValue");
assert.sameValue(log[9].args.length, 1, "next args.length");
assert.sameValue(log[9].args[0], "next-arg-2", "next args[0]");
assert.sameValue(log[10].name, "get next value (2)");
assert.sameValue(log[10].thisValue.name, "next-result-2", "get next value thisValue");
assert.sameValue(log[11].name, "get next done (2)");
assert.sameValue(log[11].thisValue.name, "next-result-2", "get next done thisValue");
assert.sameValue(log[12].name, "after yield*");
assert.sameValue(log[12].value, "next-value-2");
assert.sameValue(v.value, "return-value");
assert.sameValue(v.done, true);
assert.sameValue(log.length, 13, "log.length");
}).then($DONE, $DONE);
}).catch($DONE);
// Copyright 2017 Tooru Fujisawa. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
template: default
desc: execution order for yield* with sync iterator and return()
info: |
YieldExpression: yield * AssignmentExpression
...
6. Repeat
...
c. Else,
i. Assert: received.[[Type]] is return.
ii. Let return be ? GetMethod(iterator, "return").
iii. If return is undefined, return Completion(received).
iv. Let innerReturnResult be ? Call(return, iterator,
« received.[[Value]] »).
v. If generatorKind is async, then set innerReturnResult to
? Await(innerReturnResult).
...
vii. Let done be ? IteratorComplete(innerReturnResult).
viii. If done is true, then
1. Let value be ? IteratorValue(innerReturnResult).
2. Return Completion{[[Type]]: return, [[Value]]: value,
[[Target]]: empty}.
ix. Let received be GeneratorYield(innerResult).
%AsyncFromSyncIteratorPrototype%.return ( value )
5. Let return be GetMethod(syncIterator, "return").
...
...
8. Let returnResult be Call(return, syncIterator, « value »).
...
11. Let returnValue be IteratorValue(returnResult).
..
13. Let returnDone be IteratorComplete(returnResult).
...
16. Perform ! Call(valueWrapperCapability.[[Resolve]], undefined, « returnValue »).
...
18. Set onFulfilled.[[Done]] to returnDone.
19. Perform ! PerformPromiseThen(valueWrapperCapability.[[Promise]],
onFulfilled, undefined, promiseCapability).
...
flags: [async]
features: [async-iteration, Symbol.asyncIterator]
---*/
//- setup
var log = [];
var obj = {
[Symbol.iterator]() {
var returnCount = 0;
return {
name: "syncIterator",
get next() {
log.push({ name: "get next" });
return function() {
return {
value: "next-value-1",
done: false
};
};
},
get return() {
log.push({
name: "get return",
thisValue: this
});
return function() {
log.push({
name: "call return",
thisValue: this,
args: [...arguments]
});
returnCount++;
if (returnCount == 1) {
return {
name: "return-result-1",
get value() {
log.push({
name: "get return value (1)",
thisValue: this
});
return "return-value-1";
},
get done() {
log.push({
name: "get return done (1)",
thisValue: this
});
return false;
}
};
}
return {
name: "return-result-2",
get value() {
log.push({
name: "get return value (2)",
thisValue: this
});
return "return-value-2";
},
get done() {
log.push({
name: "get return done (2)",
thisValue: this
});
return true;
}
};
};
}
};
}
};
//- body
log.push({ name: "before yield*" });
yield* obj;
//- assertions
assert.sameValue(log.length, 0, "log.length");
iter.next().then(v => {
assert.sameValue(log[0].name, "before yield*");
assert.sameValue(log[1].name, "get next");
assert.sameValue(v.value, "next-value-1");
assert.sameValue(v.done, false);
assert.sameValue(log.length, 2, "log.length");
iter.return("return-arg-1").then(v => {
assert.sameValue(log[2].name, "get return");
assert.sameValue(log[2].thisValue.name, "syncIterator", "get return thisValue");
assert.sameValue(log[3].name, "call return");
assert.sameValue(log[3].thisValue.name, "syncIterator", "return thisValue");
assert.sameValue(log[3].args.length, 1, "return args.length");
assert.sameValue(log[3].args[0], "return-arg-1", "return args[0]");
assert.sameValue(log[4].name, "get return value (1)");
assert.sameValue(log[4].thisValue.name, "return-result-1", "get return value thisValue");
assert.sameValue(log[5].name, "get return done (1)");
assert.sameValue(log[5].thisValue.name, "return-result-1", "get return done thisValue");
assert.sameValue(v.value, "return-value-1");
assert.sameValue(v.done, false);
assert.sameValue(log.length, 6, "log.length");
iter.return("return-arg-2").then(v => {
assert.sameValue(log[6].name, "get return");
assert.sameValue(log[6].thisValue.name, "syncIterator", "get return thisValue");
assert.sameValue(log[7].name, "call return");
assert.sameValue(log[7].thisValue.name, "syncIterator", "get return thisValue");
assert.sameValue(log[7].args.length, 1, "return args.length");
assert.sameValue(log[7].args[0], "return-arg-2", "return args[0]");
assert.sameValue(log[8].name, "get return value (2)");
assert.sameValue(log[8].thisValue.name, "return-result-2", "get return value thisValue");
assert.sameValue(log[9].name, "get return done (2)");
assert.sameValue(log[9].thisValue.name, "return-result-2", "get return done thisValue");
assert.sameValue(v.value, "return-value-2");
assert.sameValue(v.done, true);
assert.sameValue(log.length, 10, "log.length");
}).then($DONE, $DONE);
}).catch($DONE);
}).catch($DONE);
// Copyright 2017 Tooru Fujisawa. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
template: default
desc: execution order for yield* with sync iterator and throw()
info: |
YieldExpression: yield * AssignmentExpression
...
6. Repeat
...
b. Else if received.[[Type]] is throw, then
i. Let throw be ? GetMethod(iterator, "throw").
ii. If throw is not undefined, then
1. Let innerResult be ? Call(throw, iterator, « received.[[Value]] »).
2. If generatorKind is async, then set innerResult to
? Await(innerResult).
...
5. Let done be ? IteratorComplete(innerResult).
6. If done is true, then
a. Return ? IteratorValue(innerResult).
7. Let received be GeneratorYield(innerResult).
...
%AsyncFromSyncIteratorPrototype%.throw ( value )
...
5. Let throw be GetMethod(syncIterator, "throw").
...
8. Let throwResult be Call(throw, syncIterator, « value »).
...
11. Let throwValue be IteratorValue(throwResult).
...
13. Let throwDone be IteratorComplete(throwResult).
...
16. Perform ! Call(valueWrapperCapability.[[Resolve]], undefined,
« throwValue »).
...
18. Set onFulfilled.[[Done]] to throwDone.
19. Perform ! PerformPromiseThen(valueWrapperCapability.[[Promise]],
onFulfilled, undefined, promiseCapability).
...
flags: [async]
features: [async-iteration]
---*/
//- setup
var log = [];
var obj = {
[Symbol.iterator]() {
var throwCount = 0;
return {
name: "syncIterator",
get next() {
log.push({ name: "get next" });
return function() {
return {
value: "next-value-1",
done: false
};
};
},
get throw() {
log.push({
name: "get throw",
thisValue: this
});
return function() {
log.push({
name: "call throw",
thisValue: this,
args: [...arguments]
});
throwCount++;
if (throwCount == 1) {
return {
name: "throw-result-1",
get value() {
log.push({
name: "get throw value (1)",
thisValue: this
});
return "throw-value-1";
},
get done() {
log.push({
name: "get throw done (1)",
thisValue: this
});
return false;
}
};
}
return {
name: "throw-result-2",
get value() {
log.push({
name: "get throw value (2)",
thisValue: this
});
return "throw-value-2";
},
get done() {
log.push({
name: "get throw done (2)",
thisValue: this
});
return true;
}
};
};
}
};
}
};
//- body
log.push({ name: "before yield*" });
var v = yield* obj;
log.push({
name: "after yield*",
value: v
});
return "return-value";
//- assertions
assert.sameValue(log.length, 0, "log.length");
iter.next().then(v => {
assert.sameValue(log[0].name, "before yield*");
assert.sameValue(log[1].name, "get next");
assert.sameValue(v.value, "next-value-1");
assert.sameValue(v.done, false);
assert.sameValue(log.length, 2, "log.length");
iter.throw("throw-arg-1").then(v => {
assert.sameValue(log[2].name, "get throw");
assert.sameValue(log[2].thisValue.name, "syncIterator", "get throw thisValue");
assert.sameValue(log[3].name, "call throw");
assert.sameValue(log[3].thisValue.name, "syncIterator", "throw thisValue");
assert.sameValue(log[3].args.length, 1, "throw args.length");
assert.sameValue(log[3].args[0], "throw-arg-1", "throw args[0]");
assert.sameValue(log[4].name, "get throw value (1)");
assert.sameValue(log[4].thisValue.name, "throw-result-1", "get throw value thisValue");
assert.sameValue(log[5].name, "get throw done (1)");
assert.sameValue(log[5].thisValue.name, "throw-result-1", "get throw done thisValue");
assert.sameValue(v.value, "throw-value-1");
assert.sameValue(v.done, false);
assert.sameValue(log.length, 6, "log.length");
iter.throw("throw-arg-2").then(v => {
assert.sameValue(log[6].name, "get throw");
assert.sameValue(log[6].thisValue.name, "syncIterator", "get throw thisValue");
assert.sameValue(log[7].name, "call throw");
assert.sameValue(log[7].thisValue.name, "syncIterator", "throw thisValue");
assert.sameValue(log[7].args.length, 1, "throw args.length");
assert.sameValue(log[7].args[0], "throw-arg-2", "throw args[0]");
assert.sameValue(log[8].name, "get throw value (2)");
assert.sameValue(log[8].thisValue.name, "throw-result-2", "get throw value thisValue");
assert.sameValue(log[9].name, "get throw done (2)");
assert.sameValue(log[9].thisValue.name, "throw-result-2", "get throw done thisValue");
assert.sameValue(log[10].name, "after yield*");
assert.sameValue(log[10].value, "throw-value-2");
assert.sameValue(v.value, "return-value");
assert.sameValue(v.done, true);
assert.sameValue(log.length, 11, "log.length");
}).then($DONE, $DONE);
}).catch($DONE);
}).catch($DONE);
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment