IteratorClose.js 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. 'use strict';
  2. var $TypeError = require('es-errors/type');
  3. var Call = require('es-abstract/2023/Call');
  4. var CompletionRecord = require('es-abstract/2023/CompletionRecord');
  5. var GetMethod = require('es-abstract/2023/GetMethod');
  6. var Type = require('es-abstract/2023/Type');
  7. var isIteratorRecord = require('es-abstract/helpers/records/iterator-record');
  8. // https://262.ecma-international.org/14.0/#sec-iteratorclose
  9. module.exports = function IteratorClose(iteratorRecord, completion) {
  10. if (!isIteratorRecord(iteratorRecord)) {
  11. throw new $TypeError('Assertion failed: `iteratorRecord` must be an Iterator Record'); // step 1
  12. }
  13. if (Type(iteratorRecord['[[Iterator]]']) !== 'Object') {
  14. throw new $TypeError('Assertion failed: iteratorRecord.[[Iterator]] must be an Object'); // step 1
  15. }
  16. if (!(completion instanceof CompletionRecord)) { // step 2
  17. throw new $TypeError('Assertion failed: completion is not a Completion Record instance');
  18. }
  19. var completionThunk = function () {
  20. var value = completion.value();
  21. if (completion.type() === 'throw') {
  22. throw value;
  23. }
  24. return value;
  25. };
  26. var iterator = iteratorRecord['[[Iterator]]']; // step 3
  27. var iteratorReturn;
  28. try {
  29. iteratorReturn = GetMethod(iterator, 'return'); // step 4
  30. } catch (e) {
  31. completionThunk(); // throws if `completion` is a throw completion // step 6
  32. completionThunk = null; // ensure it's not called twice.
  33. throw e; // step 7
  34. }
  35. if (typeof iteratorReturn === 'undefined') {
  36. return completionThunk(); // step 5.a - 5.b
  37. }
  38. var innerResult;
  39. try {
  40. innerResult = Call(iteratorReturn, iterator, []);
  41. } catch (e) {
  42. // if we hit here, then "e" is the innerResult completion that needs re-throwing
  43. completionThunk(); // throws if `completion` is a throw completion // step 6
  44. completionThunk = null; // ensure it's not called twice.
  45. // if not, then return the innerResult completion
  46. throw e; // step 7
  47. }
  48. var completionRecord = completionThunk(); // if innerResult worked, then throw if the completion does
  49. completionThunk = null; // ensure it's not called twice.
  50. if (Type(innerResult) !== 'Object') {
  51. throw new $TypeError('iterator .return must return an object');
  52. }
  53. return completionRecord;
  54. };