summaryrefslogtreecommitdiffstats
path: root/js/src/tests/test262/built-ins/Iterator
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/tests/test262/built-ins/Iterator')
-rw-r--r--js/src/tests/test262/built-ins/Iterator/browser.js0
-rw-r--r--js/src/tests/test262/built-ins/Iterator/constructor.js14
-rw-r--r--js/src/tests/test262/built-ins/Iterator/from/browser.js0
-rw-r--r--js/src/tests/test262/built-ins/Iterator/from/callable.js15
-rw-r--r--js/src/tests/test262/built-ins/Iterator/from/get-next-method-only-once.js49
-rw-r--r--js/src/tests/test262/built-ins/Iterator/from/get-next-method-throws.js28
-rw-r--r--js/src/tests/test262/built-ins/Iterator/from/is-function.js13
-rw-r--r--js/src/tests/test262/built-ins/Iterator/from/iterable-primitives.js56
-rw-r--r--js/src/tests/test262/built-ins/Iterator/from/iterable-to-iterator-fallback.js54
-rw-r--r--js/src/tests/test262/built-ins/Iterator/from/length.js25
-rw-r--r--js/src/tests/test262/built-ins/Iterator/from/name.js32
-rw-r--r--js/src/tests/test262/built-ins/Iterator/from/non-constructible.js26
-rw-r--r--js/src/tests/test262/built-ins/Iterator/from/primitives.js41
-rw-r--r--js/src/tests/test262/built-ins/Iterator/from/prop-desc.js29
-rw-r--r--js/src/tests/test262/built-ins/Iterator/from/proto.js18
-rw-r--r--js/src/tests/test262/built-ins/Iterator/from/result-proto.js32
-rw-r--r--js/src/tests/test262/built-ins/Iterator/from/shell.js0
-rw-r--r--js/src/tests/test262/built-ins/Iterator/from/supports-iterable.js18
-rw-r--r--js/src/tests/test262/built-ins/Iterator/from/supports-iterator.js32
-rw-r--r--js/src/tests/test262/built-ins/Iterator/length.js29
-rw-r--r--js/src/tests/test262/built-ins/Iterator/name.js33
-rw-r--r--js/src/tests/test262/built-ins/Iterator/newtarget-or-active-function-object.js25
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prop-desc.js30
-rw-r--r--js/src/tests/test262/built-ins/Iterator/proto-from-ctor-realm.js39
-rw-r--r--js/src/tests/test262/built-ins/Iterator/proto.js19
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/Symbol.iterator/browser.js0
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/Symbol.iterator/is-function.js15
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/Symbol.iterator/length.js32
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/Symbol.iterator/name.js35
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/Symbol.iterator/prop-desc.js25
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/Symbol.iterator/return-val.js23
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/Symbol.iterator/shell.js0
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/Symbol.toStringTag/browser.js0
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/Symbol.toStringTag/prop-desc.js19
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/Symbol.toStringTag/shell.js0
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/Symbol.toStringTag/weird-setter.js60
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/browser.js0
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/constructor/browser.js0
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/constructor/prop-desc.js19
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/constructor/shell.js0
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/constructor/weird-setter.js60
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/drop/argument-effect-order.js67
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/drop/browser.js0
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/drop/callable.js16
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/drop/exhaustion-does-not-call-return.js63
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/drop/get-next-method-only-once.js44
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/drop/get-next-method-throws.js28
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/drop/get-return-method-throws.js33
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/drop/is-function.js13
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/drop/length.js25
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/drop/limit-equals-total.js25
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/drop/limit-greater-than-total.js40
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/drop/limit-less-than-total.js33
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/drop/limit-rangeerror.js39
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/drop/limit-tonumber-throws.js25
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/drop/limit-tonumber.js40
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/drop/name.js32
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/drop/next-method-returns-non-object.js36
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/drop/next-method-returns-throwing-done.js44
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/drop/next-method-returns-throwing-value-done.js39
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/drop/next-method-returns-throwing-value.js42
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/drop/next-method-throws.js36
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/drop/non-constructible.js31
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/drop/prop-desc.js28
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/drop/proto.js14
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/drop/result-is-iterator.js14
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/drop/return-is-forwarded.js57
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/drop/return-is-not-forwarded-after-exhaustion.js53
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/drop/shell.js0
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/drop/this-non-callable-next.js22
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/drop/this-non-object.js37
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/drop/this-plain-iterator.js33
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/drop/throws-typeerror-when-generator-is-running.js42
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/drop/underlying-iterator-advanced-in-parallel.js42
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/drop/underlying-iterator-closed-in-parallel.js29
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/drop/underlying-iterator-closed.js29
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/every/argument-effect-order.js33
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/every/browser.js0
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/every/callable.js16
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/every/get-next-method-only-once.js41
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/every/get-next-method-throws.js28
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/every/get-return-method-throws.js34
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/every/is-function.js13
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/every/iterator-already-exhausted.js29
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/every/iterator-has-no-return.js30
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/every/iterator-return-method-throws.js34
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/every/length.js25
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/every/name.js32
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/every/next-method-returns-non-object.js28
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/every/next-method-returns-throwing-done.js36
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/every/next-method-returns-throwing-value-done.js33
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/every/next-method-returns-throwing-value.js36
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/every/next-method-throws.js28
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/every/non-callable-predicate.js25
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/every/non-constructible.js31
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/every/predicate-args.js46
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/every/predicate-returns-falsey.js36
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/every/predicate-returns-non-boolean.js33
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/every/predicate-returns-truthy-then-falsey.js37
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/every/predicate-returns-truthy.js27
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/every/predicate-this.js36
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/every/predicate-throws-then-closing-iterator-also-throws.js42
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/every/predicate-throws.js46
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/every/prop-desc.js28
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/every/proto.js14
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/every/result-is-boolean.js14
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/every/shell.js0
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/every/this-non-callable-next.js20
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/every/this-non-object.js29
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/every/this-plain-iterator.js35
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/filter/argument-effect-order.js33
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/filter/browser.js0
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/filter/callable.js16
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/filter/exhaustion-does-not-call-return.js40
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/filter/get-next-method-only-once.js44
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/filter/get-next-method-throws.js28
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/filter/get-return-method-throws.js33
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/filter/is-function.js13
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/filter/iterator-already-exhausted.js28
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/filter/iterator-return-method-throws.js32
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/filter/length.js25
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/filter/name.js32
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/filter/next-method-returns-non-object.js28
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/filter/next-method-returns-throwing-done.js36
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/filter/next-method-returns-throwing-value-done.js33
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/filter/next-method-returns-throwing-value.js36
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/filter/next-method-throws.js28
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/filter/non-callable-predicate.js23
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/filter/non-constructible.js31
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/filter/predicate-args.js47
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/filter/predicate-filters.js43
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/filter/predicate-returns-non-boolean.js41
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/filter/predicate-this.js36
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/filter/predicate-throws-then-closing-iterator-also-throws.js43
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/filter/predicate-throws.js44
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/filter/prop-desc.js28
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/filter/proto.js14
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/filter/result-is-iterator.js17
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/filter/return-is-forwarded.js36
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/filter/return-is-not-forwarded-after-exhaustion.js49
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/filter/shell.js0
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/filter/this-non-callable-next.js22
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/filter/this-non-object.js29
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/filter/this-plain-iterator.js36
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/filter/throws-typeerror-when-generator-is-running.js49
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/filter/underlying-iterator-advanced-in-parallel.js45
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/filter/underlying-iterator-closed-in-parallel.js29
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/filter/underlying-iterator-closed.js29
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/find/argument-effect-order.js33
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/find/browser.js0
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/find/callable.js16
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/find/get-next-method-only-once.js39
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/find/get-next-method-throws.js26
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/find/get-return-method-throws.js32
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/find/is-function.js13
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/find/iterator-already-exhausted.js26
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/find/iterator-has-no-return.js30
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/find/iterator-return-method-throws.js32
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/find/length.js25
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/find/name.js32
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/find/next-method-returns-non-object.js26
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/find/next-method-returns-throwing-done.js34
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/find/next-method-returns-throwing-value-done.js31
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/find/next-method-returns-throwing-value.js34
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/find/next-method-throws.js26
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/find/non-callable-predicate.js23
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/find/non-constructible.js31
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/find/predicate-args.js44
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/find/predicate-returns-falsey-then-truthy.js35
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/find/predicate-returns-falsey.js24
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/find/predicate-returns-non-boolean.js35
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/find/predicate-returns-truthy.js35
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/find/predicate-this.js34
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/find/predicate-throws-then-closing-iterator-also-throws.js39
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/find/predicate-throws.js43
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/find/prop-desc.js28
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/find/proto.js14
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/find/shell.js0
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/find/this-non-callable-next.js18
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/find/this-non-object.js27
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/find/this-plain-iterator.js33
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/flatMap/argument-effect-order.js45
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/flatMap/browser.js0
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/flatMap/callable.js16
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/flatMap/exhaustion-does-not-call-return.js37
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/flatMap/flattens-iterable.js33
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/flatMap/flattens-iterator.js47
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/flatMap/flattens-only-depth-1.js37
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/flatMap/get-next-method-only-once.js44
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/flatMap/get-next-method-throws.js28
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/flatMap/get-return-method-throws.js33
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/flatMap/is-function.js13
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/flatMap/iterable-primitives-are-not-flattened.js40
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/flatMap/iterable-to-iterator-fallback.js60
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/flatMap/iterator-already-exhausted.js25
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/flatMap/iterator-return-method-throws.js32
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/flatMap/length.js25
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/flatMap/mapper-args.js58
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/flatMap/mapper-returns-closed-iterator.js33
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/flatMap/mapper-returns-non-object.js37
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/flatMap/mapper-this.js36
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/flatMap/mapper-throws-then-closing-iterator-also-throws.js43
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/flatMap/mapper-throws.js44
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/flatMap/name.js32
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/flatMap/next-method-returns-non-object.js26
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/flatMap/next-method-returns-throwing-done.js34
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/flatMap/next-method-returns-throwing-value-done.js31
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/flatMap/next-method-returns-throwing-value.js34
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/flatMap/next-method-throws.js26
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/flatMap/non-callable-mapper.js23
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/flatMap/non-constructible.js31
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/flatMap/prop-desc.js28
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/flatMap/proto.js14
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/flatMap/result-is-iterator.js17
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/flatMap/return-is-forwarded-to-mapper-result.js48
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/flatMap/return-is-forwarded-to-underlying-iterator.js36
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/flatMap/return-is-not-forwarded-after-exhaustion.js49
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/flatMap/shell.js0
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/flatMap/strings-are-not-flattened.js29
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/flatMap/this-non-callable-next.js20
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/flatMap/this-non-object.js29
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/flatMap/this-plain-iterator.js34
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/flatMap/throws-typeerror-when-generator-is-running.js49
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/flatMap/underlying-iterator-advanced-in-parallel.js45
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/flatMap/underlying-iterator-closed-in-parallel.js29
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/flatMap/underlying-iterator-closed.js29
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/forEach/argument-effect-order.js38
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/forEach/browser.js0
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/forEach/callable.js16
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/forEach/fn-args.js43
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/forEach/fn-called-for-each-yielded-value.js31
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/forEach/fn-this.js33
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/forEach/fn-throws-then-closing-iterator-also-throws.js39
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/forEach/fn-throws.js43
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/forEach/get-next-method-only-once.js39
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/forEach/get-next-method-throws.js26
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/forEach/is-function.js13
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/forEach/iterator-already-exhausted.js25
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/forEach/length.js25
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/forEach/name.js32
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/forEach/next-method-returns-non-object.js26
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/forEach/next-method-returns-throwing-done.js34
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/forEach/next-method-returns-throwing-value-done.js31
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/forEach/next-method-returns-throwing-value.js34
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/forEach/next-method-throws.js26
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/forEach/non-callable-predicate.js23
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/forEach/non-constructible.js31
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/forEach/prop-desc.js28
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/forEach/proto.js14
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/forEach/result-is-undefined.js21
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/forEach/shell.js0
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/forEach/this-non-callable-next.js18
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/forEach/this-non-object.js27
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/forEach/this-plain-iterator.js32
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/initial-value.js26
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/map/argument-effect-order.js45
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/map/browser.js0
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/map/callable.js16
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/map/exhaustion-does-not-call-return.js37
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/map/get-next-method-only-once.js44
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/map/get-next-method-throws.js28
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/map/get-return-method-throws.js33
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/map/is-function.js13
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/map/iterator-already-exhausted.js25
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/map/iterator-return-method-throws.js32
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/map/length.js25
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/map/mapper-args.js58
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/map/mapper-this.js36
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/map/mapper-throws-then-closing-iterator-also-throws.js43
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/map/mapper-throws.js44
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/map/name.js32
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/map/next-method-returns-non-object.js26
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/map/next-method-returns-throwing-done.js34
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/map/next-method-returns-throwing-value-done.js31
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/map/next-method-returns-throwing-value.js34
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/map/next-method-throws.js26
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/map/non-callable-mapper.js23
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/map/non-constructible.js31
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/map/prop-desc.js28
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/map/proto.js14
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/map/result-is-iterator.js14
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/map/return-is-forwarded-to-underlying-iterator.js36
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/map/return-is-not-forwarded-after-exhaustion.js49
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/map/returned-iterator-yields-mapper-return-values.js39
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/map/shell.js0
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/map/this-non-callable-next.js20
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/map/this-non-object.js29
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/map/this-plain-iterator.js34
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/map/throws-typeerror-when-generator-is-running.js49
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/map/underlying-iterator-advanced-in-parallel.js45
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/map/underlying-iterator-closed-in-parallel.js29
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/map/underlying-iterator-closed.js29
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/reduce/argument-effect-order.js61
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/reduce/browser.js0
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/reduce/callable.js16
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/reduce/get-next-method-only-once.js39
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/reduce/get-next-method-throws.js26
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/reduce/is-function.js13
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/reduce/iterator-already-exhausted-initial-value.js24
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/reduce/iterator-already-exhausted-no-initial-value.js26
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/reduce/iterator-yields-once-initial-value.js38
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/reduce/iterator-yields-once-no-initial-value.js29
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/reduce/length.js25
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/reduce/name.js32
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/reduce/next-method-returns-non-object.js26
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/reduce/next-method-returns-throwing-done.js34
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/reduce/next-method-returns-throwing-value-done.js31
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/reduce/next-method-returns-throwing-value.js34
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/reduce/next-method-throws.js30
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/reduce/non-callable-reducer.js25
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/reduce/non-constructible.js35
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/reduce/prop-desc.js28
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/reduce/proto.js14
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/reduce/reducer-args-initial-value.js48
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/reduce/reducer-args-no-initial-value.js44
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/reduce/reducer-memo-can-be-any-type.js34
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/reduce/reducer-this.js35
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/reduce/reducer-throws-then-closing-iterator-also-throws.js39
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/reduce/reducer-throws.js43
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/reduce/shell.js0
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/reduce/this-non-callable-next.js18
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/reduce/this-non-object.js36
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/reduce/this-plain-iterator.js35
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/shell.js0
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/some/argument-effect-order.js33
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/some/browser.js0
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/some/callable.js16
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/some/get-next-method-only-once.js39
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/some/get-next-method-throws.js26
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/some/get-return-method-throws.js32
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/some/is-function.js13
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/some/iterator-already-exhausted.js26
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/some/iterator-has-no-return.js30
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/some/iterator-return-method-throws.js32
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/some/length.js25
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/some/name.js32
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/some/next-method-returns-non-object.js26
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/some/next-method-returns-throwing-done.js34
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/some/next-method-returns-throwing-value-done.js31
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/some/next-method-returns-throwing-value.js34
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/some/next-method-throws.js26
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/some/non-callable-predicate.js23
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/some/non-constructible.js31
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/some/predicate-args.js44
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/some/predicate-returns-falsey-then-truthy.js35
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/some/predicate-returns-falsey.js24
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/some/predicate-returns-non-boolean.js35
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/some/predicate-returns-truthy.js35
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/some/predicate-this.js34
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/some/predicate-throws-then-closing-iterator-also-throws.js39
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/some/predicate-throws.js43
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/some/prop-desc.js28
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/some/proto.js14
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/some/result-is-boolean.js14
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/some/shell.js0
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/some/this-non-callable-next.js18
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/some/this-non-object.js27
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/some/this-plain-iterator.js33
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/take/argument-effect-order.js75
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/take/browser.js0
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/take/callable.js16
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/take/exhaustion-calls-return.js71
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/take/get-next-method-only-once.js44
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/take/get-next-method-throws.js28
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/take/get-return-method-throws.js33
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/take/is-function.js13
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/take/length.js25
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/take/limit-greater-than-or-equal-to-total.js30
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/take/limit-less-than-total.js31
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/take/limit-rangeerror.js39
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/take/limit-tonumber-throws.js25
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/take/limit-tonumber.js64
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/take/name.js32
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/take/next-method-returns-non-object.js32
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/take/next-method-returns-throwing-done.js45
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/take/next-method-returns-throwing-value-done.js39
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/take/next-method-returns-throwing-value.js45
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/take/next-method-throws.js32
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/take/non-constructible.js31
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/take/prop-desc.js28
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/take/proto.js14
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/take/result-is-iterator.js14
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/take/return-is-forwarded.js54
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/take/return-is-not-forwarded-after-exhaustion.js53
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/take/shell.js0
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/take/this-non-callable-next.js22
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/take/this-non-object.js37
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/take/this-plain-iterator.js33
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/take/throws-typeerror-when-generator-is-running.js42
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/take/underlying-iterator-advanced-in-parallel.js42
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/take/underlying-iterator-closed-in-parallel.js29
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/take/underlying-iterator-closed.js29
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/toArray/browser.js0
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/toArray/callable.js16
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/toArray/get-next-method-only-once.js37
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/toArray/get-next-method-throws.js26
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/toArray/is-function.js13
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/toArray/iterator-already-exhausted.js27
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/toArray/length.js25
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/toArray/name.js32
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/toArray/next-method-returns-non-object.js26
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/toArray/next-method-returns-throwing-done.js34
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/toArray/next-method-returns-throwing-value-done.js31
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/toArray/next-method-returns-throwing-value.js34
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/toArray/next-method-throws.js26
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/toArray/non-constructible.js27
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/toArray/prop-desc.js28
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/toArray/proto.js14
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/toArray/shell.js0
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/toArray/this-non-callable-next.js18
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/toArray/this-non-object.js27
-rw-r--r--js/src/tests/test262/built-ins/Iterator/prototype/toArray/this-plain-iterator.js28
-rw-r--r--js/src/tests/test262/built-ins/Iterator/shell.js0
-rw-r--r--js/src/tests/test262/built-ins/Iterator/subclassable.js30
414 files changed, 12025 insertions, 0 deletions
diff --git a/js/src/tests/test262/built-ins/Iterator/browser.js b/js/src/tests/test262/built-ins/Iterator/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/browser.js
diff --git a/js/src/tests/test262/built-ins/Iterator/constructor.js b/js/src/tests/test262/built-ins/Iterator/constructor.js
new file mode 100644
index 0000000000..ba563ad495
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/constructor.js
@@ -0,0 +1,14 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-iterator-constructor
+description: >
+ The Iterator constructor is a built-in function
+features: [iterator-helpers]
+---*/
+
+assert.sameValue(typeof Iterator, 'function', 'The value of `typeof Iterator` is "function"');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/from/browser.js b/js/src/tests/test262/built-ins/Iterator/from/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/from/browser.js
diff --git a/js/src/tests/test262/built-ins/Iterator/from/callable.js b/js/src/tests/test262/built-ins/Iterator/from/callable.js
new file mode 100644
index 0000000000..2df78d05e7
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/from/callable.js
@@ -0,0 +1,15 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iterator.from
+description: >
+ Iterator.from is callable
+features: [iterator-helpers]
+---*/
+function* g() {}
+
+Iterator.from(g());
+Iterator.from.call(null, g());
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/from/get-next-method-only-once.js b/js/src/tests/test262/built-ins/Iterator/from/get-next-method-only-once.js
new file mode 100644
index 0000000000..efe706a72a
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/from/get-next-method-only-once.js
@@ -0,0 +1,49 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iterator.from
+description: >
+ Gets the next method from the underlying iterator only once
+info: |
+ Iterator.from ( O )
+
+ 2. Let iteratorRecord be ? GetIteratorFlattenable(O).
+
+features: [iterator-helpers]
+flags: []
+---*/
+let nextGets = 0;
+let nextCalls = 0;
+
+class CountingIterator {
+ get next() {
+ ++nextGets;
+ let iter = (function* () {
+ for (let i = 1; i < 5; ++i) {
+ yield i;
+ }
+ })();
+ return function () {
+ ++nextCalls;
+ return iter.next();
+ };
+ }
+}
+
+let iterator = new CountingIterator();
+
+assert.sameValue(nextGets, 0, 'The value of `nextGets` is 0');
+assert.sameValue(nextCalls, 0, 'The value of `nextCalls` is 0');
+
+iterator = Iterator.from(iterator);
+
+assert.sameValue(nextGets, 1, 'The value of `nextGets` is 1');
+assert.sameValue(nextCalls, 0, 'The value of `nextCalls` is 0');
+
+iterator.toArray();
+
+assert.sameValue(nextGets, 1, 'The value of `nextGets` is 1');
+assert.sameValue(nextCalls, 5, 'The value of `nextCalls` is 5');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/from/get-next-method-throws.js b/js/src/tests/test262/built-ins/Iterator/from/get-next-method-throws.js
new file mode 100644
index 0000000000..ea590b912b
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/from/get-next-method-throws.js
@@ -0,0 +1,28 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iterator.from
+description: >
+ Underlying iterator has throwing next getter
+info: |
+ Iterator.from ( O )
+
+ 4. Let iterated be ? GetIteratorDirect(O).
+
+features: [iterator-helpers]
+flags: []
+---*/
+class ThrowingIterator {
+ get next() {
+ throw new Test262Error();
+ }
+}
+
+let iterator = new ThrowingIterator();
+
+assert.throws(Test262Error, function () {
+ Iterator.from(iterator);
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/from/is-function.js b/js/src/tests/test262/built-ins/Iterator/from/is-function.js
new file mode 100644
index 0000000000..c350a6233d
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/from/is-function.js
@@ -0,0 +1,13 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iterator.from
+description: >
+ Iterator.from is a built-in function
+features: [iterator-helpers]
+---*/
+
+assert.sameValue(typeof Iterator.from, 'function', 'The value of `typeof Iterator.from` is "function"');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/from/iterable-primitives.js b/js/src/tests/test262/built-ins/Iterator/from/iterable-primitives.js
new file mode 100644
index 0000000000..e441136b91
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/from/iterable-primitives.js
@@ -0,0 +1,56 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iterator.from
+description: >
+ Iterator.from does not respect the iterability of any primitive except Strings
+info: |
+ Iterator.from ( O )
+
+ 1. If O is a String, set O to ! ToObject(O).
+ 2. Let iteratorRecord be ? GetIteratorFlattenable(O).
+
+includes: [compareArray.js]
+features: [iterator-helpers]
+flags: []
+---*/
+
+function* g() {
+ yield 0;
+}
+
+Number.prototype[Symbol.iterator] = function* () {
+ let i = 0;
+ let target = this >>> 0;
+ while (i < target) {
+ yield i;
+ ++i;
+ }
+};
+
+assert.compareArray(Array.from(5), [0, 1, 2, 3, 4]);
+
+assert.throws(TypeError, function () {
+ Iterator.from(5);
+});
+
+assert.compareArray(Array.from(Iterator.from(new Number(5))), [0, 1, 2, 3, 4]);
+
+assert.compareArray(Array.from(Iterator.from('string')), ['s', 't', 'r', 'i', 'n', 'g']);
+
+const originalStringIterator = String.prototype[Symbol.iterator];
+let observedType;
+Object.defineProperty(String.prototype, Symbol.iterator, {
+ get() {
+ 'use strict';
+ observedType = typeof this;
+ return originalStringIterator;
+ }
+});
+Iterator.from('');
+assert.sameValue(observedType, 'string');
+Iterator.from(new String(''));
+assert.sameValue(observedType, 'object');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/from/iterable-to-iterator-fallback.js b/js/src/tests/test262/built-ins/Iterator/from/iterable-to-iterator-fallback.js
new file mode 100644
index 0000000000..567eb7d474
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/from/iterable-to-iterator-fallback.js
@@ -0,0 +1,54 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iterator.from
+description: >
+ Iterator.from falls back to treating its parameter as an iterator if the Symbol.iterator property is null/undefined
+info: |
+ Iterator.from ( O )
+
+includes: [compareArray.js]
+features: [iterator-helpers]
+flags: []
+---*/
+
+function* g() {
+ yield 0;
+ yield 1;
+ yield 2;
+}
+
+let iter = (function () {
+ let n = g();
+ return {
+ [Symbol.iterator]: 0,
+ next: () => n.next(),
+ };
+})();
+
+assert.throws(TypeError, function () {
+ Iterator.from(iter);
+});
+
+iter = (function () {
+ let n = g();
+ return {
+ [Symbol.iterator]: null,
+ next: () => n.next(),
+ };
+})();
+
+assert.compareArray(Array.from(Iterator.from(iter)), [0, 1, 2]);
+
+iter = (function () {
+ let n = g();
+ return {
+ [Symbol.iterator]: undefined,
+ next: () => n.next(),
+ };
+})();
+
+assert.compareArray(Array.from(Iterator.from(iter)), [0, 1, 2]);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/from/length.js b/js/src/tests/test262/built-ins/Iterator/from/length.js
new file mode 100644
index 0000000000..5e434e66bb
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/from/length.js
@@ -0,0 +1,25 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iterator.from
+description: >
+ Iterator.from has a "length" property whose value is 1.
+info: |
+ ECMAScript Standard Built-in Objects
+
+ Unless otherwise specified, the length property of a built-in
+ Function object has the attributes { [[Writable]]: false, [[Enumerable]]:
+ false, [[Configurable]]: true }.
+features: [iterator-helpers]
+includes: [propertyHelper.js]
+---*/
+
+verifyProperty(Iterator.from, 'length', {
+ value: 1,
+ writable: false,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/from/name.js b/js/src/tests/test262/built-ins/Iterator/from/name.js
new file mode 100644
index 0000000000..489b62aa19
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/from/name.js
@@ -0,0 +1,32 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iterator.from
+description: >
+ The "name" property of Iterator.from
+info: |
+ 17 ECMAScript Standard Built-in Objects
+
+ Every built-in Function object, including constructors, that is not
+ identified as an anonymous function has a name property whose value is a
+ String. Unless otherwise specified, this value is the name that is given to
+ the function in this specification.
+
+ ...
+
+ Unless otherwise specified, the name property of a built-in Function
+ object, if it exists, has the attributes { [[Writable]]: false,
+ [[Enumerable]]: false, [[Configurable]]: true }.
+features: [iterator-helpers]
+includes: [propertyHelper.js]
+---*/
+
+verifyProperty(Iterator.from, 'name', {
+ value: 'from',
+ writable: false,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/from/non-constructible.js b/js/src/tests/test262/built-ins/Iterator/from/non-constructible.js
new file mode 100644
index 0000000000..21c14df223
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/from/non-constructible.js
@@ -0,0 +1,26 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iterator.from
+description: >
+ Iterator.from is not constructible.
+
+ Built-in function objects that are not identified as constructors do not implement the [[Construct]] internal method unless otherwise specified in the description of a particular function.
+features: [iterator-helpers]
+---*/
+function* g() {}
+
+assert.throws(TypeError, () => {
+ new Iterator.from();
+});
+
+assert.throws(TypeError, () => {
+ new Iterator.from(g());
+});
+
+assert.throws(TypeError, () => {
+ new class extends Iterator {}.from(g());
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/from/primitives.js b/js/src/tests/test262/built-ins/Iterator/from/primitives.js
new file mode 100644
index 0000000000..d71f4417c9
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/from/primitives.js
@@ -0,0 +1,41 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iterator.from
+description: >
+ Iterator.from throws on primitives (except Strings)
+info: |
+ Iterator.from ( O )
+
+features: [iterator-helpers]
+flags: []
+---*/
+
+assert.throws(TypeError, function () {
+ Iterator.from(null);
+});
+
+assert.throws(TypeError, function () {
+ Iterator.from(undefined);
+});
+
+assert.throws(TypeError, function () {
+ Iterator.from(0);
+});
+
+assert.throws(TypeError, function () {
+ Iterator.from(0n);
+});
+
+assert.throws(TypeError, function () {
+ Iterator.from(true);
+});
+
+assert.throws(TypeError, function () {
+ Iterator.from(Symbol());
+});
+
+Iterator.from('string');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/from/prop-desc.js b/js/src/tests/test262/built-ins/Iterator/from/prop-desc.js
new file mode 100644
index 0000000000..2bcc902e98
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/from/prop-desc.js
@@ -0,0 +1,29 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iterator.from
+description: >
+ Property descriptor of Iterator.from
+info: |
+ Iterator.from
+
+ * is the initial value of the Iterator.from property of the global object.
+
+ 17 ECMAScript Standard Built-in Objects
+
+ Every other data property described in clauses 18 through 26 and in Annex B.2
+ has the attributes { [[Writable]]: true, [[Enumerable]]: false,
+ [[Configurable]]: true } unless otherwise specified.
+features: [globalThis, iterator-helpers]
+includes: [propertyHelper.js]
+---*/
+
+verifyProperty(Iterator, 'from', {
+ value: Iterator.from,
+ writable: true,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/from/proto.js b/js/src/tests/test262/built-ins/Iterator/from/proto.js
new file mode 100644
index 0000000000..2f6c9f8c65
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/from/proto.js
@@ -0,0 +1,18 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iterator.from
+description: >
+ The value of the [[Prototype]] internal slot of Iterator.from is the
+ intrinsic object %FunctionPrototype%.
+features: [iterator-helpers]
+---*/
+
+assert.sameValue(
+ Object.getPrototypeOf(Iterator.from),
+ Function.prototype,
+ 'Object.getPrototypeOf(Iterator.from) must return the value of Function.prototype'
+);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/from/result-proto.js b/js/src/tests/test262/built-ins/Iterator/from/result-proto.js
new file mode 100644
index 0000000000..60e12e0a41
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/from/result-proto.js
@@ -0,0 +1,32 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iterator.from
+description: >
+ The value of the [[Prototype]] internal slot of the return value of Iterator.from is the
+ intrinsic object %WrapForValidIteratorPrototype%, whose [[Prototype]] is %IteratorHelperPrototype%.
+features: [iterator-helpers]
+---*/
+let iter = {
+ next() {
+ return {
+ done: true,
+ value: undefined,
+ };
+ },
+};
+
+const WrapForValidIteratorPrototype = Object.getPrototypeOf(Iterator.from(iter));
+
+assert.sameValue(Object.getPrototypeOf(WrapForValidIteratorPrototype), Iterator.prototype);
+
+class SubIterator extends Iterator {}
+assert.sameValue(Object.getPrototypeOf(SubIterator.from(iter)), WrapForValidIteratorPrototype);
+
+function* g() {}
+const GeneratorPrototype = Object.getPrototypeOf(g());
+
+assert.sameValue(Object.getPrototypeOf(Iterator.from(g())), GeneratorPrototype);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/from/shell.js b/js/src/tests/test262/built-ins/Iterator/from/shell.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/from/shell.js
diff --git a/js/src/tests/test262/built-ins/Iterator/from/supports-iterable.js b/js/src/tests/test262/built-ins/Iterator/from/supports-iterable.js
new file mode 100644
index 0000000000..06cfa66537
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/from/supports-iterable.js
@@ -0,0 +1,18 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iterator.from
+description: >
+ Iterator.from supports iterables
+info: |
+ Iterator.from ( O )
+
+includes: [compareArray.js]
+features: [iterator-helpers]
+flags: []
+---*/
+assert.compareArray(Array.from(Iterator.from([0, 1, 2, 3])), [0, 1, 2, 3]);
+assert.compareArray(Array.from(Iterator.from(new String('str'))), ['s', 't', 'r']);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/from/supports-iterator.js b/js/src/tests/test262/built-ins/Iterator/from/supports-iterator.js
new file mode 100644
index 0000000000..c7a30480e8
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/from/supports-iterator.js
@@ -0,0 +1,32 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iterator.from
+description: >
+ Iterator.from supports non-iterable iterators
+info: |
+ Iterator.from ( O )
+
+includes: [compareArray.js]
+features: [iterator-helpers]
+flags: []
+---*/
+
+function* g() {
+ yield 0;
+ yield 1;
+ yield 2;
+ yield 3;
+}
+
+let n = g();
+let iter = {
+ next() {
+ return n.next();
+ },
+};
+
+assert.compareArray(Array.from(Iterator.from(iter)), [0, 1, 2, 3]);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/length.js b/js/src/tests/test262/built-ins/Iterator/length.js
new file mode 100644
index 0000000000..17116179c2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/length.js
@@ -0,0 +1,29 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-iterator-constructor
+description: >
+ Iterator has a "length" property whose value is 0.
+info: |
+ The Iterator Constructor
+
+ The length property of the Iterator constructor function is 0.
+ ...
+
+ ES7 section 17: Unless otherwise specified, the length property of a built-in
+ Function object has the attributes { [[Writable]]: false, [[Enumerable]]:
+ false, [[Configurable]]: true }.
+features: [iterator-helpers]
+includes: [propertyHelper.js]
+---*/
+
+verifyProperty(Iterator, 'length', {
+ value: 0,
+ writable: false,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/name.js b/js/src/tests/test262/built-ins/Iterator/name.js
new file mode 100644
index 0000000000..43563b6132
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/name.js
@@ -0,0 +1,33 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-iterator-constructor
+description: >
+ The "name" property of Iterator
+info: |
+ 17 ECMAScript Standard Built-in Objects
+
+ Every built-in Function object, including constructors, that is not
+ identified as an anonymous function has a name property whose value is a
+ String. Unless otherwise specified, this value is the name that is given to
+ the function in this specification.
+
+ ...
+
+ Unless otherwise specified, the name property of a built-in Function
+ object, if it exists, has the attributes { [[Writable]]: false,
+ [[Enumerable]]: false, [[Configurable]]: true }.
+features: [iterator-helpers]
+includes: [propertyHelper.js]
+---*/
+
+verifyProperty(Iterator, 'name', {
+ value: 'Iterator',
+ writable: false,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/newtarget-or-active-function-object.js b/js/src/tests/test262/built-ins/Iterator/newtarget-or-active-function-object.js
new file mode 100644
index 0000000000..8b99541d87
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/newtarget-or-active-function-object.js
@@ -0,0 +1,25 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-iterator
+description: >
+ Iterator is not callable or constructable
+info: |
+ When the Iterator function is called, the following steps are taken:
+
+ If NewTarget is undefined or the active function object, throw a TypeError exception.
+
+features: [iterator-helpers]
+---*/
+
+assert.throws(TypeError, () => {
+ Iterator();
+});
+
+assert.throws(TypeError, () => {
+ new Iterator();
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prop-desc.js b/js/src/tests/test262/built-ins/Iterator/prop-desc.js
new file mode 100644
index 0000000000..fc2efef324
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prop-desc.js
@@ -0,0 +1,30 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-iterator-constructor
+description: >
+ Property descriptor of Iterator
+info: |
+ The Iterator Constructor
+
+ * is the initial value of the Iterator property of the global object.
+
+ 17 ECMAScript Standard Built-in Objects
+
+ Every other data property described in clauses 18 through 26 and in Annex B.2
+ has the attributes { [[Writable]]: true, [[Enumerable]]: false,
+ [[Configurable]]: true } unless otherwise specified.
+features: [globalThis, iterator-helpers]
+includes: [propertyHelper.js]
+---*/
+
+verifyProperty(globalThis, 'Iterator', {
+ value: Iterator,
+ writable: true,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/proto-from-ctor-realm.js b/js/src/tests/test262/built-ins/Iterator/proto-from-ctor-realm.js
new file mode 100644
index 0000000000..ffae2a51cb
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/proto-from-ctor-realm.js
@@ -0,0 +1,39 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-iterator
+description: Default [[Prototype]] value derived from realm of the NewTarget.
+features: [cross-realm, iterator-helpers, Reflect, Symbol]
+---*/
+
+let other = $262.createRealm().global;
+let newTarget = new other.Function();
+let ai;
+
+newTarget.prototype = undefined;
+ai = Reflect.construct(Iterator, [1], newTarget);
+assert.sameValue(Object.getPrototypeOf(ai), other.Iterator.prototype);
+
+newTarget.prototype = null;
+ai = Reflect.construct(Iterator, [1], newTarget);
+assert.sameValue(Object.getPrototypeOf(ai), other.Iterator.prototype);
+
+newTarget.prototype = true;
+ai = Reflect.construct(Iterator, [1], newTarget);
+assert.sameValue(Object.getPrototypeOf(ai), other.Iterator.prototype);
+
+newTarget.prototype = '';
+ai = Reflect.construct(Iterator, [1], newTarget);
+assert.sameValue(Object.getPrototypeOf(ai), other.Iterator.prototype);
+
+newTarget.prototype = Symbol();
+ai = Reflect.construct(Iterator, [1], newTarget);
+assert.sameValue(Object.getPrototypeOf(ai), other.Iterator.prototype);
+
+newTarget.prototype = 0;
+ai = Reflect.construct(Iterator, [1], newTarget);
+assert.sameValue(Object.getPrototypeOf(ai), other.Iterator.prototype);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/proto.js b/js/src/tests/test262/built-ins/Iterator/proto.js
new file mode 100644
index 0000000000..6e5baeff98
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/proto.js
@@ -0,0 +1,19 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-properties-of-the-iterator-constructor
+description: >
+ The value of the [[Prototype]] internal slot of the Iterator constructor is the
+ intrinsic object %FunctionPrototype%.
+features: [iterator-helpers]
+---*/
+
+assert.sameValue(
+ Object.getPrototypeOf(Iterator),
+ Function.prototype,
+ 'Object.getPrototypeOf(Iterator) must return the value of Function.prototype'
+);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/Symbol.iterator/browser.js b/js/src/tests/test262/built-ins/Iterator/prototype/Symbol.iterator/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/Symbol.iterator/browser.js
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/Symbol.iterator/is-function.js b/js/src/tests/test262/built-ins/Iterator/prototype/Symbol.iterator/is-function.js
new file mode 100644
index 0000000000..8b18d80ccd
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/Symbol.iterator/is-function.js
@@ -0,0 +1,15 @@
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.some
+description: >
+ Iterator.prototype.some is a built-in function
+features: [Symbol.iterator]
+---*/
+const IteratorPrototype = Object.getPrototypeOf(
+ Object.getPrototypeOf([][Symbol.iterator]())
+);
+
+assert.sameValue(typeof IteratorPrototype[Symbol.iterator], 'function');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/Symbol.iterator/length.js b/js/src/tests/test262/built-ins/Iterator/prototype/Symbol.iterator/length.js
new file mode 100644
index 0000000000..398404d1bb
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/Symbol.iterator/length.js
@@ -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: 25.1.2.1
+description: Length of %IteratorPrototype%[ @@iterator ]
+info: |
+ ES6 Section 17:
+ Every built-in Function object, including constructors, has a length
+ property whose value is an integer. Unless otherwise specified, this value
+ is equal to the largest number of named arguments shown in the subclause
+ headings for the function description, including optional parameters.
+
+ [...]
+
+ Unless otherwise specified, the length property of a built-in Function
+ object has the attributes { [[Writable]]: false, [[Enumerable]]: false,
+ [[Configurable]]: true }.
+features: [Symbol.iterator]
+includes: [propertyHelper.js]
+---*/
+const IteratorPrototype = Object.getPrototypeOf(
+ Object.getPrototypeOf([][Symbol.iterator]())
+);
+
+verifyProperty(IteratorPrototype[Symbol.iterator], 'length', {
+ value: 0,
+ writable: false,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/Symbol.iterator/name.js b/js/src/tests/test262/built-ins/Iterator/prototype/Symbol.iterator/name.js
new file mode 100644
index 0000000000..62b78dfbd8
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/Symbol.iterator/name.js
@@ -0,0 +1,35 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+es6id: 25.1.2.1
+description: Descriptor for `name` property
+info: |
+ The value of the name property of this function is "[Symbol.iterator]".
+
+ ES6 Section 17: ECMAScript Standard Built-in Objects
+
+ Every built-in Function object, including constructors, that is not
+ identified as an anonymous function has a name property whose value is a
+ String. Unless otherwise specified, this value is the name that is given to
+ the function in this specification.
+
+ [...]
+
+ Unless otherwise specified, the name property of a built-in Function
+ object, if it exists, has the attributes { [[Writable]]: false,
+ [[Enumerable]]: false, [[Configurable]]: true }.
+features: [Symbol.iterator]
+includes: [propertyHelper.js]
+---*/
+const IteratorPrototype = Object.getPrototypeOf(
+ Object.getPrototypeOf([][Symbol.iterator]())
+);
+
+verifyProperty(IteratorPrototype[Symbol.iterator], 'name', {
+ value: '[Symbol.iterator]',
+ writable: false,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/Symbol.iterator/prop-desc.js b/js/src/tests/test262/built-ins/Iterator/prototype/Symbol.iterator/prop-desc.js
new file mode 100644
index 0000000000..6f08e5017d
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/Symbol.iterator/prop-desc.js
@@ -0,0 +1,25 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+es6id: 25.1.2.1
+description: Property descriptor
+info: |
+ ES6 Section 17
+
+ Every other data property described in clauses 18 through 26 and in Annex
+ B.2 has the attributes { [[Writable]]: true, [[Enumerable]]: false,
+ [[Configurable]]: true } unless otherwise specified.
+features: [Symbol.iterator]
+includes: [propertyHelper.js]
+---*/
+const IteratorPrototype = Object.getPrototypeOf(
+ Object.getPrototypeOf([][Symbol.iterator]())
+);
+
+verifyProperty(IteratorPrototype, Symbol.iterator, {
+ writable: true,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/Symbol.iterator/return-val.js b/js/src/tests/test262/built-ins/Iterator/prototype/Symbol.iterator/return-val.js
new file mode 100644
index 0000000000..a2ac55b494
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/Symbol.iterator/return-val.js
@@ -0,0 +1,23 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-%iteratorprototype%-@@iterator
+description: Return value of @@iterator on %IteratorPrototype%
+info: |
+ %IteratorPrototype% [ @@iterator ] ( )
+ 1. Return the this value.
+features: [Symbol.iterator]
+---*/
+const IteratorPrototype = Object.getPrototypeOf(
+ Object.getPrototypeOf([][Symbol.iterator]())
+);
+
+const getIterator = IteratorPrototype[Symbol.iterator];
+
+const thisValues = [{}, Symbol(), 4, 4n, true, undefined, null];
+
+for (const thisValue of thisValues) {
+ assert.sameValue(getIterator.call(thisValue), thisValue);
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/Symbol.iterator/shell.js b/js/src/tests/test262/built-ins/Iterator/prototype/Symbol.iterator/shell.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/Symbol.iterator/shell.js
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/Symbol.toStringTag/browser.js b/js/src/tests/test262/built-ins/Iterator/prototype/Symbol.toStringTag/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/Symbol.toStringTag/browser.js
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/Symbol.toStringTag/prop-desc.js b/js/src/tests/test262/built-ins/Iterator/prototype/Symbol.toStringTag/prop-desc.js
new file mode 100644
index 0000000000..5aaffdb1ca
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/Symbol.toStringTag/prop-desc.js
@@ -0,0 +1,19 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype-@@tostringtag
+description: Property descriptor
+info: |
+ `Iterator.prototype[@@toStringTag]` is an accessor property with attributes { [[Enumerable]]: *false*, [[Configurable]]: *true* }
+features: [iterator-helpers]
+---*/
+let desc = Object.getOwnPropertyDescriptor(Iterator.prototype, Symbol.toStringTag);
+assert.sameValue(typeof desc.get, 'function');
+assert.sameValue(typeof desc.set, 'function');
+assert.sameValue(desc.configurable, true);
+assert.sameValue(desc.enumerable, false);
+assert.sameValue(desc.value, undefined);
+assert.sameValue(desc.writable, undefined);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/Symbol.toStringTag/shell.js b/js/src/tests/test262/built-ins/Iterator/prototype/Symbol.toStringTag/shell.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/Symbol.toStringTag/shell.js
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/Symbol.toStringTag/weird-setter.js b/js/src/tests/test262/built-ins/Iterator/prototype/Symbol.toStringTag/weird-setter.js
new file mode 100644
index 0000000000..f38db1ce10
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/Symbol.toStringTag/weird-setter.js
@@ -0,0 +1,60 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-set-iteratorprototype-@@tostringtag
+description: weird setter
+info: |
+ The value of the [[Get]] attribute is a built-in function that requires no arguments. It performs the following steps when called:
+ 1. Return *"Iterator"*.
+
+ The value of the [[Set]] attribute is a built-in function that takes an argument _v_. It performs the following steps when called:
+ 1. Perform ? SetterThatIgnoresPrototypeProperties(%Iterator.prototype%, %Symbol.toStringTag%, _v_).
+ 2. Return *undefined*.
+features: [iterator-helpers]
+---*/
+
+let IteratorPrototype = Object.getPrototypeOf(Object.getPrototypeOf([][Symbol.iterator]()))
+
+let sentinel = 'a';
+
+let { get, set } = Object.getOwnPropertyDescriptor(Iterator.prototype, Symbol.toStringTag);
+
+assert.sameValue(Iterator.prototype[Symbol.toStringTag], 'Iterator');
+assert.sameValue(get.call(), 'Iterator');
+
+// 1. If _this_ is not an Object, then
+// 1. Throw a *TypeError* exception.
+assert.throws(TypeError, () => set.call(undefined, ''));
+assert.throws(TypeError, () => set.call(null, ''));
+assert.throws(TypeError, () => set.call(true, ''));
+
+// 1. If _this_ is _home_, then
+// 1. NOTE: Throwing here emulates assignment to a non-writable data property on the _home_ object in strict mode code.
+// 1. Throw a *TypeError* exception.
+assert.throws(TypeError, () => set.call(IteratorPrototype, ''));
+assert.throws(TypeError, () => IteratorPrototype[Symbol.toStringTag] = '');
+
+assert.sameValue(Iterator.prototype[Symbol.toStringTag], 'Iterator');
+assert.sameValue(get.call(), 'Iterator');
+
+// 1. If _desc_ is *undefined*, then
+// 1. Perform ? CreateDataPropertyOrThrow(_this_, _p_, _v_).
+let FakeGeneratorPrototype = Object.create(IteratorPrototype);
+Object.freeze(IteratorPrototype);
+FakeGeneratorPrototype[Symbol.toStringTag] = sentinel;
+assert.sameValue(FakeGeneratorPrototype[Symbol.toStringTag], sentinel);
+
+assert.sameValue(Iterator.prototype[Symbol.toStringTag], 'Iterator');
+assert.sameValue(get.call(), 'Iterator');
+
+// 1. Else,
+// 1. Perform ? Set(_this_, _p_, _v_, *true*).
+let o = { [Symbol.toStringTag]: sentinel + 'a' };
+set.call(o, sentinel);
+assert.sameValue(o[Symbol.toStringTag], sentinel);
+
+assert.sameValue(Iterator.prototype[Symbol.toStringTag], 'Iterator');
+assert.sameValue(get.call(), 'Iterator');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/browser.js b/js/src/tests/test262/built-ins/Iterator/prototype/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/browser.js
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/constructor/browser.js b/js/src/tests/test262/built-ins/Iterator/prototype/constructor/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/constructor/browser.js
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/constructor/prop-desc.js b/js/src/tests/test262/built-ins/Iterator/prototype/constructor/prop-desc.js
new file mode 100644
index 0000000000..33d2c48200
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/constructor/prop-desc.js
@@ -0,0 +1,19 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.constructor
+description: Property descriptor
+info: |
+ `Iterator.prototype.constructor` is an accessor property with attributes { [[Enumerable]]: *false*, [[Configurable]]: *true* }
+features: [iterator-helpers]
+---*/
+let desc = Object.getOwnPropertyDescriptor(Iterator.prototype, 'constructor');
+assert.sameValue(typeof desc.get, 'function');
+assert.sameValue(typeof desc.set, 'function');
+assert.sameValue(desc.configurable, true);
+assert.sameValue(desc.enumerable, false);
+assert.sameValue(desc.value, undefined);
+assert.sameValue(desc.writable, undefined);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/constructor/shell.js b/js/src/tests/test262/built-ins/Iterator/prototype/constructor/shell.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/constructor/shell.js
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/constructor/weird-setter.js b/js/src/tests/test262/built-ins/Iterator/prototype/constructor/weird-setter.js
new file mode 100644
index 0000000000..b342d43189
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/constructor/weird-setter.js
@@ -0,0 +1,60 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-set-iteratorprototype-constructor
+description: weird setter
+info: |
+ The value of the [[Get]] attribute is a built-in function that requires no arguments. It performs the following steps when called:
+ 1. Return %Iterator%.
+
+ The value of the [[Set]] attribute is a built-in function that takes an argument _v_. It performs the following steps when called:
+ 1. Perform ? SetterThatIgnoresPrototypeProperties(%Iterator.prototype%, *"constructor"*, _v_).
+ 2. Return *undefined*.
+features: [iterator-helpers]
+---*/
+
+let IteratorPrototype = Object.getPrototypeOf(Object.getPrototypeOf([][Symbol.iterator]()))
+
+let sentinel = {};
+
+let { get, set } = Object.getOwnPropertyDescriptor(Iterator.prototype, 'constructor');
+
+assert.sameValue(Iterator.prototype.constructor, Iterator);
+assert.sameValue(get.call(), Iterator);
+
+// 1. If _this_ is not an Object, then
+// 1. Throw a *TypeError* exception.
+assert.throws(TypeError, () => set.call(undefined, ''));
+assert.throws(TypeError, () => set.call(null, ''));
+assert.throws(TypeError, () => set.call(true, ''));
+
+// 1. If _this_ is _home_, then
+// 1. NOTE: Throwing here emulates assignment to a non-writable data property on the _home_ object in strict mode code.
+// 1. Throw a *TypeError* exception.
+assert.throws(TypeError, () => set.call(IteratorPrototype, ''));
+assert.throws(TypeError, () => IteratorPrototype.constructor = '');
+
+assert.sameValue(Iterator.prototype.constructor, Iterator);
+assert.sameValue(get.call(), Iterator);
+
+// 1. If _desc_ is *undefined*, then
+// 1. Perform ? CreateDataPropertyOrThrow(_this_, _p_, _v_).
+let FakeGeneratorPrototype = Object.create(IteratorPrototype);
+Object.freeze(IteratorPrototype);
+FakeGeneratorPrototype.constructor = sentinel;
+assert.sameValue(FakeGeneratorPrototype.constructor, sentinel);
+
+assert.sameValue(Iterator.prototype.constructor, Iterator);
+assert.sameValue(get.call(), Iterator);
+
+// 1. Else,
+// 1. Perform ? Set(_this_, _p_, _v_, *true*).
+let o = { constructor: sentinel + 'a' };
+set.call(o, sentinel);
+assert.sameValue(o.constructor, sentinel);
+
+assert.sameValue(Iterator.prototype.constructor, Iterator);
+assert.sameValue(get.call(), Iterator);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/drop/argument-effect-order.js b/js/src/tests/test262/built-ins/Iterator/prototype/drop/argument-effect-order.js
new file mode 100644
index 0000000000..c501a64906
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/drop/argument-effect-order.js
@@ -0,0 +1,67 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.drop
+description: >
+ Arguments and this value are evaluated in the correct order
+info: |
+ %Iterator.prototype%.drop ( limit )
+
+includes: [compareArray.js]
+features: [iterator-helpers]
+flags: []
+---*/
+let effects = [];
+
+Iterator.prototype.drop.call(
+ {
+ get next() {
+ effects.push('get next');
+ return function () {
+ return { done: true, value: undefined };
+ };
+ },
+ },
+ {
+ valueOf() {
+ effects.push('ToNumber limit');
+ return 0;
+ },
+ }
+);
+
+assert.compareArray(effects, ['ToNumber limit', 'get next']);
+
+effects = [];
+
+assert.throws(TypeError, function () {
+ Iterator.prototype.drop.call(null, {
+ valueOf() {
+ effects.push('ToNumber limit');
+ return 0;
+ },
+ });
+});
+
+assert.compareArray(effects, []);
+
+effects = [];
+
+assert.throws(RangeError, function () {
+ Iterator.prototype.drop.call(
+ {
+ get next() {
+ effects.push('get next');
+ return function () {
+ return { done: true, value: undefined };
+ };
+ },
+ },
+ NaN
+ );
+});
+
+assert.compareArray(effects, []);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/drop/browser.js b/js/src/tests/test262/built-ins/Iterator/prototype/drop/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/drop/browser.js
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/drop/callable.js b/js/src/tests/test262/built-ins/Iterator/prototype/drop/callable.js
new file mode 100644
index 0000000000..d4c4963910
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/drop/callable.js
@@ -0,0 +1,16 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.drop
+description: >
+ Iterator.prototype.drop is callable
+features: [iterator-helpers]
+---*/
+function* g() {}
+Iterator.prototype.drop.call(g(), 0);
+
+let iter = g();
+iter.drop(0);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/drop/exhaustion-does-not-call-return.js b/js/src/tests/test262/built-ins/Iterator/prototype/drop/exhaustion-does-not-call-return.js
new file mode 100644
index 0000000000..93bddaa7b5
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/drop/exhaustion-does-not-call-return.js
@@ -0,0 +1,63 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.drop
+description: >
+ Underlying iterator return is not called when result iterator is exhausted
+info: |
+ %Iterator.prototype%.drop ( limit )
+
+ 6.b.ii. Let next be ? IteratorStep(iterated).
+ 6.b.iii. If next is false, return undefined.
+ 6.c. Repeat,
+ 6.c.i. Let next be ? IteratorStep(iterated).
+ 6.c.ii. If next is false, return undefined.
+
+features: [iterator-helpers]
+flags: []
+---*/
+function* g() {
+ yield 0;
+ yield 1;
+ yield 2;
+}
+
+class TestIterator extends Iterator {
+ get next() {
+ let n = g();
+ return function() {
+ return n.next();
+ };
+ }
+ return() {
+ throw new Test262Error();
+ }
+}
+
+let iterator = new TestIterator();
+iterator = iterator.drop(0);
+iterator.next();
+iterator.next();
+iterator.next();
+iterator.next();
+iterator.next();
+
+iterator = new TestIterator();
+iterator = iterator.drop(1);
+iterator.next();
+iterator.next();
+iterator.next();
+iterator.next();
+
+iterator = new TestIterator();
+iterator = iterator.drop(1).drop(1).drop(1).drop(1).drop(1);
+iterator.next();
+iterator.next();
+
+iterator = new TestIterator();
+iterator = iterator.drop(10);
+iterator.next();
+iterator.next();
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/drop/get-next-method-only-once.js b/js/src/tests/test262/built-ins/Iterator/prototype/drop/get-next-method-only-once.js
new file mode 100644
index 0000000000..753b7c03a0
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/drop/get-next-method-only-once.js
@@ -0,0 +1,44 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.drop
+description: >
+ Gets the next method from the underlying iterator only once
+info: |
+ %Iterator.prototype%.drop ( limit )
+
+ 1. Let iterated be ? GetIteratorDirect(this value).
+
+features: [iterator-helpers]
+flags: []
+---*/
+let nextGets = 0;
+let nextCalls = 0;
+
+class CountingIterator extends Iterator {
+ get next() {
+ ++nextGets;
+ let iter = (function* () {
+ for (let i = 1; i < 5; ++i) {
+ yield i;
+ }
+ })();
+ return function () {
+ ++nextCalls;
+ return iter.next();
+ };
+ }
+}
+
+let iterator = new CountingIterator();
+
+assert.sameValue(nextGets, 0);
+assert.sameValue(nextCalls, 0);
+
+for (const value of iterator.drop(2));
+
+assert.sameValue(nextGets, 1);
+assert.sameValue(nextCalls, 5);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/drop/get-next-method-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/drop/get-next-method-throws.js
new file mode 100644
index 0000000000..b6817af23c
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/drop/get-next-method-throws.js
@@ -0,0 +1,28 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.drop
+description: >
+ Underlying iterator has throwing next getter
+info: |
+ %Iterator.prototype%.drop ( limit )
+
+ 1. Let iterated be ? GetIteratorDirect(this value).
+
+features: [iterator-helpers]
+flags: []
+---*/
+class ThrowingIterator extends Iterator {
+ get next() {
+ throw new Test262Error();
+ }
+}
+
+let iterator = new ThrowingIterator();
+
+assert.throws(Test262Error, function () {
+ iterator.drop(0);
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/drop/get-return-method-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/drop/get-return-method-throws.js
new file mode 100644
index 0000000000..f8349edac5
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/drop/get-return-method-throws.js
@@ -0,0 +1,33 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.drop
+description: >
+ Underlying iterator return is throwing getter
+info: |
+ %Iterator.prototype%.drop ( limit )
+
+features: [iterator-helpers]
+flags: []
+---*/
+class TestIterator extends Iterator {
+ next() {
+ return {
+ done: false,
+ value: 1,
+ };
+ }
+ get return() {
+ throw new Test262Error();
+ }
+}
+
+let iterator = new TestIterator().drop(1);
+iterator.next();
+
+assert.throws(Test262Error, function () {
+ iterator.return();
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/drop/is-function.js b/js/src/tests/test262/built-ins/Iterator/prototype/drop/is-function.js
new file mode 100644
index 0000000000..9f8ca765af
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/drop/is-function.js
@@ -0,0 +1,13 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.drop
+description: >
+ Iterator.prototype.drop is a built-in function
+features: [iterator-helpers]
+---*/
+
+assert.sameValue(typeof Iterator.prototype.drop, 'function');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/drop/length.js b/js/src/tests/test262/built-ins/Iterator/prototype/drop/length.js
new file mode 100644
index 0000000000..ec97338db2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/drop/length.js
@@ -0,0 +1,25 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.drop
+description: >
+ Iterator.prototype.drop has a "length" property whose value is 1.
+info: |
+ ECMAScript Standard Built-in Objects
+
+ Unless otherwise specified, the length property of a built-in
+ Function object has the attributes { [[Writable]]: false, [[Enumerable]]:
+ false, [[Configurable]]: true }.
+features: [iterator-helpers]
+includes: [propertyHelper.js]
+---*/
+
+verifyProperty(Iterator.prototype.drop, 'length', {
+ value: 1,
+ writable: false,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/drop/limit-equals-total.js b/js/src/tests/test262/built-ins/Iterator/prototype/drop/limit-equals-total.js
new file mode 100644
index 0000000000..9af5174189
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/drop/limit-equals-total.js
@@ -0,0 +1,25 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.drop
+description: >
+ Removes entries from this iterator, specified by limit argument.
+info: |
+ %Iterator.prototype%.drop ( limit )
+
+features: [iterator-helpers]
+flags: []
+---*/
+function* g() {
+ yield 1;
+ yield 2;
+}
+
+let iterator = g().drop(2);
+let { value, done } = iterator.next();
+
+assert.sameValue(value, undefined);
+assert.sameValue(done, true);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/drop/limit-greater-than-total.js b/js/src/tests/test262/built-ins/Iterator/prototype/drop/limit-greater-than-total.js
new file mode 100644
index 0000000000..2330660728
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/drop/limit-greater-than-total.js
@@ -0,0 +1,40 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.drop
+description: >
+ Removes entries from this iterator, specified by limit argument.
+info: |
+ %Iterator.prototype%.drop ( limit )
+
+features: [iterator-helpers]
+flags: []
+---*/
+function* g() {
+ yield 1;
+ yield 2;
+}
+
+{
+ let iterator = g().drop(3);
+ let { value, done } = iterator.next();
+ assert.sameValue(value, undefined);
+ assert.sameValue(done, true);
+}
+
+{
+ let iterator = g().drop(Number.MAX_SAFE_INTEGER);
+ let { value, done } = iterator.next();
+ assert.sameValue(value, undefined);
+ assert.sameValue(done, true);
+}
+
+{
+ let iterator = g().drop(Infinity);
+ let { value, done } = iterator.next();
+ assert.sameValue(value, undefined);
+ assert.sameValue(done, true);
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/drop/limit-less-than-total.js b/js/src/tests/test262/built-ins/Iterator/prototype/drop/limit-less-than-total.js
new file mode 100644
index 0000000000..4502bdf90d
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/drop/limit-less-than-total.js
@@ -0,0 +1,33 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.drop
+description: >
+ Removes entries from this iterator, specified by limit argument.
+info: |
+ %Iterator.prototype%.drop ( limit )
+
+features: [iterator-helpers]
+flags: []
+---*/
+function* g() {
+ yield 1;
+ yield 2;
+}
+
+let iterator = g().drop(1);
+
+{
+ let { value, done } = iterator.next();
+ assert.sameValue(value, 2);
+ assert.sameValue(done, false);
+}
+
+{
+ let { value, done } = iterator.next();
+ assert.sameValue(value, undefined);
+ assert.sameValue(done, true);
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/drop/limit-rangeerror.js b/js/src/tests/test262/built-ins/Iterator/prototype/drop/limit-rangeerror.js
new file mode 100644
index 0000000000..2bfcd62aa6
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/drop/limit-rangeerror.js
@@ -0,0 +1,39 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.drop
+description: >
+ Throws a RangeError exception when limit argument is NaN or less than 0.
+info: |
+ %Iterator.prototype%.drop ( limit )
+
+ 3. If numLimit is NaN, throw a RangeError exception.
+ 4. Let integerLimit be ! ToIntegerOrInfinity(numLimit).
+ 5. If integerLimit < 0, throw a RangeError exception.
+
+features: [iterator-helpers]
+---*/
+let iterator = (function* () {})();
+
+iterator.drop(0);
+iterator.drop(-0.5);
+iterator.drop(null);
+
+assert.throws(RangeError, () => {
+ iterator.drop(-1);
+});
+
+assert.throws(RangeError, () => {
+ iterator.drop();
+});
+
+assert.throws(RangeError, () => {
+ iterator.drop(undefined);
+});
+
+assert.throws(RangeError, () => {
+ iterator.drop(NaN);
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/drop/limit-tonumber-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/drop/limit-tonumber-throws.js
new file mode 100644
index 0000000000..d736903a4d
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/drop/limit-tonumber-throws.js
@@ -0,0 +1,25 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.drop
+description: >
+ Throws a RangeError exception when limit argument valueOf throws.
+info: |
+ %Iterator.prototype%.drop ( limit )
+
+ 2. Let numLimit be ? ToNumber(limit).
+
+features: [iterator-helpers]
+---*/
+let iterator = (function* () {})();
+
+assert.throws(Test262Error, () => {
+ iterator.drop({
+ valueOf: function () {
+ throw new Test262Error();
+ },
+ });
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/drop/limit-tonumber.js b/js/src/tests/test262/built-ins/Iterator/prototype/drop/limit-tonumber.js
new file mode 100644
index 0000000000..a50d86aacd
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/drop/limit-tonumber.js
@@ -0,0 +1,40 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.drop
+description: >
+ Converts the limit argument to a Number using ToNumber and valueOf/toString.
+info: |
+ %Iterator.prototype%.drop ( limit )
+
+ 2. Let numLimit be ? ToNumber(limit).
+
+features: [iterator-helpers]
+---*/
+function* g() {
+ yield 1;
+ yield 2;
+}
+
+{
+ let iterator = g();
+ let { value, done } = iterator
+ .drop({
+ valueOf: function () {
+ return 1;
+ },
+ })
+ .next();
+ assert.sameValue(value, 2);
+ assert.sameValue(done, false);
+}
+
+{
+ let iterator = g();
+ let { value, done } = iterator.drop([]).drop([1]).next();
+ assert.sameValue(value, 2);
+ assert.sameValue(done, false);
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/drop/name.js b/js/src/tests/test262/built-ins/Iterator/prototype/drop/name.js
new file mode 100644
index 0000000000..cd0e599c59
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/drop/name.js
@@ -0,0 +1,32 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.drop
+description: >
+ The "name" property of Iterator.prototype.drop
+info: |
+ 17 ECMAScript Standard Built-in Objects
+
+ Every built-in Function object, including constructors, that is not
+ identified as an anonymous function has a name property whose value is a
+ String. Unless otherwise specified, this value is the name that is given to
+ the function in this specification.
+
+ ...
+
+ Unless otherwise specified, the name property of a built-in Function
+ object, if it exists, has the attributes { [[Writable]]: false,
+ [[Enumerable]]: false, [[Configurable]]: true }.
+features: [iterator-helpers]
+includes: [propertyHelper.js]
+---*/
+
+verifyProperty(Iterator.prototype.drop, 'name', {
+ value: 'drop',
+ writable: false,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/drop/next-method-returns-non-object.js b/js/src/tests/test262/built-ins/Iterator/prototype/drop/next-method-returns-non-object.js
new file mode 100644
index 0000000000..5f7b406435
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/drop/next-method-returns-non-object.js
@@ -0,0 +1,36 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.drop
+description: >
+ Underlying iterator next returns non-object
+info: |
+ %Iterator.prototype%.drop ( limit )
+
+ 6.b.ii. Let next be ? IteratorStep(iterated).
+
+ 6.c.i. Let next be ? IteratorStep(iterated).
+
+features: [iterator-helpers]
+flags: []
+---*/
+class NonObjectIterator extends Iterator {
+ next() {
+ return null;
+ }
+}
+
+let iterator = new NonObjectIterator().drop(0);
+
+assert.throws(TypeError, function () {
+ iterator.next();
+});
+
+iterator = new NonObjectIterator().drop(2);
+
+assert.throws(TypeError, function () {
+ iterator.next();
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/drop/next-method-returns-throwing-done.js b/js/src/tests/test262/built-ins/Iterator/prototype/drop/next-method-returns-throwing-done.js
new file mode 100644
index 0000000000..88c5a3a938
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/drop/next-method-returns-throwing-done.js
@@ -0,0 +1,44 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.drop
+description: >
+ Underlying iterator next returns object with throwing done getter
+info: |
+ %Iterator.prototype%.drop ( limit )
+
+ 6.b.ii. Let next be ? IteratorStep(iterated).
+
+ 6.c.i. Let next be ? IteratorStep(iterated).
+
+features: [iterator-helpers]
+flags: []
+---*/
+class ThrowingIterator extends Iterator {
+ next() {
+ return {
+ get done() {
+ throw new Test262Error();
+ },
+ value: 1,
+ };
+ }
+ return() {
+ throw new Error();
+ }
+}
+
+let iterator = new ThrowingIterator().drop(0);
+
+assert.throws(Test262Error, function () {
+ iterator.next();
+});
+
+iterator = new ThrowingIterator().drop(1);
+
+assert.throws(Test262Error, function () {
+ iterator.next();
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/drop/next-method-returns-throwing-value-done.js b/js/src/tests/test262/built-ins/Iterator/prototype/drop/next-method-returns-throwing-value-done.js
new file mode 100644
index 0000000000..3ca5d413d7
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/drop/next-method-returns-throwing-value-done.js
@@ -0,0 +1,39 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.drop
+description: >
+ Underlying iterator next returns object with throwing value getter, but is already done
+info: |
+ %Iterator.prototype%.drop ( limit )
+
+ 6.c.ii. If next is false, return undefined.
+
+features: [iterator-helpers]
+flags: []
+---*/
+class ReturnCalledError extends Error {}
+class ValueGetterError extends Error {}
+
+class ThrowingIterator extends Iterator {
+ next() {
+ return {
+ done: true,
+ get value() {
+ throw new ValueGetterError();
+ },
+ };
+ }
+ return() {
+ throw new ReturnCalledError();
+ }
+}
+
+let iterator = new ThrowingIterator().drop(0);
+iterator.next();
+
+iterator = new ThrowingIterator().drop(1);
+iterator.next();
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/drop/next-method-returns-throwing-value.js b/js/src/tests/test262/built-ins/Iterator/prototype/drop/next-method-returns-throwing-value.js
new file mode 100644
index 0000000000..d645749345
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/drop/next-method-returns-throwing-value.js
@@ -0,0 +1,42 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.drop
+description: >
+ Underlying iterator next returns object with throwing value getter
+info: |
+ %Iterator.prototype%.drop ( limit )
+
+ 6.c.iii. Let completion be Completion(Yield(? IteratorValue(next))).
+
+features: [iterator-helpers]
+flags: []
+---*/
+class ThrowingIterator extends Iterator {
+ next() {
+ return {
+ done: false,
+ get value() {
+ throw new Test262Error();
+ },
+ };
+ }
+ return() {
+ throw new Error();
+ }
+}
+
+let iterator = new ThrowingIterator().drop(0);
+
+assert.throws(Test262Error, function () {
+ iterator.next();
+});
+
+iterator = new ThrowingIterator().drop(1);
+
+assert.throws(Test262Error, function () {
+ iterator.next();
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/drop/next-method-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/drop/next-method-throws.js
new file mode 100644
index 0000000000..cdc4bdec77
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/drop/next-method-throws.js
@@ -0,0 +1,36 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.drop
+description: >
+ Underlying iterator has throwing next method
+info: |
+ %Iterator.prototype%.drop ( limit )
+
+ 6.b.ii. Let next be ? IteratorStep(iterated).
+
+ 6.c.i. Let next be ? IteratorStep(iterated).
+
+features: [iterator-helpers]
+flags: []
+---*/
+class ThrowingIterator extends Iterator {
+ next() {
+ throw new Test262Error();
+ }
+}
+
+let iterator = new ThrowingIterator().drop(0);
+
+assert.throws(Test262Error, function () {
+ iterator.next();
+});
+
+iterator = new ThrowingIterator().drop(1);
+
+assert.throws(Test262Error, function () {
+ iterator.next();
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/drop/non-constructible.js b/js/src/tests/test262/built-ins/Iterator/prototype/drop/non-constructible.js
new file mode 100644
index 0000000000..cb97d9d4ff
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/drop/non-constructible.js
@@ -0,0 +1,31 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.drop
+description: >
+ Iterator.prototype.drop is not constructible.
+
+ Built-in function objects that are not identified as constructors do not implement the [[Construct]] internal method unless otherwise specified in the description of a particular function.
+features: [iterator-helpers]
+---*/
+function* g() {}
+let iter = g();
+
+assert.throws(TypeError, () => {
+ new iter.drop();
+});
+
+assert.throws(TypeError, () => {
+ new iter.drop(0);
+});
+
+assert.throws(TypeError, () => {
+ new Iterator.prototype.drop(0);
+});
+
+assert.throws(TypeError, () => {
+ new class extends Iterator {}.drop(0);
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/drop/prop-desc.js b/js/src/tests/test262/built-ins/Iterator/prototype/drop/prop-desc.js
new file mode 100644
index 0000000000..c3a94feb6c
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/drop/prop-desc.js
@@ -0,0 +1,28 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.drop
+description: >
+ Property descriptor of Iterator.prototype.drop
+info: |
+ Iterator.prototype.drop
+
+ * is the initial value of the Iterator.prototype.drop property of the global object.
+
+ 17 ECMAScript Standard Built-in Objects
+
+ Every other data property described in clauses 18 through 26 and in Annex B.2
+ has the attributes { [[Writable]]: true, [[Enumerable]]: false,
+ [[Configurable]]: true } unless otherwise specified.
+features: [globalThis, iterator-helpers]
+includes: [propertyHelper.js]
+---*/
+
+verifyProperty(Iterator.prototype, 'drop', {
+ writable: true,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/drop/proto.js b/js/src/tests/test262/built-ins/Iterator/prototype/drop/proto.js
new file mode 100644
index 0000000000..f6fadfb5fa
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/drop/proto.js
@@ -0,0 +1,14 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.drop
+description: >
+ The value of the [[Prototype]] internal slot of Iterator.prototype.drop is the
+ intrinsic object %FunctionPrototype%.
+features: [iterator-helpers]
+---*/
+
+assert.sameValue(Object.getPrototypeOf(Iterator.prototype.drop), Function.prototype);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/drop/result-is-iterator.js b/js/src/tests/test262/built-ins/Iterator/prototype/drop/result-is-iterator.js
new file mode 100644
index 0000000000..67d99b9b96
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/drop/result-is-iterator.js
@@ -0,0 +1,14 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.drop
+description: >
+ The value of the [[Prototype]] internal slot of the return value of Iterator.prototype.drop is the
+ intrinsic object %IteratorHelperPrototype%.
+features: [iterator-helpers]
+---*/
+
+assert((function* () {})().drop(0) instanceof Iterator, 'function*(){}().drop(0) must return an Iterator');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/drop/return-is-forwarded.js b/js/src/tests/test262/built-ins/Iterator/prototype/drop/return-is-forwarded.js
new file mode 100644
index 0000000000..7aadc2f0dd
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/drop/return-is-forwarded.js
@@ -0,0 +1,57 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.drop
+description: >
+ Underlying iterator return is called when result iterator is closed
+info: |
+ %Iterator.prototype%.drop ( limit )
+
+ 6.c.iii. Let completion be Completion(Yield(? IteratorValue(next))).
+ 6.c.iv. IfAbruptCloseIterator(completion, iterated).
+
+features: [iterator-helpers]
+flags: []
+---*/
+let returnCount = 0;
+
+class TestIterator extends Iterator {
+ next() {
+ return {
+ done: false,
+ value: 1,
+ };
+ }
+ return() {
+ ++returnCount;
+ return {};
+ }
+}
+
+let iterator = new TestIterator().drop(0);
+assert.sameValue(returnCount, 0);
+iterator.return();
+assert.sameValue(returnCount, 1);
+iterator.return();
+assert.sameValue(returnCount, 1);
+
+returnCount = 0;
+
+iterator = new TestIterator().drop(1);
+assert.sameValue(returnCount, 0);
+iterator.return();
+assert.sameValue(returnCount, 1);
+iterator.return();
+assert.sameValue(returnCount, 1);
+
+returnCount = 0;
+
+iterator = new TestIterator().drop(1).drop(1).drop(1).drop(1).drop(1);
+assert.sameValue(returnCount, 0);
+iterator.return();
+assert.sameValue(returnCount, 1);
+iterator.return();
+assert.sameValue(returnCount, 1);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/drop/return-is-not-forwarded-after-exhaustion.js b/js/src/tests/test262/built-ins/Iterator/prototype/drop/return-is-not-forwarded-after-exhaustion.js
new file mode 100644
index 0000000000..27cb08f04b
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/drop/return-is-not-forwarded-after-exhaustion.js
@@ -0,0 +1,53 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.drop
+description: >
+ Underlying iterator return is not called after result iterator observes that underlying iterator is exhausted
+info: |
+ %Iterator.prototype%.drop ( limit )
+
+features: [iterator-helpers]
+flags: []
+---*/
+let returnCount = 0;
+
+class TestIterator extends Iterator {
+ next() {
+ return {
+ done: true,
+ value: undefined,
+ };
+ }
+ return() {
+ throw new Test262Error();
+ }
+}
+
+let iterator = new TestIterator().drop(0);
+assert.throws(Test262Error, function () {
+ iterator.return();
+});
+iterator.next();
+iterator.return();
+
+iterator = new TestIterator().drop(1);
+iterator.next();
+iterator.return();
+
+iterator = new TestIterator().drop(1);
+assert.throws(Test262Error, function () {
+ iterator.return();
+});
+iterator.next();
+iterator.return();
+
+iterator = new TestIterator().drop(1).drop(1).drop(1).drop(1).drop(1);
+assert.throws(Test262Error, function () {
+ iterator.return();
+});
+iterator.next();
+iterator.return();
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/drop/shell.js b/js/src/tests/test262/built-ins/Iterator/prototype/drop/shell.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/drop/shell.js
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/drop/this-non-callable-next.js b/js/src/tests/test262/built-ins/Iterator/prototype/drop/this-non-callable-next.js
new file mode 100644
index 0000000000..57ad6431c9
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/drop/this-non-callable-next.js
@@ -0,0 +1,22 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.drop
+description: >
+ Iterator.prototype.drop throws TypeError when its this value is an object with a non-callable next
+info: |
+ %Iterator.prototype%.drop ( limit )
+
+ 1. Let iterated be ? GetIteratorDirect(this value).
+
+features: [iterator-helpers]
+flags: []
+---*/
+let iter = Iterator.prototype.drop.call({ next: 0 }, 1);
+
+assert.throws(TypeError, function () {
+ iter.next();
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/drop/this-non-object.js b/js/src/tests/test262/built-ins/Iterator/prototype/drop/this-non-object.js
new file mode 100644
index 0000000000..3335b19f6e
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/drop/this-non-object.js
@@ -0,0 +1,37 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.drop
+description: >
+ Iterator.prototype.drop throws TypeError when its this value is a non-object
+info: |
+ %Iterator.prototype%.drop ( limit )
+
+ 1. Let iterated be ? GetIteratorDirect(this value).
+
+features: [iterator-helpers]
+flags: []
+---*/
+assert.throws(TypeError, function () {
+ Iterator.prototype.drop.call(null, 1);
+});
+
+assert.throws(TypeError, function () {
+ Iterator.prototype.drop.call(null, {
+ valueOf: function () {
+ throw new Test262Error();
+ },
+ });
+});
+
+Object.defineProperty(Number.prototype, 'next', {
+ get: function () {
+ throw new Test262Error();
+ },
+});
+assert.throws(TypeError, function () {
+ Iterator.prototype.drop.call(0, 1);
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/drop/this-plain-iterator.js b/js/src/tests/test262/built-ins/Iterator/prototype/drop/this-plain-iterator.js
new file mode 100644
index 0000000000..f83a4d2d8d
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/drop/this-plain-iterator.js
@@ -0,0 +1,33 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.drop
+description: >
+ Iterator.prototype.drop supports a this value that does not inherit from Iterator.prototype but implements the iterator protocol
+info: |
+ %Iterator.prototype%.drop ( limit )
+
+ 1. Let iterated be ? GetIteratorDirect(this value).
+
+features: [iterator-helpers]
+flags: []
+---*/
+let iter = {
+ get next() {
+ let count = 3;
+ return function () {
+ --count;
+ return count >= 0 ? { done: false, value: count } : { done: true, value: undefined };
+ };
+ },
+};
+
+let dropIter = Iterator.prototype.drop.call(iter, 1);
+
+let { done, value } = dropIter.next();
+
+assert.sameValue(done, false);
+assert.sameValue(value, 1);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/drop/throws-typeerror-when-generator-is-running.js b/js/src/tests/test262/built-ins/Iterator/prototype/drop/throws-typeerror-when-generator-is-running.js
new file mode 100644
index 0000000000..ea23db0508
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/drop/throws-typeerror-when-generator-is-running.js
@@ -0,0 +1,42 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 André Bargull. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.drop
+description: >
+ Throws a TypeError when the closure generator is already running.
+info: |
+ %IteratorHelperPrototype%.next ( )
+ 1. Return ? GeneratorResume(this value, undefined, "Iterator Helper").
+
+ 27.5.3.3 GeneratorResume ( generator, value, generatorBrand )
+ 1. Let state be ? GeneratorValidate(generator, generatorBrand).
+ ...
+
+ 27.5.3.2 GeneratorValidate ( generator, generatorBrand )
+ ...
+ 6. If state is executing, throw a TypeError exception.
+ ...
+
+features: [iterator-helpers]
+---*/
+
+var enterCount = 0;
+
+class TestIterator extends Iterator {
+ next() {
+ enterCount++;
+ iter.next();
+ return {done: false};
+ }
+}
+
+var iter = new TestIterator().drop(100);
+
+assert.throws(TypeError, function() {
+ iter.next();
+});
+
+assert.sameValue(enterCount, 1);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/drop/underlying-iterator-advanced-in-parallel.js b/js/src/tests/test262/built-ins/Iterator/prototype/drop/underlying-iterator-advanced-in-parallel.js
new file mode 100644
index 0000000000..635182e2cc
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/drop/underlying-iterator-advanced-in-parallel.js
@@ -0,0 +1,42 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.drop
+description: >
+ Underlying iterator is advanced after calling drop
+info: |
+ %Iterator.prototype%.drop ( limit )
+
+features: [iterator-helpers]
+flags: []
+---*/
+let iterator = (function* () {
+ for (let i = 0; i < 5; ++i) {
+ yield i;
+ }
+})();
+
+let dropped = iterator.drop(2);
+
+let { value, done } = iterator.next();
+
+assert.sameValue(value, 0);
+assert.sameValue(done, false);
+
+({ value, done } = dropped.next());
+
+assert.sameValue(value, 3);
+assert.sameValue(done, false);
+
+({ value, done } = dropped.next());
+
+assert.sameValue(value, 4);
+assert.sameValue(done, false);
+
+({ value, done } = dropped.next());
+
+assert.sameValue(value, undefined);
+assert.sameValue(done, true);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/drop/underlying-iterator-closed-in-parallel.js b/js/src/tests/test262/built-ins/Iterator/prototype/drop/underlying-iterator-closed-in-parallel.js
new file mode 100644
index 0000000000..ec68557a9d
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/drop/underlying-iterator-closed-in-parallel.js
@@ -0,0 +1,29 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.drop
+description: >
+ Underlying iterator is closed after calling drop
+info: |
+ %Iterator.prototype%.drop ( limit )
+
+features: [iterator-helpers]
+flags: []
+---*/
+let iterator = (function* () {
+ for (let i = 0; i < 5; ++i) {
+ yield i;
+ }
+})();
+
+let dropped = iterator.drop(2);
+
+iterator.return();
+
+let { value, done } = dropped.next();
+
+assert.sameValue(value, undefined);
+assert.sameValue(done, true);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/drop/underlying-iterator-closed.js b/js/src/tests/test262/built-ins/Iterator/prototype/drop/underlying-iterator-closed.js
new file mode 100644
index 0000000000..dc9298fd8e
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/drop/underlying-iterator-closed.js
@@ -0,0 +1,29 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.drop
+description: >
+ Underlying iterator is closed before calling drop
+info: |
+ %Iterator.prototype%.drop ( limit )
+
+features: [iterator-helpers]
+flags: []
+---*/
+let iterator = (function* () {
+ for (let i = 0; i < 5; ++i) {
+ yield i;
+ }
+})();
+
+iterator.return();
+
+let dropped = iterator.drop(2);
+
+let { value, done } = dropped.next();
+
+assert.sameValue(value, undefined);
+assert.sameValue(done, true);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/every/argument-effect-order.js b/js/src/tests/test262/built-ins/Iterator/prototype/every/argument-effect-order.js
new file mode 100644
index 0000000000..0e4ca1eddf
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/every/argument-effect-order.js
@@ -0,0 +1,33 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.every
+description: >
+ Arguments and this value are evaluated in the correct order
+info: |
+ %Iterator.prototype%.every ( predicate )
+
+includes: [compareArray.js]
+features: [iterator-helpers]
+flags: []
+---*/
+let effects = [];
+
+assert.throws(TypeError, function () {
+ Iterator.prototype.every.call(
+ {
+ get next() {
+ effects.push('get next');
+ return function () {
+ return { done: true, value: undefined };
+ };
+ },
+ },
+ null
+ );
+});
+
+assert.compareArray(effects, []);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/every/browser.js b/js/src/tests/test262/built-ins/Iterator/prototype/every/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/every/browser.js
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/every/callable.js b/js/src/tests/test262/built-ins/Iterator/prototype/every/callable.js
new file mode 100644
index 0000000000..bb7327786d
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/every/callable.js
@@ -0,0 +1,16 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.every
+description: >
+ Iterator.prototype.every is callable
+features: [iterator-helpers]
+---*/
+function* g() {}
+Iterator.prototype.every.call(g(), () => {});
+
+let iter = g();
+iter.every(() => {});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/every/get-next-method-only-once.js b/js/src/tests/test262/built-ins/Iterator/prototype/every/get-next-method-only-once.js
new file mode 100644
index 0000000000..e3611327a5
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/every/get-next-method-only-once.js
@@ -0,0 +1,41 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.every
+description: >
+ Gets the next method from the iterator only once
+info: |
+ %Iterator.prototype%.every ( predicate )
+
+ 1. Let iterated be ? GetIteratorDirect(this value).
+
+features: [iterator-helpers]
+flags: []
+---*/
+let nextGets = 0;
+
+class TestIterator extends Iterator {
+ get next() {
+ ++nextGets;
+ let counter = 5;
+ return function () {
+ if (counter < 0) {
+ return { done: true, value: undefined };
+ } else {
+ return { done: false, value: --counter };
+ }
+ };
+ }
+}
+
+let iterator = new TestIterator();
+
+assert.sameValue(nextGets, 0);
+assert.sameValue(
+ iterator.every(() => true),
+ true
+);
+assert.sameValue(nextGets, 1);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/every/get-next-method-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/every/get-next-method-throws.js
new file mode 100644
index 0000000000..cce9c77972
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/every/get-next-method-throws.js
@@ -0,0 +1,28 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.every
+description: >
+ Iterator has throwing next getter
+info: |
+ %Iterator.prototype%.every ( predicate )
+
+ 1. Let iterated be ? GetIteratorDirect(this value).
+
+features: [iterator-helpers]
+flags: []
+---*/
+class IteratorThrows extends Iterator {
+ get next() {
+ throw new Test262Error();
+ }
+}
+
+let iterator = new IteratorThrows();
+
+assert.throws(Test262Error, function () {
+ iterator.every(() => {});
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/every/get-return-method-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/every/get-return-method-throws.js
new file mode 100644
index 0000000000..1c22a2e0a3
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/every/get-return-method-throws.js
@@ -0,0 +1,34 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.every
+description: >
+ Iterator has throwing return getter
+info: |
+ %Iterator.prototype%.every ( predicate )
+
+ 4.f. If ToBoolean(result) is false, return ? IteratorClose(iterated, NormalCompletion(false)).
+
+features: [iterator-helpers]
+flags: []
+---*/
+class IteratorThrows extends Iterator {
+ next() {
+ return {
+ done: false,
+ value: 0,
+ };
+ }
+ get return() {
+ throw new Test262Error();
+ }
+}
+
+let iterator = new IteratorThrows([1, 2]);
+
+assert.throws(Test262Error, function () {
+ iterator.every(() => false);
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/every/is-function.js b/js/src/tests/test262/built-ins/Iterator/prototype/every/is-function.js
new file mode 100644
index 0000000000..7e37497a87
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/every/is-function.js
@@ -0,0 +1,13 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.every
+description: >
+ Iterator.prototype.every is a built-in function
+features: [iterator-helpers]
+---*/
+
+assert.sameValue(typeof Iterator.prototype.every, 'function');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/every/iterator-already-exhausted.js b/js/src/tests/test262/built-ins/Iterator/prototype/every/iterator-already-exhausted.js
new file mode 100644
index 0000000000..2a31df547b
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/every/iterator-already-exhausted.js
@@ -0,0 +1,29 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.every
+description: >
+ Iterator.prototype.every returns true when the iterator has already been exhausted
+info: |
+ %Iterator.prototype%.every ( predicate )
+
+ 4.a. Let next be ? IteratorStep(iterated).
+ 4.b. If next is false, return true.
+
+features: [iterator-helpers]
+flags: []
+---*/
+let iterator = (function* () {})();
+
+let { value, done } = iterator.next();
+assert.sameValue(value, undefined);
+assert.sameValue(done, true);
+
+let result = iterator.every(() => true);
+assert.sameValue(result, true);
+
+result = iterator.every(() => false);
+assert.sameValue(result, true);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/every/iterator-has-no-return.js b/js/src/tests/test262/built-ins/Iterator/prototype/every/iterator-has-no-return.js
new file mode 100644
index 0000000000..a58c782ab8
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/every/iterator-has-no-return.js
@@ -0,0 +1,30 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.every
+description: >
+ The underlying iterator is sometimes unable to be closed (has no return method)
+info: |
+ %Iterator.prototype%.every ( predicate )
+
+features: [iterator-helpers]
+flags: []
+---*/
+let iterator = [1, 2, 3, 4, 5][Symbol.iterator]();
+
+assert.sameValue(iterator.return, undefined);
+
+let ret = iterator.every(v => v < 4);
+
+assert.sameValue(ret, false);
+
+let { done, value } = iterator.next();
+assert.sameValue(done, false);
+assert.sameValue(value, 5);
+
+({ done, value } = iterator.next());
+assert.sameValue(done, true);
+assert.sameValue(value, undefined);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/every/iterator-return-method-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/every/iterator-return-method-throws.js
new file mode 100644
index 0000000000..d7b59f842e
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/every/iterator-return-method-throws.js
@@ -0,0 +1,34 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.every
+description: >
+ Iterator has throwing return
+info: |
+ %Iterator.prototype%.every ( predicate )
+
+ 4.f. If ToBoolean(result) is false, return ? IteratorClose(iterated, NormalCompletion(false)).
+
+features: [iterator-helpers]
+flags: []
+---*/
+class IteratorThrows extends Iterator {
+ next() {
+ return {
+ done: false,
+ value: 0,
+ };
+ }
+ return() {
+ throw new Test262Error();
+ }
+}
+
+let iterator = new IteratorThrows();
+
+assert.throws(Test262Error, function () {
+ iterator.every(() => false);
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/every/length.js b/js/src/tests/test262/built-ins/Iterator/prototype/every/length.js
new file mode 100644
index 0000000000..fd247ed9ac
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/every/length.js
@@ -0,0 +1,25 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.every
+description: >
+ Iterator.prototype.every has a "length" property whose value is 1.
+info: |
+ ECMAScript Standard Built-in Objects
+
+ Unless otherwise specified, the length property of a built-in
+ Function object has the attributes { [[Writable]]: false, [[Enumerable]]:
+ false, [[Configurable]]: true }.
+features: [iterator-helpers]
+includes: [propertyHelper.js]
+---*/
+
+verifyProperty(Iterator.prototype.every, 'length', {
+ value: 1,
+ writable: false,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/every/name.js b/js/src/tests/test262/built-ins/Iterator/prototype/every/name.js
new file mode 100644
index 0000000000..7e602ff1c2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/every/name.js
@@ -0,0 +1,32 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.every
+description: >
+ The "name" property of Iterator.prototype.every
+info: |
+ 17 ECMAScript Standard Built-in Objects
+
+ Every built-in Function object, including constructors, that is not
+ identified as an anonymous function has a name property whose value is a
+ String. Unless otherwise specified, this value is the name that is given to
+ the function in this specification.
+
+ ...
+
+ Unless otherwise specified, the name property of a built-in Function
+ object, if it exists, has the attributes { [[Writable]]: false,
+ [[Enumerable]]: false, [[Configurable]]: true }.
+features: [iterator-helpers]
+includes: [propertyHelper.js]
+---*/
+
+verifyProperty(Iterator.prototype.every, 'name', {
+ value: 'every',
+ writable: false,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/every/next-method-returns-non-object.js b/js/src/tests/test262/built-ins/Iterator/prototype/every/next-method-returns-non-object.js
new file mode 100644
index 0000000000..0e5c1a828a
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/every/next-method-returns-non-object.js
@@ -0,0 +1,28 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.every
+description: >
+ Underlying iterator next returns non-object
+info: |
+ %Iterator.prototype%.every ( predicate )
+
+ 4.a. Let next be ? IteratorStep(iterated).
+
+features: [iterator-helpers]
+flags: []
+---*/
+class NonObjectIterator extends Iterator {
+ next() {
+ return null;
+ }
+}
+
+let iterator = new NonObjectIterator();
+
+assert.throws(TypeError, function () {
+ iterator.every(() => {});
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/every/next-method-returns-throwing-done.js b/js/src/tests/test262/built-ins/Iterator/prototype/every/next-method-returns-throwing-done.js
new file mode 100644
index 0000000000..e2a56600df
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/every/next-method-returns-throwing-done.js
@@ -0,0 +1,36 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.every
+description: >
+ Underlying iterator next returns object with throwing done getter
+info: |
+ %Iterator.prototype%.every ( predicate )
+
+ 4.a. Let next be ? IteratorStep(iterated).
+
+features: [iterator-helpers]
+flags: []
+---*/
+class ThrowingIterator extends Iterator {
+ next() {
+ return {
+ get done() {
+ throw new Test262Error();
+ },
+ value: 1,
+ };
+ }
+ return() {
+ throw new Error();
+ }
+}
+
+let iterator = new ThrowingIterator();
+
+assert.throws(Test262Error, function () {
+ iterator.every(() => {});
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/every/next-method-returns-throwing-value-done.js b/js/src/tests/test262/built-ins/Iterator/prototype/every/next-method-returns-throwing-value-done.js
new file mode 100644
index 0000000000..f7e81a6321
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/every/next-method-returns-throwing-value-done.js
@@ -0,0 +1,33 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.every
+description: >
+ Underlying iterator next returns object with throwing value getter, but is already done
+info: |
+ %Iterator.prototype%.every ( predicate )
+
+ 4.c. Let value be ? IteratorValue(next).
+
+features: [iterator-helpers]
+flags: []
+---*/
+class ThrowingIterator extends Iterator {
+ next() {
+ return {
+ done: true,
+ get value() {
+ throw new Test262Error();
+ },
+ };
+ }
+ return() {
+ throw new Error();
+ }
+}
+
+let iterator = new ThrowingIterator();
+iterator.every(() => {});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/every/next-method-returns-throwing-value.js b/js/src/tests/test262/built-ins/Iterator/prototype/every/next-method-returns-throwing-value.js
new file mode 100644
index 0000000000..6799ddd165
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/every/next-method-returns-throwing-value.js
@@ -0,0 +1,36 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.every
+description: >
+ Underlying iterator next returns object with throwing value getter
+info: |
+ %Iterator.prototype%.every ( predicate )
+
+ 4.c. Let value be ? IteratorValue(next).
+
+features: [iterator-helpers]
+flags: []
+---*/
+class ThrowingIterator extends Iterator {
+ next() {
+ return {
+ done: false,
+ get value() {
+ throw new Test262Error();
+ },
+ };
+ }
+ return() {
+ throw new Error();
+ }
+}
+
+let iterator = new ThrowingIterator();
+
+assert.throws(Test262Error, function () {
+ iterator.every(() => {});
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/every/next-method-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/every/next-method-throws.js
new file mode 100644
index 0000000000..e883c21fc8
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/every/next-method-throws.js
@@ -0,0 +1,28 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.every
+description: >
+ Underlying iterator has throwing next method
+info: |
+ %Iterator.prototype%.every ( predicate )
+
+ 4.a. Let next be ? IteratorStep(iterated).
+
+features: [iterator-helpers]
+flags: []
+---*/
+class ThrowingIterator extends Iterator {
+ next() {
+ throw new Test262Error();
+ }
+}
+
+let iterator = new ThrowingIterator();
+
+assert.throws(Test262Error, function () {
+ iterator.every(() => {});
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/every/non-callable-predicate.js b/js/src/tests/test262/built-ins/Iterator/prototype/every/non-callable-predicate.js
new file mode 100644
index 0000000000..41be3d5e91
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/every/non-callable-predicate.js
@@ -0,0 +1,25 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.every
+description: >
+ Iterator.prototype.every expects to be called with a callable argument.
+info: |
+ %Iterator.prototype%.every ( predicate )
+
+ 2. If IsCallable(predicate) is false, throw a TypeError exception.
+
+features: [iterator-helpers]
+flags: []
+---*/
+let nonCallable = {};
+let iterator = (function* () {
+ yield 1;
+})();
+
+assert.throws(TypeError, function () {
+ iterator.every(nonCallable);
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/every/non-constructible.js b/js/src/tests/test262/built-ins/Iterator/prototype/every/non-constructible.js
new file mode 100644
index 0000000000..b0f280ca32
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/every/non-constructible.js
@@ -0,0 +1,31 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.every
+description: >
+ Iterator.prototype.every is not constructible.
+
+ Built-in function objects that are not identified as constructors do not implement the [[Construct]] internal method unless otherwise specified in the description of a particular function.
+features: [iterator-helpers]
+---*/
+function* g() {}
+let iter = g();
+
+assert.throws(TypeError, () => {
+ new iter.every();
+});
+
+assert.throws(TypeError, () => {
+ new iter.every(() => {});
+});
+
+assert.throws(TypeError, () => {
+ new Iterator.prototype.every(() => {});
+});
+
+assert.throws(TypeError, () => {
+ new class extends Iterator {}.every(() => {});
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/every/predicate-args.js b/js/src/tests/test262/built-ins/Iterator/prototype/every/predicate-args.js
new file mode 100644
index 0000000000..8850a9ef89
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/every/predicate-args.js
@@ -0,0 +1,46 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.every
+description: >
+ Iterator.prototype.every predicate is passed the yielded value and a counter as arguments
+info: |
+ %Iterator.prototype%.every ( predicate )
+
+ 4.d. Let result be Completion(Call(predicate, undefined, « value, 𝔽(counter) »)).
+
+features: [iterator-helpers]
+flags: []
+---*/
+function* g() {
+ yield 'a';
+ yield 'b';
+ yield 'c';
+}
+
+let iter = g();
+
+let assertionCount = 0;
+let result = iter.every((v, count) => {
+ switch (v) {
+ case 'a':
+ assert.sameValue(count, 0);
+ break;
+ case 'b':
+ assert.sameValue(count, 1);
+ break;
+ case 'c':
+ assert.sameValue(count, 2);
+ break;
+ default:
+ throw new Error();
+ }
+ ++assertionCount;
+ return true;
+});
+
+assert.sameValue(result, true);
+assert.sameValue(assertionCount, 3);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/every/predicate-returns-falsey.js b/js/src/tests/test262/built-ins/Iterator/prototype/every/predicate-returns-falsey.js
new file mode 100644
index 0000000000..4474b4cc2f
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/every/predicate-returns-falsey.js
@@ -0,0 +1,36 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.every
+description: >
+ Iterator.prototype.every returns false and closes the iterator when the predicate returns falsey immediately
+info: |
+ %Iterator.prototype%.every ( predicate )
+
+ 4.f. If ToBoolean(result) is false, return ? IteratorClose(iterated, NormalCompletion(false)).
+
+features: [iterator-helpers]
+flags: []
+---*/
+function* g() {
+ yield 0;
+ yield 1;
+}
+
+let iter = g();
+
+let predicateCalls = 0;
+let result = iter.every(v => {
+ ++predicateCalls;
+ return false;
+});
+
+assert.sameValue(result, false);
+assert.sameValue(predicateCalls, 1);
+
+let { done, value } = iter.next();
+assert.sameValue(done, true);
+assert.sameValue(value, undefined);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/every/predicate-returns-non-boolean.js b/js/src/tests/test262/built-ins/Iterator/prototype/every/predicate-returns-non-boolean.js
new file mode 100644
index 0000000000..4130445ff5
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/every/predicate-returns-non-boolean.js
@@ -0,0 +1,33 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.every
+description: >
+ Iterator.prototype.every coerces predicate return value to boolean
+info: |
+ %Iterator.prototype%.every ( predicate )
+
+ 4.f. If ToBoolean(result) is false, return ? IteratorClose(iterated, NormalCompletion(false)).
+
+features: [iterator-helpers]
+flags: []
+---*/
+function* g() {
+ for (let i = 4; i >= 0; --i) {
+ yield i;
+ }
+}
+
+let iter = g();
+
+let predicateCalls = 0;
+let result = iter.every(v => {
+ ++predicateCalls;
+ return v;
+});
+
+assert.sameValue(result, false);
+assert.sameValue(predicateCalls, 5);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/every/predicate-returns-truthy-then-falsey.js b/js/src/tests/test262/built-ins/Iterator/prototype/every/predicate-returns-truthy-then-falsey.js
new file mode 100644
index 0000000000..df4487551c
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/every/predicate-returns-truthy-then-falsey.js
@@ -0,0 +1,37 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.every
+description: >
+ Iterator.prototype.every returns false and closes the iterator when the predicate returns truthy for some iterated values and falsey for others
+info: |
+ %Iterator.prototype%.every ( predicate )
+
+ 4.f. If ToBoolean(result) is false, return ? IteratorClose(iterated, NormalCompletion(false)).
+
+features: [iterator-helpers]
+flags: []
+---*/
+function* g() {
+ for (let i = 0; i < 5; ++i) {
+ yield i;
+ }
+}
+
+let iter = g();
+
+let predicateCalls = 0;
+let result = iter.every(v => {
+ ++predicateCalls;
+ return v < 3;
+});
+
+assert.sameValue(result, false);
+assert.sameValue(predicateCalls, 4);
+
+let { done, value } = iter.next();
+assert.sameValue(done, true);
+assert.sameValue(value, undefined);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/every/predicate-returns-truthy.js b/js/src/tests/test262/built-ins/Iterator/prototype/every/predicate-returns-truthy.js
new file mode 100644
index 0000000000..1150e509e4
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/every/predicate-returns-truthy.js
@@ -0,0 +1,27 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.every
+description: >
+ Iterator.prototype.every returns true when the predicate returns truthy for all iterated values
+info: |
+ %Iterator.prototype%.every ( predicate )
+
+ 4.b. If next is false, return true.
+
+features: [iterator-helpers]
+flags: []
+---*/
+function* g() {
+ yield 0;
+ yield 1;
+ yield 2;
+ yield 3;
+ yield 4;
+}
+
+let result = g().every(() => true);
+assert.sameValue(result, true);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/every/predicate-this.js b/js/src/tests/test262/built-ins/Iterator/prototype/every/predicate-this.js
new file mode 100644
index 0000000000..0a4dcd1c4d
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/every/predicate-this.js
@@ -0,0 +1,36 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.every
+description: >
+ Iterator.prototype.every predicate this value is undefined
+info: |
+ %Iterator.prototype%.every ( predicate )
+
+ 4.d. Let result be Completion(Call(predicate, undefined, « value, 𝔽(counter) »)).
+
+features: [iterator-helpers]
+flags: []
+---*/
+function* g() {
+ yield 0;
+}
+
+let iter = g();
+
+let expectedThis = function () {
+ return this;
+}.call(undefined);
+
+let assertionCount = 0;
+let result = iter.every(function (v, count) {
+ assert.sameValue(this, expectedThis);
+ ++assertionCount;
+ return true;
+});
+
+assert.sameValue(result, true);
+assert.sameValue(assertionCount, 1);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/every/predicate-throws-then-closing-iterator-also-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/every/predicate-throws-then-closing-iterator-also-throws.js
new file mode 100644
index 0000000000..18973b57b9
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/every/predicate-throws-then-closing-iterator-also-throws.js
@@ -0,0 +1,42 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.every
+description: >
+ Attempts to close iterator when predicate throws, but that throws
+info: |
+ %Iterator.prototype%.every ( predicate )
+
+ 4.d. Let result be Completion(Call(predicate, undefined, « value, 𝔽(counter) »)).
+ 4.e. IfAbruptCloseIterator(result, iterated).
+
+features: [iterator-helpers]
+flags: []
+---*/
+let returnCalls = 0;
+
+class TestIterator extends Iterator {
+ next() {
+ return {
+ done: false,
+ value: 1,
+ };
+ }
+ return() {
+ ++returnCalls;
+ throw new Error();
+ }
+}
+
+let iterator = new TestIterator();
+
+assert.throws(Test262Error, function () {
+ iterator.every(() => {
+ throw new Test262Error();
+ });
+});
+
+assert.sameValue(returnCalls, 1);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/every/predicate-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/every/predicate-throws.js
new file mode 100644
index 0000000000..b5a2d7ef0c
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/every/predicate-throws.js
@@ -0,0 +1,46 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.every
+description: >
+ Closes iterator and throws when predicate throws
+info: |
+ %Iterator.prototype%.every ( predicate )
+
+ 4.d. Let result be Completion(Call(predicate, undefined, « value, 𝔽(counter) »)).
+ 4.e. IfAbruptCloseIterator(result, iterated).
+
+features: [iterator-helpers]
+flags: []
+---*/
+let returnCalls = 0;
+
+class TestIterator extends Iterator {
+ next() {
+ return {
+ done: false,
+ value: 1,
+ };
+ }
+ return() {
+ ++returnCalls;
+ return {};
+ }
+}
+
+let iterator = new TestIterator();
+
+let callbackCalls = 0;
+
+assert.throws(Test262Error, function () {
+ iterator.every(() => {
+ ++callbackCalls;
+ throw new Test262Error();
+ });
+});
+
+assert.sameValue(callbackCalls, 1);
+assert.sameValue(returnCalls, 1);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/every/prop-desc.js b/js/src/tests/test262/built-ins/Iterator/prototype/every/prop-desc.js
new file mode 100644
index 0000000000..0e6e10653e
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/every/prop-desc.js
@@ -0,0 +1,28 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.every
+description: >
+ Property descriptor of Iterator.prototype.every
+info: |
+ Iterator.prototype.every
+
+ * is the initial value of the Iterator.prototype.every property of the global object.
+
+ 17 ECMAScript Standard Built-in Objects
+
+ Every other data property described in clauses 18 through 26 and in Annex B.2
+ has the attributes { [[Writable]]: true, [[Enumerable]]: false,
+ [[Configurable]]: true } unless otherwise specified.
+features: [globalThis, iterator-helpers]
+includes: [propertyHelper.js]
+---*/
+
+verifyProperty(Iterator.prototype, 'every', {
+ writable: true,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/every/proto.js b/js/src/tests/test262/built-ins/Iterator/prototype/every/proto.js
new file mode 100644
index 0000000000..bddd9ab52e
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/every/proto.js
@@ -0,0 +1,14 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.every
+description: >
+ The value of the [[Prototype]] internal slot of Iterator.prototype.every is the
+ intrinsic object %Function%.
+features: [iterator-helpers]
+---*/
+
+assert.sameValue(Object.getPrototypeOf(Iterator.prototype.every), Function.prototype);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/every/result-is-boolean.js b/js/src/tests/test262/built-ins/Iterator/prototype/every/result-is-boolean.js
new file mode 100644
index 0000000000..005b254405
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/every/result-is-boolean.js
@@ -0,0 +1,14 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.every
+description: >
+ Iterator.prototype.every returns a boolean
+features: [iterator-helpers]
+---*/
+function* g() {}
+let iter = g();
+assert.sameValue(typeof iter.every(() => {}), 'boolean');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/every/shell.js b/js/src/tests/test262/built-ins/Iterator/prototype/every/shell.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/every/shell.js
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/every/this-non-callable-next.js b/js/src/tests/test262/built-ins/Iterator/prototype/every/this-non-callable-next.js
new file mode 100644
index 0000000000..ddfb318819
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/every/this-non-callable-next.js
@@ -0,0 +1,20 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.every
+description: >
+ Iterator.prototype.every throws TypeError when its this value is an object with a non-callable next
+info: |
+ %Iterator.prototype%.every ( predicate )
+
+ 1. Let iterated be ? GetIteratorDirect(this value).
+
+features: [iterator-helpers]
+flags: []
+---*/
+assert.throws(TypeError, function () {
+ Iterator.prototype.every.call({ next: 0 }, () => true);
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/every/this-non-object.js b/js/src/tests/test262/built-ins/Iterator/prototype/every/this-non-object.js
new file mode 100644
index 0000000000..4998274959
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/every/this-non-object.js
@@ -0,0 +1,29 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.every
+description: >
+ Iterator.prototype.every throws TypeError when its this value is a non-object
+info: |
+ %Iterator.prototype%.every ( predicate )
+
+ 1. Let iterated be ? GetIteratorDirect(this value).
+
+features: [iterator-helpers]
+flags: []
+---*/
+assert.throws(TypeError, function () {
+ Iterator.prototype.every.call(null, () => {});
+});
+
+Object.defineProperty(Number.prototype, 'next', {
+ get: function () {
+ throw new Test262Error();
+ },
+});
+assert.throws(TypeError, function () {
+ Iterator.prototype.every.call(0, () => {});
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/every/this-plain-iterator.js b/js/src/tests/test262/built-ins/Iterator/prototype/every/this-plain-iterator.js
new file mode 100644
index 0000000000..ce4b742a91
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/every/this-plain-iterator.js
@@ -0,0 +1,35 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.every
+description: >
+ Iterator.prototype.every supports a this value that does not inherit from Iterator.prototype but implements the iterator protocol
+info: |
+ %Iterator.prototype%.every ( predicate )
+
+ 1. Let iterated be ? GetIteratorDirect(this value).
+
+features: [iterator-helpers]
+flags: []
+---*/
+let iter = {
+ get next() {
+ let count = 3;
+ return function () {
+ --count;
+ return count >= 0 ? { done: false, value: count } : { done: true, value: undefined };
+ };
+ },
+};
+
+let predicateCalls = 0;
+let result = Iterator.prototype.every.call(iter, function (v) {
+ ++predicateCalls;
+ return v;
+});
+
+assert.sameValue(result, false);
+assert.sameValue(predicateCalls, 3);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/filter/argument-effect-order.js b/js/src/tests/test262/built-ins/Iterator/prototype/filter/argument-effect-order.js
new file mode 100644
index 0000000000..64d47cf80c
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/filter/argument-effect-order.js
@@ -0,0 +1,33 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.filter
+description: >
+ Arguments and this value are evaluated in the correct order
+info: |
+ %Iterator.prototype%.filter ( predicate )
+
+includes: [compareArray.js]
+features: [iterator-helpers]
+flags: []
+---*/
+let effects = [];
+
+assert.throws(TypeError, function () {
+ Iterator.prototype.filter.call(
+ {
+ get next() {
+ effects.push('get next');
+ return function () {
+ return { done: true, value: undefined };
+ };
+ },
+ },
+ null
+ );
+});
+
+assert.compareArray(effects, []);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/filter/browser.js b/js/src/tests/test262/built-ins/Iterator/prototype/filter/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/filter/browser.js
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/filter/callable.js b/js/src/tests/test262/built-ins/Iterator/prototype/filter/callable.js
new file mode 100644
index 0000000000..399bc881a8
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/filter/callable.js
@@ -0,0 +1,16 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.filter
+description: >
+ Iterator.prototype.filter is callable
+features: [iterator-helpers]
+---*/
+function* g() {}
+Iterator.prototype.filter.call(g(), () => false);
+
+let iter = g();
+iter.filter(() => false);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/filter/exhaustion-does-not-call-return.js b/js/src/tests/test262/built-ins/Iterator/prototype/filter/exhaustion-does-not-call-return.js
new file mode 100644
index 0000000000..8770acea38
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/filter/exhaustion-does-not-call-return.js
@@ -0,0 +1,40 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.filter
+description: >
+ Underlying iterator return is not called when result iterator is exhausted
+info: |
+ %Iterator.prototype%.filter ( predicate )
+
+ 3.b.i. Let next be ? IteratorStep(iterated).
+ 3.b.ii. If next is false, return undefined.
+
+features: [iterator-helpers]
+flags: []
+---*/
+function* g() {
+ yield 0;
+ yield 1;
+ yield 2;
+}
+
+class TestIterator extends Iterator {
+ get next() {
+ let n = g();
+ return function() {
+ return n.next();
+ };
+ }
+ return() {
+ throw new Test262Error();
+ }
+}
+
+let iterator = new TestIterator().filter(() => false);
+iterator.next();
+iterator.next();
+iterator.next();
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/filter/get-next-method-only-once.js b/js/src/tests/test262/built-ins/Iterator/prototype/filter/get-next-method-only-once.js
new file mode 100644
index 0000000000..50e2a9074a
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/filter/get-next-method-only-once.js
@@ -0,0 +1,44 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.filter
+description: >
+ Gets the next method from the underlying iterator only once
+info: |
+ %Iterator.prototype%.filter ( predicate )
+
+ 1. Let iterated be ? GetIteratorDirect(this value).
+
+features: [iterator-helpers]
+flags: []
+---*/
+let nextGets = 0;
+let nextCalls = 0;
+
+class CountingIterator extends Iterator {
+ get next() {
+ ++nextGets;
+ let iter = (function* () {
+ for (let i = 1; i < 5; ++i) {
+ yield i;
+ }
+ })();
+ return function () {
+ ++nextCalls;
+ return iter.next();
+ };
+ }
+}
+
+let iterator = new CountingIterator();
+
+assert.sameValue(nextGets, 0);
+assert.sameValue(nextCalls, 0);
+
+for (const value of iterator.filter(() => false));
+
+assert.sameValue(nextGets, 1);
+assert.sameValue(nextCalls, 5);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/filter/get-next-method-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/filter/get-next-method-throws.js
new file mode 100644
index 0000000000..655e75b206
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/filter/get-next-method-throws.js
@@ -0,0 +1,28 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.filter
+description: >
+ Underlying iterator has throwing next getter
+info: |
+ %Iterator.prototype%.filter ( predicate )
+
+ 1. Let iterated be ? GetIteratorDirect(this value).
+
+features: [iterator-helpers]
+flags: []
+---*/
+class ThrowingIterator extends Iterator {
+ get next() {
+ throw new Test262Error();
+ }
+}
+
+let iterator = new ThrowingIterator();
+
+assert.throws(Test262Error, function () {
+ iterator.filter(() => false);
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/filter/get-return-method-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/filter/get-return-method-throws.js
new file mode 100644
index 0000000000..fe38093eab
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/filter/get-return-method-throws.js
@@ -0,0 +1,33 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.filter
+description: >
+ Underlying iterator return is throwing getter
+info: |
+ %Iterator.prototype%.filter ( predicate )
+
+features: [iterator-helpers]
+flags: []
+---*/
+class TestIterator extends Iterator {
+ next() {
+ return {
+ done: false,
+ value: 1,
+ };
+ }
+ get return() {
+ throw new Test262Error();
+ }
+}
+
+let iterator = new TestIterator().filter(() => true);
+iterator.next();
+
+assert.throws(Test262Error, function () {
+ iterator.return();
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/filter/is-function.js b/js/src/tests/test262/built-ins/Iterator/prototype/filter/is-function.js
new file mode 100644
index 0000000000..8dd7bf1a85
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/filter/is-function.js
@@ -0,0 +1,13 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.filter
+description: >
+ Iterator.prototype.filter is a built-in function
+features: [iterator-helpers]
+---*/
+
+assert.sameValue(typeof Iterator.prototype.filter, 'function');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/filter/iterator-already-exhausted.js b/js/src/tests/test262/built-ins/Iterator/prototype/filter/iterator-already-exhausted.js
new file mode 100644
index 0000000000..a8682a18e7
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/filter/iterator-already-exhausted.js
@@ -0,0 +1,28 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.filter
+description: >
+ Iterator.prototype.filter returns an empty iterator when the iterator has already been exhausted
+info: |
+ %Iterator.prototype%.filter ( predicate )
+
+ 3.b.i. Let next be ? IteratorStep(iterated).
+ 3.b.ii. If next is false, return undefined.
+
+features: [iterator-helpers]
+flags: []
+---*/
+let iterator = (function* () {})();
+
+let { value, done } = iterator.next();
+assert.sameValue(value, undefined);
+assert.sameValue(done, true);
+
+iterator = iterator.filter(() => true);
+({ value, done } = iterator.next());
+assert.sameValue(value, undefined);
+assert.sameValue(done, true);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/filter/iterator-return-method-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/filter/iterator-return-method-throws.js
new file mode 100644
index 0000000000..e8511d1cc8
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/filter/iterator-return-method-throws.js
@@ -0,0 +1,32 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.filter
+description: >
+ Iterator has throwing return
+info: |
+ %Iterator.prototype%.filter ( predicate )
+
+features: [iterator-helpers]
+flags: []
+---*/
+class IteratorThrows extends Iterator {
+ next() {
+ return {
+ done: false,
+ value: 0,
+ };
+ }
+ return() {
+ throw new Test262Error();
+ }
+}
+
+let iterator = new IteratorThrows().filter(() => false);
+
+assert.throws(Test262Error, function () {
+ iterator.return();
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/filter/length.js b/js/src/tests/test262/built-ins/Iterator/prototype/filter/length.js
new file mode 100644
index 0000000000..766e0beb93
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/filter/length.js
@@ -0,0 +1,25 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.filter
+description: >
+ Iterator.prototype.filter has a "length" property whose value is 1.
+info: |
+ ECMAScript Standard Built-in Objects
+
+ Unless otherwise specified, the length property of a built-in
+ Function object has the attributes { [[Writable]]: false, [[Enumerable]]:
+ false, [[Configurable]]: true }.
+features: [iterator-helpers]
+includes: [propertyHelper.js]
+---*/
+
+verifyProperty(Iterator.prototype.filter, 'length', {
+ value: 1,
+ writable: false,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/filter/name.js b/js/src/tests/test262/built-ins/Iterator/prototype/filter/name.js
new file mode 100644
index 0000000000..1862cb1881
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/filter/name.js
@@ -0,0 +1,32 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.filter
+description: >
+ The "name" property of Iterator.prototype.filter
+info: |
+ 17 ECMAScript Standard Built-in Objects
+
+ Every built-in Function object, including constructors, that is not
+ identified as an anonymous function has a name property whose value is a
+ String. Unless otherwise specified, this value is the name that is given to
+ the function in this specification.
+
+ ...
+
+ Unless otherwise specified, the name property of a built-in Function
+ object, if it exists, has the attributes { [[Writable]]: false,
+ [[Enumerable]]: false, [[Configurable]]: true }.
+features: [iterator-helpers]
+includes: [propertyHelper.js]
+---*/
+
+verifyProperty(Iterator.prototype.filter, 'name', {
+ value: 'filter',
+ writable: false,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/filter/next-method-returns-non-object.js b/js/src/tests/test262/built-ins/Iterator/prototype/filter/next-method-returns-non-object.js
new file mode 100644
index 0000000000..92e5a2e63f
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/filter/next-method-returns-non-object.js
@@ -0,0 +1,28 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.filter
+description: >
+ Underlying iterator next returns non-object
+info: |
+ %Iterator.prototype%.filter ( predicate )
+
+ 3.b.i. Let next be ? IteratorStep(iterated).
+
+features: [iterator-helpers]
+flags: []
+---*/
+class NonObjectIterator extends Iterator {
+ next() {
+ return null;
+ }
+}
+
+let iterator = new NonObjectIterator().filter(() => true);
+
+assert.throws(TypeError, function () {
+ iterator.next();
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/filter/next-method-returns-throwing-done.js b/js/src/tests/test262/built-ins/Iterator/prototype/filter/next-method-returns-throwing-done.js
new file mode 100644
index 0000000000..69af6d35c7
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/filter/next-method-returns-throwing-done.js
@@ -0,0 +1,36 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.filter
+description: >
+ Underlying iterator next returns object with throwing done getter
+info: |
+ %Iterator.prototype%.filter ( predicate )
+
+ 3.b.i. Let next be ? IteratorStep(iterated).
+
+features: [iterator-helpers]
+flags: []
+---*/
+class ThrowingIterator extends Iterator {
+ next() {
+ return {
+ get done() {
+ throw new Test262Error();
+ },
+ value: 1,
+ };
+ }
+ return() {
+ throw new Error();
+ }
+}
+
+let iterator = new ThrowingIterator().filter(() => true);
+
+assert.throws(Test262Error, function () {
+ iterator.next();
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/filter/next-method-returns-throwing-value-done.js b/js/src/tests/test262/built-ins/Iterator/prototype/filter/next-method-returns-throwing-value-done.js
new file mode 100644
index 0000000000..daac171b28
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/filter/next-method-returns-throwing-value-done.js
@@ -0,0 +1,33 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.filter
+description: >
+ Underlying iterator next returns object with throwing value getter, but is already done
+info: |
+ %Iterator.prototype%.filter ( predicate )
+
+ 3.b.ii. If next is false, return undefined.
+
+features: [iterator-helpers]
+flags: []
+---*/
+class ThrowingIterator extends Iterator {
+ next() {
+ return {
+ done: true,
+ get value() {
+ throw new Test262Error();
+ },
+ };
+ }
+ return() {
+ throw new Error();
+ }
+}
+
+let iterator = new ThrowingIterator().filter(() => true);
+iterator.next();
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/filter/next-method-returns-throwing-value.js b/js/src/tests/test262/built-ins/Iterator/prototype/filter/next-method-returns-throwing-value.js
new file mode 100644
index 0000000000..5d441c9343
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/filter/next-method-returns-throwing-value.js
@@ -0,0 +1,36 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.filter
+description: >
+ Underlying iterator next returns object with throwing value getter
+info: |
+ %Iterator.prototype%.filter ( predicate )
+
+ 3.b.iii. Let value be ? IteratorValue(next).
+
+features: [iterator-helpers]
+flags: []
+---*/
+class ThrowingIterator extends Iterator {
+ next() {
+ return {
+ done: false,
+ get value() {
+ throw new Test262Error();
+ },
+ };
+ }
+ return() {
+ throw new Error();
+ }
+}
+
+let iterator = new ThrowingIterator().filter(() => true);
+
+assert.throws(Test262Error, function () {
+ iterator.next();
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/filter/next-method-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/filter/next-method-throws.js
new file mode 100644
index 0000000000..59f666ab40
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/filter/next-method-throws.js
@@ -0,0 +1,28 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.filter
+description: >
+ Underlying iterator has throwing next method
+info: |
+ %Iterator.prototype%.filter ( predicate )
+
+ 3.b.i. Let next be ? IteratorStep(iterated).
+
+features: [iterator-helpers]
+flags: []
+---*/
+class ThrowingIterator extends Iterator {
+ next() {
+ throw new Test262Error();
+ }
+}
+
+let iterator = new ThrowingIterator().filter(() => true);
+
+assert.throws(Test262Error, function () {
+ iterator.next();
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/filter/non-callable-predicate.js b/js/src/tests/test262/built-ins/Iterator/prototype/filter/non-callable-predicate.js
new file mode 100644
index 0000000000..97960b7112
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/filter/non-callable-predicate.js
@@ -0,0 +1,23 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.filter
+description: >
+ Iterator.prototype.filter expects to be called with a callable argument.
+info: |
+ %Iterator.prototype%.filter ( predicate )
+
+ 2. If IsCallable(predicate) is false, throw a TypeError exception.
+
+features: [iterator-helpers]
+flags: []
+---*/
+let nonCallable = {};
+let iterator = (function* () {})();
+
+assert.throws(TypeError, function () {
+ iterator.filter(nonCallable);
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/filter/non-constructible.js b/js/src/tests/test262/built-ins/Iterator/prototype/filter/non-constructible.js
new file mode 100644
index 0000000000..215721e128
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/filter/non-constructible.js
@@ -0,0 +1,31 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.filter
+description: >
+ Iterator.prototype.filter is not constructible.
+
+ Built-in function objects that are not identified as constructors do not implement the [[Construct]] internal method unless otherwise specified in the description of a particular function.
+features: [iterator-helpers]
+---*/
+function* g() {}
+let iter = g();
+
+assert.throws(TypeError, () => {
+ new iter.filter();
+});
+
+assert.throws(TypeError, () => {
+ new iter.filter(() => true);
+});
+
+assert.throws(TypeError, () => {
+ new Iterator.prototype.filter(() => true);
+});
+
+assert.throws(TypeError, () => {
+ new class extends Iterator {}.filter(() => true);
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/filter/predicate-args.js b/js/src/tests/test262/built-ins/Iterator/prototype/filter/predicate-args.js
new file mode 100644
index 0000000000..16be06895d
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/filter/predicate-args.js
@@ -0,0 +1,47 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.filter
+description: >
+ Iterator.prototype.filter predicate is passed the yielded value and a counter as arguments
+info: |
+ %Iterator.prototype%.filter ( predicate )
+
+ 3.b.iv. Let selected be Completion(Call(predicate, undefined, « value, 𝔽(counter) »)).
+
+features: [iterator-helpers]
+flags: []
+---*/
+function* g() {
+ yield 'a';
+ yield 'b';
+ yield 'c';
+}
+
+let assertionCount = 0;
+let iter = g().filter((v, count) => {
+ switch (v) {
+ case 'a':
+ assert.sameValue(count, 0);
+ break;
+ case 'b':
+ assert.sameValue(count, 1);
+ break;
+ case 'c':
+ assert.sameValue(count, 2);
+ break;
+ default:
+ throw new Error();
+ }
+ ++assertionCount;
+ return true;
+});
+
+assert.sameValue(assertionCount, 0);
+
+for (let i of iter);
+
+assert.sameValue(assertionCount, 3);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/filter/predicate-filters.js b/js/src/tests/test262/built-ins/Iterator/prototype/filter/predicate-filters.js
new file mode 100644
index 0000000000..0ff02ac852
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/filter/predicate-filters.js
@@ -0,0 +1,43 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.filter
+description: >
+ Iterator.prototype.filter returns only items for which the predicate returned true.
+info: |
+ %Iterator.prototype%.filter ( filterer )
+
+features: [iterator-helpers]
+flags: []
+---*/
+function* g() {
+ yield 1;
+ yield 0;
+ yield 2;
+ yield 0;
+ yield 3;
+ yield 0;
+ yield 4;
+}
+
+let iterator = g();
+
+let predicateCalls = 0;
+iterator = iterator.filter(value => {
+ ++predicateCalls;
+ return value !== 0;
+});
+
+let resultCount = 0;
+for (let value of iterator) {
+ ++resultCount;
+ assert.sameValue(value, resultCount);
+}
+assert.sameValue(resultCount, 4);
+
+let { value, done } = iterator.next();
+assert.sameValue(value, undefined);
+assert.sameValue(done, true);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/filter/predicate-returns-non-boolean.js b/js/src/tests/test262/built-ins/Iterator/prototype/filter/predicate-returns-non-boolean.js
new file mode 100644
index 0000000000..a4c4f44d75
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/filter/predicate-returns-non-boolean.js
@@ -0,0 +1,41 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.filter
+description: >
+ Iterator.prototype.filter coerces predicate return value to boolean
+info: |
+ %Iterator.prototype%.filter ( predicate )
+
+ 3.b.vi. If ToBoolean(selected) is true, then
+
+features: [iterator-helpers]
+flags: []
+---*/
+function* g() {
+ yield 0;
+ yield 0;
+ yield 0;
+ yield 1;
+}
+
+let iter = g();
+
+let predicateCalls = 0;
+iter = iter.filter(v => {
+ ++predicateCalls;
+ return v;
+});
+
+assert.sameValue(predicateCalls, 0);
+
+iter.next();
+
+assert.sameValue(predicateCalls, 4);
+
+iter.next();
+
+assert.sameValue(predicateCalls, 4);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/filter/predicate-this.js b/js/src/tests/test262/built-ins/Iterator/prototype/filter/predicate-this.js
new file mode 100644
index 0000000000..79b7ea8619
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/filter/predicate-this.js
@@ -0,0 +1,36 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.filter
+description: >
+ Iterator.prototype.filter predicate this value is undefined
+info: |
+ %Iterator.prototype%.filter ( predicate )
+
+ 3.b.iv. Let selected be Completion(Call(predicate, undefined, « value, 𝔽(counter) »)).
+
+features: [iterator-helpers]
+flags: []
+---*/
+function* g() {
+ yield 0;
+}
+
+let iter = g();
+
+let expectedThis = function () {
+ return this;
+}.call(undefined);
+
+let assertionCount = 0;
+iter = iter.filter(function (v, count) {
+ assert.sameValue(this, expectedThis);
+ ++assertionCount;
+ return true;
+});
+
+iter.next();
+assert.sameValue(assertionCount, 1);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/filter/predicate-throws-then-closing-iterator-also-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/filter/predicate-throws-then-closing-iterator-also-throws.js
new file mode 100644
index 0000000000..61ffe5eba0
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/filter/predicate-throws-then-closing-iterator-also-throws.js
@@ -0,0 +1,43 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.filter
+description: >
+ Attempts to close iterator when predicate throws, but that throws
+info: |
+ %Iterator.prototype%.filter ( predicate )
+
+ 3.b.v. IfAbruptCloseIterator(selected, iterated).
+
+features: [iterator-helpers]
+flags: []
+---*/
+let returnCalls = 0;
+
+class TestIterator extends Iterator {
+ next() {
+ return {
+ done: false,
+ value: 1,
+ };
+ }
+ return() {
+ ++returnCalls;
+ throw new Error();
+ }
+}
+
+let iterator = new TestIterator().filter(() => {
+ throw new Test262Error();
+});
+
+assert.sameValue(returnCalls, 0);
+
+assert.throws(Test262Error, function () {
+ iterator.next();
+});
+
+assert.sameValue(returnCalls, 1);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/filter/predicate-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/filter/predicate-throws.js
new file mode 100644
index 0000000000..1a998c12dc
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/filter/predicate-throws.js
@@ -0,0 +1,44 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.filter
+description: >
+ Closes iterator and throws when predicate throws
+info: |
+ %Iterator.prototype%.filter ( predicate )
+
+ 3.b.v. IfAbruptCloseIterator(selected, iterated).
+
+features: [iterator-helpers]
+flags: []
+---*/
+let returnCalls = 0;
+
+class TestIterator extends Iterator {
+ next() {
+ return {
+ done: false,
+ value: 1,
+ };
+ }
+ return() {
+ ++returnCalls;
+ return {};
+ }
+}
+
+let callbackCalls = 0;
+let iterator = new TestIterator().filter(() => {
+ ++callbackCalls;
+ throw new Test262Error();
+});
+
+assert.throws(Test262Error, function () {
+ iterator.next();
+});
+
+assert.sameValue(callbackCalls, 1);
+assert.sameValue(returnCalls, 1);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/filter/prop-desc.js b/js/src/tests/test262/built-ins/Iterator/prototype/filter/prop-desc.js
new file mode 100644
index 0000000000..4d1ae8b770
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/filter/prop-desc.js
@@ -0,0 +1,28 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.filter
+description: >
+ Property descriptor of Iterator.prototype.filter
+info: |
+ Iterator.prototype.filter
+
+ * is the initial value of the Iterator.prototype.filter property of the global object.
+
+ 17 ECMAScript Standard Built-in Objects
+
+ Every other data property described in clauses 18 through 26 and in Annex B.2
+ has the attributes { [[Writable]]: true, [[Enumerable]]: false,
+ [[Configurable]]: true } unless otherwise specified.
+features: [globalThis, iterator-helpers]
+includes: [propertyHelper.js]
+---*/
+
+verifyProperty(Iterator.prototype, 'filter', {
+ writable: true,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/filter/proto.js b/js/src/tests/test262/built-ins/Iterator/prototype/filter/proto.js
new file mode 100644
index 0000000000..e1e963c1f8
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/filter/proto.js
@@ -0,0 +1,14 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.filter
+description: >
+ The value of the [[Prototype]] internal slot of Iterator.prototype.filter is the
+ intrinsic object %FunctionPrototype%.
+features: [iterator-helpers]
+---*/
+
+assert.sameValue(Object.getPrototypeOf(Iterator.prototype.filter), Function.prototype);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/filter/result-is-iterator.js b/js/src/tests/test262/built-ins/Iterator/prototype/filter/result-is-iterator.js
new file mode 100644
index 0000000000..777ed443c4
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/filter/result-is-iterator.js
@@ -0,0 +1,17 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.filter
+description: >
+ The value of the [[Prototype]] internal slot of the return value of Iterator.prototype.filter is the
+ intrinsic object %IteratorHelperPrototype%.
+features: [iterator-helpers]
+---*/
+
+assert(
+ (function* () {})().filter(() => true) instanceof Iterator,
+ 'function*(){}().filter(() => true) must return an Iterator'
+);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/filter/return-is-forwarded.js b/js/src/tests/test262/built-ins/Iterator/prototype/filter/return-is-forwarded.js
new file mode 100644
index 0000000000..2c86f273f6
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/filter/return-is-forwarded.js
@@ -0,0 +1,36 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.filter
+description: >
+ Underlying iterator return is called when result iterator is closed
+info: |
+ %Iterator.prototype%.filter ( predicate )
+
+features: [iterator-helpers]
+flags: []
+---*/
+let returnCount = 0;
+
+class TestIterator extends Iterator {
+ next() {
+ return {
+ done: false,
+ value: 1,
+ };
+ }
+ return() {
+ ++returnCount;
+ return {};
+ }
+}
+
+let iterator = new TestIterator().filter(() => false);
+assert.sameValue(returnCount, 0);
+iterator.return();
+assert.sameValue(returnCount, 1);
+iterator.return();
+assert.sameValue(returnCount, 1);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/filter/return-is-not-forwarded-after-exhaustion.js b/js/src/tests/test262/built-ins/Iterator/prototype/filter/return-is-not-forwarded-after-exhaustion.js
new file mode 100644
index 0000000000..00a6a050ce
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/filter/return-is-not-forwarded-after-exhaustion.js
@@ -0,0 +1,49 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.filter
+description: >
+ Underlying iterator return is not called after result iterator observes that underlying iterator is exhausted
+info: |
+ %Iterator.prototype%.filter ( predicate )
+
+features: [iterator-helpers]
+flags: []
+---*/
+let returnCount = 0;
+
+class TestIterator extends Iterator {
+ next() {
+ return {
+ done: true,
+ value: undefined,
+ };
+ }
+ return() {
+ throw new Test262Error();
+ }
+}
+
+let iterator = new TestIterator().filter(() => true);
+assert.throws(Test262Error, function () {
+ iterator.return();
+});
+iterator.next();
+iterator.return();
+
+iterator = new TestIterator().filter(() => true);
+iterator.next();
+iterator.return();
+
+iterator = new TestIterator()
+ .filter(() => true)
+ .filter(() => true)
+ .filter(() => true);
+assert.throws(Test262Error, function () {
+ iterator.return();
+});
+iterator.next();
+iterator.return();
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/filter/shell.js b/js/src/tests/test262/built-ins/Iterator/prototype/filter/shell.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/filter/shell.js
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/filter/this-non-callable-next.js b/js/src/tests/test262/built-ins/Iterator/prototype/filter/this-non-callable-next.js
new file mode 100644
index 0000000000..f87ac0f62c
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/filter/this-non-callable-next.js
@@ -0,0 +1,22 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.filter
+description: >
+ Iterator.prototype.filter throws TypeError when its this value is an object with a non-callable next
+info: |
+ %Iterator.prototype%.filter ( predicate )
+
+ 1. Let iterated be ? GetIteratorDirect(this value).
+
+features: [iterator-helpers]
+flags: []
+---*/
+let iter = Iterator.prototype.filter.call({ next: 0 }, () => true);
+
+assert.throws(TypeError, function () {
+ iter.next();
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/filter/this-non-object.js b/js/src/tests/test262/built-ins/Iterator/prototype/filter/this-non-object.js
new file mode 100644
index 0000000000..542946348f
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/filter/this-non-object.js
@@ -0,0 +1,29 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.filter
+description: >
+ Iterator.prototype.filter throws TypeError when its this value is a non-object
+info: |
+ %Iterator.prototype%.filter ( predicate )
+
+ 1. Let iterated be ? GetIteratorDirect(this value).
+
+features: [iterator-helpers]
+flags: []
+---*/
+assert.throws(TypeError, function () {
+ Iterator.prototype.filter.call(null, () => true);
+});
+
+Object.defineProperty(Number.prototype, 'next', {
+ get: function () {
+ throw new Test262Error();
+ },
+});
+assert.throws(TypeError, function () {
+ Iterator.prototype.filter.call(0, () => true);
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/filter/this-plain-iterator.js b/js/src/tests/test262/built-ins/Iterator/prototype/filter/this-plain-iterator.js
new file mode 100644
index 0000000000..06f2412b55
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/filter/this-plain-iterator.js
@@ -0,0 +1,36 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.filter
+description: >
+ Iterator.prototype.filter supports a this value that does not inherit from Iterator.prototype but implements the iterator protocol
+info: |
+ %Iterator.prototype%.filter ( predicate )
+
+ 1. Let iterated be ? GetIteratorDirect(this value).
+
+features: [iterator-helpers]
+flags: []
+---*/
+let iter = {
+ get next() {
+ let count = 3;
+ return function () {
+ --count;
+ return count >= 0 ? { done: false, value: count } : { done: true, value: undefined };
+ };
+ },
+};
+
+let predicateCalls = 0;
+iter = Iterator.prototype.filter.call(iter, function (v) {
+ ++predicateCalls;
+ return v;
+});
+
+for (let e of iter);
+
+assert.sameValue(predicateCalls, 3);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/filter/throws-typeerror-when-generator-is-running.js b/js/src/tests/test262/built-ins/Iterator/prototype/filter/throws-typeerror-when-generator-is-running.js
new file mode 100644
index 0000000000..ed9ce10b47
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/filter/throws-typeerror-when-generator-is-running.js
@@ -0,0 +1,49 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 André Bargull. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.filter
+description: >
+ Throws a TypeError when the closure generator is already running.
+info: |
+ %IteratorHelperPrototype%.next ( )
+ 1. Return ? GeneratorResume(this value, undefined, "Iterator Helper").
+
+ 27.5.3.3 GeneratorResume ( generator, value, generatorBrand )
+ 1. Let state be ? GeneratorValidate(generator, generatorBrand).
+ ...
+
+ 27.5.3.2 GeneratorValidate ( generator, generatorBrand )
+ ...
+ 6. If state is executing, throw a TypeError exception.
+ ...
+
+features: [iterator-helpers]
+---*/
+
+var loopCount = 0;
+
+function* g() {
+ while (true) {
+ loopCount++;
+ yield;
+ }
+}
+
+var enterCount = 0;
+
+function predicate() {
+ enterCount++;
+ iter.next();
+}
+
+var iter = g().filter(predicate);
+
+assert.throws(TypeError, function() {
+ iter.next();
+});
+
+assert.sameValue(loopCount, 1);
+assert.sameValue(enterCount, 1);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/filter/underlying-iterator-advanced-in-parallel.js b/js/src/tests/test262/built-ins/Iterator/prototype/filter/underlying-iterator-advanced-in-parallel.js
new file mode 100644
index 0000000000..a34e36eed4
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/filter/underlying-iterator-advanced-in-parallel.js
@@ -0,0 +1,45 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.filter
+description: >
+ Underlying iterator is advanced after calling filter
+info: |
+ %Iterator.prototype%.filter ( predicate )
+
+features: [iterator-helpers]
+flags: []
+---*/
+let iterator = (function* () {
+ for (let i = 0; i < 5; ++i) {
+ yield i;
+ }
+})();
+
+let filtered = iterator.filter(() => true);
+
+let { value, done } = iterator.next();
+
+assert.sameValue(value, 0);
+assert.sameValue(done, false);
+
+iterator.next();
+iterator.next();
+
+({ value, done } = filtered.next());
+
+assert.sameValue(value, 3);
+assert.sameValue(done, false);
+
+({ value, done } = filtered.next());
+
+assert.sameValue(value, 4);
+assert.sameValue(done, false);
+
+({ value, done } = filtered.next());
+
+assert.sameValue(value, undefined);
+assert.sameValue(done, true);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/filter/underlying-iterator-closed-in-parallel.js b/js/src/tests/test262/built-ins/Iterator/prototype/filter/underlying-iterator-closed-in-parallel.js
new file mode 100644
index 0000000000..8af0579312
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/filter/underlying-iterator-closed-in-parallel.js
@@ -0,0 +1,29 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.filter
+description: >
+ Underlying iterator is closed after calling filter
+info: |
+ %Iterator.prototype%.filter ( predicate )
+
+features: [iterator-helpers]
+flags: []
+---*/
+let iterator = (function* () {
+ for (let i = 0; i < 5; ++i) {
+ yield i;
+ }
+})();
+
+let filtered = iterator.filter(() => true);
+
+iterator.return();
+
+let { value, done } = filtered.next();
+
+assert.sameValue(value, undefined);
+assert.sameValue(done, true);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/filter/underlying-iterator-closed.js b/js/src/tests/test262/built-ins/Iterator/prototype/filter/underlying-iterator-closed.js
new file mode 100644
index 0000000000..271b4895d3
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/filter/underlying-iterator-closed.js
@@ -0,0 +1,29 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.filter
+description: >
+ Underlying iterator is closed before calling filter
+info: |
+ %Iterator.prototype%.filter ( predicate )
+
+features: [iterator-helpers]
+flags: []
+---*/
+let iterator = (function* () {
+ for (let i = 0; i < 5; ++i) {
+ yield i;
+ }
+})();
+
+iterator.return();
+
+let filtered = iterator.filter(() => true);
+
+let { value, done } = filtered.next();
+
+assert.sameValue(value, undefined);
+assert.sameValue(done, true);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/find/argument-effect-order.js b/js/src/tests/test262/built-ins/Iterator/prototype/find/argument-effect-order.js
new file mode 100644
index 0000000000..589fc3eb5a
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/find/argument-effect-order.js
@@ -0,0 +1,33 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.find
+description: >
+ Arguments and this value are evaluated in the correct order
+info: |
+ %Iterator.prototype%.find ( predicate )
+
+includes: [compareArray.js]
+features: [iterator-helpers]
+flags: []
+---*/
+let effects = [];
+
+assert.throws(TypeError, function () {
+ Iterator.prototype.find.call(
+ {
+ get next() {
+ effects.push('get next');
+ return function () {
+ return { done: true, value: undefined };
+ };
+ },
+ },
+ null
+ );
+});
+
+assert.compareArray(effects, []);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/find/browser.js b/js/src/tests/test262/built-ins/Iterator/prototype/find/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/find/browser.js
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/find/callable.js b/js/src/tests/test262/built-ins/Iterator/prototype/find/callable.js
new file mode 100644
index 0000000000..cac9017981
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/find/callable.js
@@ -0,0 +1,16 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.find
+description: >
+ Iterator.prototype.find is callable
+features: [iterator-helpers]
+---*/
+function* g() {}
+Iterator.prototype.find.call(g(), () => {});
+
+let iter = g();
+iter.find(() => {});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/find/get-next-method-only-once.js b/js/src/tests/test262/built-ins/Iterator/prototype/find/get-next-method-only-once.js
new file mode 100644
index 0000000000..39806fc806
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/find/get-next-method-only-once.js
@@ -0,0 +1,39 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.find
+description: >
+ Gets the next method from the iterator only once
+info: |
+ %Iterator.prototype%.find ( predicate )
+
+features: [iterator-helpers]
+flags: []
+---*/
+let nextGets = 0;
+
+class TestIterator extends Iterator {
+ get next() {
+ ++nextGets;
+ let counter = 5;
+ return function () {
+ if (counter < 0) {
+ return { done: true, value: undefined };
+ } else {
+ return { done: false, value: --counter };
+ }
+ };
+ }
+}
+
+let iterator = new TestIterator();
+
+assert.sameValue(nextGets, 0);
+assert.sameValue(
+ iterator.find(() => true),
+ 4
+);
+assert.sameValue(nextGets, 1);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/find/get-next-method-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/find/get-next-method-throws.js
new file mode 100644
index 0000000000..520f746f79
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/find/get-next-method-throws.js
@@ -0,0 +1,26 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.find
+description: >
+ Iterator has throwing next getter
+info: |
+ %Iterator.prototype%.find ( predicate )
+
+features: [iterator-helpers]
+flags: []
+---*/
+class IteratorThrows extends Iterator {
+ get next() {
+ throw new Test262Error();
+ }
+}
+
+let iterator = new IteratorThrows();
+
+assert.throws(Test262Error, function () {
+ iterator.find(() => {});
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/find/get-return-method-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/find/get-return-method-throws.js
new file mode 100644
index 0000000000..c3493eee93
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/find/get-return-method-throws.js
@@ -0,0 +1,32 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.find
+description: >
+ Iterator has throwing return getter
+info: |
+ %Iterator.prototype%.find ( predicate )
+
+features: [iterator-helpers]
+flags: []
+---*/
+class IteratorThrows extends Iterator {
+ next() {
+ return {
+ done: false,
+ value: 0,
+ };
+ }
+ get return() {
+ throw new Test262Error();
+ }
+}
+
+let iterator = new IteratorThrows([1, 2]);
+
+assert.throws(Test262Error, function () {
+ iterator.find(() => true);
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/find/is-function.js b/js/src/tests/test262/built-ins/Iterator/prototype/find/is-function.js
new file mode 100644
index 0000000000..439bfde946
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/find/is-function.js
@@ -0,0 +1,13 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.find
+description: >
+ Iterator.prototype.find is a built-in function
+features: [iterator-helpers]
+---*/
+
+assert.sameValue(typeof Iterator.prototype.find, 'function');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/find/iterator-already-exhausted.js b/js/src/tests/test262/built-ins/Iterator/prototype/find/iterator-already-exhausted.js
new file mode 100644
index 0000000000..f6b903a99a
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/find/iterator-already-exhausted.js
@@ -0,0 +1,26 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.find
+description: >
+ Iterator.prototype.find returns undefined when the iterator has already been exhausted
+info: |
+ %Iterator.prototype%.find ( predicate )
+
+features: [iterator-helpers]
+flags: []
+---*/
+let iterator = (function* () {})();
+
+let { value, done } = iterator.next();
+assert.sameValue(value, undefined);
+assert.sameValue(done, true);
+
+let result = iterator.find(() => true);
+assert.sameValue(result, undefined);
+
+result = iterator.find(() => false);
+assert.sameValue(result, undefined);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/find/iterator-has-no-return.js b/js/src/tests/test262/built-ins/Iterator/prototype/find/iterator-has-no-return.js
new file mode 100644
index 0000000000..620739de77
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/find/iterator-has-no-return.js
@@ -0,0 +1,30 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.find
+description: >
+ The underlying iterator is sometimes unable to be closed (has no return method)
+info: |
+ %Iterator.prototype%.find ( predicate )
+
+features: [iterator-helpers]
+flags: []
+---*/
+let iterator = [1, 2, 3, 4, 5][Symbol.iterator]();
+
+assert.sameValue(iterator.return, undefined);
+
+let ret = iterator.find(v => v > 3);
+
+assert.sameValue(ret, 4);
+
+let { done, value } = iterator.next();
+assert.sameValue(done, false);
+assert.sameValue(value, 5);
+
+({ done, value } = iterator.next());
+assert.sameValue(done, true);
+assert.sameValue(value, undefined);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/find/iterator-return-method-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/find/iterator-return-method-throws.js
new file mode 100644
index 0000000000..52a48361ab
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/find/iterator-return-method-throws.js
@@ -0,0 +1,32 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.find
+description: >
+ Iterator has throwing return
+info: |
+ %Iterator.prototype%.find ( predicate )
+
+features: [iterator-helpers]
+flags: []
+---*/
+class IteratorThrows extends Iterator {
+ next() {
+ return {
+ done: false,
+ value: 0,
+ };
+ }
+ return() {
+ throw new Test262Error();
+ }
+}
+
+let iterator = new IteratorThrows();
+
+assert.throws(Test262Error, function () {
+ iterator.find(() => true);
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/find/length.js b/js/src/tests/test262/built-ins/Iterator/prototype/find/length.js
new file mode 100644
index 0000000000..78cf4a0bac
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/find/length.js
@@ -0,0 +1,25 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.find
+description: >
+ Iterator.prototype.find has a "length" property whose value is 1.
+info: |
+ ECMAScript Standard Built-in Objects
+
+ Unless otherwise specified, the length property of a built-in
+ Function object has the attributes { [[Writable]]: false, [[Enumerable]]:
+ false, [[Configurable]]: true }.
+features: [iterator-helpers]
+includes: [propertyHelper.js]
+---*/
+
+verifyProperty(Iterator.prototype.find, 'length', {
+ value: 1,
+ writable: false,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/find/name.js b/js/src/tests/test262/built-ins/Iterator/prototype/find/name.js
new file mode 100644
index 0000000000..b395edbf11
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/find/name.js
@@ -0,0 +1,32 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.find
+description: >
+ The "name" property of Iterator.prototype.find
+info: |
+ 17 ECMAScript Standard Built-in Objects
+
+ Every built-in Function object, including constructors, that is not
+ identified as an anonymous function has a name property whose value is a
+ String. Unless otherwise specified, this value is the name that is given to
+ the function in this specification.
+
+ ...
+
+ Unless otherwise specified, the name property of a built-in Function
+ object, if it exists, has the attributes { [[Writable]]: false,
+ [[Enumerable]]: false, [[Configurable]]: true }.
+features: [iterator-helpers]
+includes: [propertyHelper.js]
+---*/
+
+verifyProperty(Iterator.prototype.find, 'name', {
+ value: 'find',
+ writable: false,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/find/next-method-returns-non-object.js b/js/src/tests/test262/built-ins/Iterator/prototype/find/next-method-returns-non-object.js
new file mode 100644
index 0000000000..fa4e23d4b1
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/find/next-method-returns-non-object.js
@@ -0,0 +1,26 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.find
+description: >
+ Underlying iterator next returns non-object
+info: |
+ %Iterator.prototype%.find ( predicate )
+
+features: [iterator-helpers]
+flags: []
+---*/
+class NonObjectIterator extends Iterator {
+ next() {
+ return null;
+ }
+}
+
+let iterator = new NonObjectIterator();
+
+assert.throws(TypeError, function () {
+ iterator.find(() => {});
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/find/next-method-returns-throwing-done.js b/js/src/tests/test262/built-ins/Iterator/prototype/find/next-method-returns-throwing-done.js
new file mode 100644
index 0000000000..77958e527b
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/find/next-method-returns-throwing-done.js
@@ -0,0 +1,34 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.find
+description: >
+ Underlying iterator next returns object with throwing done getter
+info: |
+ %Iterator.prototype%.find ( predicate )
+
+features: [iterator-helpers]
+flags: []
+---*/
+class ThrowingIterator extends Iterator {
+ next() {
+ return {
+ get done() {
+ throw new Test262Error();
+ },
+ value: 1,
+ };
+ }
+ return() {
+ throw new Error();
+ }
+}
+
+let iterator = new ThrowingIterator();
+
+assert.throws(Test262Error, function () {
+ iterator.find(() => {});
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/find/next-method-returns-throwing-value-done.js b/js/src/tests/test262/built-ins/Iterator/prototype/find/next-method-returns-throwing-value-done.js
new file mode 100644
index 0000000000..f82b8672a9
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/find/next-method-returns-throwing-value-done.js
@@ -0,0 +1,31 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.find
+description: >
+ Underlying iterator next returns object with throwing value getter, but is already done
+info: |
+ %Iterator.prototype%.find ( predicate )
+
+features: [iterator-helpers]
+flags: []
+---*/
+class ThrowingIterator extends Iterator {
+ next() {
+ return {
+ done: true,
+ get value() {
+ throw new Test262Error();
+ },
+ };
+ }
+ return() {
+ throw new Error();
+ }
+}
+
+let iterator = new ThrowingIterator();
+iterator.find(() => {});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/find/next-method-returns-throwing-value.js b/js/src/tests/test262/built-ins/Iterator/prototype/find/next-method-returns-throwing-value.js
new file mode 100644
index 0000000000..f71202d9e0
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/find/next-method-returns-throwing-value.js
@@ -0,0 +1,34 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.find
+description: >
+ Underlying iterator next returns object with throwing value getter
+info: |
+ %Iterator.prototype%.find ( predicate )
+
+features: [iterator-helpers]
+flags: []
+---*/
+class ThrowingIterator extends Iterator {
+ next() {
+ return {
+ done: false,
+ get value() {
+ throw new Test262Error();
+ },
+ };
+ }
+ return() {
+ throw new Error();
+ }
+}
+
+let iterator = new ThrowingIterator();
+
+assert.throws(Test262Error, function () {
+ iterator.find(() => {});
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/find/next-method-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/find/next-method-throws.js
new file mode 100644
index 0000000000..59ed603d9e
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/find/next-method-throws.js
@@ -0,0 +1,26 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.find
+description: >
+ Underlying iterator has throwing next method
+info: |
+ %Iterator.prototype%.find ( predicate )
+
+features: [iterator-helpers]
+flags: []
+---*/
+class ThrowingIterator extends Iterator {
+ next() {
+ throw new Test262Error();
+ }
+}
+
+let iterator = new ThrowingIterator();
+
+assert.throws(Test262Error, function () {
+ iterator.find(() => {});
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/find/non-callable-predicate.js b/js/src/tests/test262/built-ins/Iterator/prototype/find/non-callable-predicate.js
new file mode 100644
index 0000000000..b34ba1fa0c
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/find/non-callable-predicate.js
@@ -0,0 +1,23 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.find
+description: >
+ Iterator.prototype.find expects to be called with a callable argument.
+info: |
+ %Iterator.prototype%.find ( predicate )
+
+features: [iterator-helpers]
+flags: []
+---*/
+let nonCallable = {};
+let iterator = (function* () {
+ yield 1;
+})();
+
+assert.throws(TypeError, function () {
+ iterator.find(nonCallable);
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/find/non-constructible.js b/js/src/tests/test262/built-ins/Iterator/prototype/find/non-constructible.js
new file mode 100644
index 0000000000..d7e66cc5f3
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/find/non-constructible.js
@@ -0,0 +1,31 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.find
+description: >
+ Iterator.prototype.find is not constructible.
+
+ Built-in function objects that are not identified as constructors do not implement the [[Construct]] internal method unless otherwise specified in the description of a particular function.
+features: [iterator-helpers]
+---*/
+function* g() {}
+let iter = g();
+
+assert.throws(TypeError, () => {
+ new iter.find();
+});
+
+assert.throws(TypeError, () => {
+ new iter.find(() => {});
+});
+
+assert.throws(TypeError, () => {
+ new Iterator.prototype.find(() => {});
+});
+
+assert.throws(TypeError, () => {
+ new class extends Iterator {}.find(() => {});
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/find/predicate-args.js b/js/src/tests/test262/built-ins/Iterator/prototype/find/predicate-args.js
new file mode 100644
index 0000000000..46346783e1
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/find/predicate-args.js
@@ -0,0 +1,44 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.find
+description: >
+ Iterator.prototype.find predicate is passed the yielded value and a counter as arguments
+info: |
+ %Iterator.prototype%.find ( predicate )
+
+features: [iterator-helpers]
+flags: []
+---*/
+function* g() {
+ yield 'a';
+ yield 'b';
+ yield 'c';
+}
+
+let iter = g();
+
+let assertionCount = 0;
+let result = iter.find((v, count) => {
+ switch (v) {
+ case 'a':
+ assert.sameValue(count, 0);
+ break;
+ case 'b':
+ assert.sameValue(count, 1);
+ break;
+ case 'c':
+ assert.sameValue(count, 2);
+ break;
+ default:
+ throw new Error();
+ }
+ ++assertionCount;
+ return false;
+});
+
+assert.sameValue(result, undefined);
+assert.sameValue(assertionCount, 3);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/find/predicate-returns-falsey-then-truthy.js b/js/src/tests/test262/built-ins/Iterator/prototype/find/predicate-returns-falsey-then-truthy.js
new file mode 100644
index 0000000000..7a8e2a5b27
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/find/predicate-returns-falsey-then-truthy.js
@@ -0,0 +1,35 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.find
+description: >
+ Iterator.prototype.find returns the found value and closes the iterator when the predicate returns falsey for some iterated values and truthy for others
+info: |
+ %Iterator.prototype%.find ( predicate )
+
+features: [iterator-helpers]
+flags: []
+---*/
+function* g() {
+ for (let i = 0; i < 5; ++i) {
+ yield i;
+ }
+}
+
+let iter = g();
+
+let predicateCalls = 0;
+let result = iter.find(v => {
+ ++predicateCalls;
+ return v > 2;
+});
+
+assert.sameValue(result, 3);
+assert.sameValue(predicateCalls, 4);
+
+let { done, value } = iter.next();
+assert.sameValue(done, true);
+assert.sameValue(value, undefined);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/find/predicate-returns-falsey.js b/js/src/tests/test262/built-ins/Iterator/prototype/find/predicate-returns-falsey.js
new file mode 100644
index 0000000000..a3518e73d9
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/find/predicate-returns-falsey.js
@@ -0,0 +1,24 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.find
+description: >
+ Iterator.prototype.find returns undefined when the predicate returns falsey for all iterated values
+info: |
+ %Iterator.prototype%.find ( predicate )
+
+features: [iterator-helpers]
+flags: []
+---*/
+function* g() {
+ yield 0;
+ yield 1;
+ yield 2;
+ yield 3;
+}
+
+let result = g().find(() => false);
+assert.sameValue(result, undefined);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/find/predicate-returns-non-boolean.js b/js/src/tests/test262/built-ins/Iterator/prototype/find/predicate-returns-non-boolean.js
new file mode 100644
index 0000000000..1178a9cce9
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/find/predicate-returns-non-boolean.js
@@ -0,0 +1,35 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.find
+description: >
+ Iterator.prototype.find coerces predicate return value to boolean
+info: |
+ %Iterator.prototype%.find ( predicate )
+
+features: [iterator-helpers]
+flags: []
+---*/
+function* g() {
+ yield '';
+ yield null;
+ yield undefined;
+ yield 0;
+ yield 1;
+ yield 2;
+ yield 3;
+}
+
+let iter = g();
+
+let predicateCalls = 0;
+let result = iter.find(v => {
+ ++predicateCalls;
+ return v;
+});
+
+assert.sameValue(result, 1);
+assert.sameValue(predicateCalls, 5);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/find/predicate-returns-truthy.js b/js/src/tests/test262/built-ins/Iterator/prototype/find/predicate-returns-truthy.js
new file mode 100644
index 0000000000..7a5ae69ace
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/find/predicate-returns-truthy.js
@@ -0,0 +1,35 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.find
+description: >
+ Iterator.prototype.find returns the found value and closes the iterator when the predicate returns truthy immediately
+info: |
+ %Iterator.prototype%.find ( predicate )
+
+features: [iterator-helpers]
+flags: []
+---*/
+function* g() {
+ yield 0;
+ yield 1;
+ yield 2;
+}
+
+let iter = g();
+
+let predicateCalls = 0;
+let result = iter.find(v => {
+ ++predicateCalls;
+ return true;
+});
+
+assert.sameValue(result, 0);
+assert.sameValue(predicateCalls, 1);
+
+let { done, value } = iter.next();
+assert.sameValue(done, true);
+assert.sameValue(value, undefined);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/find/predicate-this.js b/js/src/tests/test262/built-ins/Iterator/prototype/find/predicate-this.js
new file mode 100644
index 0000000000..1b4f4458c2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/find/predicate-this.js
@@ -0,0 +1,34 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.find
+description: >
+ Iterator.prototype.find predicate this value is undefined
+info: |
+ %Iterator.prototype%.find ( predicate )
+
+features: [iterator-helpers]
+flags: []
+---*/
+function* g() {
+ yield 0;
+}
+
+let iter = g();
+
+let expectedThis = function () {
+ return this;
+}.call(undefined);
+
+let assertionCount = 0;
+let result = iter.find(function (v, count) {
+ assert.sameValue(this, expectedThis);
+ ++assertionCount;
+ return true;
+});
+
+assert.sameValue(result, 0);
+assert.sameValue(assertionCount, 1);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/find/predicate-throws-then-closing-iterator-also-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/find/predicate-throws-then-closing-iterator-also-throws.js
new file mode 100644
index 0000000000..726d133268
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/find/predicate-throws-then-closing-iterator-also-throws.js
@@ -0,0 +1,39 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.find
+description: >
+ Attempts to close iterator when predicate throws, but that throws
+info: |
+ %Iterator.prototype%.find ( predicate )
+
+features: [iterator-helpers]
+flags: []
+---*/
+let returnCalls = 0;
+
+class TestIterator extends Iterator {
+ next() {
+ return {
+ done: false,
+ value: 1,
+ };
+ }
+ return() {
+ ++returnCalls;
+ throw new Error();
+ }
+}
+
+let iterator = new TestIterator();
+
+assert.throws(Test262Error, function () {
+ iterator.find(() => {
+ throw new Test262Error();
+ });
+});
+
+assert.sameValue(returnCalls, 1);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/find/predicate-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/find/predicate-throws.js
new file mode 100644
index 0000000000..e655effbed
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/find/predicate-throws.js
@@ -0,0 +1,43 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.find
+description: >
+ Closes iterator and throws when predicate throws
+info: |
+ %Iterator.prototype%.find ( predicate )
+
+features: [iterator-helpers]
+flags: []
+---*/
+let returnCalls = 0;
+
+class TestIterator extends Iterator {
+ next() {
+ return {
+ done: false,
+ value: 1,
+ };
+ }
+ return() {
+ ++returnCalls;
+ return {};
+ }
+}
+
+let iterator = new TestIterator();
+
+let callbackCalls = 0;
+
+assert.throws(Test262Error, function () {
+ iterator.find(() => {
+ ++callbackCalls;
+ throw new Test262Error();
+ });
+});
+
+assert.sameValue(callbackCalls, 1);
+assert.sameValue(returnCalls, 1);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/find/prop-desc.js b/js/src/tests/test262/built-ins/Iterator/prototype/find/prop-desc.js
new file mode 100644
index 0000000000..3d0a15d401
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/find/prop-desc.js
@@ -0,0 +1,28 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.find
+description: >
+ Property descriptor of Iterator.prototype.find
+info: |
+ Iterator.prototype.find
+
+ * is the initial value of the Iterator.prototype.find property of the global object.
+
+ 17 ECMAScript Standard Built-in Objects
+
+ every other data property described in clauses 18 through 26 and in Annex B.2
+ has the attributes { [[Writable]]: true, [[Enumerable]]: false,
+ [[Configurable]]: true } unless otherwise specified.
+features: [globalThis, iterator-helpers]
+includes: [propertyHelper.js]
+---*/
+
+verifyProperty(Iterator.prototype, 'find', {
+ writable: true,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/find/proto.js b/js/src/tests/test262/built-ins/Iterator/prototype/find/proto.js
new file mode 100644
index 0000000000..d5d04dea33
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/find/proto.js
@@ -0,0 +1,14 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.find
+description: >
+ The value of the [[Prototype]] internal slot of Iterator.prototype.find is the
+ intrinsic object %Function%.
+features: [iterator-helpers]
+---*/
+
+assert.sameValue(Object.getPrototypeOf(Iterator.prototype.find), Function.prototype);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/find/shell.js b/js/src/tests/test262/built-ins/Iterator/prototype/find/shell.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/find/shell.js
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/find/this-non-callable-next.js b/js/src/tests/test262/built-ins/Iterator/prototype/find/this-non-callable-next.js
new file mode 100644
index 0000000000..d95f825f99
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/find/this-non-callable-next.js
@@ -0,0 +1,18 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.find
+description: >
+ Iterator.prototype.find throws TypeError when its this value is an object with a non-callable next
+info: |
+ %Iterator.prototype%.find ( predicate )
+
+features: [iterator-helpers]
+flags: []
+---*/
+assert.throws(TypeError, function () {
+ Iterator.prototype.find.call({ next: 0 }, () => true);
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/find/this-non-object.js b/js/src/tests/test262/built-ins/Iterator/prototype/find/this-non-object.js
new file mode 100644
index 0000000000..8af78e9d6c
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/find/this-non-object.js
@@ -0,0 +1,27 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.find
+description: >
+ Iterator.prototype.find throws TypeError when its this value is a non-object
+info: |
+ %Iterator.prototype%.find ( predicate )
+
+features: [iterator-helpers]
+flags: []
+---*/
+assert.throws(TypeError, function () {
+ Iterator.prototype.find.call(null, () => {});
+});
+
+Object.defineProperty(Number.prototype, 'next', {
+ get: function () {
+ throw new Test262Error();
+ },
+});
+assert.throws(TypeError, function () {
+ Iterator.prototype.find.call(0, () => {});
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/find/this-plain-iterator.js b/js/src/tests/test262/built-ins/Iterator/prototype/find/this-plain-iterator.js
new file mode 100644
index 0000000000..806cd5adce
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/find/this-plain-iterator.js
@@ -0,0 +1,33 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.find
+description: >
+ Iterator.prototype.find supports a this value that does not inherit from Iterator.prototype but implements the iterator protocol
+info: |
+ %Iterator.prototype%.find ( predicate )
+
+features: [iterator-helpers]
+flags: []
+---*/
+let iter = {
+ get next() {
+ let count = 3;
+ return function () {
+ --count;
+ return count >= 0 ? { done: false, value: count } : { done: true, value: undefined };
+ };
+ },
+};
+
+let predicateCalls = 0;
+let result = Iterator.prototype.find.call(iter, function (v) {
+ ++predicateCalls;
+ return v === 0;
+});
+
+assert.sameValue(result, 0);
+assert.sameValue(predicateCalls, 3);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/argument-effect-order.js b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/argument-effect-order.js
new file mode 100644
index 0000000000..6710db0923
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/argument-effect-order.js
@@ -0,0 +1,45 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.flatMap
+description: >
+ Arguments and this value are evaluated in the correct order
+info: |
+ %Iterator.prototype%.flatMap ( mapper )
+
+ 1. Let O be the this value.
+ 2. If O is not an Object, throw a TypeError exception.
+ 3. If IsCallable(mapper) is false, throw a TypeError exception.
+ 4. Let iterated be ? GetIteratorDirect(O).
+
+includes: [compareArray.js]
+features: [iterator-helpers]
+flags: []
+---*/
+let effects = [];
+
+assert.throws(TypeError, function () {
+ Iterator.prototype.flatMap.call(
+ {
+ get next() {
+ effects.push('get next');
+ return function () {
+ return { done: true, value: undefined };
+ };
+ },
+ },
+ {
+ valueOf() {
+ effects.push('valueOf mapper');
+ return function () {
+ return [];
+ };
+ },
+ }
+ );
+});
+
+assert.compareArray(effects, []);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/browser.js b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/browser.js
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/callable.js b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/callable.js
new file mode 100644
index 0000000000..c5d106e83d
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/callable.js
@@ -0,0 +1,16 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.flatMap
+description: >
+ Iterator.prototype.flatMap is callable
+features: [iterator-helpers]
+---*/
+function* g() {}
+Iterator.prototype.flatMap.call(g(), () => []);
+
+let iter = g();
+iter.flatMap(() => []);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/exhaustion-does-not-call-return.js b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/exhaustion-does-not-call-return.js
new file mode 100644
index 0000000000..93c4516b29
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/exhaustion-does-not-call-return.js
@@ -0,0 +1,37 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.flatMap
+description: >
+ Underlying iterator return is not called when result iterator is exhausted
+info: |
+ %Iterator.prototype%.flatMap ( mapper )
+
+features: [iterator-helpers]
+flags: []
+---*/
+function* g() {
+ yield 0;
+ yield 1;
+ yield 2;
+}
+
+class TestIterator extends Iterator {
+ get next() {
+ let n = g();
+ return function() {
+ return n.next();
+ };
+ }
+ return() {
+ throw new Test262Error();
+ }
+}
+
+let iterator = new TestIterator().flatMap(() => []);
+iterator.next();
+iterator.next();
+iterator.next();
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/flattens-iterable.js b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/flattens-iterable.js
new file mode 100644
index 0000000000..90a1f9bb5e
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/flattens-iterable.js
@@ -0,0 +1,33 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.flatMap
+description: >
+ Iterator.prototype.flatMap flattens iterables returned by the mapper
+info: |
+ %Iterator.prototype%.flatMap ( mapper )
+
+includes: [compareArray.js]
+features: [iterator-helpers]
+flags: []
+---*/
+
+function* g() {
+ yield 0;
+ yield 1;
+ yield 2;
+ yield 3;
+}
+
+let iter = g().flatMap((v, count) => {
+ let result = [];
+ for (let i = 0; i < v; ++i) {
+ result.push(v);
+ }
+ return result;
+});
+
+assert.compareArray(Array.from(iter), [1, 2, 2, 3, 3, 3]);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/flattens-iterator.js b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/flattens-iterator.js
new file mode 100644
index 0000000000..d7d118863a
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/flattens-iterator.js
@@ -0,0 +1,47 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.flatMap
+description: >
+ Iterator.prototype.flatMap flattens non-iterable iterators returned by the mapper
+info: |
+ %Iterator.prototype%.flatMap ( mapper )
+
+ 5.b.vi. Let innerIterator be Completion(GetIteratorFlattenable(mapped)).
+
+includes: [compareArray.js]
+features: [iterator-helpers]
+flags: []
+---*/
+
+function* g() {
+ yield 0;
+ yield 1;
+ yield 2;
+ yield 3;
+}
+
+let iter = g().flatMap((v, count) => {
+ let i = 0;
+ return {
+ next: function () {
+ if (i < v) {
+ ++i;
+ return {
+ value: v,
+ done: false,
+ };
+ } else {
+ return {
+ value: undefined,
+ done: true,
+ };
+ }
+ },
+ };
+});
+
+assert.compareArray(Array.from(iter), [1, 2, 2, 3, 3, 3]);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/flattens-only-depth-1.js b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/flattens-only-depth-1.js
new file mode 100644
index 0000000000..e493c46020
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/flattens-only-depth-1.js
@@ -0,0 +1,37 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.flatMap
+description: >
+ Iterator.prototype.flatMap does not flatten recursively
+info: |
+ %Iterator.prototype%.flatMap ( mapper )
+
+includes: [compareArray.js]
+features: [iterator-helpers]
+flags: []
+---*/
+
+let arr = [
+ {
+ [Symbol.iterator]: function () {
+ throw new Test262Error();
+ },
+ },
+ {
+ next: function () {
+ throw new Test262Error();
+ },
+ },
+];
+
+function* g() {
+ yield arr;
+}
+
+let iter = g().flatMap(v => v);
+
+assert.compareArray(Array.from(iter), arr);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/get-next-method-only-once.js b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/get-next-method-only-once.js
new file mode 100644
index 0000000000..7c74ffe05f
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/get-next-method-only-once.js
@@ -0,0 +1,44 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.flatMap
+description: >
+ Gets the next method from the underlying iterator only once
+info: |
+ %Iterator.prototype%.flatMap ( mapper )
+
+ 4. Let iterated be ? GetIteratorDirect(O).
+
+features: [iterator-helpers]
+flags: []
+---*/
+let nextGets = 0;
+let nextCalls = 0;
+
+class CountingIterator extends Iterator {
+ get next() {
+ ++nextGets;
+ let iter = (function* () {
+ for (let i = 1; i < 5; ++i) {
+ yield i;
+ }
+ })();
+ return function () {
+ ++nextCalls;
+ return iter.next();
+ };
+ }
+}
+
+let iterator = new CountingIterator();
+
+assert.sameValue(nextGets, 0);
+assert.sameValue(nextCalls, 0);
+
+for (const value of iterator.flatMap(() => []));
+
+assert.sameValue(nextGets, 1);
+assert.sameValue(nextCalls, 5);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/get-next-method-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/get-next-method-throws.js
new file mode 100644
index 0000000000..eeb650e4f5
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/get-next-method-throws.js
@@ -0,0 +1,28 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.flatMap
+description: >
+ Underlying iterator has throwing next getter
+info: |
+ %Iterator.prototype%.flatMap ( mapper )
+
+ 4. Let iterated be ? GetIteratorDirect(O).
+
+features: [iterator-helpers]
+flags: []
+---*/
+class ThrowingIterator extends Iterator {
+ get next() {
+ throw new Test262Error();
+ }
+}
+
+let iterator = new ThrowingIterator();
+
+assert.throws(Test262Error, function () {
+ iterator.flatMap(() => []);
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/get-return-method-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/get-return-method-throws.js
new file mode 100644
index 0000000000..62958ecac6
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/get-return-method-throws.js
@@ -0,0 +1,33 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.flatMap
+description: >
+ Underlying iterator return is throwing getter
+info: |
+ %Iterator.prototype%.flatMap ( mapper )
+
+features: [iterator-helpers]
+flags: []
+---*/
+class TestIterator extends Iterator {
+ next() {
+ return {
+ done: false,
+ value: 1,
+ };
+ }
+ get return() {
+ throw new Test262Error();
+ }
+}
+
+let iterator = new TestIterator().flatMap(x => [x]);
+iterator.next();
+
+assert.throws(Test262Error, function () {
+ iterator.return();
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/is-function.js b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/is-function.js
new file mode 100644
index 0000000000..7abaa964ac
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/is-function.js
@@ -0,0 +1,13 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.flatMap
+description: >
+ Iterator.prototype.flatMap is a built-in function
+features: [iterator-helpers]
+---*/
+
+assert.sameValue(typeof Iterator.prototype.flatMap, 'function');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/iterable-primitives-are-not-flattened.js b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/iterable-primitives-are-not-flattened.js
new file mode 100644
index 0000000000..96c62357ae
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/iterable-primitives-are-not-flattened.js
@@ -0,0 +1,40 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.flatMap
+description: >
+ Iterator.prototype.flatMap does not respect the iterability of any primitive
+info: |
+ %Iterator.prototype%.flatMap ( mapper )
+
+ 5.b.vi. Let innerIterator be Completion(GetIteratorFlattenable(mapped)).
+
+includes: [compareArray.js]
+features: [iterator-helpers]
+flags: []
+---*/
+
+function* g() {
+ yield 0;
+}
+
+Number.prototype[Symbol.iterator] = function* () {
+ let i = 0;
+ let target = this >>> 0;
+ while (i < target) {
+ yield i;
+ ++i;
+ }
+};
+
+assert.compareArray(Array.from(5), [0, 1, 2, 3, 4]);
+
+assert.throws(TypeError, function () {
+ for (let unused of g().flatMap(v => 5));
+});
+
+let iter = g().flatMap(v => new Number(5));
+assert.compareArray(Array.from(iter), [0, 1, 2, 3, 4]);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/iterable-to-iterator-fallback.js b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/iterable-to-iterator-fallback.js
new file mode 100644
index 0000000000..34d870c82f
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/iterable-to-iterator-fallback.js
@@ -0,0 +1,60 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.flatMap
+description: >
+ Iterator.prototype.flatMap falls back to treating mapper return values as iterators if the Symbol.iterator property is null/undefined
+info: |
+ %Iterator.prototype%.flatMap ( mapper )
+
+ 5.b.vi. Let innerIterator be Completion(GetIteratorFlattenable(mapped)).
+
+includes: [compareArray.js]
+features: [iterator-helpers]
+flags: []
+---*/
+
+function* g() {
+ yield 0;
+}
+
+function* h() {
+ yield 0;
+ yield 1;
+ yield 2;
+}
+
+let iter = g().flatMap(v => {
+ let n = h();
+ return {
+ [Symbol.iterator]: 0,
+ next: () => n.next(),
+ };
+});
+
+assert.throws(TypeError, function () {
+ iter.next();
+});
+
+iter = g().flatMap(v => {
+ let n = h();
+ return {
+ [Symbol.iterator]: null,
+ next: () => n.next(),
+ };
+});
+
+assert.compareArray(Array.from(iter), [0, 1, 2]);
+
+iter = g().flatMap(v => {
+ let n = h();
+ return {
+ [Symbol.iterator]: undefined,
+ next: () => n.next(),
+ };
+});
+
+assert.compareArray(Array.from(iter), [0, 1, 2]);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/iterator-already-exhausted.js b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/iterator-already-exhausted.js
new file mode 100644
index 0000000000..330b9312fc
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/iterator-already-exhausted.js
@@ -0,0 +1,25 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.flatMap
+description: >
+ Iterator.prototype.flatMap returns an empty iterator when the iterator has already been exhausted
+info: |
+ %Iterator.prototype%.flatMap ( mapper )
+
+features: [iterator-helpers]
+flags: []
+---*/
+let iterator = (function* () {})();
+
+let { value, done } = iterator.next();
+assert.sameValue(value, undefined);
+assert.sameValue(done, true);
+
+iterator = iterator.flatMap(x => [x]);
+({ value, done } = iterator.next());
+assert.sameValue(value, undefined);
+assert.sameValue(done, true);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/iterator-return-method-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/iterator-return-method-throws.js
new file mode 100644
index 0000000000..c3b78b5c26
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/iterator-return-method-throws.js
@@ -0,0 +1,32 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.flatMap
+description: >
+ Iterator has throwing return
+info: |
+ %Iterator.prototype%.flatMap ( mapper )
+
+features: [iterator-helpers]
+flags: []
+---*/
+class IteratorThrows extends Iterator {
+ next() {
+ return {
+ done: false,
+ value: 0,
+ };
+ }
+ return() {
+ throw new Test262Error();
+ }
+}
+
+let iterator = new IteratorThrows().flatMap(() => []);
+
+assert.throws(Test262Error, function () {
+ iterator.return();
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/length.js b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/length.js
new file mode 100644
index 0000000000..ab4a788c55
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/length.js
@@ -0,0 +1,25 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.flatMap
+description: >
+ Iterator.prototype.flatMap has a "length" property whose value is 1.
+info: |
+ ECMAScript Standard Built-in Objects
+
+ Unless otherwise specified, the length property of a built-in
+ Function object has the attributes { [[Writable]]: false, [[Enumerable]]:
+ false, [[Configurable]]: true }.
+features: [iterator-helpers]
+includes: [propertyHelper.js]
+---*/
+
+verifyProperty(Iterator.prototype.flatMap, 'length', {
+ value: 1,
+ writable: false,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/mapper-args.js b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/mapper-args.js
new file mode 100644
index 0000000000..52ce730739
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/mapper-args.js
@@ -0,0 +1,58 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.flatMap
+description: >
+ Iterator.prototype.flatMap mapper is passed the yielded value and a counter as arguments
+info: |
+ %Iterator.prototype%.flatMap ( mapper )
+
+ 5.b.iv. Let mapped be Completion(Call(mapper, undefined, « value, 𝔽(counter) »)).
+
+features: [iterator-helpers]
+flags: []
+---*/
+function* g() {
+ yield 'a';
+ yield 'b';
+ yield 'c';
+ yield 'd';
+ yield 'e';
+}
+
+let assertionCount = 0;
+let iter = g().flatMap((v, count) => {
+ switch (v) {
+ case 'a':
+ assert.sameValue(count, 0);
+ ++assertionCount;
+ return [0];
+ case 'b':
+ assert.sameValue(count, 1);
+ ++assertionCount;
+ return [0];
+ case 'c':
+ assert.sameValue(count, 2);
+ ++assertionCount;
+ return [1, 2];
+ case 'd':
+ assert.sameValue(count, 3);
+ ++assertionCount;
+ return [3, 4, 5];
+ case 'e':
+ assert.sameValue(count, 4);
+ ++assertionCount;
+ return [6, 7, 8, 9];
+ default:
+ throw new Error();
+ }
+});
+
+assert.sameValue(assertionCount, 0);
+
+for (let i of iter);
+
+assert.sameValue(assertionCount, 5);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/mapper-returns-closed-iterator.js b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/mapper-returns-closed-iterator.js
new file mode 100644
index 0000000000..016bcbb3c0
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/mapper-returns-closed-iterator.js
@@ -0,0 +1,33 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.flatMap
+description: >
+ Iterator.prototype.flatMap handles closed return values from mapper and does not try to close them again
+info: |
+ %Iterator.prototype%.flatMap ( mapper )
+
+features: [iterator-helpers]
+flags: []
+---*/
+
+function* g() {
+ yield 0;
+ yield 1;
+ yield 2;
+}
+
+let closed = g();
+closed.return();
+closed.return = function () {
+ throw new Test262Error();
+};
+
+let iter = g().flatMap(v => closed);
+let { value, done } = iter.next();
+
+assert.sameValue(value, undefined);
+assert.sameValue(done, true);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/mapper-returns-non-object.js b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/mapper-returns-non-object.js
new file mode 100644
index 0000000000..cef235e282
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/mapper-returns-non-object.js
@@ -0,0 +1,37 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.flatMap
+description: >
+ Iterator.prototype.flatMap mapper return value must be an object
+info: |
+ %Iterator.prototype%.flatMap ( mapper )
+
+features: [iterator-helpers]
+flags: []
+---*/
+function* g() {
+ yield 0;
+ yield 0;
+ yield 0;
+ yield 1;
+}
+
+let iter = g();
+
+let mapperCalls = 0;
+iter = iter.flatMap(v => {
+ ++mapperCalls;
+ return null;
+});
+
+assert.sameValue(mapperCalls, 0);
+
+assert.throws(TypeError, function () {
+ iter.next();
+});
+
+assert.sameValue(mapperCalls, 1);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/mapper-this.js b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/mapper-this.js
new file mode 100644
index 0000000000..58a93d864d
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/mapper-this.js
@@ -0,0 +1,36 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.flatMap
+description: >
+ Iterator.prototype.flatMap mapper this value is undefined
+info: |
+ %Iterator.prototype%.flatMap ( mapper )
+
+ 5.b.iv. Let mapped be Completion(Call(mapper, undefined, « value, 𝔽(counter) »)).
+
+features: [iterator-helpers]
+flags: []
+---*/
+function* g() {
+ yield 0;
+}
+
+let iter = g();
+
+let expectedThis = function () {
+ return this;
+}.call(undefined);
+
+let assertionCount = 0;
+iter = iter.flatMap(function (v, count) {
+ assert.sameValue(this, expectedThis);
+ ++assertionCount;
+ return [v];
+});
+
+iter.next();
+assert.sameValue(assertionCount, 1);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/mapper-throws-then-closing-iterator-also-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/mapper-throws-then-closing-iterator-also-throws.js
new file mode 100644
index 0000000000..584939747a
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/mapper-throws-then-closing-iterator-also-throws.js
@@ -0,0 +1,43 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.flatMap
+description: >
+ Attempts to close iterator when mapper throws, but that throws
+info: |
+ %Iterator.prototype%.flatMap ( mapper )
+
+ 5.b.v. IfAbruptCloseIterator(mapped, iterated).
+
+features: [iterator-helpers]
+flags: []
+---*/
+let returnCalls = 0;
+
+class TestIterator extends Iterator {
+ next() {
+ return {
+ done: false,
+ value: 1,
+ };
+ }
+ return() {
+ ++returnCalls;
+ throw new Error();
+ }
+}
+
+let iterator = new TestIterator().flatMap(() => {
+ throw new Test262Error();
+});
+
+assert.sameValue(returnCalls, 0);
+
+assert.throws(Test262Error, function () {
+ iterator.next();
+});
+
+assert.sameValue(returnCalls, 1);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/mapper-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/mapper-throws.js
new file mode 100644
index 0000000000..48b367f427
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/mapper-throws.js
@@ -0,0 +1,44 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.flatMap
+description: >
+ Closes iterator and throws when mapper throws
+info: |
+ %Iterator.prototype%.flatMap ( mapper )
+
+ 5.b.v. IfAbruptCloseIterator(mapped, iterated).
+
+features: [iterator-helpers]
+flags: []
+---*/
+let returnCalls = 0;
+
+class TestIterator extends Iterator {
+ next() {
+ return {
+ done: false,
+ value: 1,
+ };
+ }
+ return() {
+ ++returnCalls;
+ return {};
+ }
+}
+
+let callbackCalls = 0;
+let iterator = new TestIterator().flatMap(() => {
+ ++callbackCalls;
+ throw new Test262Error();
+});
+
+assert.throws(Test262Error, function () {
+ iterator.next();
+});
+
+assert.sameValue(callbackCalls, 1);
+assert.sameValue(returnCalls, 1);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/name.js b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/name.js
new file mode 100644
index 0000000000..30fb1fc2cb
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/name.js
@@ -0,0 +1,32 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.flatMap
+description: >
+ The "name" property of Iterator.prototype.flatMap
+info: |
+ 17 ECMAScript Standard Built-in Objects
+
+ Every built-in Function object, including constructors, that is not
+ identified as an anonymous function has a name property whose value is a
+ String. Unless otherwise specified, this value is the name that is given to
+ the function in this specification.
+
+ ...
+
+ Unless otherwise specified, the name property of a built-in Function
+ object, if it exists, has the attributes { [[Writable]]: false,
+ [[Enumerable]]: false, [[Configurable]]: true }.
+features: [iterator-helpers]
+includes: [propertyHelper.js]
+---*/
+
+verifyProperty(Iterator.prototype.flatMap, 'name', {
+ value: 'flatMap',
+ writable: false,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/next-method-returns-non-object.js b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/next-method-returns-non-object.js
new file mode 100644
index 0000000000..2f32c1c21a
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/next-method-returns-non-object.js
@@ -0,0 +1,26 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.flatMap
+description: >
+ Underlying iterator next returns non-object
+info: |
+ %Iterator.prototype%.flatMap ( mapper )
+
+features: [iterator-helpers]
+flags: []
+---*/
+class NonObjectIterator extends Iterator {
+ next() {
+ return null;
+ }
+}
+
+let iterator = new NonObjectIterator().flatMap(x => [x]);
+
+assert.throws(TypeError, function () {
+ iterator.next();
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/next-method-returns-throwing-done.js b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/next-method-returns-throwing-done.js
new file mode 100644
index 0000000000..62fe294ed0
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/next-method-returns-throwing-done.js
@@ -0,0 +1,34 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.flatMap
+description: >
+ Underlying iterator next returns object with throwing done getter
+info: |
+ %Iterator.prototype%.flatMap ( mapper )
+
+features: [iterator-helpers]
+flags: []
+---*/
+class ThrowingIterator extends Iterator {
+ next() {
+ return {
+ get done() {
+ throw new Test262Error();
+ },
+ value: 1,
+ };
+ }
+ return() {
+ throw new Error();
+ }
+}
+
+let iterator = new ThrowingIterator().flatMap(x => [x]);
+
+assert.throws(Test262Error, function () {
+ iterator.next();
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/next-method-returns-throwing-value-done.js b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/next-method-returns-throwing-value-done.js
new file mode 100644
index 0000000000..0a7a96a199
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/next-method-returns-throwing-value-done.js
@@ -0,0 +1,31 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.flatMap
+description: >
+ Underlying iterator next returns object with throwing value getter, but is already done
+info: |
+ %Iterator.prototype%.flatMap ( mapper )
+
+features: [iterator-helpers]
+flags: []
+---*/
+class ThrowingIterator extends Iterator {
+ next() {
+ return {
+ done: true,
+ get value() {
+ throw new Test262Error();
+ },
+ };
+ }
+ return() {
+ throw new Error();
+ }
+}
+
+let iterator = new ThrowingIterator().flatMap(x => [x]);
+iterator.next();
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/next-method-returns-throwing-value.js b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/next-method-returns-throwing-value.js
new file mode 100644
index 0000000000..549adb2967
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/next-method-returns-throwing-value.js
@@ -0,0 +1,34 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.flatMap
+description: >
+ Underlying iterator next returns object with throwing value getter
+info: |
+ %Iterator.prototype%.flatMap ( mapper )
+
+features: [iterator-helpers]
+flags: []
+---*/
+class ThrowingIterator extends Iterator {
+ next() {
+ return {
+ done: false,
+ get value() {
+ throw new Test262Error();
+ },
+ };
+ }
+ return() {
+ throw new Error();
+ }
+}
+
+let iterator = new ThrowingIterator().flatMap(x => [x]);
+
+assert.throws(Test262Error, function () {
+ iterator.next();
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/next-method-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/next-method-throws.js
new file mode 100644
index 0000000000..2ba2838c2f
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/next-method-throws.js
@@ -0,0 +1,26 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.flatMap
+description: >
+ Underlying iterator has throwing next method
+info: |
+ %Iterator.prototype%.flatMap ( mapper )
+
+features: [iterator-helpers]
+flags: []
+---*/
+class ThrowingIterator extends Iterator {
+ next() {
+ throw new Test262Error();
+ }
+}
+
+let iterator = new ThrowingIterator().flatMap(x => [x]);
+
+assert.throws(Test262Error, function () {
+ iterator.next();
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/non-callable-mapper.js b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/non-callable-mapper.js
new file mode 100644
index 0000000000..93cf478aeb
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/non-callable-mapper.js
@@ -0,0 +1,23 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.flatMap
+description: >
+ Iterator.prototype.flatMap expects to be called with a callable argument.
+info: |
+ %Iterator.prototype%.flatMap ( mapper )
+
+ 3. If IsCallable(mapper) is false, throw a TypeError exception.
+
+features: [iterator-helpers]
+flags: []
+---*/
+let nonCallable = {};
+let iterator = (function* () {})();
+
+assert.throws(TypeError, function () {
+ iterator.flatMap(nonCallable);
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/non-constructible.js b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/non-constructible.js
new file mode 100644
index 0000000000..e382741aff
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/non-constructible.js
@@ -0,0 +1,31 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.flatMap
+description: >
+ Iterator.prototype.flatMap is not constructible.
+
+ Built-in function objects that are not identified as constructors do not implement the [[Construct]] internal method unless otherwise specified in the description of a particular function.
+features: [iterator-helpers]
+---*/
+function* g() {}
+let iter = g();
+
+assert.throws(TypeError, () => {
+ new iter.flatMap();
+});
+
+assert.throws(TypeError, () => {
+ new iter.flatMap(() => []);
+});
+
+assert.throws(TypeError, () => {
+ new Iterator.prototype.flatMap(() => []);
+});
+
+assert.throws(TypeError, () => {
+ new class extends Iterator {}.flatMap(() => []);
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/prop-desc.js b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/prop-desc.js
new file mode 100644
index 0000000000..b36791590d
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/prop-desc.js
@@ -0,0 +1,28 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.flatMap
+description: >
+ Property descriptor of Iterator.prototype.flatMap
+info: |
+ Iterator.prototype.flatMap
+
+ * is the initial value of the Iterator.prototype.flatMap property of the global object.
+
+ 17 ECMAScript Standard Built-in Objects
+
+ Every other data property described in clauses 18 through 26 and in Annex B.2
+ has the attributes { [[Writable]]: true, [[Enumerable]]: false,
+ [[Configurable]]: true } unless otherwise specified.
+features: [globalThis, iterator-helpers]
+includes: [propertyHelper.js]
+---*/
+
+verifyProperty(Iterator.prototype, 'flatMap', {
+ writable: true,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/proto.js b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/proto.js
new file mode 100644
index 0000000000..da49133d6c
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/proto.js
@@ -0,0 +1,14 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.flatMap
+description: >
+ The value of the [[Prototype]] internal slot of Iterator.prototype.flatMap is the
+ intrinsic object %FunctionPrototype%.
+features: [iterator-helpers]
+---*/
+
+assert.sameValue(Object.getPrototypeOf(Iterator.prototype.flatMap), Function.prototype);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/result-is-iterator.js b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/result-is-iterator.js
new file mode 100644
index 0000000000..9fd8df791c
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/result-is-iterator.js
@@ -0,0 +1,17 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.flatMap
+description: >
+ The value of the [[Prototype]] internal slot of the return value of Iterator.prototype.flatMap is the
+ intrinsic object %IteratorHelperPrototype%.
+features: [iterator-helpers]
+---*/
+
+assert(
+ (function* () {})().flatMap(() => []) instanceof Iterator,
+ 'function*(){}().flatMap(() => []) must return an Iterator'
+);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/return-is-forwarded-to-mapper-result.js b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/return-is-forwarded-to-mapper-result.js
new file mode 100644
index 0000000000..a00b5eacca
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/return-is-forwarded-to-mapper-result.js
@@ -0,0 +1,48 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.flatMap
+description: >
+ Mapper returned iterator return is called when result iterator is closed
+info: |
+ %Iterator.prototype%.flatMap ( mapper )
+
+features: [iterator-helpers]
+flags: []
+---*/
+let returnCount = 0;
+
+function* g() {
+ yield 0;
+}
+
+let iter = g().flatMap(v => ({
+ next() {
+ return {
+ done: false,
+ value: 1,
+ };
+ },
+ return() {
+ ++returnCount;
+ return {};
+ },
+}));
+
+assert.sameValue(returnCount, 0);
+
+let { done, value } = iter.next();
+
+assert.sameValue(done, false);
+assert.sameValue(value, 1);
+
+assert.sameValue(returnCount, 0);
+
+iter.return();
+assert.sameValue(returnCount, 1);
+
+iter.return();
+assert.sameValue(returnCount, 1);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/return-is-forwarded-to-underlying-iterator.js b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/return-is-forwarded-to-underlying-iterator.js
new file mode 100644
index 0000000000..7681a806c8
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/return-is-forwarded-to-underlying-iterator.js
@@ -0,0 +1,36 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.flatMap
+description: >
+ Underlying iterator return is called when result iterator is closed
+info: |
+ %Iterator.prototype%.flatMap ( mapper )
+
+features: [iterator-helpers]
+flags: []
+---*/
+let returnCount = 0;
+
+class TestIterator extends Iterator {
+ next() {
+ return {
+ done: false,
+ value: 1,
+ };
+ }
+ return() {
+ ++returnCount;
+ return {};
+ }
+}
+
+let iterator = new TestIterator().flatMap(() => []);
+assert.sameValue(returnCount, 0);
+iterator.return();
+assert.sameValue(returnCount, 1);
+iterator.return();
+assert.sameValue(returnCount, 1);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/return-is-not-forwarded-after-exhaustion.js b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/return-is-not-forwarded-after-exhaustion.js
new file mode 100644
index 0000000000..418bc1f8d1
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/return-is-not-forwarded-after-exhaustion.js
@@ -0,0 +1,49 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.flatMap
+description: >
+ Underlying iterator return is not called after result iterator observes that underlying iterator is exhausted
+info: |
+ %Iterator.prototype%.flatMap ( mapper )
+
+features: [iterator-helpers]
+flags: []
+---*/
+let returnCount = 0;
+
+class TestIterator extends Iterator {
+ next() {
+ return {
+ done: true,
+ value: undefined,
+ };
+ }
+ return() {
+ throw new Test262Error();
+ }
+}
+
+let iterator = new TestIterator().flatMap(x => [x]);
+assert.throws(Test262Error, function () {
+ iterator.return();
+});
+iterator.next();
+iterator.return();
+
+iterator = new TestIterator().flatMap(x => [x]);
+iterator.next();
+iterator.return();
+
+iterator = new TestIterator()
+ .flatMap(x => [x])
+ .flatMap(x => [x])
+ .flatMap(x => [x]);
+assert.throws(Test262Error, function () {
+ iterator.return();
+});
+iterator.next();
+iterator.return();
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/shell.js b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/shell.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/shell.js
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/strings-are-not-flattened.js b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/strings-are-not-flattened.js
new file mode 100644
index 0000000000..31aaaf4cfd
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/strings-are-not-flattened.js
@@ -0,0 +1,29 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.flatMap
+description: >
+ Iterator.prototype.flatMap does not respect the iterability of primitive strings
+info: |
+ %Iterator.prototype%.flatMap ( mapper )
+
+ 5.b.vi. Let innerIterator be Completion(GetIteratorFlattenable(mapped)).
+
+includes: [compareArray.js]
+features: [iterator-helpers]
+flags: []
+---*/
+
+function* g() {
+ yield 0;
+}
+
+assert.throws(TypeError, function () {
+ for (let unused of g().flatMap(v => 'string'));
+});
+
+let iter = g().flatMap(v => new String('string'));
+assert.compareArray(Array.from(iter), ['s', 't', 'r', 'i', 'n', 'g']);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/this-non-callable-next.js b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/this-non-callable-next.js
new file mode 100644
index 0000000000..4161d1081e
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/this-non-callable-next.js
@@ -0,0 +1,20 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.flatMap
+description: >
+ Iterator.prototype.flatMap throws TypeError when its this value is an object with a non-callable next
+info: |
+ %Iterator.prototype%.flatMap ( mapper )
+
+features: [iterator-helpers]
+flags: []
+---*/
+let iter = Iterator.prototype.flatMap.call({ next: 0 }, () => []);
+
+assert.throws(TypeError, function () {
+ iter.next();
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/this-non-object.js b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/this-non-object.js
new file mode 100644
index 0000000000..d0eaae2dfb
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/this-non-object.js
@@ -0,0 +1,29 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.flatMap
+description: >
+ Iterator.prototype.flatMap throws TypeError when its this value is a non-object
+info: |
+ %Iterator.prototype%.flatMap ( mapper )
+
+ 2. If O is not an Object, throw a TypeError exception.
+
+features: [iterator-helpers]
+flags: []
+---*/
+assert.throws(TypeError, function () {
+ Iterator.prototype.flatMap.call(null, () => []);
+});
+
+Object.defineProperty(Number.prototype, 'next', {
+ get: function () {
+ throw new Test262Error();
+ },
+});
+assert.throws(TypeError, function () {
+ Iterator.prototype.flatMap.call(0, () => []);
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/this-plain-iterator.js b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/this-plain-iterator.js
new file mode 100644
index 0000000000..405ba975f0
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/this-plain-iterator.js
@@ -0,0 +1,34 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.flatMap
+description: >
+ Iterator.prototype.flatMap supports a this value that does not inherit from Iterator.prototype but implements the iterator protocol
+info: |
+ %Iterator.prototype%.flatMap ( mapper )
+
+features: [iterator-helpers]
+flags: []
+---*/
+let iter = {
+ get next() {
+ let count = 3;
+ return function () {
+ --count;
+ return count >= 0 ? { done: false, value: count } : { done: true, value: undefined };
+ };
+ },
+};
+
+let mapperCalls = 0;
+iter = Iterator.prototype.flatMap.call(iter, function (v) {
+ ++mapperCalls;
+ return [v];
+});
+
+for (let e of iter);
+
+assert.sameValue(mapperCalls, 3);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/throws-typeerror-when-generator-is-running.js b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/throws-typeerror-when-generator-is-running.js
new file mode 100644
index 0000000000..2d404dd2e7
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/throws-typeerror-when-generator-is-running.js
@@ -0,0 +1,49 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 André Bargull. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.flatmap
+description: >
+ Throws a TypeError when the closure generator is already running.
+info: |
+ %IteratorHelperPrototype%.next ( )
+ 1. Return ? GeneratorResume(this value, undefined, "Iterator Helper").
+
+ 27.5.3.3 GeneratorResume ( generator, value, generatorBrand )
+ 1. Let state be ? GeneratorValidate(generator, generatorBrand).
+ ...
+
+ 27.5.3.2 GeneratorValidate ( generator, generatorBrand )
+ ...
+ 6. If state is executing, throw a TypeError exception.
+ ...
+
+features: [iterator-helpers]
+---*/
+
+var loopCount = 0;
+
+function* g() {
+ while (true) {
+ loopCount++;
+ yield;
+ }
+}
+
+var enterCount = 0;
+
+function mapper() {
+ enterCount++;
+ iter.next();
+}
+
+var iter = g().flatMap(mapper);
+
+assert.throws(TypeError, function() {
+ iter.next();
+});
+
+assert.sameValue(loopCount, 1);
+assert.sameValue(enterCount, 1);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/underlying-iterator-advanced-in-parallel.js b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/underlying-iterator-advanced-in-parallel.js
new file mode 100644
index 0000000000..cc5b401319
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/underlying-iterator-advanced-in-parallel.js
@@ -0,0 +1,45 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.flatMap
+description: >
+ Underlying iterator is advanced after calling flatMap
+info: |
+ %Iterator.prototype%.flatMap ( mapper )
+
+features: [iterator-helpers]
+flags: []
+---*/
+let iterator = (function* () {
+ for (let i = 0; i < 5; ++i) {
+ yield i;
+ }
+})();
+
+let mapped = iterator.flatMap(x => [x]);
+
+let { value, done } = iterator.next();
+
+assert.sameValue(value, 0);
+assert.sameValue(done, false);
+
+iterator.next();
+iterator.next();
+
+({ value, done } = mapped.next());
+
+assert.sameValue(value, 3);
+assert.sameValue(done, false);
+
+({ value, done } = mapped.next());
+
+assert.sameValue(value, 4);
+assert.sameValue(done, false);
+
+({ value, done } = mapped.next());
+
+assert.sameValue(value, undefined);
+assert.sameValue(done, true);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/underlying-iterator-closed-in-parallel.js b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/underlying-iterator-closed-in-parallel.js
new file mode 100644
index 0000000000..e20c48c844
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/underlying-iterator-closed-in-parallel.js
@@ -0,0 +1,29 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.flatMap
+description: >
+ Underlying iterator is closed after calling flatMap
+info: |
+ %Iterator.prototype%.flatMap ( mapper )
+
+features: [iterator-helpers]
+flags: []
+---*/
+let iterator = (function* () {
+ for (let i = 0; i < 5; ++i) {
+ yield i;
+ }
+})();
+
+let mapped = iterator.flatMap(x => [x]);
+
+iterator.return();
+
+let { value, done } = mapped.next();
+
+assert.sameValue(value, undefined);
+assert.sameValue(done, true);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/underlying-iterator-closed.js b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/underlying-iterator-closed.js
new file mode 100644
index 0000000000..ab3e369a43
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/underlying-iterator-closed.js
@@ -0,0 +1,29 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.flatMap
+description: >
+ Underlying iterator is closed before calling flatMap
+info: |
+ %Iterator.prototype%.flatMap ( mapper )
+
+features: [iterator-helpers]
+flags: []
+---*/
+let iterator = (function* () {
+ for (let i = 0; i < 5; ++i) {
+ yield i;
+ }
+})();
+
+iterator.return();
+
+let mapped = iterator.flatMap(() => []);
+
+let { value, done } = mapped.next();
+
+assert.sameValue(value, undefined);
+assert.sameValue(done, true);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/forEach/argument-effect-order.js b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/argument-effect-order.js
new file mode 100644
index 0000000000..4f44924efa
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/argument-effect-order.js
@@ -0,0 +1,38 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.forEach
+description: >
+ Arguments and this value are evaluated in the correct order
+info: |
+ %Iterator.prototype%.forEach ( fn )
+
+ 1. Let O be the this value.
+ 2. If O is not an Object, throw a TypeError exception.
+ 3. If IsCallable(fn) is false, throw a TypeError exception.
+ 4. Let iterated be ? GetIteratorDirect(O).
+
+includes: [compareArray.js]
+features: [iterator-helpers]
+flags: []
+---*/
+let effects = [];
+
+assert.throws(TypeError, function () {
+ Iterator.prototype.forEach.call(
+ {
+ get next() {
+ effects.push('get next');
+ return function () {
+ return { done: true, value: undefined };
+ };
+ },
+ },
+ null
+ );
+});
+
+assert.compareArray(effects, []);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/forEach/browser.js b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/browser.js
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/forEach/callable.js b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/callable.js
new file mode 100644
index 0000000000..91c4030aed
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/callable.js
@@ -0,0 +1,16 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.forEach
+description: >
+ Iterator.prototype.forEach is callable
+features: [iterator-helpers]
+---*/
+function* g() {}
+Iterator.prototype.forEach.call(g(), () => {});
+
+let iter = g();
+iter.forEach(() => {});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/forEach/fn-args.js b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/fn-args.js
new file mode 100644
index 0000000000..951ad07e27
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/fn-args.js
@@ -0,0 +1,43 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.forEach
+description: >
+ Iterator.prototype.forEach fn is passed the yielded value and a counter as arguments
+info: |
+ %Iterator.prototype%.forEach ( fn )
+
+features: [iterator-helpers]
+flags: []
+---*/
+function* g() {
+ yield 'a';
+ yield 'b';
+ yield 'c';
+}
+
+let iter = g();
+
+let assertionCount = 0;
+let result = iter.forEach((v, count) => {
+ switch (v) {
+ case 'a':
+ assert.sameValue(count, 0);
+ break;
+ case 'b':
+ assert.sameValue(count, 1);
+ break;
+ case 'c':
+ assert.sameValue(count, 2);
+ break;
+ default:
+ throw new Error();
+ }
+ ++assertionCount;
+});
+
+assert.sameValue(result, undefined);
+assert.sameValue(assertionCount, 3);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/forEach/fn-called-for-each-yielded-value.js b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/fn-called-for-each-yielded-value.js
new file mode 100644
index 0000000000..774f6e76c9
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/fn-called-for-each-yielded-value.js
@@ -0,0 +1,31 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.forEach
+description: >
+ Iterator.prototype.forEach calls fn once for each yielded value, in order
+info: |
+ %Iterator.prototype%.forEach ( fn )
+
+ 6.d. Let result be Completion(Call(fn, undefined, « value, 𝔽(counter) »)).
+
+includes: [compareArray.js]
+features: [iterator-helpers]
+flags: []
+---*/
+let effects = [];
+
+function* g() {
+ yield 'a';
+ yield 'b';
+ yield 'c';
+}
+
+g().forEach((value, count) => {
+ effects.push(value, count);
+});
+
+assert.compareArray(effects, ['a', 0, 'b', 1, 'c', 2]);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/forEach/fn-this.js b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/fn-this.js
new file mode 100644
index 0000000000..a43b5f0b38
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/fn-this.js
@@ -0,0 +1,33 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.forEach
+description: >
+ Iterator.prototype.forEach fn this value is undefined
+info: |
+ %Iterator.prototype%.forEach ( fn )
+
+features: [iterator-helpers]
+flags: []
+---*/
+function* g() {
+ yield 0;
+}
+
+let iter = g();
+
+let expectedThis = function () {
+ return this;
+}.call(undefined);
+
+let assertionCount = 0;
+let result = iter.forEach(function (v, count) {
+ assert.sameValue(this, expectedThis);
+ ++assertionCount;
+});
+
+assert.sameValue(result, undefined);
+assert.sameValue(assertionCount, 1);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/forEach/fn-throws-then-closing-iterator-also-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/fn-throws-then-closing-iterator-also-throws.js
new file mode 100644
index 0000000000..972f61c93e
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/fn-throws-then-closing-iterator-also-throws.js
@@ -0,0 +1,39 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.forEach
+description: >
+ Attempts to close iterator when fn throws, but that throws
+info: |
+ %Iterator.prototype%.forEach ( fn )
+
+features: [iterator-helpers]
+flags: []
+---*/
+let returnCalls = 0;
+
+class TestIterator extends Iterator {
+ next() {
+ return {
+ done: false,
+ value: 1,
+ };
+ }
+ return() {
+ ++returnCalls;
+ throw new Error();
+ }
+}
+
+let iterator = new TestIterator();
+
+assert.throws(Test262Error, function () {
+ iterator.forEach(() => {
+ throw new Test262Error();
+ });
+});
+
+assert.sameValue(returnCalls, 1);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/forEach/fn-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/fn-throws.js
new file mode 100644
index 0000000000..c7e1fe638d
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/fn-throws.js
@@ -0,0 +1,43 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.forEach
+description: >
+ Closes iterator and throws when fn throws
+info: |
+ %Iterator.prototype%.forEach ( fn )
+
+features: [iterator-helpers]
+flags: []
+---*/
+let returnCalls = 0;
+
+class TestIterator extends Iterator {
+ next() {
+ return {
+ done: false,
+ value: 1,
+ };
+ }
+ return() {
+ ++returnCalls;
+ return {};
+ }
+}
+
+let iterator = new TestIterator();
+
+let callbackCalls = 0;
+
+assert.throws(Test262Error, function () {
+ iterator.forEach(() => {
+ ++callbackCalls;
+ throw new Test262Error();
+ });
+});
+
+assert.sameValue(callbackCalls, 1);
+assert.sameValue(returnCalls, 1);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/forEach/get-next-method-only-once.js b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/get-next-method-only-once.js
new file mode 100644
index 0000000000..06e64bf63d
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/get-next-method-only-once.js
@@ -0,0 +1,39 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.forEach
+description: >
+ Gets the next method from the iterator only once
+info: |
+ %Iterator.prototype%.forEach ( fn )
+
+features: [iterator-helpers]
+flags: []
+---*/
+let nextGets = 0;
+
+class TestIterator extends Iterator {
+ get next() {
+ ++nextGets;
+ let counter = 5;
+ return function () {
+ if (counter < 0) {
+ return { done: true, value: undefined };
+ } else {
+ return { done: false, value: --counter };
+ }
+ };
+ }
+}
+
+let iterator = new TestIterator();
+
+assert.sameValue(nextGets, 0);
+assert.sameValue(
+ iterator.forEach(() => {}),
+ undefined
+);
+assert.sameValue(nextGets, 1);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/forEach/get-next-method-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/get-next-method-throws.js
new file mode 100644
index 0000000000..dcb1557bff
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/get-next-method-throws.js
@@ -0,0 +1,26 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.forEach
+description: >
+ Iterator has throwing next getter
+info: |
+ %Iterator.prototype%.forEach ( fn )
+
+features: [iterator-helpers]
+flags: []
+---*/
+class IteratorThrows extends Iterator {
+ get next() {
+ throw new Test262Error();
+ }
+}
+
+let iterator = new IteratorThrows();
+
+assert.throws(Test262Error, function () {
+ iterator.forEach(() => {});
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/forEach/is-function.js b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/is-function.js
new file mode 100644
index 0000000000..5a716cf888
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/is-function.js
@@ -0,0 +1,13 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.forEach
+description: >
+ Iterator.prototype.forEach is a built-in function
+features: [iterator-helpers]
+---*/
+
+assert.sameValue(typeof Iterator.prototype.forEach, 'function');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/forEach/iterator-already-exhausted.js b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/iterator-already-exhausted.js
new file mode 100644
index 0000000000..455d6b8474
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/iterator-already-exhausted.js
@@ -0,0 +1,25 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.forEach
+description: >
+ Iterator.prototype.forEach returns immediately when the iterator has already been exhausted
+info: |
+ %Iterator.prototype%.forEach ( fn )
+
+features: [iterator-helpers]
+flags: []
+---*/
+let iterator = (function* () {})();
+
+let { value, done } = iterator.next();
+assert.sameValue(value, undefined);
+assert.sameValue(done, true);
+
+let result = iterator.forEach(() => {
+ throw new Error();
+});
+assert.sameValue(result, undefined);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/forEach/length.js b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/length.js
new file mode 100644
index 0000000000..b4addf5fbb
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/length.js
@@ -0,0 +1,25 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.forEach
+description: >
+ Iterator.prototype.forEach has a "length" property whose value is 1.
+info: |
+ ECMAScript Standard Built-in Objects
+
+ Unless otherwise specified, the length property of a built-in
+ Function object has the attributes { [[Writable]]: false, [[Enumerable]]:
+ false, [[Configurable]]: true }.
+features: [iterator-helpers]
+includes: [propertyHelper.js]
+---*/
+
+verifyProperty(Iterator.prototype.forEach, 'length', {
+ value: 1,
+ writable: false,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/forEach/name.js b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/name.js
new file mode 100644
index 0000000000..caeae259e0
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/name.js
@@ -0,0 +1,32 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.forEach
+description: >
+ The "name" property of Iterator.prototype.forEach
+info: |
+ 17 ECMAScript Standard Built-in Objects
+
+ every built-in Function object, including constructors, that is not
+ identified as an anonymous function has a name property whose value is a
+ String. Unless otherwise specified, this value is the name that is given to
+ the function in this specification.
+
+ ...
+
+ Unless otherwise specified, the name property of a built-in Function
+ object, if it exists, has the attributes { [[Writable]]: false,
+ [[Enumerable]]: false, [[Configurable]]: true }.
+features: [iterator-helpers]
+includes: [propertyHelper.js]
+---*/
+
+verifyProperty(Iterator.prototype.forEach, 'name', {
+ value: 'forEach',
+ writable: false,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/forEach/next-method-returns-non-object.js b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/next-method-returns-non-object.js
new file mode 100644
index 0000000000..297adffeab
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/next-method-returns-non-object.js
@@ -0,0 +1,26 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.forEach
+description: >
+ Underlying iterator next returns non-object
+info: |
+ %Iterator.prototype%.forEach ( fn )
+
+features: [iterator-helpers]
+flags: []
+---*/
+class NonObjectIterator extends Iterator {
+ next() {
+ return null;
+ }
+}
+
+let iterator = new NonObjectIterator();
+
+assert.throws(TypeError, function () {
+ iterator.forEach(() => {});
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/forEach/next-method-returns-throwing-done.js b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/next-method-returns-throwing-done.js
new file mode 100644
index 0000000000..adec874a7c
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/next-method-returns-throwing-done.js
@@ -0,0 +1,34 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.forEach
+description: >
+ Underlying iterator next returns object with throwing done getter
+info: |
+ %Iterator.prototype%.forEach ( fn )
+
+features: [iterator-helpers]
+flags: []
+---*/
+class ThrowingIterator extends Iterator {
+ next() {
+ return {
+ get done() {
+ throw new Test262Error();
+ },
+ value: 1,
+ };
+ }
+ return() {
+ throw new Error();
+ }
+}
+
+let iterator = new ThrowingIterator();
+
+assert.throws(Test262Error, function () {
+ iterator.forEach(() => {});
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/forEach/next-method-returns-throwing-value-done.js b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/next-method-returns-throwing-value-done.js
new file mode 100644
index 0000000000..403e03ae5d
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/next-method-returns-throwing-value-done.js
@@ -0,0 +1,31 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.forEach
+description: >
+ Underlying iterator next returns object with throwing value getter, but is already done
+info: |
+ %Iterator.prototype%.forEach ( fn )
+
+features: [iterator-helpers]
+flags: []
+---*/
+class ThrowingIterator extends Iterator {
+ next() {
+ return {
+ done: true,
+ get value() {
+ throw new Test262Error();
+ },
+ };
+ }
+ return() {
+ throw new Error();
+ }
+}
+
+let iterator = new ThrowingIterator();
+iterator.forEach(() => {});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/forEach/next-method-returns-throwing-value.js b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/next-method-returns-throwing-value.js
new file mode 100644
index 0000000000..07d3061bdc
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/next-method-returns-throwing-value.js
@@ -0,0 +1,34 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.forEach
+description: >
+ Underlying iterator next returns object with throwing value getter
+info: |
+ %Iterator.prototype%.forEach ( fn )
+
+features: [iterator-helpers]
+flags: []
+---*/
+class ThrowingIterator extends Iterator {
+ next() {
+ return {
+ done: false,
+ get value() {
+ throw new Test262Error();
+ },
+ };
+ }
+ return() {
+ throw new Error();
+ }
+}
+
+let iterator = new ThrowingIterator();
+
+assert.throws(Test262Error, function () {
+ iterator.forEach(() => {});
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/forEach/next-method-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/next-method-throws.js
new file mode 100644
index 0000000000..1b77529403
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/next-method-throws.js
@@ -0,0 +1,26 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.forEach
+description: >
+ Underlying iterator has throwing next method
+info: |
+ %Iterator.prototype%.forEach ( fn )
+
+features: [iterator-helpers]
+flags: []
+---*/
+class ThrowingIterator extends Iterator {
+ next() {
+ throw new Test262Error();
+ }
+}
+
+let iterator = new ThrowingIterator();
+
+assert.throws(Test262Error, function () {
+ iterator.forEach(() => {});
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/forEach/non-callable-predicate.js b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/non-callable-predicate.js
new file mode 100644
index 0000000000..e8bf741cc9
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/non-callable-predicate.js
@@ -0,0 +1,23 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.forEach
+description: >
+ Iterator.prototype.forEach expects to be called with a callable argument.
+info: |
+ %Iterator.prototype%.forEach ( fn )
+
+features: [iterator-helpers]
+flags: []
+---*/
+let nonCallable = {};
+let iterator = (function* () {
+ yield 1;
+})();
+
+assert.throws(TypeError, function () {
+ iterator.forEach(nonCallable);
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/forEach/non-constructible.js b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/non-constructible.js
new file mode 100644
index 0000000000..358b73aca3
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/non-constructible.js
@@ -0,0 +1,31 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.forEach
+description: >
+ Iterator.prototype.forEach is not constructible.
+
+ Built-in function objects that are not identified as constructors do not implement the [[Construct]] internal method unless otherwise specified in the description of a particular function.
+features: [iterator-helpers]
+---*/
+function* g() {}
+let iter = g();
+
+assert.throws(TypeError, () => {
+ new iter.forEach();
+});
+
+assert.throws(TypeError, () => {
+ new iter.forEach(() => {});
+});
+
+assert.throws(TypeError, () => {
+ new Iterator.prototype.forEach(() => {});
+});
+
+assert.throws(TypeError, () => {
+ new class extends Iterator {}.forEach(() => {});
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/forEach/prop-desc.js b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/prop-desc.js
new file mode 100644
index 0000000000..0d3089f8d1
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/prop-desc.js
@@ -0,0 +1,28 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.forEach
+description: >
+ Property descriptor of Iterator.prototype.forEach
+info: |
+ Iterator.prototype.forEach
+
+ * is the initial value of the Iterator.prototype.forEach property of the global object.
+
+ 17 ECMAScript Standard Built-in Objects
+
+ every other data property described in clauses 18 through 26 and in Annex B.2
+ has the attributes { [[Writable]]: true, [[Enumerable]]: false,
+ [[Configurable]]: true } unless otherwise specified.
+features: [globalThis, iterator-helpers]
+includes: [propertyHelper.js]
+---*/
+
+verifyProperty(Iterator.prototype, 'forEach', {
+ writable: true,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/forEach/proto.js b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/proto.js
new file mode 100644
index 0000000000..710a20e865
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/proto.js
@@ -0,0 +1,14 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.forEach
+description: >
+ The value of the [[Prototype]] internal slot of Iterator.prototype.forEach is the
+ intrinsic object %Function%.
+features: [iterator-helpers]
+---*/
+
+assert.sameValue(Object.getPrototypeOf(Iterator.prototype.forEach), Function.prototype);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/forEach/result-is-undefined.js b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/result-is-undefined.js
new file mode 100644
index 0000000000..4e4362e44a
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/result-is-undefined.js
@@ -0,0 +1,21 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.forEach
+description: >
+ Iterator.prototype.forEach returns undefined
+features: [iterator-helpers]
+---*/
+function* g() {}
+let iter = g();
+assert.sameValue(
+ iter.forEach(() => {}),
+ undefined
+);
+assert.sameValue(
+ iter.forEach(() => 0),
+ undefined
+);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/forEach/shell.js b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/shell.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/shell.js
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/forEach/this-non-callable-next.js b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/this-non-callable-next.js
new file mode 100644
index 0000000000..e91c710e9a
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/this-non-callable-next.js
@@ -0,0 +1,18 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.forEach
+description: >
+ Iterator.prototype.forEach throws TypeError when its this value is an object with a non-callable next
+info: |
+ %Iterator.prototype%.forEach ( fn )
+
+features: [iterator-helpers]
+flags: []
+---*/
+assert.throws(TypeError, function () {
+ Iterator.prototype.forEach.call({ next: 0 }, () => true);
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/forEach/this-non-object.js b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/this-non-object.js
new file mode 100644
index 0000000000..1573a6b221
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/this-non-object.js
@@ -0,0 +1,27 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.forEach
+description: >
+ Iterator.prototype.forEach throws TypeError when its this value is a non-object
+info: |
+ %Iterator.prototype%.forEach ( fn )
+
+features: [iterator-helpers]
+flags: []
+---*/
+assert.throws(TypeError, function () {
+ Iterator.prototype.forEach.call(null, () => {});
+});
+
+Object.defineProperty(Number.prototype, 'next', {
+ get: function () {
+ throw new Test262Error();
+ },
+});
+assert.throws(TypeError, function () {
+ Iterator.prototype.forEach.call(0, () => {});
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/forEach/this-plain-iterator.js b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/this-plain-iterator.js
new file mode 100644
index 0000000000..0f60504d28
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/this-plain-iterator.js
@@ -0,0 +1,32 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.forEach
+description: >
+ Iterator.prototype.forEach supports a this value that does not inherit from Iterator.prototype but implements the iterator protocol
+info: |
+ %Iterator.prototype%.forEach ( fn )
+
+features: [iterator-helpers]
+flags: []
+---*/
+let iter = {
+ get next() {
+ let count = 3;
+ return function () {
+ --count;
+ return count >= 0 ? { done: false, value: count } : { done: true, value: undefined };
+ };
+ },
+};
+
+let fnCalls = 0;
+let result = Iterator.prototype.forEach.call(iter, function (v) {
+ ++fnCalls;
+});
+
+assert.sameValue(result, undefined);
+assert.sameValue(fnCalls, 3);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/initial-value.js b/js/src/tests/test262/built-ins/Iterator/prototype/initial-value.js
new file mode 100644
index 0000000000..dc1113a721
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/initial-value.js
@@ -0,0 +1,26 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-iterator.prototype
+description: >
+ The initial value of Iterator.prototype is %Iterator.prototype%.
+info: |
+ Iterator.prototype
+
+ The initial value of Iterator.prototype is %Iterator.prototype%.
+
+ This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }.
+features: [iterator-helpers]
+includes: [propertyHelper.js]
+---*/
+
+verifyProperty(Iterator, 'prototype', {
+ value: Iterator.prototype,
+ writable: false,
+ enumerable: false,
+ configurable: false,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/map/argument-effect-order.js b/js/src/tests/test262/built-ins/Iterator/prototype/map/argument-effect-order.js
new file mode 100644
index 0000000000..fef19280d8
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/map/argument-effect-order.js
@@ -0,0 +1,45 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.map
+description: >
+ Arguments and this value are evaluated in the correct order
+info: |
+ %Iterator.prototype%.map ( mapper )
+
+ 1. Let O be the this value.
+ 2. If O is not an Object, throw a TypeError exception.
+ 3. If IsCallable(mapper) is false, throw a TypeError exception.
+ 4. Let iterated be ? GetIteratorDirect(O).
+
+includes: [compareArray.js]
+features: [iterator-helpers]
+flags: []
+---*/
+let effects = [];
+
+assert.throws(TypeError, function () {
+ Iterator.prototype.map.call(
+ {
+ get next() {
+ effects.push('get next');
+ return function () {
+ return { done: true, value: undefined };
+ };
+ },
+ },
+ {
+ valueOf() {
+ effects.push('valueOf mapper');
+ return function () {
+ return [];
+ };
+ },
+ }
+ );
+});
+
+assert.compareArray(effects, []);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/map/browser.js b/js/src/tests/test262/built-ins/Iterator/prototype/map/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/map/browser.js
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/map/callable.js b/js/src/tests/test262/built-ins/Iterator/prototype/map/callable.js
new file mode 100644
index 0000000000..57ebb543d3
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/map/callable.js
@@ -0,0 +1,16 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.map
+description: >
+ Iterator.prototype.map is callable
+features: [iterator-helpers]
+---*/
+function* g() {}
+Iterator.prototype.map.call(g(), () => 0);
+
+let iter = g();
+iter.map(() => 0);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/map/exhaustion-does-not-call-return.js b/js/src/tests/test262/built-ins/Iterator/prototype/map/exhaustion-does-not-call-return.js
new file mode 100644
index 0000000000..025da41336
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/map/exhaustion-does-not-call-return.js
@@ -0,0 +1,37 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.map
+description: >
+ Underlying iterator return is not called when result iterator is exhausted
+info: |
+ %Iterator.prototype%.map ( mapper )
+
+features: [iterator-helpers]
+flags: []
+---*/
+function* g() {
+ yield 0;
+ yield 1;
+ yield 2;
+}
+
+class TestIterator extends Iterator {
+ get next() {
+ let n = g();
+ return function() {
+ return n.next();
+ };
+ }
+ return() {
+ throw new Test262Error();
+ }
+}
+
+let iterator = new TestIterator().map(() => 0);
+iterator.next();
+iterator.next();
+iterator.next();
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/map/get-next-method-only-once.js b/js/src/tests/test262/built-ins/Iterator/prototype/map/get-next-method-only-once.js
new file mode 100644
index 0000000000..16b7c7331b
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/map/get-next-method-only-once.js
@@ -0,0 +1,44 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.map
+description: >
+ Gets the next method from the underlying iterator only once
+info: |
+ %Iterator.prototype%.map ( mapper )
+
+ 4. Let iterated be ? GetIteratorDirect(O).
+
+features: [iterator-helpers]
+flags: []
+---*/
+let nextGets = 0;
+let nextCalls = 0;
+
+class CountingIterator extends Iterator {
+ get next() {
+ ++nextGets;
+ let iter = (function* () {
+ for (let i = 1; i < 5; ++i) {
+ yield i;
+ }
+ })();
+ return function () {
+ ++nextCalls;
+ return iter.next();
+ };
+ }
+}
+
+let iterator = new CountingIterator();
+
+assert.sameValue(nextGets, 0);
+assert.sameValue(nextCalls, 0);
+
+for (const value of iterator.map(() => 0));
+
+assert.sameValue(nextGets, 1);
+assert.sameValue(nextCalls, 5);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/map/get-next-method-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/map/get-next-method-throws.js
new file mode 100644
index 0000000000..6a804093fa
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/map/get-next-method-throws.js
@@ -0,0 +1,28 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.map
+description: >
+ Underlying iterator has throwing next getter
+info: |
+ %Iterator.prototype%.map ( mapper )
+
+ 4. Let iterated be ? GetIteratorDirect(O).
+
+features: [iterator-helpers]
+flags: []
+---*/
+class ThrowingIterator extends Iterator {
+ get next() {
+ throw new Test262Error();
+ }
+}
+
+let iterator = new ThrowingIterator();
+
+assert.throws(Test262Error, function () {
+ iterator.map(() => 0);
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/map/get-return-method-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/map/get-return-method-throws.js
new file mode 100644
index 0000000000..15aa7219d1
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/map/get-return-method-throws.js
@@ -0,0 +1,33 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.map
+description: >
+ Underlying iterator return is throwing getter
+info: |
+ %Iterator.prototype%.map ( mapper )
+
+features: [iterator-helpers]
+flags: []
+---*/
+class TestIterator extends Iterator {
+ next() {
+ return {
+ done: false,
+ value: 1,
+ };
+ }
+ get return() {
+ throw new Test262Error();
+ }
+}
+
+let iterator = new TestIterator().map(() => 0);
+iterator.next();
+
+assert.throws(Test262Error, function () {
+ iterator.return();
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/map/is-function.js b/js/src/tests/test262/built-ins/Iterator/prototype/map/is-function.js
new file mode 100644
index 0000000000..428a20c4c2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/map/is-function.js
@@ -0,0 +1,13 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.map
+description: >
+ Iterator.prototype.map is a built-in function
+features: [iterator-helpers]
+---*/
+
+assert.sameValue(typeof Iterator.prototype.map, 'function');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/map/iterator-already-exhausted.js b/js/src/tests/test262/built-ins/Iterator/prototype/map/iterator-already-exhausted.js
new file mode 100644
index 0000000000..2f75050173
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/map/iterator-already-exhausted.js
@@ -0,0 +1,25 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.map
+description: >
+ Iterator.prototype.map returns an empty iterator when the iterator has already been exhausted
+info: |
+ %Iterator.prototype%.map ( mapper )
+
+features: [iterator-helpers]
+flags: []
+---*/
+let iterator = (function* () {})();
+
+let { value, done } = iterator.next();
+assert.sameValue(value, undefined);
+assert.sameValue(done, true);
+
+iterator = iterator.map(() => 0);
+({ value, done } = iterator.next());
+assert.sameValue(value, undefined);
+assert.sameValue(done, true);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/map/iterator-return-method-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/map/iterator-return-method-throws.js
new file mode 100644
index 0000000000..d81031c2a4
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/map/iterator-return-method-throws.js
@@ -0,0 +1,32 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.map
+description: >
+ Iterator has throwing return
+info: |
+ %Iterator.prototype%.map ( mapper )
+
+features: [iterator-helpers]
+flags: []
+---*/
+class IteratorThrows extends Iterator {
+ next() {
+ return {
+ done: false,
+ value: 0,
+ };
+ }
+ return() {
+ throw new Test262Error();
+ }
+}
+
+let iterator = new IteratorThrows().map(() => 0);
+
+assert.throws(Test262Error, function () {
+ iterator.return();
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/map/length.js b/js/src/tests/test262/built-ins/Iterator/prototype/map/length.js
new file mode 100644
index 0000000000..d11d3330e0
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/map/length.js
@@ -0,0 +1,25 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.map
+description: >
+ Iterator.prototype.map has a "length" property whose value is 1.
+info: |
+ ECMAScript Standard Built-in Objects
+
+ Unless otherwise specified, the length property of a built-in
+ Function object has the attributes { [[Writable]]: false, [[Enumerable]]:
+ false, [[Configurable]]: true }.
+features: [iterator-helpers]
+includes: [propertyHelper.js]
+---*/
+
+verifyProperty(Iterator.prototype.map, 'length', {
+ value: 1,
+ writable: false,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/map/mapper-args.js b/js/src/tests/test262/built-ins/Iterator/prototype/map/mapper-args.js
new file mode 100644
index 0000000000..132fcdeeee
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/map/mapper-args.js
@@ -0,0 +1,58 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.map
+description: >
+ Iterator.prototype.map mapper is passed the yielded value and a counter as arguments
+info: |
+ %Iterator.prototype%.map ( mapper )
+
+ 5.b.iv. Let mapped be Completion(Call(mapper, undefined, « value, 𝔽(counter) »)).
+
+features: [iterator-helpers]
+flags: []
+---*/
+function* g() {
+ yield 'a';
+ yield 'b';
+ yield 'c';
+ yield 'd';
+ yield 'e';
+}
+
+let assertionCount = 0;
+let iter = g().map((v, count) => {
+ switch (v) {
+ case 'a':
+ assert.sameValue(count, 0);
+ ++assertionCount;
+ return 0;
+ case 'b':
+ assert.sameValue(count, 1);
+ ++assertionCount;
+ return 1;
+ case 'c':
+ assert.sameValue(count, 2);
+ ++assertionCount;
+ return 2;
+ case 'd':
+ assert.sameValue(count, 3);
+ ++assertionCount;
+ return 3;
+ case 'e':
+ assert.sameValue(count, 4);
+ ++assertionCount;
+ return 4;
+ default:
+ throw new Error();
+ }
+});
+
+assert.sameValue(assertionCount, 0);
+
+for (let i of iter);
+
+assert.sameValue(assertionCount, 5);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/map/mapper-this.js b/js/src/tests/test262/built-ins/Iterator/prototype/map/mapper-this.js
new file mode 100644
index 0000000000..5c7ac20423
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/map/mapper-this.js
@@ -0,0 +1,36 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.map
+description: >
+ Iterator.prototype.map mapper this value is undefined
+info: |
+ %Iterator.prototype%.map ( mapper )
+
+ 5.b.iv. Let mapped be Completion(Call(mapper, undefined, « value, 𝔽(counter) »)).
+
+features: [iterator-helpers]
+flags: []
+---*/
+function* g() {
+ yield 0;
+}
+
+let iter = g();
+
+let expectedThis = function () {
+ return this;
+}.call(undefined);
+
+let assertionCount = 0;
+iter = iter.map(function (v, count) {
+ assert.sameValue(this, expectedThis);
+ ++assertionCount;
+ return v;
+});
+
+iter.next();
+assert.sameValue(assertionCount, 1);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/map/mapper-throws-then-closing-iterator-also-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/map/mapper-throws-then-closing-iterator-also-throws.js
new file mode 100644
index 0000000000..22cb2cb78f
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/map/mapper-throws-then-closing-iterator-also-throws.js
@@ -0,0 +1,43 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.map
+description: >
+ Attempts to close iterator when mapper throws, but that throws
+info: |
+ %Iterator.prototype%.map ( mapper )
+
+ 5.b.v. IfAbruptCloseIterator(mapped, iterated).
+
+features: [iterator-helpers]
+flags: []
+---*/
+let returnCalls = 0;
+
+class TestIterator extends Iterator {
+ next() {
+ return {
+ done: false,
+ value: 1,
+ };
+ }
+ return() {
+ ++returnCalls;
+ throw new Error();
+ }
+}
+
+let iterator = new TestIterator().map(() => {
+ throw new Test262Error();
+});
+
+assert.sameValue(returnCalls, 0);
+
+assert.throws(Test262Error, function () {
+ iterator.next();
+});
+
+assert.sameValue(returnCalls, 1);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/map/mapper-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/map/mapper-throws.js
new file mode 100644
index 0000000000..0a7eb400bd
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/map/mapper-throws.js
@@ -0,0 +1,44 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.map
+description: >
+ Closes iterator and throws when mapper throws
+info: |
+ %Iterator.prototype%.map ( mapper )
+
+ 5.b.v. IfAbruptCloseIterator(mapped, iterated).
+
+features: [iterator-helpers]
+flags: []
+---*/
+let returnCalls = 0;
+
+class TestIterator extends Iterator {
+ next() {
+ return {
+ done: false,
+ value: 1,
+ };
+ }
+ return() {
+ ++returnCalls;
+ return {};
+ }
+}
+
+let callbackCalls = 0;
+let iterator = new TestIterator().map(() => {
+ ++callbackCalls;
+ throw new Test262Error();
+});
+
+assert.throws(Test262Error, function () {
+ iterator.next();
+});
+
+assert.sameValue(callbackCalls, 1);
+assert.sameValue(returnCalls, 1);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/map/name.js b/js/src/tests/test262/built-ins/Iterator/prototype/map/name.js
new file mode 100644
index 0000000000..e48bada845
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/map/name.js
@@ -0,0 +1,32 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.map
+description: >
+ The "name" property of Iterator.prototype.map
+info: |
+ 17 ECMAScript Standard Built-in Objects
+
+ Every built-in Function object, including constructors, that is not
+ identified as an anonymous function has a name property whose value is a
+ String. Unless otherwise specified, this value is the name that is given to
+ the function in this specification.
+
+ ...
+
+ Unless otherwise specified, the name property of a built-in Function
+ object, if it exists, has the attributes { [[Writable]]: false,
+ [[Enumerable]]: false, [[Configurable]]: true }.
+features: [iterator-helpers]
+includes: [propertyHelper.js]
+---*/
+
+verifyProperty(Iterator.prototype.map, 'name', {
+ value: 'map',
+ writable: false,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/map/next-method-returns-non-object.js b/js/src/tests/test262/built-ins/Iterator/prototype/map/next-method-returns-non-object.js
new file mode 100644
index 0000000000..f4404b5bae
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/map/next-method-returns-non-object.js
@@ -0,0 +1,26 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.map
+description: >
+ Underlying iterator next returns non-object
+info: |
+ %Iterator.prototype%.map ( mapper )
+
+features: [iterator-helpers]
+flags: []
+---*/
+class NonObjectIterator extends Iterator {
+ next() {
+ return null;
+ }
+}
+
+let iterator = new NonObjectIterator().map(() => 0);
+
+assert.throws(TypeError, function () {
+ iterator.next();
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/map/next-method-returns-throwing-done.js b/js/src/tests/test262/built-ins/Iterator/prototype/map/next-method-returns-throwing-done.js
new file mode 100644
index 0000000000..2bb236050c
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/map/next-method-returns-throwing-done.js
@@ -0,0 +1,34 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.map
+description: >
+ Underlying iterator next returns object with throwing done getter
+info: |
+ %Iterator.prototype%.map ( mapper )
+
+features: [iterator-helpers]
+flags: []
+---*/
+class ThrowingIterator extends Iterator {
+ next() {
+ return {
+ get done() {
+ throw new Test262Error();
+ },
+ value: 1,
+ };
+ }
+ return() {
+ throw new Error();
+ }
+}
+
+let iterator = new ThrowingIterator().map(() => 0);
+
+assert.throws(Test262Error, function () {
+ iterator.next();
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/map/next-method-returns-throwing-value-done.js b/js/src/tests/test262/built-ins/Iterator/prototype/map/next-method-returns-throwing-value-done.js
new file mode 100644
index 0000000000..017fa210b6
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/map/next-method-returns-throwing-value-done.js
@@ -0,0 +1,31 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.map
+description: >
+ Underlying iterator next returns object with throwing value getter, but is already done
+info: |
+ %Iterator.prototype%.map ( mapper )
+
+features: [iterator-helpers]
+flags: []
+---*/
+class ThrowingIterator extends Iterator {
+ next() {
+ return {
+ done: true,
+ get value() {
+ throw new Test262Error();
+ },
+ };
+ }
+ return() {
+ throw new Error();
+ }
+}
+
+let iterator = new ThrowingIterator().map(() => 0);
+iterator.next();
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/map/next-method-returns-throwing-value.js b/js/src/tests/test262/built-ins/Iterator/prototype/map/next-method-returns-throwing-value.js
new file mode 100644
index 0000000000..50208c73ed
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/map/next-method-returns-throwing-value.js
@@ -0,0 +1,34 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.map
+description: >
+ Underlying iterator next returns object with throwing value getter
+info: |
+ %Iterator.prototype%.map ( mapper )
+
+features: [iterator-helpers]
+flags: []
+---*/
+class ThrowingIterator extends Iterator {
+ next() {
+ return {
+ done: false,
+ get value() {
+ throw new Test262Error();
+ },
+ };
+ }
+ return() {
+ throw new Error();
+ }
+}
+
+let iterator = new ThrowingIterator().map(() => 0);
+
+assert.throws(Test262Error, function () {
+ iterator.next();
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/map/next-method-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/map/next-method-throws.js
new file mode 100644
index 0000000000..52ad97d16d
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/map/next-method-throws.js
@@ -0,0 +1,26 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.map
+description: >
+ Underlying iterator has throwing next method
+info: |
+ %Iterator.prototype%.map ( mapper )
+
+features: [iterator-helpers]
+flags: []
+---*/
+class ThrowingIterator extends Iterator {
+ next() {
+ throw new Test262Error();
+ }
+}
+
+let iterator = new ThrowingIterator().map(() => 0);
+
+assert.throws(Test262Error, function () {
+ iterator.next();
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/map/non-callable-mapper.js b/js/src/tests/test262/built-ins/Iterator/prototype/map/non-callable-mapper.js
new file mode 100644
index 0000000000..14e05228be
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/map/non-callable-mapper.js
@@ -0,0 +1,23 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.map
+description: >
+ Iterator.prototype.map expects to be called with a callable argument.
+info: |
+ %Iterator.prototype%.map ( mapper )
+
+ 3. If IsCallable(mapper) is false, throw a TypeError exception.
+
+features: [iterator-helpers]
+flags: []
+---*/
+let nonCallable = {};
+let iterator = (function* () {})();
+
+assert.throws(TypeError, function () {
+ iterator.map(nonCallable);
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/map/non-constructible.js b/js/src/tests/test262/built-ins/Iterator/prototype/map/non-constructible.js
new file mode 100644
index 0000000000..5bf482766c
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/map/non-constructible.js
@@ -0,0 +1,31 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.map
+description: >
+ Iterator.prototype.map is not constructible.
+
+ Built-in function objects that are not identified as constructors do not implement the [[Construct]] internal method unless otherwise specified in the description of a particular function.
+features: [iterator-helpers]
+---*/
+function* g() {}
+let iter = g();
+
+assert.throws(TypeError, () => {
+ new iter.map();
+});
+
+assert.throws(TypeError, () => {
+ new iter.map(() => 0);
+});
+
+assert.throws(TypeError, () => {
+ new Iterator.prototype.map(() => 0);
+});
+
+assert.throws(TypeError, () => {
+ new class extends Iterator {}.map(() => 0);
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/map/prop-desc.js b/js/src/tests/test262/built-ins/Iterator/prototype/map/prop-desc.js
new file mode 100644
index 0000000000..f321f9ba5a
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/map/prop-desc.js
@@ -0,0 +1,28 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.map
+description: >
+ Property descriptor of Iterator.prototype.map
+info: |
+ Iterator.prototype.map
+
+ * is the initial value of the Iterator.prototype.map property of the global object.
+
+ 17 ECMAScript Standard Built-in Objects
+
+ Every other data property described in clauses 18 through 26 and in Annex B.2
+ has the attributes { [[Writable]]: true, [[Enumerable]]: false,
+ [[Configurable]]: true } unless otherwise specified.
+features: [globalThis, iterator-helpers]
+includes: [propertyHelper.js]
+---*/
+
+verifyProperty(Iterator.prototype, 'map', {
+ writable: true,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/map/proto.js b/js/src/tests/test262/built-ins/Iterator/prototype/map/proto.js
new file mode 100644
index 0000000000..1e8cf63822
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/map/proto.js
@@ -0,0 +1,14 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.map
+description: >
+ The value of the [[Prototype]] internal slot of Iterator.prototype.map is the
+ intrinsic object %FunctionPrototype%.
+features: [iterator-helpers]
+---*/
+
+assert.sameValue(Object.getPrototypeOf(Iterator.prototype.map), Function.prototype);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/map/result-is-iterator.js b/js/src/tests/test262/built-ins/Iterator/prototype/map/result-is-iterator.js
new file mode 100644
index 0000000000..c4aea92b89
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/map/result-is-iterator.js
@@ -0,0 +1,14 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.map
+description: >
+ The value of the [[Prototype]] internal slot of the return value of Iterator.prototype.map is the
+ intrinsic object %IteratorHelperPrototype%.
+features: [iterator-helpers]
+---*/
+
+assert((function* () {})().map(() => 0) instanceof Iterator, 'function*(){}().map(() => 0) must return an Iterator');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/map/return-is-forwarded-to-underlying-iterator.js b/js/src/tests/test262/built-ins/Iterator/prototype/map/return-is-forwarded-to-underlying-iterator.js
new file mode 100644
index 0000000000..3e1cab2d40
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/map/return-is-forwarded-to-underlying-iterator.js
@@ -0,0 +1,36 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.map
+description: >
+ Underlying iterator return is called when result iterator is closed
+info: |
+ %Iterator.prototype%.map ( mapper )
+
+features: [iterator-helpers]
+flags: []
+---*/
+let returnCount = 0;
+
+class TestIterator extends Iterator {
+ next() {
+ return {
+ done: false,
+ value: 1,
+ };
+ }
+ return() {
+ ++returnCount;
+ return {};
+ }
+}
+
+let iterator = new TestIterator().map(() => 0);
+assert.sameValue(returnCount, 0);
+iterator.return();
+assert.sameValue(returnCount, 1);
+iterator.return();
+assert.sameValue(returnCount, 1);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/map/return-is-not-forwarded-after-exhaustion.js b/js/src/tests/test262/built-ins/Iterator/prototype/map/return-is-not-forwarded-after-exhaustion.js
new file mode 100644
index 0000000000..4b22864b33
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/map/return-is-not-forwarded-after-exhaustion.js
@@ -0,0 +1,49 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.map
+description: >
+ Underlying iterator return is not called after result iterator observes that underlying iterator is exhausted
+info: |
+ %Iterator.prototype%.map ( mapper )
+
+features: [iterator-helpers]
+flags: []
+---*/
+let returnCount = 0;
+
+class TestIterator extends Iterator {
+ next() {
+ return {
+ done: true,
+ value: undefined,
+ };
+ }
+ return() {
+ throw new Test262Error();
+ }
+}
+
+let iterator = new TestIterator().map(() => 0);
+assert.throws(Test262Error, function () {
+ iterator.return();
+});
+iterator.next();
+iterator.return();
+
+iterator = new TestIterator().map(() => 0);
+iterator.next();
+iterator.return();
+
+iterator = new TestIterator()
+ .map(x => x)
+ .map(x => x)
+ .map(x => x);
+assert.throws(Test262Error, function () {
+ iterator.return();
+});
+iterator.next();
+iterator.return();
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/map/returned-iterator-yields-mapper-return-values.js b/js/src/tests/test262/built-ins/Iterator/prototype/map/returned-iterator-yields-mapper-return-values.js
new file mode 100644
index 0000000000..f999fd80a0
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/map/returned-iterator-yields-mapper-return-values.js
@@ -0,0 +1,39 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.map
+description: >
+ The values returned by the mapper are the values that are yielded by the iterator returned by map
+info: |
+ %Iterator.prototype%.map ( mapper )
+
+ 5.b.vi. Let completion be Completion(Yield(mapped)).
+
+includes: [compareArray.js]
+features: [iterator-helpers]
+flags: []
+---*/
+function* g() {
+ for (let i = 0; i < 5; ++i) {
+ yield i;
+ }
+}
+
+assert.compareArray(Array.from(g()), [0, 1, 2, 3, 4]);
+assert.compareArray(Array.from(g().map(x => x)), [0, 1, 2, 3, 4]);
+assert.compareArray(Array.from(g().map(() => 0)), [0, 0, 0, 0, 0]);
+assert.compareArray(
+ Array.from(
+ g()
+ .map(() => 0)
+ .map((v, c) => c)
+ ),
+ [0, 1, 2, 3, 4]
+);
+assert.compareArray(Array.from(g().map(x => x * 2)), [0, 2, 4, 6, 8]);
+
+let obj = {};
+assert.compareArray(Array.from(g().map(() => obj)), [obj, obj, obj, obj, obj]);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/map/shell.js b/js/src/tests/test262/built-ins/Iterator/prototype/map/shell.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/map/shell.js
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/map/this-non-callable-next.js b/js/src/tests/test262/built-ins/Iterator/prototype/map/this-non-callable-next.js
new file mode 100644
index 0000000000..fe58985b32
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/map/this-non-callable-next.js
@@ -0,0 +1,20 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.map
+description: >
+ Iterator.prototype.map throws TypeError when its this value is an object with a non-callable next
+info: |
+ %Iterator.prototype%.map ( mapper )
+
+features: [iterator-helpers]
+flags: []
+---*/
+let iter = Iterator.prototype.map.call({ next: 0 }, () => 0);
+
+assert.throws(TypeError, function () {
+ iter.next();
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/map/this-non-object.js b/js/src/tests/test262/built-ins/Iterator/prototype/map/this-non-object.js
new file mode 100644
index 0000000000..cc8ab9ea47
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/map/this-non-object.js
@@ -0,0 +1,29 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.map
+description: >
+ Iterator.prototype.map throws TypeError when its this value is a non-object
+info: |
+ %Iterator.prototype%.map ( mapper )
+
+ 2. If O is not an Object, throw a TypeError exception.
+
+features: [iterator-helpers]
+flags: []
+---*/
+assert.throws(TypeError, function () {
+ Iterator.prototype.map.call(null, () => 0);
+});
+
+Object.defineProperty(Number.prototype, 'next', {
+ get: function () {
+ throw new Test262Error();
+ },
+});
+assert.throws(TypeError, function () {
+ Iterator.prototype.map.call(0, () => 0);
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/map/this-plain-iterator.js b/js/src/tests/test262/built-ins/Iterator/prototype/map/this-plain-iterator.js
new file mode 100644
index 0000000000..8a243a9889
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/map/this-plain-iterator.js
@@ -0,0 +1,34 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.map
+description: >
+ Iterator.prototype.map supports a this value that does not inherit from Iterator.prototype but implements the iterator protocol
+info: |
+ %Iterator.prototype%.map ( mapper )
+
+features: [iterator-helpers]
+flags: []
+---*/
+let iter = {
+ get next() {
+ let count = 3;
+ return function () {
+ --count;
+ return count >= 0 ? { done: false, value: count } : { done: true, value: undefined };
+ };
+ },
+};
+
+let mapperCalls = 0;
+iter = Iterator.prototype.map.call(iter, function (v) {
+ ++mapperCalls;
+ return v;
+});
+
+for (let e of iter);
+
+assert.sameValue(mapperCalls, 3);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/map/throws-typeerror-when-generator-is-running.js b/js/src/tests/test262/built-ins/Iterator/prototype/map/throws-typeerror-when-generator-is-running.js
new file mode 100644
index 0000000000..a288c7f0ba
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/map/throws-typeerror-when-generator-is-running.js
@@ -0,0 +1,49 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 André Bargull. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.map
+description: >
+ Throws a TypeError when the closure generator is already running.
+info: |
+ %IteratorHelperPrototype%.next ( )
+ 1. Return ? GeneratorResume(this value, undefined, "Iterator Helper").
+
+ 27.5.3.3 GeneratorResume ( generator, value, generatorBrand )
+ 1. Let state be ? GeneratorValidate(generator, generatorBrand).
+ ...
+
+ 27.5.3.2 GeneratorValidate ( generator, generatorBrand )
+ ...
+ 6. If state is executing, throw a TypeError exception.
+ ...
+
+features: [iterator-helpers]
+---*/
+
+var loopCount = 0;
+
+function* g() {
+ while (true) {
+ loopCount++;
+ yield;
+ }
+}
+
+var enterCount = 0;
+
+function mapper() {
+ enterCount++;
+ iter.next();
+}
+
+var iter = g().map(mapper);
+
+assert.throws(TypeError, function() {
+ iter.next();
+});
+
+assert.sameValue(loopCount, 1);
+assert.sameValue(enterCount, 1);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/map/underlying-iterator-advanced-in-parallel.js b/js/src/tests/test262/built-ins/Iterator/prototype/map/underlying-iterator-advanced-in-parallel.js
new file mode 100644
index 0000000000..e54d75fab1
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/map/underlying-iterator-advanced-in-parallel.js
@@ -0,0 +1,45 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.map
+description: >
+ Underlying iterator is advanced after calling map
+info: |
+ %Iterator.prototype%.map ( mapper )
+
+features: [iterator-helpers]
+flags: []
+---*/
+let iterator = (function* () {
+ for (let i = 0; i < 5; ++i) {
+ yield i;
+ }
+})();
+
+let mapped = iterator.map(x => x);
+
+let { value, done } = iterator.next();
+
+assert.sameValue(value, 0);
+assert.sameValue(done, false);
+
+iterator.next();
+iterator.next();
+
+({ value, done } = mapped.next());
+
+assert.sameValue(value, 3);
+assert.sameValue(done, false);
+
+({ value, done } = mapped.next());
+
+assert.sameValue(value, 4);
+assert.sameValue(done, false);
+
+({ value, done } = mapped.next());
+
+assert.sameValue(value, undefined);
+assert.sameValue(done, true);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/map/underlying-iterator-closed-in-parallel.js b/js/src/tests/test262/built-ins/Iterator/prototype/map/underlying-iterator-closed-in-parallel.js
new file mode 100644
index 0000000000..090abaaaea
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/map/underlying-iterator-closed-in-parallel.js
@@ -0,0 +1,29 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.map
+description: >
+ Underlying iterator is closed after calling map
+info: |
+ %Iterator.prototype%.map ( mapper )
+
+features: [iterator-helpers]
+flags: []
+---*/
+let iterator = (function* () {
+ for (let i = 0; i < 5; ++i) {
+ yield i;
+ }
+})();
+
+let mapped = iterator.map(() => 0);
+
+iterator.return();
+
+let { value, done } = mapped.next();
+
+assert.sameValue(value, undefined);
+assert.sameValue(done, true);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/map/underlying-iterator-closed.js b/js/src/tests/test262/built-ins/Iterator/prototype/map/underlying-iterator-closed.js
new file mode 100644
index 0000000000..478903700d
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/map/underlying-iterator-closed.js
@@ -0,0 +1,29 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.map
+description: >
+ Underlying iterator is closed before calling map
+info: |
+ %Iterator.prototype%.map ( mapper )
+
+features: [iterator-helpers]
+flags: []
+---*/
+let iterator = (function* () {
+ for (let i = 0; i < 5; ++i) {
+ yield i;
+ }
+})();
+
+iterator.return();
+
+let mapped = iterator.map(() => 0);
+
+let { value, done } = mapped.next();
+
+assert.sameValue(value, undefined);
+assert.sameValue(done, true);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/reduce/argument-effect-order.js b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/argument-effect-order.js
new file mode 100644
index 0000000000..1f66e7c18a
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/argument-effect-order.js
@@ -0,0 +1,61 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.reduce
+description: >
+ Arguments and this value are evaluated in the correct order
+info: |
+ %Iterator.prototype%.reduce ( reducer )
+
+includes: [compareArray.js]
+features: [iterator-helpers]
+flags: []
+---*/
+let effects = [];
+
+assert.throws(TypeError, function () {
+ Iterator.prototype.reduce.call(
+ {
+ get next() {
+ effects.push('get next');
+ return function () {
+ return { done: true, value: undefined };
+ };
+ },
+ },
+ {
+ valueOf() {
+ effects.push('reducer valueOf');
+ }
+ },
+ {
+ valueOf() {
+ effects.push('initial value valueOf');
+ }
+ }
+ );
+});
+
+assert.compareArray(effects, []);
+
+Iterator.prototype.reduce.call(
+ {
+ get next() {
+ effects.push('get next');
+ return function () {
+ return { done: true, value: undefined };
+ };
+ },
+ },
+ () => {},
+ {
+ valueOf() {
+ effects.push('initial value valueOf');
+ }
+ }
+);
+
+assert.compareArray(effects, ['get next']);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/reduce/browser.js b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/browser.js
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/reduce/callable.js b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/callable.js
new file mode 100644
index 0000000000..ce5ecf8bbe
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/callable.js
@@ -0,0 +1,16 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.reduce
+description: >
+ Iterator.prototype.reduce is callable
+features: [iterator-helpers]
+---*/
+function* g() {}
+Iterator.prototype.reduce.call(g(), () => {}, 0);
+
+let iter = g();
+iter.reduce(() => {}, 0);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/reduce/get-next-method-only-once.js b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/get-next-method-only-once.js
new file mode 100644
index 0000000000..016eebf94c
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/get-next-method-only-once.js
@@ -0,0 +1,39 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.reduce
+description: >
+ Gets the next method from the iterator only once
+info: |
+ %Iterator.prototype%.reduce ( reducer )
+
+features: [iterator-helpers]
+flags: []
+---*/
+let nextGets = 0;
+
+class TestIterator extends Iterator {
+ get next() {
+ ++nextGets;
+ let counter = 5;
+ return function () {
+ if (counter <= 0) {
+ return { done: true, value: undefined };
+ } else {
+ return { done: false, value: --counter };
+ }
+ };
+ }
+}
+
+let iterator = new TestIterator();
+
+assert.sameValue(nextGets, 0);
+assert.sameValue(
+ iterator.reduce(x => x),
+ 4
+);
+assert.sameValue(nextGets, 1);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/reduce/get-next-method-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/get-next-method-throws.js
new file mode 100644
index 0000000000..579e567b9b
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/get-next-method-throws.js
@@ -0,0 +1,26 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.reduce
+description: >
+ Iterator has throwing next getter
+info: |
+ %Iterator.prototype%.reduce ( reducer )
+
+features: [iterator-helpers]
+flags: []
+---*/
+class IteratorThrows extends Iterator {
+ get next() {
+ throw new Test262Error();
+ }
+}
+
+let iterator = new IteratorThrows();
+
+assert.throws(Test262Error, function () {
+ iterator.reduce(() => {});
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/reduce/is-function.js b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/is-function.js
new file mode 100644
index 0000000000..9c79a4c3ab
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/is-function.js
@@ -0,0 +1,13 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.reduce
+description: >
+ Iterator.prototype.reduce is a built-in function
+features: [iterator-helpers]
+---*/
+
+assert.sameValue(typeof Iterator.prototype.reduce, 'function');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/reduce/iterator-already-exhausted-initial-value.js b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/iterator-already-exhausted-initial-value.js
new file mode 100644
index 0000000000..1d2b64374b
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/iterator-already-exhausted-initial-value.js
@@ -0,0 +1,24 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.reduce
+description: >
+ Iterator.prototype.reduce returns the initial value when the iterator has already been exhausted
+info: |
+ %Iterator.prototype%.reduce ( reducer )
+
+features: [iterator-helpers]
+flags: []
+---*/
+let iterator = (function* () {})();
+
+let { value, done } = iterator.next();
+assert.sameValue(value, undefined);
+assert.sameValue(done, true);
+
+const initialValue = {};
+let result = iterator.reduce(() => {}, initialValue);
+assert.sameValue(result, initialValue);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/reduce/iterator-already-exhausted-no-initial-value.js b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/iterator-already-exhausted-no-initial-value.js
new file mode 100644
index 0000000000..28b2910f92
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/iterator-already-exhausted-no-initial-value.js
@@ -0,0 +1,26 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.reduce
+description: >
+ Iterator.prototype.reduce without an initial value throws when the iterator has already been exhausted
+info: |
+ %Iterator.prototype%.reduce ( reducer )
+
+features: [iterator-helpers]
+flags: []
+---*/
+let iterator = (function* () {})();
+
+let { value, done } = iterator.next();
+assert.sameValue(value, undefined);
+assert.sameValue(done, true);
+
+assert.throws(TypeError, function() {
+ iterator.reduce(() => {});
+});
+
+iterator.reduce(() => {}, 0);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/reduce/iterator-yields-once-initial-value.js b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/iterator-yields-once-initial-value.js
new file mode 100644
index 0000000000..cdaaaf409b
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/iterator-yields-once-initial-value.js
@@ -0,0 +1,38 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.reduce
+description: >
+ Iterator.prototype.reduce calls reducer once for each value yielded by the underlying iterator when passed an initial value
+info: |
+ %Iterator.prototype%.reduce ( reducer )
+
+features: [iterator-helpers]
+flags: []
+---*/
+function* g() {
+ yield 'a';
+}
+
+let iter = g();
+
+let assertionCount = 0;
+let initialValue = {};
+let result = iter.reduce((memo, v, count) => {
+ switch (v) {
+ case 'a':
+ assert.sameValue(memo, initialValue);
+ assert.sameValue(count, 0);
+ break;
+ default:
+ throw new Error();
+ }
+ ++assertionCount;
+ return v;
+}, initialValue);
+
+assert.sameValue(result, 'a');
+assert.sameValue(assertionCount, 1);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/reduce/iterator-yields-once-no-initial-value.js b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/iterator-yields-once-no-initial-value.js
new file mode 100644
index 0000000000..d71a781737
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/iterator-yields-once-no-initial-value.js
@@ -0,0 +1,29 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.reduce
+description: >
+ Iterator.prototype.reduce calls reducer once for each value yielded by the underlying iterator except the first when not passed an initial value
+info: |
+ %Iterator.prototype%.reduce ( reducer )
+
+features: [iterator-helpers]
+flags: []
+---*/
+function* g() {
+ yield 'a';
+}
+
+let iter = g();
+
+let assertionCount = 0;
+let result = iter.reduce((memo, v, count) => {
+ ++assertionCount;
+ return v;
+});
+
+assert.sameValue(result, 'a');
+assert.sameValue(assertionCount, 0);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/reduce/length.js b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/length.js
new file mode 100644
index 0000000000..5e1d35d57a
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/length.js
@@ -0,0 +1,25 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.reduce
+description: >
+ Iterator.prototype.reduce has a "length" property whose value is 1.
+info: |
+ ECMAScript Standard Built-in Objects
+
+ Unless otherwise specified, the length property of a built-in
+ Function object has the attributes { [[Writable]]: false, [[Enumerable]]:
+ false, [[Configurable]]: true }.
+features: [iterator-helpers]
+includes: [propertyHelper.js]
+---*/
+
+verifyProperty(Iterator.prototype.reduce, 'length', {
+ value: 1,
+ writable: false,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/reduce/name.js b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/name.js
new file mode 100644
index 0000000000..3af38b0ea9
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/name.js
@@ -0,0 +1,32 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.reduce
+description: >
+ The "name" property of Iterator.prototype.reduce
+info: |
+ 17 ECMAScript Standard Built-in Objects
+
+ Every built-in Function object, including constructors, that is not
+ identified as an anonymous function has a name property whose value is a
+ String. Unless otherwise specified, this value is the name that is given to
+ the function in this specification.
+
+ ...
+
+ Unless otherwise specified, the name property of a built-in Function
+ object, if it exists, has the attributes { [[Writable]]: false,
+ [[Enumerable]]: false, [[Configurable]]: true }.
+features: [iterator-helpers]
+includes: [propertyHelper.js]
+---*/
+
+verifyProperty(Iterator.prototype.reduce, 'name', {
+ value: 'reduce',
+ writable: false,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/reduce/next-method-returns-non-object.js b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/next-method-returns-non-object.js
new file mode 100644
index 0000000000..238a4cceff
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/next-method-returns-non-object.js
@@ -0,0 +1,26 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.reduce
+description: >
+ Underlying iterator next returns non-object
+info: |
+ %Iterator.prototype%.reduce ( reducer )
+
+features: [iterator-helpers]
+flags: []
+---*/
+class NonObjectIterator extends Iterator {
+ next() {
+ return null;
+ }
+}
+
+let iterator = new NonObjectIterator();
+
+assert.throws(TypeError, function () {
+ iterator.reduce(() => {});
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/reduce/next-method-returns-throwing-done.js b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/next-method-returns-throwing-done.js
new file mode 100644
index 0000000000..e1dc0e0876
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/next-method-returns-throwing-done.js
@@ -0,0 +1,34 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.reduce
+description: >
+ Underlying iterator next returns object with throwing done getter
+info: |
+ %Iterator.prototype%.reduce ( reducer )
+
+features: [iterator-helpers]
+flags: []
+---*/
+class ThrowingIterator extends Iterator {
+ next() {
+ return {
+ get done() {
+ throw new Test262Error();
+ },
+ value: 1,
+ };
+ }
+ return() {
+ throw new Error();
+ }
+}
+
+let iterator = new ThrowingIterator();
+
+assert.throws(Test262Error, function () {
+ iterator.reduce(() => {});
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/reduce/next-method-returns-throwing-value-done.js b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/next-method-returns-throwing-value-done.js
new file mode 100644
index 0000000000..53c7984e64
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/next-method-returns-throwing-value-done.js
@@ -0,0 +1,31 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.reduce
+description: >
+ Underlying iterator next returns object with throwing value getter, but is already done
+info: |
+ %Iterator.prototype%.reduce ( reducer )
+
+features: [iterator-helpers]
+flags: []
+---*/
+class ThrowingIterator extends Iterator {
+ next() {
+ return {
+ done: true,
+ get value() {
+ throw new Test262Error();
+ },
+ };
+ }
+ return() {
+ throw new Error();
+ }
+}
+
+let iterator = new ThrowingIterator();
+iterator.reduce(() => {}, 0);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/reduce/next-method-returns-throwing-value.js b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/next-method-returns-throwing-value.js
new file mode 100644
index 0000000000..7dd83c4881
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/next-method-returns-throwing-value.js
@@ -0,0 +1,34 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.reduce
+description: >
+ Underlying iterator next returns object with throwing value getter
+info: |
+ %Iterator.prototype%.reduce ( reducer )
+
+features: [iterator-helpers]
+flags: []
+---*/
+class ThrowingIterator extends Iterator {
+ next() {
+ return {
+ done: false,
+ get value() {
+ throw new Test262Error();
+ },
+ };
+ }
+ return() {
+ throw new Error();
+ }
+}
+
+let iterator = new ThrowingIterator();
+
+assert.throws(Test262Error, function () {
+ iterator.reduce(() => {});
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/reduce/next-method-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/next-method-throws.js
new file mode 100644
index 0000000000..6907971b8b
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/next-method-throws.js
@@ -0,0 +1,30 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.reduce
+description: >
+ Underlying iterator has throwing next method
+info: |
+ %Iterator.prototype%.reduce ( reducer )
+
+features: [iterator-helpers]
+flags: []
+---*/
+class ThrowingIterator extends Iterator {
+ next() {
+ throw new Test262Error();
+ }
+}
+
+let iterator = new ThrowingIterator();
+
+assert.throws(Test262Error, function () {
+ iterator.reduce(() => {});
+});
+
+assert.throws(Test262Error, function () {
+ iterator.reduce(() => {}, 0);
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/reduce/non-callable-reducer.js b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/non-callable-reducer.js
new file mode 100644
index 0000000000..424d97e44b
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/non-callable-reducer.js
@@ -0,0 +1,25 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.reduce
+description: >
+ Iterator.prototype.reduce expects to be called with a callable argument.
+info: |
+ %Iterator.prototype%.reduce ( reducer )
+
+features: [iterator-helpers]
+flags: []
+---*/
+let nonCallable = {};
+let iterator = (function* () {
+ yield 1;
+})();
+
+assert.throws(TypeError, function () {
+ iterator.reduce(nonCallable);
+});
+
+iterator.reduce(() => {});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/reduce/non-constructible.js b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/non-constructible.js
new file mode 100644
index 0000000000..cd3468b6f2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/non-constructible.js
@@ -0,0 +1,35 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.reduce
+description: >
+ Iterator.prototype.reduce is not constructible.
+
+ Built-in function objects that are not identified as constructors do not implement the [[Construct]] internal method unless otherwise specified in the description of a particular function.
+features: [iterator-helpers]
+---*/
+function* g() {}
+let iter = g();
+
+assert.throws(TypeError, () => {
+ new iter.reduce();
+});
+
+assert.throws(TypeError, () => {
+ new iter.reduce(() => {});
+});
+
+assert.throws(TypeError, () => {
+ new iter.reduce(() => {}, 0);
+});
+
+assert.throws(TypeError, () => {
+ new Iterator.prototype.reduce(() => {}, 0);
+});
+
+assert.throws(TypeError, () => {
+ new class extends Iterator {}.reduce(() => {}, 0);
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/reduce/prop-desc.js b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/prop-desc.js
new file mode 100644
index 0000000000..5578ba8ab5
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/prop-desc.js
@@ -0,0 +1,28 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.reduce
+description: >
+ Property descriptor of Iterator.prototype.reduce
+info: |
+ Iterator.prototype.reduce
+
+ * is the initial value of the Iterator.prototype.reduce property of the global object.
+
+ 17 ECMAScript Standard Built-in Objects
+
+ every other data property described in clauses 18 through 26 and in Annex B.2
+ has the attributes { [[Writable]]: true, [[Enumerable]]: false,
+ [[Configurable]]: true } unless otherwise specified.
+features: [globalThis, iterator-helpers]
+includes: [propertyHelper.js]
+---*/
+
+verifyProperty(Iterator.prototype, 'reduce', {
+ writable: true,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/reduce/proto.js b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/proto.js
new file mode 100644
index 0000000000..218513991c
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/proto.js
@@ -0,0 +1,14 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.reduce
+description: >
+ The value of the [[Prototype]] internal slot of Iterator.prototype.reduce is the
+ intrinsic object %Function%.
+features: [iterator-helpers]
+---*/
+
+assert.sameValue(Object.getPrototypeOf(Iterator.prototype.reduce), Function.prototype);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/reduce/reducer-args-initial-value.js b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/reducer-args-initial-value.js
new file mode 100644
index 0000000000..316c32fc1d
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/reducer-args-initial-value.js
@@ -0,0 +1,48 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.reduce
+description: >
+ Iterator.prototype.reduce reducer is passed the yielded value and a counter as arguments
+info: |
+ %Iterator.prototype%.reduce ( reducer )
+
+features: [iterator-helpers]
+flags: []
+---*/
+function* g() {
+ yield 'a';
+ yield 'b';
+ yield 'c';
+}
+
+let iter = g();
+
+let assertionCount = 0;
+let initialValue = {};
+let result = iter.reduce((memo, v, count) => {
+ switch (v) {
+ case 'a':
+ assert.sameValue(memo, initialValue);
+ assert.sameValue(count, 0);
+ break;
+ case 'b':
+ assert.sameValue(memo, 'a');
+ assert.sameValue(count, 1);
+ break;
+ case 'c':
+ assert.sameValue(memo, 'b');
+ assert.sameValue(count, 2);
+ break;
+ default:
+ throw new Error();
+ }
+ ++assertionCount;
+ return v;
+}, initialValue);
+
+assert.sameValue(result, 'c');
+assert.sameValue(assertionCount, 3);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/reduce/reducer-args-no-initial-value.js b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/reducer-args-no-initial-value.js
new file mode 100644
index 0000000000..ac637391aa
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/reducer-args-no-initial-value.js
@@ -0,0 +1,44 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.reduce
+description: >
+ Iterator.prototype.reduce reducer is passed the yielded value and a counter as arguments
+info: |
+ %Iterator.prototype%.reduce ( reducer )
+
+features: [iterator-helpers]
+flags: []
+---*/
+function* g() {
+ yield 'a';
+ yield 'b';
+ yield 'c';
+}
+
+let iter = g();
+
+let assertionCount = 0;
+let result = iter.reduce((memo, v, count) => {
+ switch (v) {
+ case 'b':
+ assert.sameValue(memo, 'a');
+ assert.sameValue(count, 1);
+ break;
+ case 'c':
+ assert.sameValue(memo, 'b');
+ assert.sameValue(count, 2);
+ break;
+ case 'a':
+ default:
+ throw new Error();
+ }
+ ++assertionCount;
+ return v;
+});
+
+assert.sameValue(result, 'c');
+assert.sameValue(assertionCount, 2);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/reduce/reducer-memo-can-be-any-type.js b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/reducer-memo-can-be-any-type.js
new file mode 100644
index 0000000000..8d2802f4de
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/reducer-memo-can-be-any-type.js
@@ -0,0 +1,34 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.reduce
+description: >
+ Iterator.prototype.reduce reducer can return any ECMAScript language value
+info: |
+ %Iterator.prototype%.reduce ( reducer )
+
+features: [iterator-helpers]
+flags: []
+---*/
+
+const values = [undefined, null, true, false, 0, -0, 1, NaN, Infinity, "string", Symbol(), 0n, {}, [], () => {}];
+
+let iter = values[Symbol.iterator]();
+
+let assertionCount = 0;
+let initialValue = {};
+let result = iter.reduce((memo, v, count) => {
+ if (count == 0) {
+ assert.sameValue(memo, initialValue);
+ } else {
+ assert.sameValue(memo, values[count - 1]);
+ }
+ ++assertionCount;
+ return v;
+}, initialValue);
+
+assert.sameValue(result, values[values.length - 1]);
+assert.sameValue(assertionCount, values.length);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/reduce/reducer-this.js b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/reducer-this.js
new file mode 100644
index 0000000000..91cb6c7b36
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/reducer-this.js
@@ -0,0 +1,35 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.reduce
+description: >
+ Iterator.prototype.reduce reducer this value is undefined
+info: |
+ %Iterator.prototype%.reduce ( reducer )
+
+features: [iterator-helpers]
+flags: []
+---*/
+function* g() {
+ yield 0;
+ yield 1;
+}
+
+let iter = g();
+
+let expectedThis = function () {
+ return this;
+}.call(undefined);
+
+let assertionCount = 0;
+let result = iter.reduce(function (memo, v, count) {
+ assert.sameValue(this, expectedThis);
+ ++assertionCount;
+ return memo;
+});
+
+assert.sameValue(result, 0);
+assert.sameValue(assertionCount, 1);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/reduce/reducer-throws-then-closing-iterator-also-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/reducer-throws-then-closing-iterator-also-throws.js
new file mode 100644
index 0000000000..020a37db48
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/reducer-throws-then-closing-iterator-also-throws.js
@@ -0,0 +1,39 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.reduce
+description: >
+ Attempts to close iterator when reducer throws, but that throws
+info: |
+ %Iterator.prototype%.reduce ( reducer )
+
+features: [iterator-helpers]
+flags: []
+---*/
+let returnCalls = 0;
+
+class TestIterator extends Iterator {
+ next() {
+ return {
+ done: false,
+ value: 1,
+ };
+ }
+ return() {
+ ++returnCalls;
+ throw new Error();
+ }
+}
+
+let iterator = new TestIterator();
+
+assert.throws(Test262Error, function () {
+ iterator.reduce(() => {
+ throw new Test262Error();
+ });
+});
+
+assert.sameValue(returnCalls, 1);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/reduce/reducer-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/reducer-throws.js
new file mode 100644
index 0000000000..a2be3a86c8
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/reducer-throws.js
@@ -0,0 +1,43 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.reduce
+description: >
+ Closes iterator and throws when reducer throws
+info: |
+ %Iterator.prototype%.reduce ( reducer )
+
+features: [iterator-helpers]
+flags: []
+---*/
+let returnCalls = 0;
+
+class TestIterator extends Iterator {
+ next() {
+ return {
+ done: false,
+ value: 1,
+ };
+ }
+ return() {
+ ++returnCalls;
+ return {};
+ }
+}
+
+let iterator = new TestIterator();
+
+let callbackCalls = 0;
+
+assert.throws(Test262Error, function () {
+ iterator.reduce(() => {
+ ++callbackCalls;
+ throw new Test262Error();
+ });
+});
+
+assert.sameValue(callbackCalls, 1);
+assert.sameValue(returnCalls, 1);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/reduce/shell.js b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/shell.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/shell.js
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/reduce/this-non-callable-next.js b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/this-non-callable-next.js
new file mode 100644
index 0000000000..c8ee441091
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/this-non-callable-next.js
@@ -0,0 +1,18 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.reduce
+description: >
+ Iterator.prototype.reduce throws TypeError when its this value is an object with a non-callable next
+info: |
+ %Iterator.prototype%.reduce ( reducer )
+
+features: [iterator-helpers]
+flags: []
+---*/
+assert.throws(TypeError, function () {
+ Iterator.prototype.reduce.call({ next: 0 }, () => {}, 0);
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/reduce/this-non-object.js b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/this-non-object.js
new file mode 100644
index 0000000000..a910b83879
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/this-non-object.js
@@ -0,0 +1,36 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.reduce
+description: >
+ Iterator.prototype.reduce throws TypeError when its this value is a non-object
+info: |
+ %Iterator.prototype%.reduce ( reducer )
+
+features: [iterator-helpers]
+flags: []
+---*/
+assert.throws(TypeError, function () {
+ Iterator.prototype.reduce.call(null, () => {});
+});
+
+assert.throws(TypeError, function () {
+ Iterator.prototype.reduce.call(null, () => {}, 0);
+});
+
+Object.defineProperty(Number.prototype, 'next', {
+ get: function () {
+ throw new Test262Error();
+ },
+});
+
+assert.throws(TypeError, function () {
+ Iterator.prototype.reduce.call(0, () => {});
+});
+
+assert.throws(TypeError, function () {
+ Iterator.prototype.reduce.call(0, () => {}, 0);
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/reduce/this-plain-iterator.js b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/this-plain-iterator.js
new file mode 100644
index 0000000000..ccd2da7c33
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/this-plain-iterator.js
@@ -0,0 +1,35 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.reduce
+description: >
+ Iterator.prototype.reduce supports a this value that does not inherit from Iterator.prototype but implements the iterator protocol
+info: |
+ %Iterator.prototype%.reduce ( reducer )
+
+includes: [compareArray.js]
+features: [iterator-helpers]
+flags: []
+---*/
+let iter = {
+ get next() {
+ let count = 3;
+ return function () {
+ --count;
+ return count >= 0 ? { done: false, value: count } : { done: true, value: undefined };
+ };
+ },
+};
+
+let reducerCalls = 0;
+let result = Iterator.prototype.reduce.call(iter, function (memo, v) {
+ ++reducerCalls;
+ memo.push(v);
+ return memo;
+}, []);
+
+assert.compareArray(result, [2, 1, 0]);
+assert.sameValue(reducerCalls, 3);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/shell.js b/js/src/tests/test262/built-ins/Iterator/prototype/shell.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/shell.js
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/some/argument-effect-order.js b/js/src/tests/test262/built-ins/Iterator/prototype/some/argument-effect-order.js
new file mode 100644
index 0000000000..12c461697e
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/some/argument-effect-order.js
@@ -0,0 +1,33 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.some
+description: >
+ Arguments and this value are evaluated in the correct order
+info: |
+ %Iterator.prototype%.some ( predicate )
+
+includes: [compareArray.js]
+features: [iterator-helpers]
+flags: []
+---*/
+let effects = [];
+
+assert.throws(TypeError, function () {
+ Iterator.prototype.some.call(
+ {
+ get next() {
+ effects.push('get next');
+ return function () {
+ return { done: true, value: undefined };
+ };
+ },
+ },
+ null
+ );
+});
+
+assert.compareArray(effects, []);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/some/browser.js b/js/src/tests/test262/built-ins/Iterator/prototype/some/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/some/browser.js
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/some/callable.js b/js/src/tests/test262/built-ins/Iterator/prototype/some/callable.js
new file mode 100644
index 0000000000..4b67ca0521
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/some/callable.js
@@ -0,0 +1,16 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.some
+description: >
+ Iterator.prototype.some is callable
+features: [iterator-helpers]
+---*/
+function* g() {}
+Iterator.prototype.some.call(g(), () => {});
+
+let iter = g();
+iter.some(() => {});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/some/get-next-method-only-once.js b/js/src/tests/test262/built-ins/Iterator/prototype/some/get-next-method-only-once.js
new file mode 100644
index 0000000000..00b3c28f5b
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/some/get-next-method-only-once.js
@@ -0,0 +1,39 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.some
+description: >
+ Gets the next method from the iterator only once
+info: |
+ %Iterator.prototype%.some ( predicate )
+
+features: [iterator-helpers]
+flags: []
+---*/
+let nextGets = 0;
+
+class TestIterator extends Iterator {
+ get next() {
+ ++nextGets;
+ let counter = 5;
+ return function () {
+ if (counter < 0) {
+ return { done: true, value: undefined };
+ } else {
+ return { done: false, value: --counter };
+ }
+ };
+ }
+}
+
+let iterator = new TestIterator();
+
+assert.sameValue(nextGets, 0);
+assert.sameValue(
+ iterator.some(() => true),
+ true
+);
+assert.sameValue(nextGets, 1);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/some/get-next-method-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/some/get-next-method-throws.js
new file mode 100644
index 0000000000..dfd42bb7ab
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/some/get-next-method-throws.js
@@ -0,0 +1,26 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.some
+description: >
+ Iterator has throwing next getter
+info: |
+ %Iterator.prototype%.some ( predicate )
+
+features: [iterator-helpers]
+flags: []
+---*/
+class IteratorThrows extends Iterator {
+ get next() {
+ throw new Test262Error();
+ }
+}
+
+let iterator = new IteratorThrows();
+
+assert.throws(Test262Error, function () {
+ iterator.some(() => {});
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/some/get-return-method-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/some/get-return-method-throws.js
new file mode 100644
index 0000000000..0493bcbed3
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/some/get-return-method-throws.js
@@ -0,0 +1,32 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.some
+description: >
+ Iterator has throwing return getter
+info: |
+ %Iterator.prototype%.some ( predicate )
+
+features: [iterator-helpers]
+flags: []
+---*/
+class IteratorThrows extends Iterator {
+ next() {
+ return {
+ done: false,
+ value: 0,
+ };
+ }
+ get return() {
+ throw new Test262Error();
+ }
+}
+
+let iterator = new IteratorThrows([1, 2]);
+
+assert.throws(Test262Error, function () {
+ iterator.some(() => true);
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/some/is-function.js b/js/src/tests/test262/built-ins/Iterator/prototype/some/is-function.js
new file mode 100644
index 0000000000..f5f4ac676d
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/some/is-function.js
@@ -0,0 +1,13 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.some
+description: >
+ Iterator.prototype.some is a built-in function
+features: [iterator-helpers]
+---*/
+
+assert.sameValue(typeof Iterator.prototype.some, 'function');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/some/iterator-already-exhausted.js b/js/src/tests/test262/built-ins/Iterator/prototype/some/iterator-already-exhausted.js
new file mode 100644
index 0000000000..94de3a2c98
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/some/iterator-already-exhausted.js
@@ -0,0 +1,26 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.some
+description: >
+ Iterator.prototype.some returns true when the iterator has already been exhausted
+info: |
+ %Iterator.prototype%.some ( predicate )
+
+features: [iterator-helpers]
+flags: []
+---*/
+let iterator = (function* () {})();
+
+let { value, done } = iterator.next();
+assert.sameValue(value, undefined);
+assert.sameValue(done, true);
+
+let result = iterator.some(() => true);
+assert.sameValue(result, false);
+
+result = iterator.some(() => false);
+assert.sameValue(result, false);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/some/iterator-has-no-return.js b/js/src/tests/test262/built-ins/Iterator/prototype/some/iterator-has-no-return.js
new file mode 100644
index 0000000000..514a887484
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/some/iterator-has-no-return.js
@@ -0,0 +1,30 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.some
+description: >
+ The underlying iterator is sometimes unable to be closed (has no return method)
+info: |
+ %Iterator.prototype%.some ( predicate )
+
+features: [iterator-helpers]
+flags: []
+---*/
+let iterator = [1, 2, 3, 4, 5][Symbol.iterator]();
+
+assert.sameValue(iterator.return, undefined);
+
+let ret = iterator.some(v => v > 3);
+
+assert.sameValue(ret, true);
+
+let { done, value } = iterator.next();
+assert.sameValue(done, false);
+assert.sameValue(value, 5);
+
+({ done, value } = iterator.next());
+assert.sameValue(done, true);
+assert.sameValue(value, undefined);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/some/iterator-return-method-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/some/iterator-return-method-throws.js
new file mode 100644
index 0000000000..82bd47cd90
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/some/iterator-return-method-throws.js
@@ -0,0 +1,32 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.some
+description: >
+ Iterator has throwing return
+info: |
+ %Iterator.prototype%.some ( predicate )
+
+features: [iterator-helpers]
+flags: []
+---*/
+class IteratorThrows extends Iterator {
+ next() {
+ return {
+ done: false,
+ value: 0,
+ };
+ }
+ return() {
+ throw new Test262Error();
+ }
+}
+
+let iterator = new IteratorThrows();
+
+assert.throws(Test262Error, function () {
+ iterator.some(() => true);
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/some/length.js b/js/src/tests/test262/built-ins/Iterator/prototype/some/length.js
new file mode 100644
index 0000000000..5c536518b4
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/some/length.js
@@ -0,0 +1,25 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.some
+description: >
+ Iterator.prototype.some has a "length" property whose value is 1.
+info: |
+ ECMAScript Standard Built-in Objects
+
+ Unless otherwise specified, the length property of a built-in
+ Function object has the attributes { [[Writable]]: false, [[Enumerable]]:
+ false, [[Configurable]]: true }.
+features: [iterator-helpers]
+includes: [propertyHelper.js]
+---*/
+
+verifyProperty(Iterator.prototype.some, 'length', {
+ value: 1,
+ writable: false,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/some/name.js b/js/src/tests/test262/built-ins/Iterator/prototype/some/name.js
new file mode 100644
index 0000000000..0a9dc1fd41
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/some/name.js
@@ -0,0 +1,32 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.some
+description: >
+ The "name" property of Iterator.prototype.some
+info: |
+ 17 ECMAScript Standard Built-in Objects
+
+ Every built-in Function object, including constructors, that is not
+ identified as an anonymous function has a name property whose value is a
+ String. Unless otherwise specified, this value is the name that is given to
+ the function in this specification.
+
+ ...
+
+ Unless otherwise specified, the name property of a built-in Function
+ object, if it exists, has the attributes { [[Writable]]: false,
+ [[Enumerable]]: false, [[Configurable]]: true }.
+features: [iterator-helpers]
+includes: [propertyHelper.js]
+---*/
+
+verifyProperty(Iterator.prototype.some, 'name', {
+ value: 'some',
+ writable: false,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/some/next-method-returns-non-object.js b/js/src/tests/test262/built-ins/Iterator/prototype/some/next-method-returns-non-object.js
new file mode 100644
index 0000000000..08317fcbd5
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/some/next-method-returns-non-object.js
@@ -0,0 +1,26 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.some
+description: >
+ Underlying iterator next returns non-object
+info: |
+ %Iterator.prototype%.some ( predicate )
+
+features: [iterator-helpers]
+flags: []
+---*/
+class NonObjectIterator extends Iterator {
+ next() {
+ return null;
+ }
+}
+
+let iterator = new NonObjectIterator();
+
+assert.throws(TypeError, function () {
+ iterator.some(() => {});
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/some/next-method-returns-throwing-done.js b/js/src/tests/test262/built-ins/Iterator/prototype/some/next-method-returns-throwing-done.js
new file mode 100644
index 0000000000..0932c31658
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/some/next-method-returns-throwing-done.js
@@ -0,0 +1,34 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.some
+description: >
+ Underlying iterator next returns object with throwing done getter
+info: |
+ %Iterator.prototype%.some ( predicate )
+
+features: [iterator-helpers]
+flags: []
+---*/
+class ThrowingIterator extends Iterator {
+ next() {
+ return {
+ get done() {
+ throw new Test262Error();
+ },
+ value: 1,
+ };
+ }
+ return() {
+ throw new Error();
+ }
+}
+
+let iterator = new ThrowingIterator();
+
+assert.throws(Test262Error, function () {
+ iterator.some(() => {});
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/some/next-method-returns-throwing-value-done.js b/js/src/tests/test262/built-ins/Iterator/prototype/some/next-method-returns-throwing-value-done.js
new file mode 100644
index 0000000000..f130e25afe
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/some/next-method-returns-throwing-value-done.js
@@ -0,0 +1,31 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.some
+description: >
+ Underlying iterator next returns object with throwing value getter, but is already done
+info: |
+ %Iterator.prototype%.some ( predicate )
+
+features: [iterator-helpers]
+flags: []
+---*/
+class ThrowingIterator extends Iterator {
+ next() {
+ return {
+ done: true,
+ get value() {
+ throw new Test262Error();
+ },
+ };
+ }
+ return() {
+ throw new Error();
+ }
+}
+
+let iterator = new ThrowingIterator();
+iterator.some(() => {});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/some/next-method-returns-throwing-value.js b/js/src/tests/test262/built-ins/Iterator/prototype/some/next-method-returns-throwing-value.js
new file mode 100644
index 0000000000..8ce95dec1d
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/some/next-method-returns-throwing-value.js
@@ -0,0 +1,34 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.some
+description: >
+ Underlying iterator next returns object with throwing value getter
+info: |
+ %Iterator.prototype%.some ( predicate )
+
+features: [iterator-helpers]
+flags: []
+---*/
+class ThrowingIterator extends Iterator {
+ next() {
+ return {
+ done: false,
+ get value() {
+ throw new Test262Error();
+ },
+ };
+ }
+ return() {
+ throw new Error();
+ }
+}
+
+let iterator = new ThrowingIterator();
+
+assert.throws(Test262Error, function () {
+ iterator.some(() => {});
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/some/next-method-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/some/next-method-throws.js
new file mode 100644
index 0000000000..273c6d8deb
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/some/next-method-throws.js
@@ -0,0 +1,26 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.some
+description: >
+ Underlying iterator has throwing next method
+info: |
+ %Iterator.prototype%.some ( predicate )
+
+features: [iterator-helpers]
+flags: []
+---*/
+class ThrowingIterator extends Iterator {
+ next() {
+ throw new Test262Error();
+ }
+}
+
+let iterator = new ThrowingIterator();
+
+assert.throws(Test262Error, function () {
+ iterator.some(() => {});
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/some/non-callable-predicate.js b/js/src/tests/test262/built-ins/Iterator/prototype/some/non-callable-predicate.js
new file mode 100644
index 0000000000..9a94690966
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/some/non-callable-predicate.js
@@ -0,0 +1,23 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.some
+description: >
+ Iterator.prototype.some expects to be called with a callable argument.
+info: |
+ %Iterator.prototype%.some ( predicate )
+
+features: [iterator-helpers]
+flags: []
+---*/
+let nonCallable = {};
+let iterator = (function* () {
+ yield 1;
+})();
+
+assert.throws(TypeError, function () {
+ iterator.some(nonCallable);
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/some/non-constructible.js b/js/src/tests/test262/built-ins/Iterator/prototype/some/non-constructible.js
new file mode 100644
index 0000000000..0b8e53f88b
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/some/non-constructible.js
@@ -0,0 +1,31 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.some
+description: >
+ Iterator.prototype.some is not constructible.
+
+ Built-in function objects that are not identified as constructors do not implement the [[Construct]] internal method unless otherwise specified in the description of a particular function.
+features: [iterator-helpers]
+---*/
+function* g() {}
+let iter = g();
+
+assert.throws(TypeError, () => {
+ new iter.some();
+});
+
+assert.throws(TypeError, () => {
+ new iter.some(() => {});
+});
+
+assert.throws(TypeError, () => {
+ new Iterator.prototype.some(() => {});
+});
+
+assert.throws(TypeError, () => {
+ new class extends Iterator {}.some(() => {});
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/some/predicate-args.js b/js/src/tests/test262/built-ins/Iterator/prototype/some/predicate-args.js
new file mode 100644
index 0000000000..6c270d47f6
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/some/predicate-args.js
@@ -0,0 +1,44 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.some
+description: >
+ Iterator.prototype.some predicate is passed the yielded value and a counter as arguments
+info: |
+ %Iterator.prototype%.some ( predicate )
+
+features: [iterator-helpers]
+flags: []
+---*/
+function* g() {
+ yield 'a';
+ yield 'b';
+ yield 'c';
+}
+
+let iter = g();
+
+let assertionCount = 0;
+let result = iter.some((v, count) => {
+ switch (v) {
+ case 'a':
+ assert.sameValue(count, 0);
+ break;
+ case 'b':
+ assert.sameValue(count, 1);
+ break;
+ case 'c':
+ assert.sameValue(count, 2);
+ break;
+ default:
+ throw new Error();
+ }
+ ++assertionCount;
+ return false;
+});
+
+assert.sameValue(result, false);
+assert.sameValue(assertionCount, 3);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/some/predicate-returns-falsey-then-truthy.js b/js/src/tests/test262/built-ins/Iterator/prototype/some/predicate-returns-falsey-then-truthy.js
new file mode 100644
index 0000000000..b3171a85ff
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/some/predicate-returns-falsey-then-truthy.js
@@ -0,0 +1,35 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.some
+description: >
+ Iterator.prototype.some returns true and closes the iterator when the predicate returns falsey for some iterated values and truthy for others
+info: |
+ %Iterator.prototype%.some ( predicate )
+
+features: [iterator-helpers]
+flags: []
+---*/
+function* g() {
+ for (let i = 0; i < 5; ++i) {
+ yield i;
+ }
+}
+
+let iter = g();
+
+let predicateCalls = 0;
+let result = iter.some(v => {
+ ++predicateCalls;
+ return v > 2;
+});
+
+assert.sameValue(result, true);
+assert.sameValue(predicateCalls, 4);
+
+let { done, value } = iter.next();
+assert.sameValue(done, true);
+assert.sameValue(value, undefined);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/some/predicate-returns-falsey.js b/js/src/tests/test262/built-ins/Iterator/prototype/some/predicate-returns-falsey.js
new file mode 100644
index 0000000000..7b7d91a449
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/some/predicate-returns-falsey.js
@@ -0,0 +1,24 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.some
+description: >
+ Iterator.prototype.some returns false when the predicate returns falsey for all iterated values
+info: |
+ %Iterator.prototype%.some ( predicate )
+
+features: [iterator-helpers]
+flags: []
+---*/
+function* g() {
+ yield 0;
+ yield 1;
+ yield 2;
+ yield 3;
+}
+
+let result = g().some(() => false);
+assert.sameValue(result, false);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/some/predicate-returns-non-boolean.js b/js/src/tests/test262/built-ins/Iterator/prototype/some/predicate-returns-non-boolean.js
new file mode 100644
index 0000000000..18ee4764ba
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/some/predicate-returns-non-boolean.js
@@ -0,0 +1,35 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.some
+description: >
+ Iterator.prototype.some coerces predicate return value to boolean
+info: |
+ %Iterator.prototype%.some ( predicate )
+
+features: [iterator-helpers]
+flags: []
+---*/
+function* g() {
+ yield '';
+ yield null;
+ yield undefined;
+ yield 0;
+ yield 1;
+ yield 2;
+ yield 3;
+}
+
+let iter = g();
+
+let predicateCalls = 0;
+let result = iter.some(v => {
+ ++predicateCalls;
+ return v;
+});
+
+assert.sameValue(result, true);
+assert.sameValue(predicateCalls, 5);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/some/predicate-returns-truthy.js b/js/src/tests/test262/built-ins/Iterator/prototype/some/predicate-returns-truthy.js
new file mode 100644
index 0000000000..25b0769304
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/some/predicate-returns-truthy.js
@@ -0,0 +1,35 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.some
+description: >
+ Iterator.prototype.some returns true and closes the iterator when the predicate returns truthy immediately
+info: |
+ %Iterator.prototype%.some ( predicate )
+
+features: [iterator-helpers]
+flags: []
+---*/
+function* g() {
+ yield 0;
+ yield 1;
+ yield 2;
+}
+
+let iter = g();
+
+let predicateCalls = 0;
+let result = iter.some(v => {
+ ++predicateCalls;
+ return true;
+});
+
+assert.sameValue(result, true);
+assert.sameValue(predicateCalls, 1);
+
+let { done, value } = iter.next();
+assert.sameValue(done, true);
+assert.sameValue(value, undefined);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/some/predicate-this.js b/js/src/tests/test262/built-ins/Iterator/prototype/some/predicate-this.js
new file mode 100644
index 0000000000..0ae8609b55
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/some/predicate-this.js
@@ -0,0 +1,34 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.some
+description: >
+ Iterator.prototype.some predicate this value is undefined
+info: |
+ %Iterator.prototype%.some ( predicate )
+
+features: [iterator-helpers]
+flags: []
+---*/
+function* g() {
+ yield 0;
+}
+
+let iter = g();
+
+let expectedThis = function () {
+ return this;
+}.call(undefined);
+
+let assertionCount = 0;
+let result = iter.some(function (v, count) {
+ assert.sameValue(this, expectedThis);
+ ++assertionCount;
+ return true;
+});
+
+assert.sameValue(result, true);
+assert.sameValue(assertionCount, 1);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/some/predicate-throws-then-closing-iterator-also-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/some/predicate-throws-then-closing-iterator-also-throws.js
new file mode 100644
index 0000000000..2ccd16d92a
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/some/predicate-throws-then-closing-iterator-also-throws.js
@@ -0,0 +1,39 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.some
+description: >
+ Attempts to close iterator when predicate throws, but that throws
+info: |
+ %Iterator.prototype%.some ( predicate )
+
+features: [iterator-helpers]
+flags: []
+---*/
+let returnCalls = 0;
+
+class TestIterator extends Iterator {
+ next() {
+ return {
+ done: false,
+ value: 1,
+ };
+ }
+ return() {
+ ++returnCalls;
+ throw new Error();
+ }
+}
+
+let iterator = new TestIterator();
+
+assert.throws(Test262Error, function () {
+ iterator.some(() => {
+ throw new Test262Error();
+ });
+});
+
+assert.sameValue(returnCalls, 1);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/some/predicate-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/some/predicate-throws.js
new file mode 100644
index 0000000000..a39878fa25
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/some/predicate-throws.js
@@ -0,0 +1,43 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.some
+description: >
+ Closes iterator and throws when predicate throws
+info: |
+ %Iterator.prototype%.some ( predicate )
+
+features: [iterator-helpers]
+flags: []
+---*/
+let returnCalls = 0;
+
+class TestIterator extends Iterator {
+ next() {
+ return {
+ done: false,
+ value: 1,
+ };
+ }
+ return() {
+ ++returnCalls;
+ return {};
+ }
+}
+
+let iterator = new TestIterator();
+
+let callbackCalls = 0;
+
+assert.throws(Test262Error, function () {
+ iterator.some(() => {
+ ++callbackCalls;
+ throw new Test262Error();
+ });
+});
+
+assert.sameValue(callbackCalls, 1);
+assert.sameValue(returnCalls, 1);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/some/prop-desc.js b/js/src/tests/test262/built-ins/Iterator/prototype/some/prop-desc.js
new file mode 100644
index 0000000000..ded03f7c7f
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/some/prop-desc.js
@@ -0,0 +1,28 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.some
+description: >
+ Property descriptor of Iterator.prototype.some
+info: |
+ Iterator.prototype.some
+
+ * is the initial value of the Iterator.prototype.some property of the global object.
+
+ 17 ECMAScript Standard Built-in Objects
+
+ every other data property described in clauses 18 through 26 and in Annex B.2
+ has the attributes { [[Writable]]: true, [[Enumerable]]: false,
+ [[Configurable]]: true } unless otherwise specified.
+features: [globalThis, iterator-helpers]
+includes: [propertyHelper.js]
+---*/
+
+verifyProperty(Iterator.prototype, 'some', {
+ writable: true,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/some/proto.js b/js/src/tests/test262/built-ins/Iterator/prototype/some/proto.js
new file mode 100644
index 0000000000..24eeda1679
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/some/proto.js
@@ -0,0 +1,14 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.some
+description: >
+ The value of the [[Prototype]] internal slot of Iterator.prototype.some is the
+ intrinsic object %Function%.
+features: [iterator-helpers]
+---*/
+
+assert.sameValue(Object.getPrototypeOf(Iterator.prototype.some), Function.prototype);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/some/result-is-boolean.js b/js/src/tests/test262/built-ins/Iterator/prototype/some/result-is-boolean.js
new file mode 100644
index 0000000000..d92e6df618
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/some/result-is-boolean.js
@@ -0,0 +1,14 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.some
+description: >
+ Iterator.prototype.some returns a boolean
+features: [iterator-helpers]
+---*/
+function* g() {}
+let iter = g();
+assert.sameValue(typeof iter.some(() => {}), 'boolean');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/some/shell.js b/js/src/tests/test262/built-ins/Iterator/prototype/some/shell.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/some/shell.js
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/some/this-non-callable-next.js b/js/src/tests/test262/built-ins/Iterator/prototype/some/this-non-callable-next.js
new file mode 100644
index 0000000000..18e57c87a6
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/some/this-non-callable-next.js
@@ -0,0 +1,18 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.some
+description: >
+ Iterator.prototype.some throws TypeError when its this value is an object with a non-callable next
+info: |
+ %Iterator.prototype%.some ( predicate )
+
+features: [iterator-helpers]
+flags: []
+---*/
+assert.throws(TypeError, function () {
+ Iterator.prototype.some.call({ next: 0 }, () => true);
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/some/this-non-object.js b/js/src/tests/test262/built-ins/Iterator/prototype/some/this-non-object.js
new file mode 100644
index 0000000000..136fe18fb8
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/some/this-non-object.js
@@ -0,0 +1,27 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.some
+description: >
+ Iterator.prototype.some throws TypeError when its this value is a non-object
+info: |
+ %Iterator.prototype%.some ( predicate )
+
+features: [iterator-helpers]
+flags: []
+---*/
+assert.throws(TypeError, function () {
+ Iterator.prototype.some.call(null, () => {});
+});
+
+Object.defineProperty(Number.prototype, 'next', {
+ get: function () {
+ throw new Test262Error();
+ },
+});
+assert.throws(TypeError, function () {
+ Iterator.prototype.some.call(0, () => {});
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/some/this-plain-iterator.js b/js/src/tests/test262/built-ins/Iterator/prototype/some/this-plain-iterator.js
new file mode 100644
index 0000000000..949f1dbc8e
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/some/this-plain-iterator.js
@@ -0,0 +1,33 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.some
+description: >
+ Iterator.prototype.some supports a this value that does not inherit from Iterator.prototype but implements the iterator protocol
+info: |
+ %Iterator.prototype%.some ( predicate )
+
+features: [iterator-helpers]
+flags: []
+---*/
+let iter = {
+ get next() {
+ let count = 3;
+ return function () {
+ --count;
+ return count >= 0 ? { done: false, value: count } : { done: true, value: undefined };
+ };
+ },
+};
+
+let predicateCalls = 0;
+let result = Iterator.prototype.some.call(iter, function (v) {
+ ++predicateCalls;
+ return v === 0;
+});
+
+assert.sameValue(result, true);
+assert.sameValue(predicateCalls, 3);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/take/argument-effect-order.js b/js/src/tests/test262/built-ins/Iterator/prototype/take/argument-effect-order.js
new file mode 100644
index 0000000000..942c379c79
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/take/argument-effect-order.js
@@ -0,0 +1,75 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.take
+description: >
+ Arguments and this value are evaluated in the correct order
+info: |
+ %Iterator.prototype%.take ( limit )
+
+ 1. Let O be the this value.
+ 2. If O is not an Object, throw a TypeError exception.
+ 3. Let numLimit be ? ToNumber(limit).
+ 4. If numLimit is NaN, throw a RangeError exception.
+ 5. Let integerLimit be ! ToIntegerOrInfinity(numLimit).
+ 6. If integerLimit < 0, throw a RangeError exception.
+ 7. Let iterated be ? GetIteratorDirect(O).
+
+includes: [compareArray.js]
+features: [iterator-helpers]
+flags: []
+---*/
+let effects = [];
+
+Iterator.prototype.take.call(
+ {
+ get next() {
+ effects.push('get next');
+ return function () {
+ return { done: true, value: undefined };
+ };
+ },
+ },
+ {
+ valueOf() {
+ effects.push('ToNumber limit');
+ return 0;
+ },
+ }
+);
+
+assert.compareArray(effects, ['ToNumber limit', 'get next']);
+
+effects = [];
+
+assert.throws(TypeError, function () {
+ Iterator.prototype.take.call(null, {
+ valueOf() {
+ effects.push('ToNumber limit');
+ return 0;
+ },
+ });
+});
+
+assert.compareArray(effects, []);
+
+effects = [];
+
+assert.throws(RangeError, function () {
+ Iterator.prototype.take.call(
+ {
+ get next() {
+ effects.push('get next');
+ return function () {
+ return { done: true, value: undefined };
+ };
+ },
+ },
+ NaN
+ );
+});
+
+assert.compareArray(effects, []);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/take/browser.js b/js/src/tests/test262/built-ins/Iterator/prototype/take/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/take/browser.js
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/take/callable.js b/js/src/tests/test262/built-ins/Iterator/prototype/take/callable.js
new file mode 100644
index 0000000000..adb37486b4
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/take/callable.js
@@ -0,0 +1,16 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.take
+description: >
+ Iterator.prototype.take is callable
+features: [iterator-helpers]
+---*/
+function* g() {}
+Iterator.prototype.take.call(g(), 0);
+
+let iter = g();
+iter.take(0);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/take/exhaustion-calls-return.js b/js/src/tests/test262/built-ins/Iterator/prototype/take/exhaustion-calls-return.js
new file mode 100644
index 0000000000..67a51cc926
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/take/exhaustion-calls-return.js
@@ -0,0 +1,71 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.take
+description: >
+ Underlying iterator return is called when result iterator is exhausted
+info: |
+ %Iterator.prototype%.take ( limit )
+
+ 8.b.i. If remaining is 0, then
+ 8.b.i.1. Return ? IteratorClose(iterated, NormalCompletion(undefined)).
+
+features: [iterator-helpers]
+flags: []
+---*/
+function* g() {
+ yield 0;
+ yield 1;
+ yield 2;
+}
+
+class TestIterator extends Iterator {
+ get next() {
+ let n = g();
+ return function() {
+ return n.next();
+ };
+ }
+ return() {
+ throw new Test262Error();
+ }
+}
+
+let iterator = new TestIterator();
+iterator = iterator.take(0);
+assert.throws(Test262Error, function () {
+ iterator.next();
+});
+iterator.next();
+iterator.next();
+
+iterator = new TestIterator();
+iterator = iterator.take(1);
+iterator.next();
+assert.throws(Test262Error, function () {
+ iterator.next();
+});
+iterator.next();
+iterator.next();
+
+iterator = new TestIterator();
+iterator = iterator.take(1).take(1).take(1).take(1).take(1);
+iterator.next();
+assert.throws(Test262Error, function () {
+ iterator.next();
+});
+iterator.next();
+iterator.next();
+
+iterator = new TestIterator();
+iterator = iterator.take(5);
+iterator.next();
+iterator.next();
+iterator.next();
+iterator.next();
+iterator.next();
+iterator.next();
+iterator.next();
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/take/get-next-method-only-once.js b/js/src/tests/test262/built-ins/Iterator/prototype/take/get-next-method-only-once.js
new file mode 100644
index 0000000000..2aba39ecde
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/take/get-next-method-only-once.js
@@ -0,0 +1,44 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.take
+description: >
+ Gets the next method from the underlying iterator only once
+info: |
+ %Iterator.prototype%.take ( limit )
+
+ 7. Let iterated be ? GetIteratorDirect(this value).
+
+features: [iterator-helpers]
+flags: []
+---*/
+let nextGets = 0;
+let nextCalls = 0;
+
+class CountingIterator extends Iterator {
+ get next() {
+ ++nextGets;
+ let iter = (function* () {
+ for (let i = 1; i < 5; ++i) {
+ yield i;
+ }
+ })();
+ return function () {
+ ++nextCalls;
+ return iter.next();
+ };
+ }
+}
+
+let iterator = new CountingIterator();
+
+assert.sameValue(nextGets, 0);
+assert.sameValue(nextCalls, 0);
+
+for (const value of iterator.take(2));
+
+assert.sameValue(nextGets, 1);
+assert.sameValue(nextCalls, 2);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/take/get-next-method-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/take/get-next-method-throws.js
new file mode 100644
index 0000000000..75176f7aa6
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/take/get-next-method-throws.js
@@ -0,0 +1,28 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.take
+description: >
+ Underlying iterator has throwing next getter
+info: |
+ %Iterator.prototype%.take ( limit )
+
+ 7. Let iterated be ? GetIteratorDirect(this value).
+
+features: [iterator-helpers]
+flags: []
+---*/
+class ThrowingIterator extends Iterator {
+ get next() {
+ throw new Test262Error();
+ }
+}
+
+let iterator = new ThrowingIterator();
+
+assert.throws(Test262Error, function () {
+ iterator.take(0);
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/take/get-return-method-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/take/get-return-method-throws.js
new file mode 100644
index 0000000000..cbd9528cd5
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/take/get-return-method-throws.js
@@ -0,0 +1,33 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.take
+description: >
+ Underlying iterator return is throwing getter
+info: |
+ %Iterator.prototype%.take ( limit )
+
+features: [iterator-helpers]
+flags: []
+---*/
+class TestIterator extends Iterator {
+ next() {
+ return {
+ done: false,
+ value: 1,
+ };
+ }
+ get return() {
+ throw new Test262Error();
+ }
+}
+
+let iterator = new TestIterator().take(1);
+iterator.next();
+
+assert.throws(Test262Error, function () {
+ iterator.return();
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/take/is-function.js b/js/src/tests/test262/built-ins/Iterator/prototype/take/is-function.js
new file mode 100644
index 0000000000..98d95a8360
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/take/is-function.js
@@ -0,0 +1,13 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.take
+description: >
+ Iterator.prototype.take is a built-in function
+features: [iterator-helpers]
+---*/
+
+assert.sameValue(typeof Iterator.prototype.take, 'function');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/take/length.js b/js/src/tests/test262/built-ins/Iterator/prototype/take/length.js
new file mode 100644
index 0000000000..3bf59e4234
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/take/length.js
@@ -0,0 +1,25 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.take
+description: >
+ Iterator.prototype.take has a "length" property whose value is 1.
+info: |
+ ECMAScript Standard Built-in Objects
+
+ Unless otherwise specified, the length property of a built-in
+ Function object has the attributes { [[Writable]]: false, [[Enumerable]]:
+ false, [[Configurable]]: true }.
+features: [iterator-helpers]
+includes: [propertyHelper.js]
+---*/
+
+verifyProperty(Iterator.prototype.take, 'length', {
+ value: 1,
+ writable: false,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/take/limit-greater-than-or-equal-to-total.js b/js/src/tests/test262/built-ins/Iterator/prototype/take/limit-greater-than-or-equal-to-total.js
new file mode 100644
index 0000000000..431fede456
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/take/limit-greater-than-or-equal-to-total.js
@@ -0,0 +1,30 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.take
+description: >
+ Takes entries from this iterator until it is exhausted or the limit is reached.
+info: |
+ %Iterator.prototype%.take ( limit )
+
+ 8.b.iii. Let next be ? IteratorStep(iterated).
+ 8.b.iv. If next is false, return undefined.
+
+includes: [compareArray.js]
+features: [iterator-helpers]
+flags: []
+---*/
+function* g() {
+ yield 0;
+ yield 1;
+ yield 2;
+}
+
+assert.compareArray(Array.from(g().take(3)), [0, 1, 2]);
+assert.compareArray(Array.from(g().take(4)), [0, 1, 2]);
+assert.compareArray(Array.from(g().take(5)), [0, 1, 2]);
+assert.compareArray(Array.from(g().take(Number.MAX_SAFE_INTEGER)), [0, 1, 2]);
+assert.compareArray(Array.from(g().take(Infinity)), [0, 1, 2]);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/take/limit-less-than-total.js b/js/src/tests/test262/built-ins/Iterator/prototype/take/limit-less-than-total.js
new file mode 100644
index 0000000000..008b937adb
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/take/limit-less-than-total.js
@@ -0,0 +1,31 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.take
+description: >
+ Takes entries from this iterator until the limit is reached.
+info: |
+ %Iterator.prototype%.take ( limit )
+
+ 8.b.i If remaining is 0, then
+ 8.b.i.1. Return ? IteratorClose(iterated, NormalCompletion(undefined)).
+
+includes: [compareArray.js]
+features: [iterator-helpers]
+flags: []
+---*/
+function* g() {
+ let i = 0;
+ while (true) {
+ yield i;
+ ++i;
+ }
+}
+
+assert.compareArray(Array.from(g().take(0)), []);
+assert.compareArray(Array.from(g().take(1)), [0]);
+assert.compareArray(Array.from(g().take(2)), [0, 1]);
+assert.compareArray(Array.from(g().take(3)), [0, 1, 2]);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/take/limit-rangeerror.js b/js/src/tests/test262/built-ins/Iterator/prototype/take/limit-rangeerror.js
new file mode 100644
index 0000000000..7f7249f2f0
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/take/limit-rangeerror.js
@@ -0,0 +1,39 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.take
+description: >
+ Throws a RangeError exception when limit argument is NaN or less than 0.
+info: |
+ %Iterator.prototype%.take ( limit )
+
+ 4. If numLimit is NaN, throw a RangeError exception.
+ 5. Let integerLimit be ! ToIntegerOrInfinity(numLimit).
+ 6. If integerLimit < 0, throw a RangeError exception.
+
+features: [iterator-helpers]
+---*/
+let iterator = (function* () {})();
+
+iterator.take(0);
+iterator.take(-0.5);
+iterator.take(null);
+
+assert.throws(RangeError, () => {
+ iterator.take(-1);
+});
+
+assert.throws(RangeError, () => {
+ iterator.take();
+});
+
+assert.throws(RangeError, () => {
+ iterator.take(undefined);
+});
+
+assert.throws(RangeError, () => {
+ iterator.take(NaN);
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/take/limit-tonumber-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/take/limit-tonumber-throws.js
new file mode 100644
index 0000000000..94e0dd22e8
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/take/limit-tonumber-throws.js
@@ -0,0 +1,25 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.take
+description: >
+ Throws a RangeError exception when limit argument valueOf throws.
+info: |
+ %Iterator.prototype%.take ( limit )
+
+ 3. Let numLimit be ? ToNumber(limit).
+
+features: [iterator-helpers]
+---*/
+let iterator = (function* () {})();
+
+assert.throws(Test262Error, () => {
+ iterator.take({
+ valueOf: function () {
+ throw new Test262Error();
+ },
+ });
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/take/limit-tonumber.js b/js/src/tests/test262/built-ins/Iterator/prototype/take/limit-tonumber.js
new file mode 100644
index 0000000000..e6d460727c
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/take/limit-tonumber.js
@@ -0,0 +1,64 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.take
+description: >
+ Converts the limit argument to a Number using ToNumber and valueOf/toString.
+info: |
+ %Iterator.prototype%.take ( limit )
+
+ 3. Let numLimit be ? ToNumber(limit).
+
+includes: [compareArray.js]
+features: [iterator-helpers]
+---*/
+function* g() {
+ yield 0;
+ yield 1;
+ yield 2;
+}
+
+assert.compareArray(
+ Array.from(
+ g().take({
+ valueOf: function () {
+ return 0;
+ },
+ })
+ ),
+ []
+);
+assert.compareArray(
+ Array.from(
+ g().take({
+ valueOf: function () {
+ return 1;
+ },
+ })
+ ),
+ [0]
+);
+assert.compareArray(
+ Array.from(
+ g().take({
+ valueOf: function () {
+ return 2;
+ },
+ })
+ ),
+ [0, 1]
+);
+assert.compareArray(Array.from(g().take([1])), [0]);
+assert.compareArray(
+ Array.from(
+ g().take({
+ toString: function () {
+ return '1';
+ },
+ })
+ ),
+ [0]
+);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/take/name.js b/js/src/tests/test262/built-ins/Iterator/prototype/take/name.js
new file mode 100644
index 0000000000..bf1606d24c
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/take/name.js
@@ -0,0 +1,32 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.take
+description: >
+ The "name" property of Iterator.prototype.take
+info: |
+ 17 ECMAScript Standard Built-in Objects
+
+ Every built-in Function object, including constructors, that is not
+ identified as an anonymous function has a name property whose value is a
+ String. Unless otherwise specified, this value is the name that is given to
+ the function in this specification.
+
+ ...
+
+ Unless otherwise specified, the name property of a built-in Function
+ object, if it exists, has the attributes { [[Writable]]: false,
+ [[Enumerable]]: false, [[Configurable]]: true }.
+features: [iterator-helpers]
+includes: [propertyHelper.js]
+---*/
+
+verifyProperty(Iterator.prototype.take, 'name', {
+ value: 'take',
+ writable: false,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/take/next-method-returns-non-object.js b/js/src/tests/test262/built-ins/Iterator/prototype/take/next-method-returns-non-object.js
new file mode 100644
index 0000000000..5d54497776
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/take/next-method-returns-non-object.js
@@ -0,0 +1,32 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.take
+description: >
+ Underlying iterator next returns non-object
+info: |
+ %Iterator.prototype%.take ( limit )
+
+ 8.b.iii. Let next be ? IteratorStep(iterated).
+
+features: [iterator-helpers]
+flags: []
+---*/
+class NonObjectIterator extends Iterator {
+ next() {
+ return null;
+ }
+}
+
+let iterator = new NonObjectIterator().take(0);
+
+iterator.next();
+
+iterator = new NonObjectIterator().take(1);
+
+assert.throws(TypeError, function () {
+ iterator.next();
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/take/next-method-returns-throwing-done.js b/js/src/tests/test262/built-ins/Iterator/prototype/take/next-method-returns-throwing-done.js
new file mode 100644
index 0000000000..8eef5f8ace
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/take/next-method-returns-throwing-done.js
@@ -0,0 +1,45 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.take
+description: >
+ Underlying iterator next returns object with throwing done getter
+info: |
+ %Iterator.prototype%.take ( limit )
+
+ 8.b.iii. Let next be ? IteratorStep(iterated).
+
+features: [iterator-helpers]
+flags: []
+---*/
+class ReturnCalledError extends Error {}
+class DoneGetterError extends Error {}
+
+class ThrowingIterator extends Iterator {
+ next() {
+ return {
+ get done() {
+ throw new DoneGetterError();
+ },
+ value: 1,
+ };
+ }
+ return() {
+ throw new ReturnCalledError();
+ }
+}
+
+let iterator = new ThrowingIterator().take(0);
+
+assert.throws(ReturnCalledError, function () {
+ iterator.next();
+});
+
+iterator = new ThrowingIterator().take(1);
+
+assert.throws(DoneGetterError, function () {
+ iterator.next();
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/take/next-method-returns-throwing-value-done.js b/js/src/tests/test262/built-ins/Iterator/prototype/take/next-method-returns-throwing-value-done.js
new file mode 100644
index 0000000000..c423d05f38
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/take/next-method-returns-throwing-value-done.js
@@ -0,0 +1,39 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.take
+description: >
+ Underlying iterator next returns object with throwing value getter, but is already done
+info: |
+ %Iterator.prototype%.take ( limit )
+
+features: [iterator-helpers]
+flags: []
+---*/
+class ReturnCalledError extends Error {}
+class ValueGetterError extends Error {}
+
+class ThrowingIterator extends Iterator {
+ next() {
+ return {
+ done: true,
+ get value() {
+ throw new ValueGetterError();
+ },
+ };
+ }
+ return() {
+ throw new ReturnCalledError();
+ }
+}
+
+let iterator = new ThrowingIterator().take(0);
+assert.throws(ReturnCalledError, function () {
+ iterator.next();
+});
+
+iterator = new ThrowingIterator().take(1);
+iterator.next();
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/take/next-method-returns-throwing-value.js b/js/src/tests/test262/built-ins/Iterator/prototype/take/next-method-returns-throwing-value.js
new file mode 100644
index 0000000000..cd3d247b12
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/take/next-method-returns-throwing-value.js
@@ -0,0 +1,45 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.take
+description: >
+ Underlying iterator next returns object with throwing value getter
+info: |
+ %Iterator.prototype%.take ( limit )
+
+ 8.b.v. Let completion be Completion(Yield(? IteratorValue(next))).
+
+features: [iterator-helpers]
+flags: []
+---*/
+class ReturnCalledError extends Error {}
+class ValueGetterError extends Error {}
+
+class ThrowingIterator extends Iterator {
+ next() {
+ return {
+ done: false,
+ get value() {
+ throw new ValueGetterError();
+ },
+ };
+ }
+ return() {
+ throw new ReturnCalledError();
+ }
+}
+
+let iterator = new ThrowingIterator().take(0);
+
+assert.throws(ReturnCalledError, function () {
+ iterator.next();
+});
+
+iterator = new ThrowingIterator().take(1);
+
+assert.throws(ValueGetterError, function () {
+ iterator.next();
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/take/next-method-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/take/next-method-throws.js
new file mode 100644
index 0000000000..1124b663d3
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/take/next-method-throws.js
@@ -0,0 +1,32 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.take
+description: >
+ Underlying iterator has throwing next method
+info: |
+ %Iterator.prototype%.take ( limit )
+
+ 8.b.iii. Let next be ? IteratorStep(iterated).
+
+features: [iterator-helpers]
+flags: []
+---*/
+class ThrowingIterator extends Iterator {
+ next() {
+ throw new Test262Error();
+ }
+}
+
+let iterator = new ThrowingIterator().take(0);
+
+iterator.next();
+
+iterator = new ThrowingIterator().take(1);
+
+assert.throws(Test262Error, function () {
+ iterator.next();
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/take/non-constructible.js b/js/src/tests/test262/built-ins/Iterator/prototype/take/non-constructible.js
new file mode 100644
index 0000000000..be4cf34aac
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/take/non-constructible.js
@@ -0,0 +1,31 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.take
+description: >
+ Iterator.prototype.take is not constructible.
+
+ Built-in function objects that are not identified as constructors do not implement the [[Construct]] internal method unless otherwise specified in the description of a particular function.
+features: [iterator-helpers]
+---*/
+function* g() {}
+let iter = g();
+
+assert.throws(TypeError, () => {
+ new iter.take();
+});
+
+assert.throws(TypeError, () => {
+ new iter.take(0);
+});
+
+assert.throws(TypeError, () => {
+ new Iterator.prototype.take(0);
+});
+
+assert.throws(TypeError, () => {
+ new class extends Iterator {}.take(0);
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/take/prop-desc.js b/js/src/tests/test262/built-ins/Iterator/prototype/take/prop-desc.js
new file mode 100644
index 0000000000..4ae182c44d
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/take/prop-desc.js
@@ -0,0 +1,28 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.take
+description: >
+ Property descriptor of Iterator.prototype.take
+info: |
+ Iterator.prototype.take
+
+ * is the initial value of the Iterator.prototype.take property of the global object.
+
+ 17 ECMAScript Standard Built-in Objects
+
+ Every other data property described in clauses 18 through 26 and in Annex B.2
+ has the attributes { [[Writable]]: true, [[Enumerable]]: false,
+ [[Configurable]]: true } unless otherwise specified.
+features: [globalThis, iterator-helpers]
+includes: [propertyHelper.js]
+---*/
+
+verifyProperty(Iterator.prototype, 'take', {
+ writable: true,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/take/proto.js b/js/src/tests/test262/built-ins/Iterator/prototype/take/proto.js
new file mode 100644
index 0000000000..f83ce61b14
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/take/proto.js
@@ -0,0 +1,14 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.take
+description: >
+ The value of the [[Prototype]] internal slot of Iterator.prototype.take is the
+ intrinsic object %FunctionPrototype%.
+features: [iterator-helpers]
+---*/
+
+assert.sameValue(Object.getPrototypeOf(Iterator.prototype.take), Function.prototype);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/take/result-is-iterator.js b/js/src/tests/test262/built-ins/Iterator/prototype/take/result-is-iterator.js
new file mode 100644
index 0000000000..a180a38e42
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/take/result-is-iterator.js
@@ -0,0 +1,14 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.take
+description: >
+ The value of the [[Prototype]] internal slot of the return value of Iterator.prototype.take is the
+ intrinsic object %IteratorHelperPrototype%.
+features: [iterator-helpers]
+---*/
+
+assert((function* () {})().take(0) instanceof Iterator, 'function*(){}().take(0) must return an Iterator');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/take/return-is-forwarded.js b/js/src/tests/test262/built-ins/Iterator/prototype/take/return-is-forwarded.js
new file mode 100644
index 0000000000..77d46b2563
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/take/return-is-forwarded.js
@@ -0,0 +1,54 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.take
+description: >
+ Underlying iterator return is called when result iterator is closed
+info: |
+ %Iterator.prototype%.take ( limit )
+
+features: [iterator-helpers]
+flags: []
+---*/
+let returnCount = 0;
+
+class TestIterator extends Iterator {
+ next() {
+ return {
+ done: false,
+ value: 1,
+ };
+ }
+ return() {
+ ++returnCount;
+ return {};
+ }
+}
+
+let iterator = new TestIterator().take(0);
+assert.sameValue(returnCount, 0);
+iterator.return();
+assert.sameValue(returnCount, 1);
+iterator.return();
+assert.sameValue(returnCount, 1);
+
+returnCount = 0;
+
+iterator = new TestIterator().take(1);
+assert.sameValue(returnCount, 0);
+iterator.return();
+assert.sameValue(returnCount, 1);
+iterator.return();
+assert.sameValue(returnCount, 1);
+
+returnCount = 0;
+
+iterator = new TestIterator().take(1).take(1).take(1).take(1).take(1);
+assert.sameValue(returnCount, 0);
+iterator.return();
+assert.sameValue(returnCount, 1);
+iterator.return();
+assert.sameValue(returnCount, 1);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/take/return-is-not-forwarded-after-exhaustion.js b/js/src/tests/test262/built-ins/Iterator/prototype/take/return-is-not-forwarded-after-exhaustion.js
new file mode 100644
index 0000000000..edb5b7deef
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/take/return-is-not-forwarded-after-exhaustion.js
@@ -0,0 +1,53 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.take
+description: >
+ Underlying iterator return is not called after result iterator observes that underlying iterator is exhausted
+info: |
+ %Iterator.prototype%.take ( limit )
+
+features: [iterator-helpers]
+flags: []
+---*/
+let returnCount = 0;
+
+class TestIterator extends Iterator {
+ next() {
+ return {
+ done: true,
+ value: undefined,
+ };
+ }
+ return() {
+ throw new Test262Error();
+ }
+}
+
+let iterator = new TestIterator().take(0);
+assert.throws(Test262Error, function () {
+ iterator.return();
+});
+iterator.next();
+iterator.return();
+
+iterator = new TestIterator().take(1);
+iterator.next();
+iterator.return();
+
+iterator = new TestIterator().take(1);
+assert.throws(Test262Error, function () {
+ iterator.return();
+});
+iterator.next();
+iterator.return();
+
+iterator = new TestIterator().take(1).take(1).take(1).take(1).take(1);
+assert.throws(Test262Error, function () {
+ iterator.return();
+});
+iterator.next();
+iterator.return();
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/take/shell.js b/js/src/tests/test262/built-ins/Iterator/prototype/take/shell.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/take/shell.js
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/take/this-non-callable-next.js b/js/src/tests/test262/built-ins/Iterator/prototype/take/this-non-callable-next.js
new file mode 100644
index 0000000000..6169b576ce
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/take/this-non-callable-next.js
@@ -0,0 +1,22 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.take
+description: >
+ Iterator.prototype.take throws TypeError when its this value is an object with a non-callable next
+info: |
+ %Iterator.prototype%.take ( limit )
+
+ 7. Let iterated be ? GetIteratorDirect(this value).
+
+features: [iterator-helpers]
+flags: []
+---*/
+let iter = Iterator.prototype.take.call({ next: 0 }, 1);
+
+assert.throws(TypeError, function () {
+ iter.next();
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/take/this-non-object.js b/js/src/tests/test262/built-ins/Iterator/prototype/take/this-non-object.js
new file mode 100644
index 0000000000..85910af8f4
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/take/this-non-object.js
@@ -0,0 +1,37 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.take
+description: >
+ Iterator.prototype.take throws TypeError when its this value is a non-object
+info: |
+ %Iterator.prototype%.take ( limit )
+
+ 7. Let iterated be ? GetIteratorDirect(this value).
+
+features: [iterator-helpers]
+flags: []
+---*/
+assert.throws(TypeError, function () {
+ Iterator.prototype.take.call(null, 1);
+});
+
+assert.throws(TypeError, function () {
+ Iterator.prototype.take.call(null, {
+ valueOf: function () {
+ throw new Test262Error();
+ },
+ });
+});
+
+Object.defineProperty(Number.prototype, 'next', {
+ get: function () {
+ throw new Test262Error();
+ },
+});
+assert.throws(TypeError, function () {
+ Iterator.prototype.take.call(0, 1);
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/take/this-plain-iterator.js b/js/src/tests/test262/built-ins/Iterator/prototype/take/this-plain-iterator.js
new file mode 100644
index 0000000000..d83fea848d
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/take/this-plain-iterator.js
@@ -0,0 +1,33 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.take
+description: >
+ Iterator.prototype.take supports a this value that does not inherit from Iterator.prototype but implements the iterator protocol
+info: |
+ %Iterator.prototype%.take ( limit )
+
+ 7. Let iterated be ? GetIteratorDirect(this value).
+
+features: [iterator-helpers]
+flags: []
+---*/
+let iter = {
+ get next() {
+ let count = 3;
+ return function () {
+ --count;
+ return count >= 0 ? { done: false, value: count } : { done: true, value: undefined };
+ };
+ },
+};
+
+let takeIter = Iterator.prototype.take.call(iter, 1);
+
+let { done, value } = takeIter.next();
+
+assert.sameValue(done, false);
+assert.sameValue(value, 2);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/take/throws-typeerror-when-generator-is-running.js b/js/src/tests/test262/built-ins/Iterator/prototype/take/throws-typeerror-when-generator-is-running.js
new file mode 100644
index 0000000000..9eb8e3827e
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/take/throws-typeerror-when-generator-is-running.js
@@ -0,0 +1,42 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 André Bargull. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.take
+description: >
+ Throws a TypeError when the closure generator is already running.
+info: |
+ %IteratorHelperPrototype%.next ( )
+ 1. Return ? GeneratorResume(this value, undefined, "Iterator Helper").
+
+ 27.5.3.3 GeneratorResume ( generator, value, generatorBrand )
+ 1. Let state be ? GeneratorValidate(generator, generatorBrand).
+ ...
+
+ 27.5.3.2 GeneratorValidate ( generator, generatorBrand )
+ ...
+ 6. If state is executing, throw a TypeError exception.
+ ...
+
+features: [iterator-helpers]
+---*/
+
+var enterCount = 0;
+
+class TestIterator extends Iterator {
+ next() {
+ enterCount++;
+ iter.next();
+ return {done: false};
+ }
+}
+
+var iter = new TestIterator().take(100);
+
+assert.throws(TypeError, function() {
+ iter.next();
+});
+
+assert.sameValue(enterCount, 1);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/take/underlying-iterator-advanced-in-parallel.js b/js/src/tests/test262/built-ins/Iterator/prototype/take/underlying-iterator-advanced-in-parallel.js
new file mode 100644
index 0000000000..883e9350c0
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/take/underlying-iterator-advanced-in-parallel.js
@@ -0,0 +1,42 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.take
+description: >
+ Underlying iterator is advanced after calling take
+info: |
+ %Iterator.prototype%.take ( limit )
+
+features: [iterator-helpers]
+flags: []
+---*/
+let iterator = (function* () {
+ for (let i = 0; i < 5; ++i) {
+ yield i;
+ }
+})();
+
+let taken = iterator.take(2);
+
+let { value, done } = iterator.next();
+
+assert.sameValue(value, 0);
+assert.sameValue(done, false);
+
+({ value, done } = taken.next());
+
+assert.sameValue(value, 1);
+assert.sameValue(done, false);
+
+({ value, done } = taken.next());
+
+assert.sameValue(value, 2);
+assert.sameValue(done, false);
+
+({ value, done } = taken.next());
+
+assert.sameValue(value, undefined);
+assert.sameValue(done, true);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/take/underlying-iterator-closed-in-parallel.js b/js/src/tests/test262/built-ins/Iterator/prototype/take/underlying-iterator-closed-in-parallel.js
new file mode 100644
index 0000000000..2b25b7ebba
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/take/underlying-iterator-closed-in-parallel.js
@@ -0,0 +1,29 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.take
+description: >
+ Underlying iterator is closed after calling take
+info: |
+ %Iterator.prototype%.take ( limit )
+
+features: [iterator-helpers]
+flags: []
+---*/
+let iterator = (function* () {
+ for (let i = 0; i < 5; ++i) {
+ yield i;
+ }
+})();
+
+let taken = iterator.take(2);
+
+iterator.return();
+
+let { value, done } = taken.next();
+
+assert.sameValue(value, undefined);
+assert.sameValue(done, true);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/take/underlying-iterator-closed.js b/js/src/tests/test262/built-ins/Iterator/prototype/take/underlying-iterator-closed.js
new file mode 100644
index 0000000000..b045bf8874
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/take/underlying-iterator-closed.js
@@ -0,0 +1,29 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.take
+description: >
+ Underlying iterator is closed before calling take
+info: |
+ %Iterator.prototype%.take ( limit )
+
+features: [iterator-helpers]
+flags: []
+---*/
+let iterator = (function* () {
+ for (let i = 0; i < 5; ++i) {
+ yield i;
+ }
+})();
+
+iterator.return();
+
+let taken = iterator.take(2);
+
+let { value, done } = taken.next();
+
+assert.sameValue(value, undefined);
+assert.sameValue(done, true);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/toArray/browser.js b/js/src/tests/test262/built-ins/Iterator/prototype/toArray/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/toArray/browser.js
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/toArray/callable.js b/js/src/tests/test262/built-ins/Iterator/prototype/toArray/callable.js
new file mode 100644
index 0000000000..cef99e083a
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/toArray/callable.js
@@ -0,0 +1,16 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.toArray
+description: >
+ Iterator.prototype.toArray is callable
+features: [iterator-helpers]
+---*/
+function* g() {}
+Iterator.prototype.toArray.call(g());
+
+let iter = g();
+iter.toArray();
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/toArray/get-next-method-only-once.js b/js/src/tests/test262/built-ins/Iterator/prototype/toArray/get-next-method-only-once.js
new file mode 100644
index 0000000000..587c8d7a3a
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/toArray/get-next-method-only-once.js
@@ -0,0 +1,37 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.toArray
+description: >
+ Gets the next method from the iterator only once
+info: |
+ %Iterator.prototype%.toArray ( )
+
+includes: [compareArray.js]
+features: [iterator-helpers]
+flags: []
+---*/
+let nextGets = 0;
+
+class TestIterator extends Iterator {
+ get next() {
+ ++nextGets;
+ let counter = 5;
+ return function () {
+ if (counter <= 0) {
+ return { done: true, value: undefined };
+ } else {
+ return { done: false, value: --counter };
+ }
+ };
+ }
+}
+
+let iterator = new TestIterator();
+
+assert.sameValue(nextGets, 0);
+assert.compareArray(iterator.toArray(), [4, 3, 2, 1, 0]);
+assert.sameValue(nextGets, 1);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/toArray/get-next-method-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/toArray/get-next-method-throws.js
new file mode 100644
index 0000000000..df4eac1bdb
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/toArray/get-next-method-throws.js
@@ -0,0 +1,26 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.toArray
+description: >
+ Iterator has throwing next getter
+info: |
+ %Iterator.prototype%.toArray ( )
+
+features: [iterator-helpers]
+flags: []
+---*/
+class IteratorThrows extends Iterator {
+ get next() {
+ throw new Test262Error();
+ }
+}
+
+let iterator = new IteratorThrows();
+
+assert.throws(Test262Error, function () {
+ iterator.toArray();
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/toArray/is-function.js b/js/src/tests/test262/built-ins/Iterator/prototype/toArray/is-function.js
new file mode 100644
index 0000000000..70e06f968d
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/toArray/is-function.js
@@ -0,0 +1,13 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.toArray
+description: >
+ Iterator.prototype.toArray is a built-in function
+features: [iterator-helpers]
+---*/
+
+assert.sameValue(typeof Iterator.prototype.toArray, 'function');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/toArray/iterator-already-exhausted.js b/js/src/tests/test262/built-ins/Iterator/prototype/toArray/iterator-already-exhausted.js
new file mode 100644
index 0000000000..78cf342b1a
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/toArray/iterator-already-exhausted.js
@@ -0,0 +1,27 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.toArray
+description: >
+ Iterator.prototype.toArray returns an empty array when the iterator has already been exhausted
+info: |
+ %Iterator.prototype%.toArray ( )
+
+includes: [compareArray.js]
+features: [iterator-helpers]
+flags: []
+---*/
+let iterator = (function* () {})();
+
+let { value, done } = iterator.next();
+assert.sameValue(value, undefined);
+assert.sameValue(done, true);
+
+let result = iterator.toArray();
+assert.compareArray(result, []);
+
+result = iterator.toArray();
+assert.compareArray(result, []);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/toArray/length.js b/js/src/tests/test262/built-ins/Iterator/prototype/toArray/length.js
new file mode 100644
index 0000000000..24635c44a2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/toArray/length.js
@@ -0,0 +1,25 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.toArray
+description: >
+ Iterator.prototype.toArray has a "length" property whose value is 0.
+info: |
+ ECMAScript Standard Built-in Objects
+
+ Unless otherwise specified, the length property of a built-in
+ Function object has the attributes { [[Writable]]: false, [[Enumerable]]:
+ false, [[Configurable]]: true }.
+features: [iterator-helpers]
+includes: [propertyHelper.js]
+---*/
+
+verifyProperty(Iterator.prototype.toArray, 'length', {
+ value: 0,
+ writable: false,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/toArray/name.js b/js/src/tests/test262/built-ins/Iterator/prototype/toArray/name.js
new file mode 100644
index 0000000000..a58fffdd8f
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/toArray/name.js
@@ -0,0 +1,32 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.toArray
+description: >
+ The "name" property of Iterator.prototype.toArray
+info: |
+ 17 ECMAScript Standard Built-in Objects
+
+ Every built-in Function object, including constructors, that is not
+ identified as an anonymous function has a name property whose value is a
+ String. Unless otherwise specified, this value is the name that is given to
+ the function in this specification.
+
+ ...
+
+ Unless otherwise specified, the name property of a built-in Function
+ object, if it exists, has the attributes { [[Writable]]: false,
+ [[Enumerable]]: false, [[Configurable]]: true }.
+features: [iterator-helpers]
+includes: [propertyHelper.js]
+---*/
+
+verifyProperty(Iterator.prototype.toArray, 'name', {
+ value: 'toArray',
+ writable: false,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/toArray/next-method-returns-non-object.js b/js/src/tests/test262/built-ins/Iterator/prototype/toArray/next-method-returns-non-object.js
new file mode 100644
index 0000000000..929bbde5f5
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/toArray/next-method-returns-non-object.js
@@ -0,0 +1,26 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.toArray
+description: >
+ Underlying iterator next returns non-object
+info: |
+ %Iterator.prototype%.toArray ( )
+
+features: [iterator-helpers]
+flags: []
+---*/
+class NonObjectIterator extends Iterator {
+ next() {
+ return null;
+ }
+}
+
+let iterator = new NonObjectIterator();
+
+assert.throws(TypeError, function () {
+ iterator.toArray();
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/toArray/next-method-returns-throwing-done.js b/js/src/tests/test262/built-ins/Iterator/prototype/toArray/next-method-returns-throwing-done.js
new file mode 100644
index 0000000000..ad4a244488
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/toArray/next-method-returns-throwing-done.js
@@ -0,0 +1,34 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.toArray
+description: >
+ Underlying iterator next returns object with throwing done getter
+info: |
+ %Iterator.prototype%.toArray ( )
+
+features: [iterator-helpers]
+flags: []
+---*/
+class ThrowingIterator extends Iterator {
+ next() {
+ return {
+ get done() {
+ throw new Test262Error();
+ },
+ value: 1,
+ };
+ }
+ return() {
+ throw new Error();
+ }
+}
+
+let iterator = new ThrowingIterator();
+
+assert.throws(Test262Error, function () {
+ iterator.toArray();
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/toArray/next-method-returns-throwing-value-done.js b/js/src/tests/test262/built-ins/Iterator/prototype/toArray/next-method-returns-throwing-value-done.js
new file mode 100644
index 0000000000..ffb8f05a64
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/toArray/next-method-returns-throwing-value-done.js
@@ -0,0 +1,31 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.toArray
+description: >
+ Underlying iterator next returns object with throwing value getter, but is already done
+info: |
+ %Iterator.prototype%.toArray ( )
+
+features: [iterator-helpers]
+flags: []
+---*/
+class ThrowingIterator extends Iterator {
+ next() {
+ return {
+ done: true,
+ get value() {
+ throw new Test262Error();
+ },
+ };
+ }
+ return() {
+ throw new Error();
+ }
+}
+
+let iterator = new ThrowingIterator();
+iterator.toArray();
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/toArray/next-method-returns-throwing-value.js b/js/src/tests/test262/built-ins/Iterator/prototype/toArray/next-method-returns-throwing-value.js
new file mode 100644
index 0000000000..ab9b899827
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/toArray/next-method-returns-throwing-value.js
@@ -0,0 +1,34 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.toArray
+description: >
+ Underlying iterator next returns object with throwing value getter
+info: |
+ %Iterator.prototype%.toArray ( )
+
+features: [iterator-helpers]
+flags: []
+---*/
+class ThrowingIterator extends Iterator {
+ next() {
+ return {
+ done: false,
+ get value() {
+ throw new Test262Error();
+ },
+ };
+ }
+ return() {
+ throw new Error();
+ }
+}
+
+let iterator = new ThrowingIterator();
+
+assert.throws(Test262Error, function () {
+ iterator.toArray();
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/toArray/next-method-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/toArray/next-method-throws.js
new file mode 100644
index 0000000000..cd16b49738
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/toArray/next-method-throws.js
@@ -0,0 +1,26 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.toArray
+description: >
+ Underlying iterator has throwing next method
+info: |
+ %Iterator.prototype%.toArray ( )
+
+features: [iterator-helpers]
+flags: []
+---*/
+class ThrowingIterator extends Iterator {
+ next() {
+ throw new Test262Error();
+ }
+}
+
+let iterator = new ThrowingIterator();
+
+assert.throws(Test262Error, function () {
+ iterator.toArray();
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/toArray/non-constructible.js b/js/src/tests/test262/built-ins/Iterator/prototype/toArray/non-constructible.js
new file mode 100644
index 0000000000..4f30e95134
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/toArray/non-constructible.js
@@ -0,0 +1,27 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.toArray
+description: >
+ Iterator.prototype.toArray is not constructible.
+
+ Built-in function objects that are not identified as constructors do not implement the [[Construct]] internal method unless otherwise specified in the description of a particular function.
+features: [iterator-helpers]
+---*/
+function* g() {}
+let iter = g();
+
+assert.throws(TypeError, () => {
+ new iter.toArray();
+});
+
+assert.throws(TypeError, () => {
+ new Iterator.prototype.toArray();
+});
+
+assert.throws(TypeError, () => {
+ new class extends Iterator {}.toArray();
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/toArray/prop-desc.js b/js/src/tests/test262/built-ins/Iterator/prototype/toArray/prop-desc.js
new file mode 100644
index 0000000000..ff05174204
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/toArray/prop-desc.js
@@ -0,0 +1,28 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.toArray
+description: >
+ Property descriptor of Iterator.prototype.toArray
+info: |
+ Iterator.prototype.toArray
+
+ * is the initial value of the Iterator.prototype.toArray property of the global object.
+
+ 17 ECMAScript Standard Built-in Objects
+
+ every other data property described in clauses 18 through 26 and in Annex B.2
+ has the attributes { [[Writable]]: true, [[Enumerable]]: false,
+ [[Configurable]]: true } unless otherwise specified.
+features: [globalThis, iterator-helpers]
+includes: [propertyHelper.js]
+---*/
+
+verifyProperty(Iterator.prototype, 'toArray', {
+ writable: true,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/toArray/proto.js b/js/src/tests/test262/built-ins/Iterator/prototype/toArray/proto.js
new file mode 100644
index 0000000000..f35bd4afa0
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/toArray/proto.js
@@ -0,0 +1,14 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.toArray
+description: >
+ The value of the [[Prototype]] internal slot of Iterator.prototype.toArray is the
+ intrinsic object %Function%.
+features: [iterator-helpers]
+---*/
+
+assert.sameValue(Object.getPrototypeOf(Iterator.prototype.toArray), Function.prototype);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/toArray/shell.js b/js/src/tests/test262/built-ins/Iterator/prototype/toArray/shell.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/toArray/shell.js
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/toArray/this-non-callable-next.js b/js/src/tests/test262/built-ins/Iterator/prototype/toArray/this-non-callable-next.js
new file mode 100644
index 0000000000..857f4af7f5
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/toArray/this-non-callable-next.js
@@ -0,0 +1,18 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.toArray
+description: >
+ Iterator.prototype.toArray throws TypeError when its this value is an object with a non-callable next
+info: |
+ %Iterator.prototype%.toArray ( )
+
+features: [iterator-helpers]
+flags: []
+---*/
+assert.throws(TypeError, function () {
+ Iterator.prototype.toArray.call({ next: 0 });
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/toArray/this-non-object.js b/js/src/tests/test262/built-ins/Iterator/prototype/toArray/this-non-object.js
new file mode 100644
index 0000000000..27ff3bfdb9
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/toArray/this-non-object.js
@@ -0,0 +1,27 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.toArray
+description: >
+ Iterator.prototype.toArray throws TypeError when its this value is a non-object
+info: |
+ %Iterator.prototype%.toArray ( )
+
+features: [iterator-helpers]
+flags: []
+---*/
+assert.throws(TypeError, function () {
+ Iterator.prototype.toArray.call(null);
+});
+
+Object.defineProperty(Number.prototype, 'next', {
+ get: function () {
+ throw new Test262Error();
+ },
+});
+assert.throws(TypeError, function () {
+ Iterator.prototype.toArray.call(0);
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/toArray/this-plain-iterator.js b/js/src/tests/test262/built-ins/Iterator/prototype/toArray/this-plain-iterator.js
new file mode 100644
index 0000000000..85a065ba4b
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/prototype/toArray/this-plain-iterator.js
@@ -0,0 +1,28 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2023 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-iteratorprototype.toArray
+description: >
+ Iterator.prototype.toArray supports a this value that does not inherit from Iterator.prototype but implements the iterator protocol
+info: |
+ %Iterator.prototype%.toArray ( )
+
+includes: [compareArray.js]
+features: [iterator-helpers]
+flags: []
+---*/
+let iter = {
+ get next() {
+ let count = 3;
+ return function () {
+ --count;
+ return count >= 0 ? { done: false, value: count } : { done: true, value: undefined };
+ };
+ },
+};
+
+let result = Iterator.prototype.toArray.call(iter);
+assert.compareArray(result, [2, 1, 0]);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Iterator/shell.js b/js/src/tests/test262/built-ins/Iterator/shell.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/shell.js
diff --git a/js/src/tests/test262/built-ins/Iterator/subclassable.js b/js/src/tests/test262/built-ins/Iterator/subclassable.js
new file mode 100644
index 0000000000..f6f440b346
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Iterator/subclassable.js
@@ -0,0 +1,30 @@
+// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-iterator-constructor
+description: >
+ The Iterator constructor is designed to be subclassable.
+info: |
+ The Iterator constructor
+
+ - is designed to be subclassable. It may be used as the value of an extends clause of a class defintion.
+
+features: [iterator-helpers]
+---*/
+
+class SubIterator extends Iterator {}
+
+assert.sameValue(
+ new SubIterator() instanceof SubIterator,
+ true,
+ 'The result of `(new SubIterator() instanceof SubIterator)` is true'
+);
+assert.sameValue(
+ new SubIterator() instanceof Iterator,
+ true,
+ 'The result of `(new SubIterator() instanceof Iterator)` is true'
+);
+
+reportCompare(0, 0);