suspended-yield-iterator-close-calls-next.js (3274B)
1 // Copyright (C) 2025 André Bargull. All rights reserved. 2 // This code is governed by the BSD license found in the LICENSE file. 3 4 /*--- 5 esid: sec-iterator.zipkeyed 6 description: > 7 Generator is closed from suspended-yield state and IteratorClose calls next. 8 info: | 9 %IteratorHelperPrototype%.return ( ) 10 ... 11 5. Let C be ReturnCompletion(undefined). 12 6. Return ? GeneratorResumeAbrupt(O, C, "Iterator Helper"). 13 14 GeneratorResumeAbrupt ( generator, abruptCompletion, generatorBrand ) 15 1. Let state be ? GeneratorValidate(generator, generatorBrand). 16 ... 17 4. Assert: state is suspended-yield. 18 ... 19 8. Set generator.[[GeneratorState]] to executing. 20 ... 21 10. Resume the suspended evaluation of genContext using abruptCompletion as 22 the result of the operation that suspended it. Let result be the 23 Completion Record returned by the resumed computation. 24 ... 25 26 GeneratorValidate ( generator, generatorBrand ) 27 ... 28 5. Let state be generator.[[GeneratorState]]. 29 6. If state is executing, throw a TypeError exception. 30 7. Return state. 31 32 IteratorZip ( iters, mode, padding, finishResults ) 33 ... 34 3. Let closure be a new Abstract Closure with no parameters that captures 35 iters, iterCount, openIters, mode, padding, and finishResults, and 36 performs the following steps when called: 37 ... 38 b. Repeat, 39 ... 40 v. Let completion be Completion(Yield(results)). 41 vi. If completion is an abrupt completion, then 42 1. Return ? IteratorCloseAll(openIters, completion). 43 ... 44 45 IteratorCloseAll ( iters, completion ) 46 1. For each element iter of iters, in reverse List order, do 47 a. Set completion to Completion(IteratorClose(iter, completion)). 48 2. Return ? completion. 49 50 IteratorClose ( iteratorRecord, completion ) 51 ... 52 3. Let innerResult be Completion(GetMethod(iterator, "return")). 53 4. If innerResult is a normal completion, then 54 a. Let return be innerResult.[[Value]]. 55 b. If return is undefined, return ? completion. 56 c. Set innerResult to Completion(Call(return, iterator)). 57 ... 58 59 %IteratorHelperPrototype%.next ( ) 60 1. Return ? GeneratorResume(this value, undefined, "Iterator Helper"). 61 62 GeneratorResume ( generator, value, generatorBrand ) 63 1. Let state be ? GeneratorValidate(generator, generatorBrand). 64 ... 65 features: [joint-iteration] 66 ---*/ 67 68 var returnCallCount = 0; 69 70 var underlying = { 71 next() { 72 return {value: 123, done: false}; 73 }, 74 return() { 75 returnCallCount += 1; 76 77 // The generator state is set to "executing", so this `next()` call throws 78 // a TypeError when `GeneratorResume` performs `GeneratorValidate`. 79 assert.throws(TypeError, function() { 80 it.next(); 81 }); 82 83 return {}; 84 }, 85 }; 86 87 var it = Iterator.zipKeyed({a: underlying}); 88 89 // Move generator into "suspended-yield" state. 90 var result = it.next(); 91 assert.sameValue(result.value.a, 123); 92 assert.sameValue(result.done, false); 93 94 assert.sameValue(returnCallCount, 0); 95 96 // This `return()` call continues execution in the suspended generator. 97 var result = it.return(); 98 assert.sameValue(result.value, undefined); 99 assert.sameValue(result.done, true); 100 101 assert.sameValue(returnCallCount, 1); 102 103 reportCompare(0, 0);