From dfc7ce4c28bbec7b5f771e8f59842e5429cc69a8 Mon Sep 17 00:00:00 2001 From: Rick Waldron Date: Thu, 15 Jun 2023 11:07:41 -0400 Subject: [PATCH] Iterator Helpers (#2818) drop: property descriptor name length [[Prototype]] is a function is not constructible result instanceof Iterator limit is given a non-primitive that needs to be converted to a number through valueOf through toString (array) limit coercion to number throws limit converts to NaN same as limit not supplied limit behaves properly limit < number of values limit = number of values limit > number of values gets the next method from the underlying iterator only once underlying iterator has throwing next getter underlying iterator next throws when advancing past dropped items underlying iterator is advanced after calling drop underlying iterator is closed after calling drop underlying iterator is already closed underlying iterator next returns non-object underlying iterator next returns object with throwing done/value getters underlying iterator return is never called when result iterator is closed every: property descriptor name length [[Prototype]] is a function is callable is not constructible result is a Boolean predicate is non-callable iterator already exhausted called on non-object called on object with "next" method called on object with non-callable "next" method predicate returns non-Boolean predicate returns truthy for all iterated values returns true predicate returns truthy for some iterated values but then falsey for at least one iterated value returns false iteration stops iterator is closed predicate returns falsey immediately returns false iteration stops iterator is closed predicate throws every throws iterator is closed predicate throws then iterator close also throws predicate this value is undefined predicate is passed the yielded value as the first parameter and a counter as second parameter gets the next method from the iterator only once iterator has throwing next getter iterator has throwing return getter iterator next throws iterator return throws iterator next returns non-object iterator next returns object with throwing done/value getters Co-authored-by: Michael Ficarra Co-authored-by: Jordan Harband --- features.txt | 4 ++ test/built-ins/Iterator/constructor.js | 11 +++ test/built-ins/Iterator/from/callable.js | 12 ++++ .../from/get-next-method-only-once.js | 46 ++++++++++++ .../Iterator/from/get-next-method-throws.js | 25 +++++++ test/built-ins/Iterator/from/is-function.js | 10 +++ .../Iterator/from/iterable-primitives.js | 39 ++++++++++ .../from/iterable-to-iterator-fallback.js | 51 +++++++++++++ test/built-ins/Iterator/from/length.js | 22 ++++++ test/built-ins/Iterator/from/name.js | 29 ++++++++ .../Iterator/from/non-constructible.js | 23 ++++++ test/built-ins/Iterator/from/primitives.js | 38 ++++++++++ test/built-ins/Iterator/from/prop-desc.js | 26 +++++++ test/built-ins/Iterator/from/proto.js | 15 ++++ test/built-ins/Iterator/from/result-proto.js | 29 ++++++++ .../Iterator/from/supports-iterable.js | 14 ++++ .../Iterator/from/supports-iterator.js | 29 ++++++++ test/built-ins/Iterator/length.js | 26 +++++++ test/built-ins/Iterator/name.js | 30 ++++++++ .../newtarget-or-active-function-object.js | 22 ++++++ test/built-ins/Iterator/prop-desc.js | 27 +++++++ .../Iterator/proto-from-ctor-realm.js | 36 ++++++++++ test/built-ins/Iterator/proto.js | 16 +++++ .../prototype/Symbol.iterator/is-function.js | 13 ++++ .../prototype}/Symbol.iterator/length.js | 16 ++--- .../prototype}/Symbol.iterator/name.js | 14 ++-- .../prototype}/Symbol.iterator/prop-desc.js | 12 ++-- .../prototype}/Symbol.iterator/return-val.js | 19 ++--- .../prototype/Symbol.toStringTag/prop-desc.js | 20 ++++++ .../prototype/drop/argument-effect-order.js | 64 +++++++++++++++++ .../Iterator/prototype/drop/callable.js | 13 ++++ .../drop/exhaustion-does-not-call-return.js | 60 ++++++++++++++++ .../drop/get-next-method-only-once.js | 41 +++++++++++ .../prototype/drop/get-next-method-throws.js | 25 +++++++ .../drop/get-return-method-throws.js | 30 ++++++++ .../Iterator/prototype/drop/is-function.js | 10 +++ .../Iterator/prototype/drop/length.js | 22 ++++++ .../prototype/drop/limit-equals-total.js | 22 ++++++ .../drop/limit-greater-than-total.js | 37 ++++++++++ .../prototype/drop/limit-less-than-total.js | 30 ++++++++ .../prototype/drop/limit-rangeerror.js | 36 ++++++++++ .../prototype/drop/limit-tonumber-throws.js | 22 ++++++ .../Iterator/prototype/drop/limit-tonumber.js | 37 ++++++++++ .../built-ins/Iterator/prototype/drop/name.js | 29 ++++++++ .../drop/next-method-returns-non-object.js | 33 +++++++++ .../drop/next-method-returns-throwing-done.js | 41 +++++++++++ ...next-method-returns-throwing-value-done.js | 36 ++++++++++ .../next-method-returns-throwing-value.js | 39 ++++++++++ .../prototype/drop/next-method-throws.js | 33 +++++++++ .../prototype/drop/non-constructible.js | 28 ++++++++ .../Iterator/prototype/drop/prop-desc.js | 25 +++++++ .../Iterator/prototype/drop/proto.js | 11 +++ .../prototype/drop/result-is-iterator.js | 11 +++ .../prototype/drop/return-is-forwarded.js | 54 ++++++++++++++ ...eturn-is-not-forwarded-after-exhaustion.js | 50 +++++++++++++ .../prototype/drop/this-non-callable-next.js | 19 +++++ .../prototype/drop/this-non-object.js | 34 +++++++++ .../prototype/drop/this-plain-iterator.js | 30 ++++++++ ...nderlying-iterator-advanced-in-parallel.js | 39 ++++++++++ .../underlying-iterator-closed-in-parallel.js | 26 +++++++ .../drop/underlying-iterator-closed.js | 26 +++++++ .../prototype/every/argument-effect-order.js | 30 ++++++++ .../Iterator/prototype/every/callable.js | 13 ++++ .../every/get-next-method-only-once.js | 38 ++++++++++ .../prototype/every/get-next-method-throws.js | 25 +++++++ .../every/get-return-method-throws.js | 31 ++++++++ .../Iterator/prototype/every/is-function.js | 10 +++ .../every/iterator-already-exhausted.js | 26 +++++++ .../prototype/every/iterator-has-no-return.js | 27 +++++++ .../every/iterator-return-method-throws.js | 31 ++++++++ .../Iterator/prototype/every/length.js | 22 ++++++ .../Iterator/prototype/every/name.js | 29 ++++++++ .../every/next-method-returns-non-object.js | 25 +++++++ .../next-method-returns-throwing-done.js | 33 +++++++++ ...next-method-returns-throwing-value-done.js | 30 ++++++++ .../next-method-returns-throwing-value.js | 33 +++++++++ .../prototype/every/next-method-throws.js | 25 +++++++ .../prototype/every/non-callable-predicate.js | 22 ++++++ .../prototype/every/non-constructible.js | 28 ++++++++ .../prototype/every/predicate-args.js | 43 +++++++++++ .../every/predicate-returns-falsey.js | 33 +++++++++ .../every/predicate-returns-non-boolean.js | 30 ++++++++ .../predicate-returns-truthy-then-falsey.js | 34 +++++++++ .../every/predicate-returns-truthy.js | 24 +++++++ .../prototype/every/predicate-this.js | 33 +++++++++ ...hrows-then-closing-iterator-also-throws.js | 39 ++++++++++ .../prototype/every/predicate-throws.js | 43 +++++++++++ .../Iterator/prototype/every/prop-desc.js | 25 +++++++ .../Iterator/prototype/every/proto.js | 11 +++ .../prototype/every/result-is-boolean.js | 11 +++ .../prototype/every/this-non-callable-next.js | 17 +++++ .../prototype/every/this-non-object.js | 26 +++++++ .../prototype/every/this-plain-iterator.js | 32 +++++++++ .../prototype/filter/argument-effect-order.js | 30 ++++++++ .../Iterator/prototype/filter/callable.js | 13 ++++ .../filter/exhaustion-does-not-call-return.js | 37 ++++++++++ .../filter/get-next-method-only-once.js | 41 +++++++++++ .../filter/get-next-method-throws.js | 25 +++++++ .../filter/get-return-method-throws.js | 30 ++++++++ .../Iterator/prototype/filter/is-function.js | 10 +++ .../filter/iterator-already-exhausted.js | 25 +++++++ .../filter/iterator-return-method-throws.js | 29 ++++++++ .../Iterator/prototype/filter/length.js | 22 ++++++ .../Iterator/prototype/filter/name.js | 29 ++++++++ .../filter/next-method-returns-non-object.js | 25 +++++++ .../next-method-returns-throwing-done.js | 33 +++++++++ ...next-method-returns-throwing-value-done.js | 30 ++++++++ .../next-method-returns-throwing-value.js | 33 +++++++++ .../prototype/filter/next-method-throws.js | 25 +++++++ .../filter/non-callable-predicate.js | 20 ++++++ .../prototype/filter/non-constructible.js | 28 ++++++++ .../prototype/filter/predicate-args.js | 44 ++++++++++++ .../prototype/filter/predicate-filters.js | 40 +++++++++++ .../filter/predicate-returns-non-boolean.js | 38 ++++++++++ .../prototype/filter/predicate-this.js | 33 +++++++++ ...hrows-then-closing-iterator-also-throws.js | 40 +++++++++++ .../prototype/filter/predicate-throws.js | 41 +++++++++++ .../Iterator/prototype/filter/prop-desc.js | 25 +++++++ .../Iterator/prototype/filter/proto.js | 11 +++ .../prototype/filter/result-is-iterator.js | 14 ++++ .../prototype/filter/return-is-forwarded.js | 33 +++++++++ ...eturn-is-not-forwarded-after-exhaustion.js | 46 ++++++++++++ .../filter/this-non-callable-next.js | 19 +++++ .../prototype/filter/this-non-object.js | 26 +++++++ .../prototype/filter/this-plain-iterator.js | 33 +++++++++ ...nderlying-iterator-advanced-in-parallel.js | 42 +++++++++++ .../underlying-iterator-closed-in-parallel.js | 26 +++++++ .../filter/underlying-iterator-closed.js | 26 +++++++ .../prototype/find/argument-effect-order.js | 30 ++++++++ .../Iterator/prototype/find/callable.js | 13 ++++ .../find/get-next-method-only-once.js | 36 ++++++++++ .../prototype/find/get-next-method-throws.js | 23 ++++++ .../find/get-return-method-throws.js | 29 ++++++++ .../Iterator/prototype/find/is-function.js | 10 +++ .../find/iterator-already-exhausted.js | 23 ++++++ .../prototype/find/iterator-has-no-return.js | 27 +++++++ .../find/iterator-return-method-throws.js | 29 ++++++++ .../Iterator/prototype/find/length.js | 22 ++++++ .../built-ins/Iterator/prototype/find/name.js | 29 ++++++++ .../find/next-method-returns-non-object.js | 23 ++++++ .../find/next-method-returns-throwing-done.js | 31 ++++++++ ...next-method-returns-throwing-value-done.js | 28 ++++++++ .../next-method-returns-throwing-value.js | 31 ++++++++ .../prototype/find/next-method-throws.js | 23 ++++++ .../prototype/find/non-callable-predicate.js | 20 ++++++ .../prototype/find/non-constructible.js | 28 ++++++++ .../Iterator/prototype/find/predicate-args.js | 41 +++++++++++ .../predicate-returns-falsey-then-truthy.js | 32 +++++++++ .../find/predicate-returns-falsey.js | 21 ++++++ .../find/predicate-returns-non-boolean.js | 32 +++++++++ .../find/predicate-returns-truthy.js | 32 +++++++++ .../Iterator/prototype/find/predicate-this.js | 31 ++++++++ ...hrows-then-closing-iterator-also-throws.js | 36 ++++++++++ .../prototype/find/predicate-throws.js | 40 +++++++++++ .../Iterator/prototype/find/prop-desc.js | 25 +++++++ .../Iterator/prototype/find/proto.js | 11 +++ .../prototype/find/this-non-callable-next.js | 15 ++++ .../prototype/find/this-non-object.js | 24 +++++++ .../prototype/find/this-plain-iterator.js | 30 ++++++++ .../flatMap/argument-effect-order.js | 42 +++++++++++ .../Iterator/prototype/flatMap/callable.js | 13 ++++ .../exhaustion-does-not-call-return.js | 34 +++++++++ .../prototype/flatMap/flattens-iterable.js | 30 ++++++++ .../prototype/flatMap/flattens-iterator.js | 44 ++++++++++++ .../flatMap/flattens-only-depth-1.js | 34 +++++++++ .../flatMap/get-next-method-only-once.js | 41 +++++++++++ .../flatMap/get-next-method-throws.js | 25 +++++++ .../flatMap/get-return-method-throws.js | 30 ++++++++ .../Iterator/prototype/flatMap/is-function.js | 10 +++ .../iterable-primitives-are-not-flattened.js | 37 ++++++++++ .../flatMap/iterable-to-iterator-fallback.js | 57 +++++++++++++++ .../flatMap/iterator-already-exhausted.js | 22 ++++++ .../flatMap/iterator-return-method-throws.js | 29 ++++++++ .../Iterator/prototype/flatMap/length.js | 22 ++++++ .../Iterator/prototype/flatMap/mapper-args.js | 55 ++++++++++++++ .../flatMap/mapper-returns-closed-iterator.js | 30 ++++++++ .../flatMap/mapper-returns-non-object.js | 34 +++++++++ .../Iterator/prototype/flatMap/mapper-this.js | 33 +++++++++ ...hrows-then-closing-iterator-also-throws.js | 40 +++++++++++ .../prototype/flatMap/mapper-throws.js | 41 +++++++++++ .../Iterator/prototype/flatMap/name.js | 29 ++++++++ .../flatMap/next-method-returns-non-object.js | 23 ++++++ .../next-method-returns-throwing-done.js | 31 ++++++++ ...next-method-returns-throwing-value-done.js | 28 ++++++++ .../next-method-returns-throwing-value.js | 31 ++++++++ .../prototype/flatMap/next-method-throws.js | 23 ++++++ .../prototype/flatMap/non-callable-mapper.js | 20 ++++++ .../prototype/flatMap/non-constructible.js | 28 ++++++++ .../Iterator/prototype/flatMap/prop-desc.js | 25 +++++++ .../Iterator/prototype/flatMap/proto.js | 11 +++ .../prototype/flatMap/result-is-iterator.js | 14 ++++ .../return-is-forwarded-to-mapper-result.js | 45 ++++++++++++ ...urn-is-forwarded-to-underlying-iterator.js | 33 +++++++++ ...eturn-is-not-forwarded-after-exhaustion.js | 46 ++++++++++++ .../flatMap/strings-are-not-flattened.js | 26 +++++++ .../flatMap/this-non-callable-next.js | 17 +++++ .../prototype/flatMap/this-non-object.js | 26 +++++++ .../prototype/flatMap/this-plain-iterator.js | 31 ++++++++ ...nderlying-iterator-advanced-in-parallel.js | 42 +++++++++++ .../underlying-iterator-closed-in-parallel.js | 26 +++++++ .../flatMap/underlying-iterator-closed.js | 26 +++++++ .../forEach/argument-effect-order.js | 35 +++++++++ .../Iterator/prototype/forEach/callable.js | 13 ++++ .../Iterator/prototype/forEach/fn-args.js | 40 +++++++++++ .../fn-called-for-each-yielded-value.js | 28 ++++++++ .../Iterator/prototype/forEach/fn-this.js | 30 ++++++++ ...hrows-then-closing-iterator-also-throws.js | 36 ++++++++++ .../Iterator/prototype/forEach/fn-throws.js | 40 +++++++++++ .../forEach/get-next-method-only-once.js | 36 ++++++++++ .../forEach/get-next-method-throws.js | 23 ++++++ .../Iterator/prototype/forEach/is-function.js | 10 +++ .../forEach/iterator-already-exhausted.js | 22 ++++++ .../Iterator/prototype/forEach/length.js | 22 ++++++ .../Iterator/prototype/forEach/name.js | 29 ++++++++ .../forEach/next-method-returns-non-object.js | 23 ++++++ .../next-method-returns-throwing-done.js | 31 ++++++++ ...next-method-returns-throwing-value-done.js | 28 ++++++++ .../next-method-returns-throwing-value.js | 31 ++++++++ .../prototype/forEach/next-method-throws.js | 23 ++++++ .../forEach/non-callable-predicate.js | 20 ++++++ .../prototype/forEach/non-constructible.js | 28 ++++++++ .../Iterator/prototype/forEach/prop-desc.js | 25 +++++++ .../Iterator/prototype/forEach/proto.js | 11 +++ .../prototype/forEach/result-is-undefined.js | 18 +++++ .../forEach/this-non-callable-next.js | 15 ++++ .../prototype/forEach/this-non-object.js | 24 +++++++ .../prototype/forEach/this-plain-iterator.js | 29 ++++++++ .../Iterator/prototype/initial-value.js | 23 ++++++ .../prototype/map/argument-effect-order.js | 42 +++++++++++ .../Iterator/prototype/map/callable.js | 13 ++++ .../map/exhaustion-does-not-call-return.js | 34 +++++++++ .../map/get-next-method-only-once.js | 41 +++++++++++ .../prototype/map/get-next-method-throws.js | 25 +++++++ .../prototype/map/get-return-method-throws.js | 30 ++++++++ .../Iterator/prototype/map/is-function.js | 10 +++ .../map/iterator-already-exhausted.js | 22 ++++++ .../map/iterator-return-method-throws.js | 29 ++++++++ .../Iterator/prototype/map/length.js | 22 ++++++ .../Iterator/prototype/map/mapper-args.js | 55 ++++++++++++++ .../Iterator/prototype/map/mapper-this.js | 33 +++++++++ ...hrows-then-closing-iterator-also-throws.js | 40 +++++++++++ .../Iterator/prototype/map/mapper-throws.js | 41 +++++++++++ test/built-ins/Iterator/prototype/map/name.js | 29 ++++++++ .../map/next-method-returns-non-object.js | 23 ++++++ .../map/next-method-returns-throwing-done.js | 31 ++++++++ ...next-method-returns-throwing-value-done.js | 28 ++++++++ .../map/next-method-returns-throwing-value.js | 31 ++++++++ .../prototype/map/next-method-throws.js | 23 ++++++ .../prototype/map/non-callable-mapper.js | 20 ++++++ .../prototype/map/non-constructible.js | 28 ++++++++ .../Iterator/prototype/map/prop-desc.js | 25 +++++++ .../built-ins/Iterator/prototype/map/proto.js | 11 +++ .../prototype/map/result-is-iterator.js | 11 +++ ...urn-is-forwarded-to-underlying-iterator.js | 33 +++++++++ ...eturn-is-not-forwarded-after-exhaustion.js | 46 ++++++++++++ ...ed-iterator-yields-mapper-return-values.js | 36 ++++++++++ .../prototype/map/this-non-callable-next.js | 17 +++++ .../Iterator/prototype/map/this-non-object.js | 26 +++++++ .../prototype/map/this-plain-iterator.js | 31 ++++++++ ...nderlying-iterator-advanced-in-parallel.js | 42 +++++++++++ .../underlying-iterator-closed-in-parallel.js | 26 +++++++ .../map/underlying-iterator-closed.js | 26 +++++++ .../prototype/reduce/argument-effect-order.js | 58 +++++++++++++++ .../Iterator/prototype/reduce/callable.js | 13 ++++ .../reduce/get-next-method-only-once.js | 36 ++++++++++ .../reduce/get-next-method-throws.js | 23 ++++++ .../Iterator/prototype/reduce/is-function.js | 10 +++ ...terator-already-exhausted-initial-value.js | 21 ++++++ ...ator-already-exhausted-no-initial-value.js | 21 ++++++ .../iterator-yields-once-initial-value.js | 35 +++++++++ .../iterator-yields-once-no-initial-value.js | 26 +++++++ .../Iterator/prototype/reduce/length.js | 22 ++++++ .../Iterator/prototype/reduce/name.js | 29 ++++++++ .../reduce/next-method-returns-non-object.js | 23 ++++++ .../next-method-returns-throwing-done.js | 31 ++++++++ ...next-method-returns-throwing-value-done.js | 28 ++++++++ .../next-method-returns-throwing-value.js | 31 ++++++++ .../prototype/reduce/next-method-throws.js | 27 +++++++ .../prototype/reduce/non-callable-reducer.js | 20 ++++++ .../prototype/reduce/non-constructible.js | 32 +++++++++ .../Iterator/prototype/reduce/prop-desc.js | 25 +++++++ .../Iterator/prototype/reduce/proto.js | 11 +++ .../reduce/reducer-args-initial-value.js | 45 ++++++++++++ .../reduce/reducer-args-no-initial-value.js | 41 +++++++++++ .../reduce/reducer-memo-can-be-any-type.js | 31 ++++++++ .../Iterator/prototype/reduce/reducer-this.js | 32 +++++++++ ...hrows-then-closing-iterator-also-throws.js | 36 ++++++++++ .../prototype/reduce/reducer-throws.js | 40 +++++++++++ .../reduce/this-non-callable-next.js | 15 ++++ .../prototype/reduce/this-non-object.js | 33 +++++++++ .../prototype/reduce/this-plain-iterator.js | 32 +++++++++ .../prototype/some/argument-effect-order.js | 30 ++++++++ .../Iterator/prototype/some/callable.js | 13 ++++ .../some/get-next-method-only-once.js | 36 ++++++++++ .../prototype/some/get-next-method-throws.js | 23 ++++++ .../some/get-return-method-throws.js | 29 ++++++++ .../Iterator/prototype/some/is-function.js | 10 +++ .../some/iterator-already-exhausted.js | 23 ++++++ .../prototype/some/iterator-has-no-return.js | 27 +++++++ .../some/iterator-return-method-throws.js | 29 ++++++++ .../Iterator/prototype/some/length.js | 22 ++++++ .../built-ins/Iterator/prototype/some/name.js | 29 ++++++++ .../some/next-method-returns-non-object.js | 23 ++++++ .../some/next-method-returns-throwing-done.js | 31 ++++++++ ...next-method-returns-throwing-value-done.js | 28 ++++++++ .../next-method-returns-throwing-value.js | 31 ++++++++ .../prototype/some/next-method-throws.js | 23 ++++++ .../prototype/some/non-callable-predicate.js | 20 ++++++ .../prototype/some/non-constructible.js | 28 ++++++++ .../Iterator/prototype/some/predicate-args.js | 41 +++++++++++ .../predicate-returns-falsey-then-truthy.js | 32 +++++++++ .../some/predicate-returns-falsey.js | 21 ++++++ .../some/predicate-returns-non-boolean.js | 32 +++++++++ .../some/predicate-returns-truthy.js | 32 +++++++++ .../Iterator/prototype/some/predicate-this.js | 31 ++++++++ ...hrows-then-closing-iterator-also-throws.js | 36 ++++++++++ .../prototype/some/predicate-throws.js | 40 +++++++++++ .../Iterator/prototype/some/prop-desc.js | 25 +++++++ .../Iterator/prototype/some/proto.js | 11 +++ .../prototype/some/result-is-boolean.js | 11 +++ .../prototype/some/this-non-callable-next.js | 15 ++++ .../prototype/some/this-non-object.js | 24 +++++++ .../prototype/some/this-plain-iterator.js | 30 ++++++++ .../prototype/take/argument-effect-order.js | 72 +++++++++++++++++++ .../Iterator/prototype/take/callable.js | 13 ++++ .../prototype/take/exhaustion-calls-return.js | 68 ++++++++++++++++++ .../take/get-next-method-only-once.js | 41 +++++++++++ .../prototype/take/get-next-method-throws.js | 25 +++++++ .../take/get-return-method-throws.js | 30 ++++++++ .../Iterator/prototype/take/is-function.js | 10 +++ .../Iterator/prototype/take/length.js | 22 ++++++ .../limit-greater-than-or-equal-to-total.js | 27 +++++++ .../prototype/take/limit-less-than-total.js | 28 ++++++++ .../prototype/take/limit-rangeerror.js | 36 ++++++++++ .../prototype/take/limit-tonumber-throws.js | 22 ++++++ .../Iterator/prototype/take/limit-tonumber.js | 61 ++++++++++++++++ .../built-ins/Iterator/prototype/take/name.js | 29 ++++++++ .../take/next-method-returns-non-object.js | 29 ++++++++ .../take/next-method-returns-throwing-done.js | 42 +++++++++++ ...next-method-returns-throwing-value-done.js | 36 ++++++++++ .../next-method-returns-throwing-value.js | 42 +++++++++++ .../prototype/take/next-method-throws.js | 29 ++++++++ .../prototype/take/non-constructible.js | 28 ++++++++ .../Iterator/prototype/take/prop-desc.js | 25 +++++++ .../Iterator/prototype/take/proto.js | 11 +++ .../prototype/take/result-is-iterator.js | 11 +++ .../prototype/take/return-is-forwarded.js | 51 +++++++++++++ ...eturn-is-not-forwarded-after-exhaustion.js | 50 +++++++++++++ .../prototype/take/this-non-callable-next.js | 19 +++++ .../prototype/take/this-non-object.js | 34 +++++++++ .../prototype/take/this-plain-iterator.js | 30 ++++++++ ...nderlying-iterator-advanced-in-parallel.js | 39 ++++++++++ .../underlying-iterator-closed-in-parallel.js | 26 +++++++ .../take/underlying-iterator-closed.js | 26 +++++++ .../Iterator/prototype/toArray/callable.js | 13 ++++ .../toArray/get-next-method-only-once.js | 34 +++++++++ .../toArray/get-next-method-throws.js | 23 ++++++ .../Iterator/prototype/toArray/is-function.js | 10 +++ .../toArray/iterator-already-exhausted.js | 24 +++++++ .../Iterator/prototype/toArray/length.js | 22 ++++++ .../Iterator/prototype/toArray/name.js | 29 ++++++++ .../toArray/next-method-returns-non-object.js | 23 ++++++ .../next-method-returns-throwing-done.js | 31 ++++++++ ...next-method-returns-throwing-value-done.js | 28 ++++++++ .../next-method-returns-throwing-value.js | 31 ++++++++ .../prototype/toArray/next-method-throws.js | 23 ++++++ .../prototype/toArray/non-constructible.js | 24 +++++++ .../Iterator/prototype/toArray/prop-desc.js | 25 +++++++ .../Iterator/prototype/toArray/proto.js | 11 +++ .../toArray/this-non-callable-next.js | 15 ++++ .../prototype/toArray/this-non-object.js | 24 +++++++ .../prototype/toArray/this-plain-iterator.js | 25 +++++++ test/built-ins/Iterator/subclassable.js | 27 +++++++ .../toString/symbol-tag-non-str-builtin.js | 2 +- 374 files changed, 10452 insertions(+), 37 deletions(-) create mode 100644 test/built-ins/Iterator/constructor.js create mode 100644 test/built-ins/Iterator/from/callable.js create mode 100644 test/built-ins/Iterator/from/get-next-method-only-once.js create mode 100644 test/built-ins/Iterator/from/get-next-method-throws.js create mode 100644 test/built-ins/Iterator/from/is-function.js create mode 100644 test/built-ins/Iterator/from/iterable-primitives.js create mode 100644 test/built-ins/Iterator/from/iterable-to-iterator-fallback.js create mode 100644 test/built-ins/Iterator/from/length.js create mode 100644 test/built-ins/Iterator/from/name.js create mode 100644 test/built-ins/Iterator/from/non-constructible.js create mode 100644 test/built-ins/Iterator/from/primitives.js create mode 100644 test/built-ins/Iterator/from/prop-desc.js create mode 100644 test/built-ins/Iterator/from/proto.js create mode 100644 test/built-ins/Iterator/from/result-proto.js create mode 100644 test/built-ins/Iterator/from/supports-iterable.js create mode 100644 test/built-ins/Iterator/from/supports-iterator.js create mode 100644 test/built-ins/Iterator/length.js create mode 100644 test/built-ins/Iterator/name.js create mode 100644 test/built-ins/Iterator/newtarget-or-active-function-object.js create mode 100644 test/built-ins/Iterator/prop-desc.js create mode 100644 test/built-ins/Iterator/proto-from-ctor-realm.js create mode 100644 test/built-ins/Iterator/proto.js create mode 100644 test/built-ins/Iterator/prototype/Symbol.iterator/is-function.js rename test/built-ins/{IteratorPrototype => Iterator/prototype}/Symbol.iterator/length.js (68%) rename test/built-ins/{IteratorPrototype => Iterator/prototype}/Symbol.iterator/name.js (74%) rename test/built-ins/{IteratorPrototype => Iterator/prototype}/Symbol.iterator/prop-desc.js (65%) rename test/built-ins/{IteratorPrototype => Iterator/prototype}/Symbol.iterator/return-val.js (67%) create mode 100644 test/built-ins/Iterator/prototype/Symbol.toStringTag/prop-desc.js create mode 100644 test/built-ins/Iterator/prototype/drop/argument-effect-order.js create mode 100644 test/built-ins/Iterator/prototype/drop/callable.js create mode 100644 test/built-ins/Iterator/prototype/drop/exhaustion-does-not-call-return.js create mode 100644 test/built-ins/Iterator/prototype/drop/get-next-method-only-once.js create mode 100644 test/built-ins/Iterator/prototype/drop/get-next-method-throws.js create mode 100644 test/built-ins/Iterator/prototype/drop/get-return-method-throws.js create mode 100644 test/built-ins/Iterator/prototype/drop/is-function.js create mode 100644 test/built-ins/Iterator/prototype/drop/length.js create mode 100644 test/built-ins/Iterator/prototype/drop/limit-equals-total.js create mode 100644 test/built-ins/Iterator/prototype/drop/limit-greater-than-total.js create mode 100644 test/built-ins/Iterator/prototype/drop/limit-less-than-total.js create mode 100644 test/built-ins/Iterator/prototype/drop/limit-rangeerror.js create mode 100644 test/built-ins/Iterator/prototype/drop/limit-tonumber-throws.js create mode 100644 test/built-ins/Iterator/prototype/drop/limit-tonumber.js create mode 100644 test/built-ins/Iterator/prototype/drop/name.js create mode 100644 test/built-ins/Iterator/prototype/drop/next-method-returns-non-object.js create mode 100644 test/built-ins/Iterator/prototype/drop/next-method-returns-throwing-done.js create mode 100644 test/built-ins/Iterator/prototype/drop/next-method-returns-throwing-value-done.js create mode 100644 test/built-ins/Iterator/prototype/drop/next-method-returns-throwing-value.js create mode 100644 test/built-ins/Iterator/prototype/drop/next-method-throws.js create mode 100644 test/built-ins/Iterator/prototype/drop/non-constructible.js create mode 100644 test/built-ins/Iterator/prototype/drop/prop-desc.js create mode 100644 test/built-ins/Iterator/prototype/drop/proto.js create mode 100644 test/built-ins/Iterator/prototype/drop/result-is-iterator.js create mode 100644 test/built-ins/Iterator/prototype/drop/return-is-forwarded.js create mode 100644 test/built-ins/Iterator/prototype/drop/return-is-not-forwarded-after-exhaustion.js create mode 100644 test/built-ins/Iterator/prototype/drop/this-non-callable-next.js create mode 100644 test/built-ins/Iterator/prototype/drop/this-non-object.js create mode 100644 test/built-ins/Iterator/prototype/drop/this-plain-iterator.js create mode 100644 test/built-ins/Iterator/prototype/drop/underlying-iterator-advanced-in-parallel.js create mode 100644 test/built-ins/Iterator/prototype/drop/underlying-iterator-closed-in-parallel.js create mode 100644 test/built-ins/Iterator/prototype/drop/underlying-iterator-closed.js create mode 100644 test/built-ins/Iterator/prototype/every/argument-effect-order.js create mode 100644 test/built-ins/Iterator/prototype/every/callable.js create mode 100644 test/built-ins/Iterator/prototype/every/get-next-method-only-once.js create mode 100644 test/built-ins/Iterator/prototype/every/get-next-method-throws.js create mode 100644 test/built-ins/Iterator/prototype/every/get-return-method-throws.js create mode 100644 test/built-ins/Iterator/prototype/every/is-function.js create mode 100644 test/built-ins/Iterator/prototype/every/iterator-already-exhausted.js create mode 100644 test/built-ins/Iterator/prototype/every/iterator-has-no-return.js create mode 100644 test/built-ins/Iterator/prototype/every/iterator-return-method-throws.js create mode 100644 test/built-ins/Iterator/prototype/every/length.js create mode 100644 test/built-ins/Iterator/prototype/every/name.js create mode 100644 test/built-ins/Iterator/prototype/every/next-method-returns-non-object.js create mode 100644 test/built-ins/Iterator/prototype/every/next-method-returns-throwing-done.js create mode 100644 test/built-ins/Iterator/prototype/every/next-method-returns-throwing-value-done.js create mode 100644 test/built-ins/Iterator/prototype/every/next-method-returns-throwing-value.js create mode 100644 test/built-ins/Iterator/prototype/every/next-method-throws.js create mode 100644 test/built-ins/Iterator/prototype/every/non-callable-predicate.js create mode 100644 test/built-ins/Iterator/prototype/every/non-constructible.js create mode 100644 test/built-ins/Iterator/prototype/every/predicate-args.js create mode 100644 test/built-ins/Iterator/prototype/every/predicate-returns-falsey.js create mode 100644 test/built-ins/Iterator/prototype/every/predicate-returns-non-boolean.js create mode 100644 test/built-ins/Iterator/prototype/every/predicate-returns-truthy-then-falsey.js create mode 100644 test/built-ins/Iterator/prototype/every/predicate-returns-truthy.js create mode 100644 test/built-ins/Iterator/prototype/every/predicate-this.js create mode 100644 test/built-ins/Iterator/prototype/every/predicate-throws-then-closing-iterator-also-throws.js create mode 100644 test/built-ins/Iterator/prototype/every/predicate-throws.js create mode 100644 test/built-ins/Iterator/prototype/every/prop-desc.js create mode 100644 test/built-ins/Iterator/prototype/every/proto.js create mode 100644 test/built-ins/Iterator/prototype/every/result-is-boolean.js create mode 100644 test/built-ins/Iterator/prototype/every/this-non-callable-next.js create mode 100644 test/built-ins/Iterator/prototype/every/this-non-object.js create mode 100644 test/built-ins/Iterator/prototype/every/this-plain-iterator.js create mode 100644 test/built-ins/Iterator/prototype/filter/argument-effect-order.js create mode 100644 test/built-ins/Iterator/prototype/filter/callable.js create mode 100644 test/built-ins/Iterator/prototype/filter/exhaustion-does-not-call-return.js create mode 100644 test/built-ins/Iterator/prototype/filter/get-next-method-only-once.js create mode 100644 test/built-ins/Iterator/prototype/filter/get-next-method-throws.js create mode 100644 test/built-ins/Iterator/prototype/filter/get-return-method-throws.js create mode 100644 test/built-ins/Iterator/prototype/filter/is-function.js create mode 100644 test/built-ins/Iterator/prototype/filter/iterator-already-exhausted.js create mode 100644 test/built-ins/Iterator/prototype/filter/iterator-return-method-throws.js create mode 100644 test/built-ins/Iterator/prototype/filter/length.js create mode 100644 test/built-ins/Iterator/prototype/filter/name.js create mode 100644 test/built-ins/Iterator/prototype/filter/next-method-returns-non-object.js create mode 100644 test/built-ins/Iterator/prototype/filter/next-method-returns-throwing-done.js create mode 100644 test/built-ins/Iterator/prototype/filter/next-method-returns-throwing-value-done.js create mode 100644 test/built-ins/Iterator/prototype/filter/next-method-returns-throwing-value.js create mode 100644 test/built-ins/Iterator/prototype/filter/next-method-throws.js create mode 100644 test/built-ins/Iterator/prototype/filter/non-callable-predicate.js create mode 100644 test/built-ins/Iterator/prototype/filter/non-constructible.js create mode 100644 test/built-ins/Iterator/prototype/filter/predicate-args.js create mode 100644 test/built-ins/Iterator/prototype/filter/predicate-filters.js create mode 100644 test/built-ins/Iterator/prototype/filter/predicate-returns-non-boolean.js create mode 100644 test/built-ins/Iterator/prototype/filter/predicate-this.js create mode 100644 test/built-ins/Iterator/prototype/filter/predicate-throws-then-closing-iterator-also-throws.js create mode 100644 test/built-ins/Iterator/prototype/filter/predicate-throws.js create mode 100644 test/built-ins/Iterator/prototype/filter/prop-desc.js create mode 100644 test/built-ins/Iterator/prototype/filter/proto.js create mode 100644 test/built-ins/Iterator/prototype/filter/result-is-iterator.js create mode 100644 test/built-ins/Iterator/prototype/filter/return-is-forwarded.js create mode 100644 test/built-ins/Iterator/prototype/filter/return-is-not-forwarded-after-exhaustion.js create mode 100644 test/built-ins/Iterator/prototype/filter/this-non-callable-next.js create mode 100644 test/built-ins/Iterator/prototype/filter/this-non-object.js create mode 100644 test/built-ins/Iterator/prototype/filter/this-plain-iterator.js create mode 100644 test/built-ins/Iterator/prototype/filter/underlying-iterator-advanced-in-parallel.js create mode 100644 test/built-ins/Iterator/prototype/filter/underlying-iterator-closed-in-parallel.js create mode 100644 test/built-ins/Iterator/prototype/filter/underlying-iterator-closed.js create mode 100644 test/built-ins/Iterator/prototype/find/argument-effect-order.js create mode 100644 test/built-ins/Iterator/prototype/find/callable.js create mode 100644 test/built-ins/Iterator/prototype/find/get-next-method-only-once.js create mode 100644 test/built-ins/Iterator/prototype/find/get-next-method-throws.js create mode 100644 test/built-ins/Iterator/prototype/find/get-return-method-throws.js create mode 100644 test/built-ins/Iterator/prototype/find/is-function.js create mode 100644 test/built-ins/Iterator/prototype/find/iterator-already-exhausted.js create mode 100644 test/built-ins/Iterator/prototype/find/iterator-has-no-return.js create mode 100644 test/built-ins/Iterator/prototype/find/iterator-return-method-throws.js create mode 100644 test/built-ins/Iterator/prototype/find/length.js create mode 100644 test/built-ins/Iterator/prototype/find/name.js create mode 100644 test/built-ins/Iterator/prototype/find/next-method-returns-non-object.js create mode 100644 test/built-ins/Iterator/prototype/find/next-method-returns-throwing-done.js create mode 100644 test/built-ins/Iterator/prototype/find/next-method-returns-throwing-value-done.js create mode 100644 test/built-ins/Iterator/prototype/find/next-method-returns-throwing-value.js create mode 100644 test/built-ins/Iterator/prototype/find/next-method-throws.js create mode 100644 test/built-ins/Iterator/prototype/find/non-callable-predicate.js create mode 100644 test/built-ins/Iterator/prototype/find/non-constructible.js create mode 100644 test/built-ins/Iterator/prototype/find/predicate-args.js create mode 100644 test/built-ins/Iterator/prototype/find/predicate-returns-falsey-then-truthy.js create mode 100644 test/built-ins/Iterator/prototype/find/predicate-returns-falsey.js create mode 100644 test/built-ins/Iterator/prototype/find/predicate-returns-non-boolean.js create mode 100644 test/built-ins/Iterator/prototype/find/predicate-returns-truthy.js create mode 100644 test/built-ins/Iterator/prototype/find/predicate-this.js create mode 100644 test/built-ins/Iterator/prototype/find/predicate-throws-then-closing-iterator-also-throws.js create mode 100644 test/built-ins/Iterator/prototype/find/predicate-throws.js create mode 100644 test/built-ins/Iterator/prototype/find/prop-desc.js create mode 100644 test/built-ins/Iterator/prototype/find/proto.js create mode 100644 test/built-ins/Iterator/prototype/find/this-non-callable-next.js create mode 100644 test/built-ins/Iterator/prototype/find/this-non-object.js create mode 100644 test/built-ins/Iterator/prototype/find/this-plain-iterator.js create mode 100644 test/built-ins/Iterator/prototype/flatMap/argument-effect-order.js create mode 100644 test/built-ins/Iterator/prototype/flatMap/callable.js create mode 100644 test/built-ins/Iterator/prototype/flatMap/exhaustion-does-not-call-return.js create mode 100644 test/built-ins/Iterator/prototype/flatMap/flattens-iterable.js create mode 100644 test/built-ins/Iterator/prototype/flatMap/flattens-iterator.js create mode 100644 test/built-ins/Iterator/prototype/flatMap/flattens-only-depth-1.js create mode 100644 test/built-ins/Iterator/prototype/flatMap/get-next-method-only-once.js create mode 100644 test/built-ins/Iterator/prototype/flatMap/get-next-method-throws.js create mode 100644 test/built-ins/Iterator/prototype/flatMap/get-return-method-throws.js create mode 100644 test/built-ins/Iterator/prototype/flatMap/is-function.js create mode 100644 test/built-ins/Iterator/prototype/flatMap/iterable-primitives-are-not-flattened.js create mode 100644 test/built-ins/Iterator/prototype/flatMap/iterable-to-iterator-fallback.js create mode 100644 test/built-ins/Iterator/prototype/flatMap/iterator-already-exhausted.js create mode 100644 test/built-ins/Iterator/prototype/flatMap/iterator-return-method-throws.js create mode 100644 test/built-ins/Iterator/prototype/flatMap/length.js create mode 100644 test/built-ins/Iterator/prototype/flatMap/mapper-args.js create mode 100644 test/built-ins/Iterator/prototype/flatMap/mapper-returns-closed-iterator.js create mode 100644 test/built-ins/Iterator/prototype/flatMap/mapper-returns-non-object.js create mode 100644 test/built-ins/Iterator/prototype/flatMap/mapper-this.js create mode 100644 test/built-ins/Iterator/prototype/flatMap/mapper-throws-then-closing-iterator-also-throws.js create mode 100644 test/built-ins/Iterator/prototype/flatMap/mapper-throws.js create mode 100644 test/built-ins/Iterator/prototype/flatMap/name.js create mode 100644 test/built-ins/Iterator/prototype/flatMap/next-method-returns-non-object.js create mode 100644 test/built-ins/Iterator/prototype/flatMap/next-method-returns-throwing-done.js create mode 100644 test/built-ins/Iterator/prototype/flatMap/next-method-returns-throwing-value-done.js create mode 100644 test/built-ins/Iterator/prototype/flatMap/next-method-returns-throwing-value.js create mode 100644 test/built-ins/Iterator/prototype/flatMap/next-method-throws.js create mode 100644 test/built-ins/Iterator/prototype/flatMap/non-callable-mapper.js create mode 100644 test/built-ins/Iterator/prototype/flatMap/non-constructible.js create mode 100644 test/built-ins/Iterator/prototype/flatMap/prop-desc.js create mode 100644 test/built-ins/Iterator/prototype/flatMap/proto.js create mode 100644 test/built-ins/Iterator/prototype/flatMap/result-is-iterator.js create mode 100644 test/built-ins/Iterator/prototype/flatMap/return-is-forwarded-to-mapper-result.js create mode 100644 test/built-ins/Iterator/prototype/flatMap/return-is-forwarded-to-underlying-iterator.js create mode 100644 test/built-ins/Iterator/prototype/flatMap/return-is-not-forwarded-after-exhaustion.js create mode 100644 test/built-ins/Iterator/prototype/flatMap/strings-are-not-flattened.js create mode 100644 test/built-ins/Iterator/prototype/flatMap/this-non-callable-next.js create mode 100644 test/built-ins/Iterator/prototype/flatMap/this-non-object.js create mode 100644 test/built-ins/Iterator/prototype/flatMap/this-plain-iterator.js create mode 100644 test/built-ins/Iterator/prototype/flatMap/underlying-iterator-advanced-in-parallel.js create mode 100644 test/built-ins/Iterator/prototype/flatMap/underlying-iterator-closed-in-parallel.js create mode 100644 test/built-ins/Iterator/prototype/flatMap/underlying-iterator-closed.js create mode 100644 test/built-ins/Iterator/prototype/forEach/argument-effect-order.js create mode 100644 test/built-ins/Iterator/prototype/forEach/callable.js create mode 100644 test/built-ins/Iterator/prototype/forEach/fn-args.js create mode 100644 test/built-ins/Iterator/prototype/forEach/fn-called-for-each-yielded-value.js create mode 100644 test/built-ins/Iterator/prototype/forEach/fn-this.js create mode 100644 test/built-ins/Iterator/prototype/forEach/fn-throws-then-closing-iterator-also-throws.js create mode 100644 test/built-ins/Iterator/prototype/forEach/fn-throws.js create mode 100644 test/built-ins/Iterator/prototype/forEach/get-next-method-only-once.js create mode 100644 test/built-ins/Iterator/prototype/forEach/get-next-method-throws.js create mode 100644 test/built-ins/Iterator/prototype/forEach/is-function.js create mode 100644 test/built-ins/Iterator/prototype/forEach/iterator-already-exhausted.js create mode 100644 test/built-ins/Iterator/prototype/forEach/length.js create mode 100644 test/built-ins/Iterator/prototype/forEach/name.js create mode 100644 test/built-ins/Iterator/prototype/forEach/next-method-returns-non-object.js create mode 100644 test/built-ins/Iterator/prototype/forEach/next-method-returns-throwing-done.js create mode 100644 test/built-ins/Iterator/prototype/forEach/next-method-returns-throwing-value-done.js create mode 100644 test/built-ins/Iterator/prototype/forEach/next-method-returns-throwing-value.js create mode 100644 test/built-ins/Iterator/prototype/forEach/next-method-throws.js create mode 100644 test/built-ins/Iterator/prototype/forEach/non-callable-predicate.js create mode 100644 test/built-ins/Iterator/prototype/forEach/non-constructible.js create mode 100644 test/built-ins/Iterator/prototype/forEach/prop-desc.js create mode 100644 test/built-ins/Iterator/prototype/forEach/proto.js create mode 100644 test/built-ins/Iterator/prototype/forEach/result-is-undefined.js create mode 100644 test/built-ins/Iterator/prototype/forEach/this-non-callable-next.js create mode 100644 test/built-ins/Iterator/prototype/forEach/this-non-object.js create mode 100644 test/built-ins/Iterator/prototype/forEach/this-plain-iterator.js create mode 100644 test/built-ins/Iterator/prototype/initial-value.js create mode 100644 test/built-ins/Iterator/prototype/map/argument-effect-order.js create mode 100644 test/built-ins/Iterator/prototype/map/callable.js create mode 100644 test/built-ins/Iterator/prototype/map/exhaustion-does-not-call-return.js create mode 100644 test/built-ins/Iterator/prototype/map/get-next-method-only-once.js create mode 100644 test/built-ins/Iterator/prototype/map/get-next-method-throws.js create mode 100644 test/built-ins/Iterator/prototype/map/get-return-method-throws.js create mode 100644 test/built-ins/Iterator/prototype/map/is-function.js create mode 100644 test/built-ins/Iterator/prototype/map/iterator-already-exhausted.js create mode 100644 test/built-ins/Iterator/prototype/map/iterator-return-method-throws.js create mode 100644 test/built-ins/Iterator/prototype/map/length.js create mode 100644 test/built-ins/Iterator/prototype/map/mapper-args.js create mode 100644 test/built-ins/Iterator/prototype/map/mapper-this.js create mode 100644 test/built-ins/Iterator/prototype/map/mapper-throws-then-closing-iterator-also-throws.js create mode 100644 test/built-ins/Iterator/prototype/map/mapper-throws.js create mode 100644 test/built-ins/Iterator/prototype/map/name.js create mode 100644 test/built-ins/Iterator/prototype/map/next-method-returns-non-object.js create mode 100644 test/built-ins/Iterator/prototype/map/next-method-returns-throwing-done.js create mode 100644 test/built-ins/Iterator/prototype/map/next-method-returns-throwing-value-done.js create mode 100644 test/built-ins/Iterator/prototype/map/next-method-returns-throwing-value.js create mode 100644 test/built-ins/Iterator/prototype/map/next-method-throws.js create mode 100644 test/built-ins/Iterator/prototype/map/non-callable-mapper.js create mode 100644 test/built-ins/Iterator/prototype/map/non-constructible.js create mode 100644 test/built-ins/Iterator/prototype/map/prop-desc.js create mode 100644 test/built-ins/Iterator/prototype/map/proto.js create mode 100644 test/built-ins/Iterator/prototype/map/result-is-iterator.js create mode 100644 test/built-ins/Iterator/prototype/map/return-is-forwarded-to-underlying-iterator.js create mode 100644 test/built-ins/Iterator/prototype/map/return-is-not-forwarded-after-exhaustion.js create mode 100644 test/built-ins/Iterator/prototype/map/returned-iterator-yields-mapper-return-values.js create mode 100644 test/built-ins/Iterator/prototype/map/this-non-callable-next.js create mode 100644 test/built-ins/Iterator/prototype/map/this-non-object.js create mode 100644 test/built-ins/Iterator/prototype/map/this-plain-iterator.js create mode 100644 test/built-ins/Iterator/prototype/map/underlying-iterator-advanced-in-parallel.js create mode 100644 test/built-ins/Iterator/prototype/map/underlying-iterator-closed-in-parallel.js create mode 100644 test/built-ins/Iterator/prototype/map/underlying-iterator-closed.js create mode 100644 test/built-ins/Iterator/prototype/reduce/argument-effect-order.js create mode 100644 test/built-ins/Iterator/prototype/reduce/callable.js create mode 100644 test/built-ins/Iterator/prototype/reduce/get-next-method-only-once.js create mode 100644 test/built-ins/Iterator/prototype/reduce/get-next-method-throws.js create mode 100644 test/built-ins/Iterator/prototype/reduce/is-function.js create mode 100644 test/built-ins/Iterator/prototype/reduce/iterator-already-exhausted-initial-value.js create mode 100644 test/built-ins/Iterator/prototype/reduce/iterator-already-exhausted-no-initial-value.js create mode 100644 test/built-ins/Iterator/prototype/reduce/iterator-yields-once-initial-value.js create mode 100644 test/built-ins/Iterator/prototype/reduce/iterator-yields-once-no-initial-value.js create mode 100644 test/built-ins/Iterator/prototype/reduce/length.js create mode 100644 test/built-ins/Iterator/prototype/reduce/name.js create mode 100644 test/built-ins/Iterator/prototype/reduce/next-method-returns-non-object.js create mode 100644 test/built-ins/Iterator/prototype/reduce/next-method-returns-throwing-done.js create mode 100644 test/built-ins/Iterator/prototype/reduce/next-method-returns-throwing-value-done.js create mode 100644 test/built-ins/Iterator/prototype/reduce/next-method-returns-throwing-value.js create mode 100644 test/built-ins/Iterator/prototype/reduce/next-method-throws.js create mode 100644 test/built-ins/Iterator/prototype/reduce/non-callable-reducer.js create mode 100644 test/built-ins/Iterator/prototype/reduce/non-constructible.js create mode 100644 test/built-ins/Iterator/prototype/reduce/prop-desc.js create mode 100644 test/built-ins/Iterator/prototype/reduce/proto.js create mode 100644 test/built-ins/Iterator/prototype/reduce/reducer-args-initial-value.js create mode 100644 test/built-ins/Iterator/prototype/reduce/reducer-args-no-initial-value.js create mode 100644 test/built-ins/Iterator/prototype/reduce/reducer-memo-can-be-any-type.js create mode 100644 test/built-ins/Iterator/prototype/reduce/reducer-this.js create mode 100644 test/built-ins/Iterator/prototype/reduce/reducer-throws-then-closing-iterator-also-throws.js create mode 100644 test/built-ins/Iterator/prototype/reduce/reducer-throws.js create mode 100644 test/built-ins/Iterator/prototype/reduce/this-non-callable-next.js create mode 100644 test/built-ins/Iterator/prototype/reduce/this-non-object.js create mode 100644 test/built-ins/Iterator/prototype/reduce/this-plain-iterator.js create mode 100644 test/built-ins/Iterator/prototype/some/argument-effect-order.js create mode 100644 test/built-ins/Iterator/prototype/some/callable.js create mode 100644 test/built-ins/Iterator/prototype/some/get-next-method-only-once.js create mode 100644 test/built-ins/Iterator/prototype/some/get-next-method-throws.js create mode 100644 test/built-ins/Iterator/prototype/some/get-return-method-throws.js create mode 100644 test/built-ins/Iterator/prototype/some/is-function.js create mode 100644 test/built-ins/Iterator/prototype/some/iterator-already-exhausted.js create mode 100644 test/built-ins/Iterator/prototype/some/iterator-has-no-return.js create mode 100644 test/built-ins/Iterator/prototype/some/iterator-return-method-throws.js create mode 100644 test/built-ins/Iterator/prototype/some/length.js create mode 100644 test/built-ins/Iterator/prototype/some/name.js create mode 100644 test/built-ins/Iterator/prototype/some/next-method-returns-non-object.js create mode 100644 test/built-ins/Iterator/prototype/some/next-method-returns-throwing-done.js create mode 100644 test/built-ins/Iterator/prototype/some/next-method-returns-throwing-value-done.js create mode 100644 test/built-ins/Iterator/prototype/some/next-method-returns-throwing-value.js create mode 100644 test/built-ins/Iterator/prototype/some/next-method-throws.js create mode 100644 test/built-ins/Iterator/prototype/some/non-callable-predicate.js create mode 100644 test/built-ins/Iterator/prototype/some/non-constructible.js create mode 100644 test/built-ins/Iterator/prototype/some/predicate-args.js create mode 100644 test/built-ins/Iterator/prototype/some/predicate-returns-falsey-then-truthy.js create mode 100644 test/built-ins/Iterator/prototype/some/predicate-returns-falsey.js create mode 100644 test/built-ins/Iterator/prototype/some/predicate-returns-non-boolean.js create mode 100644 test/built-ins/Iterator/prototype/some/predicate-returns-truthy.js create mode 100644 test/built-ins/Iterator/prototype/some/predicate-this.js create mode 100644 test/built-ins/Iterator/prototype/some/predicate-throws-then-closing-iterator-also-throws.js create mode 100644 test/built-ins/Iterator/prototype/some/predicate-throws.js create mode 100644 test/built-ins/Iterator/prototype/some/prop-desc.js create mode 100644 test/built-ins/Iterator/prototype/some/proto.js create mode 100644 test/built-ins/Iterator/prototype/some/result-is-boolean.js create mode 100644 test/built-ins/Iterator/prototype/some/this-non-callable-next.js create mode 100644 test/built-ins/Iterator/prototype/some/this-non-object.js create mode 100644 test/built-ins/Iterator/prototype/some/this-plain-iterator.js create mode 100644 test/built-ins/Iterator/prototype/take/argument-effect-order.js create mode 100644 test/built-ins/Iterator/prototype/take/callable.js create mode 100644 test/built-ins/Iterator/prototype/take/exhaustion-calls-return.js create mode 100644 test/built-ins/Iterator/prototype/take/get-next-method-only-once.js create mode 100644 test/built-ins/Iterator/prototype/take/get-next-method-throws.js create mode 100644 test/built-ins/Iterator/prototype/take/get-return-method-throws.js create mode 100644 test/built-ins/Iterator/prototype/take/is-function.js create mode 100644 test/built-ins/Iterator/prototype/take/length.js create mode 100644 test/built-ins/Iterator/prototype/take/limit-greater-than-or-equal-to-total.js create mode 100644 test/built-ins/Iterator/prototype/take/limit-less-than-total.js create mode 100644 test/built-ins/Iterator/prototype/take/limit-rangeerror.js create mode 100644 test/built-ins/Iterator/prototype/take/limit-tonumber-throws.js create mode 100644 test/built-ins/Iterator/prototype/take/limit-tonumber.js create mode 100644 test/built-ins/Iterator/prototype/take/name.js create mode 100644 test/built-ins/Iterator/prototype/take/next-method-returns-non-object.js create mode 100644 test/built-ins/Iterator/prototype/take/next-method-returns-throwing-done.js create mode 100644 test/built-ins/Iterator/prototype/take/next-method-returns-throwing-value-done.js create mode 100644 test/built-ins/Iterator/prototype/take/next-method-returns-throwing-value.js create mode 100644 test/built-ins/Iterator/prototype/take/next-method-throws.js create mode 100644 test/built-ins/Iterator/prototype/take/non-constructible.js create mode 100644 test/built-ins/Iterator/prototype/take/prop-desc.js create mode 100644 test/built-ins/Iterator/prototype/take/proto.js create mode 100644 test/built-ins/Iterator/prototype/take/result-is-iterator.js create mode 100644 test/built-ins/Iterator/prototype/take/return-is-forwarded.js create mode 100644 test/built-ins/Iterator/prototype/take/return-is-not-forwarded-after-exhaustion.js create mode 100644 test/built-ins/Iterator/prototype/take/this-non-callable-next.js create mode 100644 test/built-ins/Iterator/prototype/take/this-non-object.js create mode 100644 test/built-ins/Iterator/prototype/take/this-plain-iterator.js create mode 100644 test/built-ins/Iterator/prototype/take/underlying-iterator-advanced-in-parallel.js create mode 100644 test/built-ins/Iterator/prototype/take/underlying-iterator-closed-in-parallel.js create mode 100644 test/built-ins/Iterator/prototype/take/underlying-iterator-closed.js create mode 100644 test/built-ins/Iterator/prototype/toArray/callable.js create mode 100644 test/built-ins/Iterator/prototype/toArray/get-next-method-only-once.js create mode 100644 test/built-ins/Iterator/prototype/toArray/get-next-method-throws.js create mode 100644 test/built-ins/Iterator/prototype/toArray/is-function.js create mode 100644 test/built-ins/Iterator/prototype/toArray/iterator-already-exhausted.js create mode 100644 test/built-ins/Iterator/prototype/toArray/length.js create mode 100644 test/built-ins/Iterator/prototype/toArray/name.js create mode 100644 test/built-ins/Iterator/prototype/toArray/next-method-returns-non-object.js create mode 100644 test/built-ins/Iterator/prototype/toArray/next-method-returns-throwing-done.js create mode 100644 test/built-ins/Iterator/prototype/toArray/next-method-returns-throwing-value-done.js create mode 100644 test/built-ins/Iterator/prototype/toArray/next-method-returns-throwing-value.js create mode 100644 test/built-ins/Iterator/prototype/toArray/next-method-throws.js create mode 100644 test/built-ins/Iterator/prototype/toArray/non-constructible.js create mode 100644 test/built-ins/Iterator/prototype/toArray/prop-desc.js create mode 100644 test/built-ins/Iterator/prototype/toArray/proto.js create mode 100644 test/built-ins/Iterator/prototype/toArray/this-non-callable-next.js create mode 100644 test/built-ins/Iterator/prototype/toArray/this-non-object.js create mode 100644 test/built-ins/Iterator/prototype/toArray/this-plain-iterator.js create mode 100644 test/built-ins/Iterator/subclassable.js diff --git a/features.txt b/features.txt index a193406c8d..b4350fea6c 100644 --- a/features.txt +++ b/features.txt @@ -104,6 +104,10 @@ String.prototype.toWellFormed # https://github.com/tc39/proposal-json-parse-with-source json-parse-with-source +# Iterator Helpers +# https://github.com/tc39/proposal-iterator-helpers +iterator-helpers + ## Standard language features # # Language features that have been included in a published version of the diff --git a/test/built-ins/Iterator/constructor.js b/test/built-ins/Iterator/constructor.js new file mode 100644 index 0000000000..9c06d9a964 --- /dev/null +++ b/test/built-ins/Iterator/constructor.js @@ -0,0 +1,11 @@ +// 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"'); diff --git a/test/built-ins/Iterator/from/callable.js b/test/built-ins/Iterator/from/callable.js new file mode 100644 index 0000000000..738257dc0c --- /dev/null +++ b/test/built-ins/Iterator/from/callable.js @@ -0,0 +1,12 @@ +// 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()); diff --git a/test/built-ins/Iterator/from/get-next-method-only-once.js b/test/built-ins/Iterator/from/get-next-method-only-once.js new file mode 100644 index 0000000000..1c75257f58 --- /dev/null +++ b/test/built-ins/Iterator/from/get-next-method-only-once.js @@ -0,0 +1,46 @@ +// 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'); diff --git a/test/built-ins/Iterator/from/get-next-method-throws.js b/test/built-ins/Iterator/from/get-next-method-throws.js new file mode 100644 index 0000000000..1b1083f2b2 --- /dev/null +++ b/test/built-ins/Iterator/from/get-next-method-throws.js @@ -0,0 +1,25 @@ +// 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); +}); diff --git a/test/built-ins/Iterator/from/is-function.js b/test/built-ins/Iterator/from/is-function.js new file mode 100644 index 0000000000..dc8eff9fd5 --- /dev/null +++ b/test/built-ins/Iterator/from/is-function.js @@ -0,0 +1,10 @@ +// 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"'); diff --git a/test/built-ins/Iterator/from/iterable-primitives.js b/test/built-ins/Iterator/from/iterable-primitives.js new file mode 100644 index 0000000000..f162ee1cc0 --- /dev/null +++ b/test/built-ins/Iterator/from/iterable-primitives.js @@ -0,0 +1,39 @@ +// 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']); diff --git a/test/built-ins/Iterator/from/iterable-to-iterator-fallback.js b/test/built-ins/Iterator/from/iterable-to-iterator-fallback.js new file mode 100644 index 0000000000..3228cb47f7 --- /dev/null +++ b/test/built-ins/Iterator/from/iterable-to-iterator-fallback.js @@ -0,0 +1,51 @@ +// 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]); diff --git a/test/built-ins/Iterator/from/length.js b/test/built-ins/Iterator/from/length.js new file mode 100644 index 0000000000..05df92269c --- /dev/null +++ b/test/built-ins/Iterator/from/length.js @@ -0,0 +1,22 @@ +// 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, +}); diff --git a/test/built-ins/Iterator/from/name.js b/test/built-ins/Iterator/from/name.js new file mode 100644 index 0000000000..cff643bd1f --- /dev/null +++ b/test/built-ins/Iterator/from/name.js @@ -0,0 +1,29 @@ +// 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, +}); diff --git a/test/built-ins/Iterator/from/non-constructible.js b/test/built-ins/Iterator/from/non-constructible.js new file mode 100644 index 0000000000..02eae9a510 --- /dev/null +++ b/test/built-ins/Iterator/from/non-constructible.js @@ -0,0 +1,23 @@ +// 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()); +}); diff --git a/test/built-ins/Iterator/from/primitives.js b/test/built-ins/Iterator/from/primitives.js new file mode 100644 index 0000000000..4c016765c8 --- /dev/null +++ b/test/built-ins/Iterator/from/primitives.js @@ -0,0 +1,38 @@ +// 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'); diff --git a/test/built-ins/Iterator/from/prop-desc.js b/test/built-ins/Iterator/from/prop-desc.js new file mode 100644 index 0000000000..92fbc25761 --- /dev/null +++ b/test/built-ins/Iterator/from/prop-desc.js @@ -0,0 +1,26 @@ +// 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, +}); diff --git a/test/built-ins/Iterator/from/proto.js b/test/built-ins/Iterator/from/proto.js new file mode 100644 index 0000000000..b99e04fad2 --- /dev/null +++ b/test/built-ins/Iterator/from/proto.js @@ -0,0 +1,15 @@ +// 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' +); diff --git a/test/built-ins/Iterator/from/result-proto.js b/test/built-ins/Iterator/from/result-proto.js new file mode 100644 index 0000000000..0888791d7b --- /dev/null +++ b/test/built-ins/Iterator/from/result-proto.js @@ -0,0 +1,29 @@ +// 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); diff --git a/test/built-ins/Iterator/from/supports-iterable.js b/test/built-ins/Iterator/from/supports-iterable.js new file mode 100644 index 0000000000..03e26258cb --- /dev/null +++ b/test/built-ins/Iterator/from/supports-iterable.js @@ -0,0 +1,14 @@ +// 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]); diff --git a/test/built-ins/Iterator/from/supports-iterator.js b/test/built-ins/Iterator/from/supports-iterator.js new file mode 100644 index 0000000000..888d8dc916 --- /dev/null +++ b/test/built-ins/Iterator/from/supports-iterator.js @@ -0,0 +1,29 @@ +// 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]); diff --git a/test/built-ins/Iterator/length.js b/test/built-ins/Iterator/length.js new file mode 100644 index 0000000000..78d596a3eb --- /dev/null +++ b/test/built-ins/Iterator/length.js @@ -0,0 +1,26 @@ +// 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, +}); diff --git a/test/built-ins/Iterator/name.js b/test/built-ins/Iterator/name.js new file mode 100644 index 0000000000..bb7ada2b6e --- /dev/null +++ b/test/built-ins/Iterator/name.js @@ -0,0 +1,30 @@ +// 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, +}); diff --git a/test/built-ins/Iterator/newtarget-or-active-function-object.js b/test/built-ins/Iterator/newtarget-or-active-function-object.js new file mode 100644 index 0000000000..de5ad257fc --- /dev/null +++ b/test/built-ins/Iterator/newtarget-or-active-function-object.js @@ -0,0 +1,22 @@ +// 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(); +}); diff --git a/test/built-ins/Iterator/prop-desc.js b/test/built-ins/Iterator/prop-desc.js new file mode 100644 index 0000000000..e93e9e5136 --- /dev/null +++ b/test/built-ins/Iterator/prop-desc.js @@ -0,0 +1,27 @@ +// 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, +}); diff --git a/test/built-ins/Iterator/proto-from-ctor-realm.js b/test/built-ins/Iterator/proto-from-ctor-realm.js new file mode 100644 index 0000000000..2f2f72b33f --- /dev/null +++ b/test/built-ins/Iterator/proto-from-ctor-realm.js @@ -0,0 +1,36 @@ +// 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); diff --git a/test/built-ins/Iterator/proto.js b/test/built-ins/Iterator/proto.js new file mode 100644 index 0000000000..f71d6eb7cd --- /dev/null +++ b/test/built-ins/Iterator/proto.js @@ -0,0 +1,16 @@ +// 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' +); diff --git a/test/built-ins/Iterator/prototype/Symbol.iterator/is-function.js b/test/built-ins/Iterator/prototype/Symbol.iterator/is-function.js new file mode 100644 index 0000000000..cd6d2d96bf --- /dev/null +++ b/test/built-ins/Iterator/prototype/Symbol.iterator/is-function.js @@ -0,0 +1,13 @@ +// 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'); diff --git a/test/built-ins/IteratorPrototype/Symbol.iterator/length.js b/test/built-ins/Iterator/prototype/Symbol.iterator/length.js similarity index 68% rename from test/built-ins/IteratorPrototype/Symbol.iterator/length.js rename to test/built-ins/Iterator/prototype/Symbol.iterator/length.js index 7c69aec54a..404b17b1a5 100644 --- a/test/built-ins/IteratorPrototype/Symbol.iterator/length.js +++ b/test/built-ins/Iterator/prototype/Symbol.iterator/length.js @@ -2,7 +2,7 @@ // This code is governed by the BSD license found in the LICENSE file. /*--- es6id: 25.1.2.1 -description: Length of IteratorPrototype[ @@iterator ] +description: Length of %IteratorPrototype%[ @@iterator ] info: | ES6 Section 17: Every built-in Function object, including constructors, has a length @@ -18,13 +18,13 @@ info: | features: [Symbol.iterator] includes: [propertyHelper.js] ---*/ - -var IteratorPrototype = Object.getPrototypeOf( +const IteratorPrototype = Object.getPrototypeOf( Object.getPrototypeOf([][Symbol.iterator]()) ); -assert.sameValue(IteratorPrototype[Symbol.iterator].length, 0); - -verifyNotEnumerable(IteratorPrototype[Symbol.iterator], 'length'); -verifyNotWritable(IteratorPrototype[Symbol.iterator], 'length'); -verifyConfigurable(IteratorPrototype[Symbol.iterator], 'length'); +verifyProperty(IteratorPrototype[Symbol.iterator], 'length', { + value: 0, + writable: false, + enumerable: false, + configurable: true, +}); diff --git a/test/built-ins/IteratorPrototype/Symbol.iterator/name.js b/test/built-ins/Iterator/prototype/Symbol.iterator/name.js similarity index 74% rename from test/built-ins/IteratorPrototype/Symbol.iterator/name.js rename to test/built-ins/Iterator/prototype/Symbol.iterator/name.js index 06132f5af2..2688c3d4b6 100644 --- a/test/built-ins/IteratorPrototype/Symbol.iterator/name.js +++ b/test/built-ins/Iterator/prototype/Symbol.iterator/name.js @@ -21,13 +21,13 @@ info: | features: [Symbol.iterator] includes: [propertyHelper.js] ---*/ - -var IteratorPrototype = Object.getPrototypeOf( +const IteratorPrototype = Object.getPrototypeOf( Object.getPrototypeOf([][Symbol.iterator]()) ); -assert.sameValue(IteratorPrototype[Symbol.iterator].name, '[Symbol.iterator]'); - -verifyNotEnumerable(IteratorPrototype[Symbol.iterator], 'name'); -verifyNotWritable(IteratorPrototype[Symbol.iterator], 'name'); -verifyConfigurable(IteratorPrototype[Symbol.iterator], 'name'); +verifyProperty(IteratorPrototype[Symbol.iterator], 'name', { + value: '[Symbol.iterator]', + writable: false, + enumerable: false, + configurable: true, +}); diff --git a/test/built-ins/IteratorPrototype/Symbol.iterator/prop-desc.js b/test/built-ins/Iterator/prototype/Symbol.iterator/prop-desc.js similarity index 65% rename from test/built-ins/IteratorPrototype/Symbol.iterator/prop-desc.js rename to test/built-ins/Iterator/prototype/Symbol.iterator/prop-desc.js index 1395c32d22..29437e8f0f 100644 --- a/test/built-ins/IteratorPrototype/Symbol.iterator/prop-desc.js +++ b/test/built-ins/Iterator/prototype/Symbol.iterator/prop-desc.js @@ -12,12 +12,12 @@ info: | features: [Symbol.iterator] includes: [propertyHelper.js] ---*/ - -var IteratorPrototype = Object.getPrototypeOf( +const IteratorPrototype = Object.getPrototypeOf( Object.getPrototypeOf([][Symbol.iterator]()) ); -assert.sameValue(typeof IteratorPrototype[Symbol.iterator], 'function'); -verifyNotEnumerable(IteratorPrototype, Symbol.iterator); -verifyWritable(IteratorPrototype, Symbol.iterator); -verifyConfigurable(IteratorPrototype, Symbol.iterator); +verifyProperty(IteratorPrototype, Symbol.iterator, { + writable: true, + enumerable: false, + configurable: true, +}); diff --git a/test/built-ins/IteratorPrototype/Symbol.iterator/return-val.js b/test/built-ins/Iterator/prototype/Symbol.iterator/return-val.js similarity index 67% rename from test/built-ins/IteratorPrototype/Symbol.iterator/return-val.js rename to test/built-ins/Iterator/prototype/Symbol.iterator/return-val.js index d9bc41752f..d7c511149d 100644 --- a/test/built-ins/IteratorPrototype/Symbol.iterator/return-val.js +++ b/test/built-ins/Iterator/prototype/Symbol.iterator/return-val.js @@ -2,31 +2,20 @@ // This code is governed by the BSD license found in the LICENSE file. /*--- esid: sec-%iteratorprototype%-@@iterator -description: Return value of @@iterator on IteratorPrototype +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, -]; +const thisValues = [{}, Symbol(), 4, 4n, true, undefined, null]; for (const thisValue of thisValues) { - assert.sameValue( - getIterator.call(thisValue), - thisValue - ); + assert.sameValue(getIterator.call(thisValue), thisValue); } diff --git a/test/built-ins/Iterator/prototype/Symbol.toStringTag/prop-desc.js b/test/built-ins/Iterator/prototype/Symbol.toStringTag/prop-desc.js new file mode 100644 index 0000000000..8048fcf5c7 --- /dev/null +++ b/test/built-ins/Iterator/prototype/Symbol.toStringTag/prop-desc.js @@ -0,0 +1,20 @@ +// Copyright (C) 2023 Michael Ficarra. 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: [iterator-helpers] +includes: [propertyHelper.js] +---*/ +verifyProperty(Iterator.prototype, Symbol.toStringTag, { + value: 'Iterator', + writable: true, + enumerable: false, + configurable: true, +}); diff --git a/test/built-ins/Iterator/prototype/drop/argument-effect-order.js b/test/built-ins/Iterator/prototype/drop/argument-effect-order.js new file mode 100644 index 0000000000..0917e8b3d0 --- /dev/null +++ b/test/built-ins/Iterator/prototype/drop/argument-effect-order.js @@ -0,0 +1,64 @@ +// 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, []); diff --git a/test/built-ins/Iterator/prototype/drop/callable.js b/test/built-ins/Iterator/prototype/drop/callable.js new file mode 100644 index 0000000000..79536d2564 --- /dev/null +++ b/test/built-ins/Iterator/prototype/drop/callable.js @@ -0,0 +1,13 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/drop/exhaustion-does-not-call-return.js b/test/built-ins/Iterator/prototype/drop/exhaustion-does-not-call-return.js new file mode 100644 index 0000000000..744574b6cd --- /dev/null +++ b/test/built-ins/Iterator/prototype/drop/exhaustion-does-not-call-return.js @@ -0,0 +1,60 @@ +// 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(); diff --git a/test/built-ins/Iterator/prototype/drop/get-next-method-only-once.js b/test/built-ins/Iterator/prototype/drop/get-next-method-only-once.js new file mode 100644 index 0000000000..c6d574614c --- /dev/null +++ b/test/built-ins/Iterator/prototype/drop/get-next-method-only-once.js @@ -0,0 +1,41 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/drop/get-next-method-throws.js b/test/built-ins/Iterator/prototype/drop/get-next-method-throws.js new file mode 100644 index 0000000000..20b97d688b --- /dev/null +++ b/test/built-ins/Iterator/prototype/drop/get-next-method-throws.js @@ -0,0 +1,25 @@ +// 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); +}); diff --git a/test/built-ins/Iterator/prototype/drop/get-return-method-throws.js b/test/built-ins/Iterator/prototype/drop/get-return-method-throws.js new file mode 100644 index 0000000000..2ecc1a1b1f --- /dev/null +++ b/test/built-ins/Iterator/prototype/drop/get-return-method-throws.js @@ -0,0 +1,30 @@ +// 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(); +}); diff --git a/test/built-ins/Iterator/prototype/drop/is-function.js b/test/built-ins/Iterator/prototype/drop/is-function.js new file mode 100644 index 0000000000..9f20d000aa --- /dev/null +++ b/test/built-ins/Iterator/prototype/drop/is-function.js @@ -0,0 +1,10 @@ +// 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'); diff --git a/test/built-ins/Iterator/prototype/drop/length.js b/test/built-ins/Iterator/prototype/drop/length.js new file mode 100644 index 0000000000..5258228bd5 --- /dev/null +++ b/test/built-ins/Iterator/prototype/drop/length.js @@ -0,0 +1,22 @@ +// 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, +}); diff --git a/test/built-ins/Iterator/prototype/drop/limit-equals-total.js b/test/built-ins/Iterator/prototype/drop/limit-equals-total.js new file mode 100644 index 0000000000..6dab6111de --- /dev/null +++ b/test/built-ins/Iterator/prototype/drop/limit-equals-total.js @@ -0,0 +1,22 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/drop/limit-greater-than-total.js b/test/built-ins/Iterator/prototype/drop/limit-greater-than-total.js new file mode 100644 index 0000000000..97670ad825 --- /dev/null +++ b/test/built-ins/Iterator/prototype/drop/limit-greater-than-total.js @@ -0,0 +1,37 @@ +// 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); +} diff --git a/test/built-ins/Iterator/prototype/drop/limit-less-than-total.js b/test/built-ins/Iterator/prototype/drop/limit-less-than-total.js new file mode 100644 index 0000000000..a08ede3591 --- /dev/null +++ b/test/built-ins/Iterator/prototype/drop/limit-less-than-total.js @@ -0,0 +1,30 @@ +// 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); +} diff --git a/test/built-ins/Iterator/prototype/drop/limit-rangeerror.js b/test/built-ins/Iterator/prototype/drop/limit-rangeerror.js new file mode 100644 index 0000000000..f30ea6ba87 --- /dev/null +++ b/test/built-ins/Iterator/prototype/drop/limit-rangeerror.js @@ -0,0 +1,36 @@ +// 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); +}); diff --git a/test/built-ins/Iterator/prototype/drop/limit-tonumber-throws.js b/test/built-ins/Iterator/prototype/drop/limit-tonumber-throws.js new file mode 100644 index 0000000000..44145e530b --- /dev/null +++ b/test/built-ins/Iterator/prototype/drop/limit-tonumber-throws.js @@ -0,0 +1,22 @@ +// 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(); + }, + }); +}); diff --git a/test/built-ins/Iterator/prototype/drop/limit-tonumber.js b/test/built-ins/Iterator/prototype/drop/limit-tonumber.js new file mode 100644 index 0000000000..80b9bbd483 --- /dev/null +++ b/test/built-ins/Iterator/prototype/drop/limit-tonumber.js @@ -0,0 +1,37 @@ +// 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); +} diff --git a/test/built-ins/Iterator/prototype/drop/name.js b/test/built-ins/Iterator/prototype/drop/name.js new file mode 100644 index 0000000000..928e376570 --- /dev/null +++ b/test/built-ins/Iterator/prototype/drop/name.js @@ -0,0 +1,29 @@ +// 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, +}); diff --git a/test/built-ins/Iterator/prototype/drop/next-method-returns-non-object.js b/test/built-ins/Iterator/prototype/drop/next-method-returns-non-object.js new file mode 100644 index 0000000000..028db0226b --- /dev/null +++ b/test/built-ins/Iterator/prototype/drop/next-method-returns-non-object.js @@ -0,0 +1,33 @@ +// 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(); +}); diff --git a/test/built-ins/Iterator/prototype/drop/next-method-returns-throwing-done.js b/test/built-ins/Iterator/prototype/drop/next-method-returns-throwing-done.js new file mode 100644 index 0000000000..88ef17ea19 --- /dev/null +++ b/test/built-ins/Iterator/prototype/drop/next-method-returns-throwing-done.js @@ -0,0 +1,41 @@ +// 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(); +}); diff --git a/test/built-ins/Iterator/prototype/drop/next-method-returns-throwing-value-done.js b/test/built-ins/Iterator/prototype/drop/next-method-returns-throwing-value-done.js new file mode 100644 index 0000000000..06adf97062 --- /dev/null +++ b/test/built-ins/Iterator/prototype/drop/next-method-returns-throwing-value-done.js @@ -0,0 +1,36 @@ +// 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(); diff --git a/test/built-ins/Iterator/prototype/drop/next-method-returns-throwing-value.js b/test/built-ins/Iterator/prototype/drop/next-method-returns-throwing-value.js new file mode 100644 index 0000000000..da90956616 --- /dev/null +++ b/test/built-ins/Iterator/prototype/drop/next-method-returns-throwing-value.js @@ -0,0 +1,39 @@ +// 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(); +}); diff --git a/test/built-ins/Iterator/prototype/drop/next-method-throws.js b/test/built-ins/Iterator/prototype/drop/next-method-throws.js new file mode 100644 index 0000000000..573294057a --- /dev/null +++ b/test/built-ins/Iterator/prototype/drop/next-method-throws.js @@ -0,0 +1,33 @@ +// 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(); +}); diff --git a/test/built-ins/Iterator/prototype/drop/non-constructible.js b/test/built-ins/Iterator/prototype/drop/non-constructible.js new file mode 100644 index 0000000000..391c53d849 --- /dev/null +++ b/test/built-ins/Iterator/prototype/drop/non-constructible.js @@ -0,0 +1,28 @@ +// 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); +}); diff --git a/test/built-ins/Iterator/prototype/drop/prop-desc.js b/test/built-ins/Iterator/prototype/drop/prop-desc.js new file mode 100644 index 0000000000..f2018fcc8a --- /dev/null +++ b/test/built-ins/Iterator/prototype/drop/prop-desc.js @@ -0,0 +1,25 @@ +// 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, +}); diff --git a/test/built-ins/Iterator/prototype/drop/proto.js b/test/built-ins/Iterator/prototype/drop/proto.js new file mode 100644 index 0000000000..97ee037427 --- /dev/null +++ b/test/built-ins/Iterator/prototype/drop/proto.js @@ -0,0 +1,11 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/drop/result-is-iterator.js b/test/built-ins/Iterator/prototype/drop/result-is-iterator.js new file mode 100644 index 0000000000..7ccf4aa57f --- /dev/null +++ b/test/built-ins/Iterator/prototype/drop/result-is-iterator.js @@ -0,0 +1,11 @@ +// 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'); diff --git a/test/built-ins/Iterator/prototype/drop/return-is-forwarded.js b/test/built-ins/Iterator/prototype/drop/return-is-forwarded.js new file mode 100644 index 0000000000..fea82f7ab7 --- /dev/null +++ b/test/built-ins/Iterator/prototype/drop/return-is-forwarded.js @@ -0,0 +1,54 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/drop/return-is-not-forwarded-after-exhaustion.js b/test/built-ins/Iterator/prototype/drop/return-is-not-forwarded-after-exhaustion.js new file mode 100644 index 0000000000..0917b4a423 --- /dev/null +++ b/test/built-ins/Iterator/prototype/drop/return-is-not-forwarded-after-exhaustion.js @@ -0,0 +1,50 @@ +// 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(); diff --git a/test/built-ins/Iterator/prototype/drop/this-non-callable-next.js b/test/built-ins/Iterator/prototype/drop/this-non-callable-next.js new file mode 100644 index 0000000000..6fed69ac23 --- /dev/null +++ b/test/built-ins/Iterator/prototype/drop/this-non-callable-next.js @@ -0,0 +1,19 @@ +// 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(); +}); diff --git a/test/built-ins/Iterator/prototype/drop/this-non-object.js b/test/built-ins/Iterator/prototype/drop/this-non-object.js new file mode 100644 index 0000000000..2e3b2f3f78 --- /dev/null +++ b/test/built-ins/Iterator/prototype/drop/this-non-object.js @@ -0,0 +1,34 @@ +// 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); +}); diff --git a/test/built-ins/Iterator/prototype/drop/this-plain-iterator.js b/test/built-ins/Iterator/prototype/drop/this-plain-iterator.js new file mode 100644 index 0000000000..77071c652f --- /dev/null +++ b/test/built-ins/Iterator/prototype/drop/this-plain-iterator.js @@ -0,0 +1,30 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/drop/underlying-iterator-advanced-in-parallel.js b/test/built-ins/Iterator/prototype/drop/underlying-iterator-advanced-in-parallel.js new file mode 100644 index 0000000000..5040a33d63 --- /dev/null +++ b/test/built-ins/Iterator/prototype/drop/underlying-iterator-advanced-in-parallel.js @@ -0,0 +1,39 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/drop/underlying-iterator-closed-in-parallel.js b/test/built-ins/Iterator/prototype/drop/underlying-iterator-closed-in-parallel.js new file mode 100644 index 0000000000..f8f68198ae --- /dev/null +++ b/test/built-ins/Iterator/prototype/drop/underlying-iterator-closed-in-parallel.js @@ -0,0 +1,26 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/drop/underlying-iterator-closed.js b/test/built-ins/Iterator/prototype/drop/underlying-iterator-closed.js new file mode 100644 index 0000000000..e3cfd1ec4f --- /dev/null +++ b/test/built-ins/Iterator/prototype/drop/underlying-iterator-closed.js @@ -0,0 +1,26 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/every/argument-effect-order.js b/test/built-ins/Iterator/prototype/every/argument-effect-order.js new file mode 100644 index 0000000000..7675398259 --- /dev/null +++ b/test/built-ins/Iterator/prototype/every/argument-effect-order.js @@ -0,0 +1,30 @@ +// 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, []); diff --git a/test/built-ins/Iterator/prototype/every/callable.js b/test/built-ins/Iterator/prototype/every/callable.js new file mode 100644 index 0000000000..30bd81e7e7 --- /dev/null +++ b/test/built-ins/Iterator/prototype/every/callable.js @@ -0,0 +1,13 @@ +// 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(() => {}); diff --git a/test/built-ins/Iterator/prototype/every/get-next-method-only-once.js b/test/built-ins/Iterator/prototype/every/get-next-method-only-once.js new file mode 100644 index 0000000000..58baec8714 --- /dev/null +++ b/test/built-ins/Iterator/prototype/every/get-next-method-only-once.js @@ -0,0 +1,38 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/every/get-next-method-throws.js b/test/built-ins/Iterator/prototype/every/get-next-method-throws.js new file mode 100644 index 0000000000..067167aa9c --- /dev/null +++ b/test/built-ins/Iterator/prototype/every/get-next-method-throws.js @@ -0,0 +1,25 @@ +// 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(() => {}); +}); diff --git a/test/built-ins/Iterator/prototype/every/get-return-method-throws.js b/test/built-ins/Iterator/prototype/every/get-return-method-throws.js new file mode 100644 index 0000000000..b90f0b103a --- /dev/null +++ b/test/built-ins/Iterator/prototype/every/get-return-method-throws.js @@ -0,0 +1,31 @@ +// 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); +}); diff --git a/test/built-ins/Iterator/prototype/every/is-function.js b/test/built-ins/Iterator/prototype/every/is-function.js new file mode 100644 index 0000000000..91367c99c0 --- /dev/null +++ b/test/built-ins/Iterator/prototype/every/is-function.js @@ -0,0 +1,10 @@ +// 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'); diff --git a/test/built-ins/Iterator/prototype/every/iterator-already-exhausted.js b/test/built-ins/Iterator/prototype/every/iterator-already-exhausted.js new file mode 100644 index 0000000000..43b5bc7216 --- /dev/null +++ b/test/built-ins/Iterator/prototype/every/iterator-already-exhausted.js @@ -0,0 +1,26 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/every/iterator-has-no-return.js b/test/built-ins/Iterator/prototype/every/iterator-has-no-return.js new file mode 100644 index 0000000000..d772403ace --- /dev/null +++ b/test/built-ins/Iterator/prototype/every/iterator-has-no-return.js @@ -0,0 +1,27 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/every/iterator-return-method-throws.js b/test/built-ins/Iterator/prototype/every/iterator-return-method-throws.js new file mode 100644 index 0000000000..b221322e76 --- /dev/null +++ b/test/built-ins/Iterator/prototype/every/iterator-return-method-throws.js @@ -0,0 +1,31 @@ +// 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); +}); diff --git a/test/built-ins/Iterator/prototype/every/length.js b/test/built-ins/Iterator/prototype/every/length.js new file mode 100644 index 0000000000..762f9bdbe1 --- /dev/null +++ b/test/built-ins/Iterator/prototype/every/length.js @@ -0,0 +1,22 @@ +// 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, +}); diff --git a/test/built-ins/Iterator/prototype/every/name.js b/test/built-ins/Iterator/prototype/every/name.js new file mode 100644 index 0000000000..a0226f8778 --- /dev/null +++ b/test/built-ins/Iterator/prototype/every/name.js @@ -0,0 +1,29 @@ +// 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, +}); diff --git a/test/built-ins/Iterator/prototype/every/next-method-returns-non-object.js b/test/built-ins/Iterator/prototype/every/next-method-returns-non-object.js new file mode 100644 index 0000000000..d0ec0e3ee3 --- /dev/null +++ b/test/built-ins/Iterator/prototype/every/next-method-returns-non-object.js @@ -0,0 +1,25 @@ +// 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(() => {}); +}); diff --git a/test/built-ins/Iterator/prototype/every/next-method-returns-throwing-done.js b/test/built-ins/Iterator/prototype/every/next-method-returns-throwing-done.js new file mode 100644 index 0000000000..56dc8d62d4 --- /dev/null +++ b/test/built-ins/Iterator/prototype/every/next-method-returns-throwing-done.js @@ -0,0 +1,33 @@ +// 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(() => {}); +}); diff --git a/test/built-ins/Iterator/prototype/every/next-method-returns-throwing-value-done.js b/test/built-ins/Iterator/prototype/every/next-method-returns-throwing-value-done.js new file mode 100644 index 0000000000..983a243ab0 --- /dev/null +++ b/test/built-ins/Iterator/prototype/every/next-method-returns-throwing-value-done.js @@ -0,0 +1,30 @@ +// 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(() => {}); diff --git a/test/built-ins/Iterator/prototype/every/next-method-returns-throwing-value.js b/test/built-ins/Iterator/prototype/every/next-method-returns-throwing-value.js new file mode 100644 index 0000000000..b2b5f53558 --- /dev/null +++ b/test/built-ins/Iterator/prototype/every/next-method-returns-throwing-value.js @@ -0,0 +1,33 @@ +// 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(() => {}); +}); diff --git a/test/built-ins/Iterator/prototype/every/next-method-throws.js b/test/built-ins/Iterator/prototype/every/next-method-throws.js new file mode 100644 index 0000000000..91df2bcf65 --- /dev/null +++ b/test/built-ins/Iterator/prototype/every/next-method-throws.js @@ -0,0 +1,25 @@ +// 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(() => {}); +}); diff --git a/test/built-ins/Iterator/prototype/every/non-callable-predicate.js b/test/built-ins/Iterator/prototype/every/non-callable-predicate.js new file mode 100644 index 0000000000..51728975bf --- /dev/null +++ b/test/built-ins/Iterator/prototype/every/non-callable-predicate.js @@ -0,0 +1,22 @@ +// 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); +}); diff --git a/test/built-ins/Iterator/prototype/every/non-constructible.js b/test/built-ins/Iterator/prototype/every/non-constructible.js new file mode 100644 index 0000000000..1b222db1c1 --- /dev/null +++ b/test/built-ins/Iterator/prototype/every/non-constructible.js @@ -0,0 +1,28 @@ +// 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(() => {}); +}); diff --git a/test/built-ins/Iterator/prototype/every/predicate-args.js b/test/built-ins/Iterator/prototype/every/predicate-args.js new file mode 100644 index 0000000000..e2f2fb0e61 --- /dev/null +++ b/test/built-ins/Iterator/prototype/every/predicate-args.js @@ -0,0 +1,43 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/every/predicate-returns-falsey.js b/test/built-ins/Iterator/prototype/every/predicate-returns-falsey.js new file mode 100644 index 0000000000..6e5b973cfb --- /dev/null +++ b/test/built-ins/Iterator/prototype/every/predicate-returns-falsey.js @@ -0,0 +1,33 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/every/predicate-returns-non-boolean.js b/test/built-ins/Iterator/prototype/every/predicate-returns-non-boolean.js new file mode 100644 index 0000000000..3c545ed70c --- /dev/null +++ b/test/built-ins/Iterator/prototype/every/predicate-returns-non-boolean.js @@ -0,0 +1,30 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/every/predicate-returns-truthy-then-falsey.js b/test/built-ins/Iterator/prototype/every/predicate-returns-truthy-then-falsey.js new file mode 100644 index 0000000000..28c3bfa43c --- /dev/null +++ b/test/built-ins/Iterator/prototype/every/predicate-returns-truthy-then-falsey.js @@ -0,0 +1,34 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/every/predicate-returns-truthy.js b/test/built-ins/Iterator/prototype/every/predicate-returns-truthy.js new file mode 100644 index 0000000000..3305f926d6 --- /dev/null +++ b/test/built-ins/Iterator/prototype/every/predicate-returns-truthy.js @@ -0,0 +1,24 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/every/predicate-this.js b/test/built-ins/Iterator/prototype/every/predicate-this.js new file mode 100644 index 0000000000..529c809a2c --- /dev/null +++ b/test/built-ins/Iterator/prototype/every/predicate-this.js @@ -0,0 +1,33 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/every/predicate-throws-then-closing-iterator-also-throws.js b/test/built-ins/Iterator/prototype/every/predicate-throws-then-closing-iterator-also-throws.js new file mode 100644 index 0000000000..9f149cae37 --- /dev/null +++ b/test/built-ins/Iterator/prototype/every/predicate-throws-then-closing-iterator-also-throws.js @@ -0,0 +1,39 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/every/predicate-throws.js b/test/built-ins/Iterator/prototype/every/predicate-throws.js new file mode 100644 index 0000000000..c99c983314 --- /dev/null +++ b/test/built-ins/Iterator/prototype/every/predicate-throws.js @@ -0,0 +1,43 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/every/prop-desc.js b/test/built-ins/Iterator/prototype/every/prop-desc.js new file mode 100644 index 0000000000..fe365a87a2 --- /dev/null +++ b/test/built-ins/Iterator/prototype/every/prop-desc.js @@ -0,0 +1,25 @@ +// 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, +}); diff --git a/test/built-ins/Iterator/prototype/every/proto.js b/test/built-ins/Iterator/prototype/every/proto.js new file mode 100644 index 0000000000..be8c22cb3b --- /dev/null +++ b/test/built-ins/Iterator/prototype/every/proto.js @@ -0,0 +1,11 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/every/result-is-boolean.js b/test/built-ins/Iterator/prototype/every/result-is-boolean.js new file mode 100644 index 0000000000..9d19ac672d --- /dev/null +++ b/test/built-ins/Iterator/prototype/every/result-is-boolean.js @@ -0,0 +1,11 @@ +// 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'); diff --git a/test/built-ins/Iterator/prototype/every/this-non-callable-next.js b/test/built-ins/Iterator/prototype/every/this-non-callable-next.js new file mode 100644 index 0000000000..7c9d792cd3 --- /dev/null +++ b/test/built-ins/Iterator/prototype/every/this-non-callable-next.js @@ -0,0 +1,17 @@ +// 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); +}); diff --git a/test/built-ins/Iterator/prototype/every/this-non-object.js b/test/built-ins/Iterator/prototype/every/this-non-object.js new file mode 100644 index 0000000000..c8d8953071 --- /dev/null +++ b/test/built-ins/Iterator/prototype/every/this-non-object.js @@ -0,0 +1,26 @@ +// 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, () => {}); +}); diff --git a/test/built-ins/Iterator/prototype/every/this-plain-iterator.js b/test/built-ins/Iterator/prototype/every/this-plain-iterator.js new file mode 100644 index 0000000000..bf3ba73da6 --- /dev/null +++ b/test/built-ins/Iterator/prototype/every/this-plain-iterator.js @@ -0,0 +1,32 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/filter/argument-effect-order.js b/test/built-ins/Iterator/prototype/filter/argument-effect-order.js new file mode 100644 index 0000000000..66b390806b --- /dev/null +++ b/test/built-ins/Iterator/prototype/filter/argument-effect-order.js @@ -0,0 +1,30 @@ +// 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, []); diff --git a/test/built-ins/Iterator/prototype/filter/callable.js b/test/built-ins/Iterator/prototype/filter/callable.js new file mode 100644 index 0000000000..c27e2fb450 --- /dev/null +++ b/test/built-ins/Iterator/prototype/filter/callable.js @@ -0,0 +1,13 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/filter/exhaustion-does-not-call-return.js b/test/built-ins/Iterator/prototype/filter/exhaustion-does-not-call-return.js new file mode 100644 index 0000000000..7176212a16 --- /dev/null +++ b/test/built-ins/Iterator/prototype/filter/exhaustion-does-not-call-return.js @@ -0,0 +1,37 @@ +// 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(); diff --git a/test/built-ins/Iterator/prototype/filter/get-next-method-only-once.js b/test/built-ins/Iterator/prototype/filter/get-next-method-only-once.js new file mode 100644 index 0000000000..fc7a957a41 --- /dev/null +++ b/test/built-ins/Iterator/prototype/filter/get-next-method-only-once.js @@ -0,0 +1,41 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/filter/get-next-method-throws.js b/test/built-ins/Iterator/prototype/filter/get-next-method-throws.js new file mode 100644 index 0000000000..4b411d3239 --- /dev/null +++ b/test/built-ins/Iterator/prototype/filter/get-next-method-throws.js @@ -0,0 +1,25 @@ +// 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); +}); diff --git a/test/built-ins/Iterator/prototype/filter/get-return-method-throws.js b/test/built-ins/Iterator/prototype/filter/get-return-method-throws.js new file mode 100644 index 0000000000..30831e5cd1 --- /dev/null +++ b/test/built-ins/Iterator/prototype/filter/get-return-method-throws.js @@ -0,0 +1,30 @@ +// 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(); +}); diff --git a/test/built-ins/Iterator/prototype/filter/is-function.js b/test/built-ins/Iterator/prototype/filter/is-function.js new file mode 100644 index 0000000000..f43e683c37 --- /dev/null +++ b/test/built-ins/Iterator/prototype/filter/is-function.js @@ -0,0 +1,10 @@ +// 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'); diff --git a/test/built-ins/Iterator/prototype/filter/iterator-already-exhausted.js b/test/built-ins/Iterator/prototype/filter/iterator-already-exhausted.js new file mode 100644 index 0000000000..ddb4ba65f9 --- /dev/null +++ b/test/built-ins/Iterator/prototype/filter/iterator-already-exhausted.js @@ -0,0 +1,25 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/filter/iterator-return-method-throws.js b/test/built-ins/Iterator/prototype/filter/iterator-return-method-throws.js new file mode 100644 index 0000000000..a1d74c2c1b --- /dev/null +++ b/test/built-ins/Iterator/prototype/filter/iterator-return-method-throws.js @@ -0,0 +1,29 @@ +// 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(); +}); diff --git a/test/built-ins/Iterator/prototype/filter/length.js b/test/built-ins/Iterator/prototype/filter/length.js new file mode 100644 index 0000000000..7ae2f45278 --- /dev/null +++ b/test/built-ins/Iterator/prototype/filter/length.js @@ -0,0 +1,22 @@ +// 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, +}); diff --git a/test/built-ins/Iterator/prototype/filter/name.js b/test/built-ins/Iterator/prototype/filter/name.js new file mode 100644 index 0000000000..3e556d4f76 --- /dev/null +++ b/test/built-ins/Iterator/prototype/filter/name.js @@ -0,0 +1,29 @@ +// 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, +}); diff --git a/test/built-ins/Iterator/prototype/filter/next-method-returns-non-object.js b/test/built-ins/Iterator/prototype/filter/next-method-returns-non-object.js new file mode 100644 index 0000000000..06e154363a --- /dev/null +++ b/test/built-ins/Iterator/prototype/filter/next-method-returns-non-object.js @@ -0,0 +1,25 @@ +// 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(); +}); diff --git a/test/built-ins/Iterator/prototype/filter/next-method-returns-throwing-done.js b/test/built-ins/Iterator/prototype/filter/next-method-returns-throwing-done.js new file mode 100644 index 0000000000..e0ea4d820f --- /dev/null +++ b/test/built-ins/Iterator/prototype/filter/next-method-returns-throwing-done.js @@ -0,0 +1,33 @@ +// 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(); +}); diff --git a/test/built-ins/Iterator/prototype/filter/next-method-returns-throwing-value-done.js b/test/built-ins/Iterator/prototype/filter/next-method-returns-throwing-value-done.js new file mode 100644 index 0000000000..1f7c325d77 --- /dev/null +++ b/test/built-ins/Iterator/prototype/filter/next-method-returns-throwing-value-done.js @@ -0,0 +1,30 @@ +// 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(); diff --git a/test/built-ins/Iterator/prototype/filter/next-method-returns-throwing-value.js b/test/built-ins/Iterator/prototype/filter/next-method-returns-throwing-value.js new file mode 100644 index 0000000000..11e67ee5e2 --- /dev/null +++ b/test/built-ins/Iterator/prototype/filter/next-method-returns-throwing-value.js @@ -0,0 +1,33 @@ +// 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(); +}); diff --git a/test/built-ins/Iterator/prototype/filter/next-method-throws.js b/test/built-ins/Iterator/prototype/filter/next-method-throws.js new file mode 100644 index 0000000000..b114cf1d97 --- /dev/null +++ b/test/built-ins/Iterator/prototype/filter/next-method-throws.js @@ -0,0 +1,25 @@ +// 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(); +}); diff --git a/test/built-ins/Iterator/prototype/filter/non-callable-predicate.js b/test/built-ins/Iterator/prototype/filter/non-callable-predicate.js new file mode 100644 index 0000000000..8bf18c5113 --- /dev/null +++ b/test/built-ins/Iterator/prototype/filter/non-callable-predicate.js @@ -0,0 +1,20 @@ +// 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); +}); diff --git a/test/built-ins/Iterator/prototype/filter/non-constructible.js b/test/built-ins/Iterator/prototype/filter/non-constructible.js new file mode 100644 index 0000000000..3f63331b4c --- /dev/null +++ b/test/built-ins/Iterator/prototype/filter/non-constructible.js @@ -0,0 +1,28 @@ +// 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); +}); diff --git a/test/built-ins/Iterator/prototype/filter/predicate-args.js b/test/built-ins/Iterator/prototype/filter/predicate-args.js new file mode 100644 index 0000000000..aefcf7c03f --- /dev/null +++ b/test/built-ins/Iterator/prototype/filter/predicate-args.js @@ -0,0 +1,44 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/filter/predicate-filters.js b/test/built-ins/Iterator/prototype/filter/predicate-filters.js new file mode 100644 index 0000000000..8bef4428a9 --- /dev/null +++ b/test/built-ins/Iterator/prototype/filter/predicate-filters.js @@ -0,0 +1,40 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/filter/predicate-returns-non-boolean.js b/test/built-ins/Iterator/prototype/filter/predicate-returns-non-boolean.js new file mode 100644 index 0000000000..7ec64e314f --- /dev/null +++ b/test/built-ins/Iterator/prototype/filter/predicate-returns-non-boolean.js @@ -0,0 +1,38 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/filter/predicate-this.js b/test/built-ins/Iterator/prototype/filter/predicate-this.js new file mode 100644 index 0000000000..4d8d8ba014 --- /dev/null +++ b/test/built-ins/Iterator/prototype/filter/predicate-this.js @@ -0,0 +1,33 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/filter/predicate-throws-then-closing-iterator-also-throws.js b/test/built-ins/Iterator/prototype/filter/predicate-throws-then-closing-iterator-also-throws.js new file mode 100644 index 0000000000..ec033aba71 --- /dev/null +++ b/test/built-ins/Iterator/prototype/filter/predicate-throws-then-closing-iterator-also-throws.js @@ -0,0 +1,40 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/filter/predicate-throws.js b/test/built-ins/Iterator/prototype/filter/predicate-throws.js new file mode 100644 index 0000000000..63bba837eb --- /dev/null +++ b/test/built-ins/Iterator/prototype/filter/predicate-throws.js @@ -0,0 +1,41 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/filter/prop-desc.js b/test/built-ins/Iterator/prototype/filter/prop-desc.js new file mode 100644 index 0000000000..8f9d9dbab8 --- /dev/null +++ b/test/built-ins/Iterator/prototype/filter/prop-desc.js @@ -0,0 +1,25 @@ +// 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, +}); diff --git a/test/built-ins/Iterator/prototype/filter/proto.js b/test/built-ins/Iterator/prototype/filter/proto.js new file mode 100644 index 0000000000..f496d487bc --- /dev/null +++ b/test/built-ins/Iterator/prototype/filter/proto.js @@ -0,0 +1,11 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/filter/result-is-iterator.js b/test/built-ins/Iterator/prototype/filter/result-is-iterator.js new file mode 100644 index 0000000000..462afb585a --- /dev/null +++ b/test/built-ins/Iterator/prototype/filter/result-is-iterator.js @@ -0,0 +1,14 @@ +// 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' +); diff --git a/test/built-ins/Iterator/prototype/filter/return-is-forwarded.js b/test/built-ins/Iterator/prototype/filter/return-is-forwarded.js new file mode 100644 index 0000000000..0a6efad3c4 --- /dev/null +++ b/test/built-ins/Iterator/prototype/filter/return-is-forwarded.js @@ -0,0 +1,33 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/filter/return-is-not-forwarded-after-exhaustion.js b/test/built-ins/Iterator/prototype/filter/return-is-not-forwarded-after-exhaustion.js new file mode 100644 index 0000000000..196f903fa6 --- /dev/null +++ b/test/built-ins/Iterator/prototype/filter/return-is-not-forwarded-after-exhaustion.js @@ -0,0 +1,46 @@ +// 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(); diff --git a/test/built-ins/Iterator/prototype/filter/this-non-callable-next.js b/test/built-ins/Iterator/prototype/filter/this-non-callable-next.js new file mode 100644 index 0000000000..bd43672c5c --- /dev/null +++ b/test/built-ins/Iterator/prototype/filter/this-non-callable-next.js @@ -0,0 +1,19 @@ +// 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(); +}); diff --git a/test/built-ins/Iterator/prototype/filter/this-non-object.js b/test/built-ins/Iterator/prototype/filter/this-non-object.js new file mode 100644 index 0000000000..3a48b97608 --- /dev/null +++ b/test/built-ins/Iterator/prototype/filter/this-non-object.js @@ -0,0 +1,26 @@ +// 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); +}); diff --git a/test/built-ins/Iterator/prototype/filter/this-plain-iterator.js b/test/built-ins/Iterator/prototype/filter/this-plain-iterator.js new file mode 100644 index 0000000000..2bddfe1b76 --- /dev/null +++ b/test/built-ins/Iterator/prototype/filter/this-plain-iterator.js @@ -0,0 +1,33 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/filter/underlying-iterator-advanced-in-parallel.js b/test/built-ins/Iterator/prototype/filter/underlying-iterator-advanced-in-parallel.js new file mode 100644 index 0000000000..4ff2b6f623 --- /dev/null +++ b/test/built-ins/Iterator/prototype/filter/underlying-iterator-advanced-in-parallel.js @@ -0,0 +1,42 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/filter/underlying-iterator-closed-in-parallel.js b/test/built-ins/Iterator/prototype/filter/underlying-iterator-closed-in-parallel.js new file mode 100644 index 0000000000..2888553c70 --- /dev/null +++ b/test/built-ins/Iterator/prototype/filter/underlying-iterator-closed-in-parallel.js @@ -0,0 +1,26 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/filter/underlying-iterator-closed.js b/test/built-ins/Iterator/prototype/filter/underlying-iterator-closed.js new file mode 100644 index 0000000000..92de4e3d79 --- /dev/null +++ b/test/built-ins/Iterator/prototype/filter/underlying-iterator-closed.js @@ -0,0 +1,26 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/find/argument-effect-order.js b/test/built-ins/Iterator/prototype/find/argument-effect-order.js new file mode 100644 index 0000000000..3651081f73 --- /dev/null +++ b/test/built-ins/Iterator/prototype/find/argument-effect-order.js @@ -0,0 +1,30 @@ +// 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, []); diff --git a/test/built-ins/Iterator/prototype/find/callable.js b/test/built-ins/Iterator/prototype/find/callable.js new file mode 100644 index 0000000000..a7238402c7 --- /dev/null +++ b/test/built-ins/Iterator/prototype/find/callable.js @@ -0,0 +1,13 @@ +// 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(() => {}); diff --git a/test/built-ins/Iterator/prototype/find/get-next-method-only-once.js b/test/built-ins/Iterator/prototype/find/get-next-method-only-once.js new file mode 100644 index 0000000000..2851c3f563 --- /dev/null +++ b/test/built-ins/Iterator/prototype/find/get-next-method-only-once.js @@ -0,0 +1,36 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/find/get-next-method-throws.js b/test/built-ins/Iterator/prototype/find/get-next-method-throws.js new file mode 100644 index 0000000000..9f74b3135a --- /dev/null +++ b/test/built-ins/Iterator/prototype/find/get-next-method-throws.js @@ -0,0 +1,23 @@ +// 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(() => {}); +}); diff --git a/test/built-ins/Iterator/prototype/find/get-return-method-throws.js b/test/built-ins/Iterator/prototype/find/get-return-method-throws.js new file mode 100644 index 0000000000..c50098651c --- /dev/null +++ b/test/built-ins/Iterator/prototype/find/get-return-method-throws.js @@ -0,0 +1,29 @@ +// 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); +}); diff --git a/test/built-ins/Iterator/prototype/find/is-function.js b/test/built-ins/Iterator/prototype/find/is-function.js new file mode 100644 index 0000000000..146bdeec3a --- /dev/null +++ b/test/built-ins/Iterator/prototype/find/is-function.js @@ -0,0 +1,10 @@ +// 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'); diff --git a/test/built-ins/Iterator/prototype/find/iterator-already-exhausted.js b/test/built-ins/Iterator/prototype/find/iterator-already-exhausted.js new file mode 100644 index 0000000000..ca383b24a6 --- /dev/null +++ b/test/built-ins/Iterator/prototype/find/iterator-already-exhausted.js @@ -0,0 +1,23 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/find/iterator-has-no-return.js b/test/built-ins/Iterator/prototype/find/iterator-has-no-return.js new file mode 100644 index 0000000000..09862a2009 --- /dev/null +++ b/test/built-ins/Iterator/prototype/find/iterator-has-no-return.js @@ -0,0 +1,27 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/find/iterator-return-method-throws.js b/test/built-ins/Iterator/prototype/find/iterator-return-method-throws.js new file mode 100644 index 0000000000..9dc822570a --- /dev/null +++ b/test/built-ins/Iterator/prototype/find/iterator-return-method-throws.js @@ -0,0 +1,29 @@ +// 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); +}); diff --git a/test/built-ins/Iterator/prototype/find/length.js b/test/built-ins/Iterator/prototype/find/length.js new file mode 100644 index 0000000000..e7d50f0637 --- /dev/null +++ b/test/built-ins/Iterator/prototype/find/length.js @@ -0,0 +1,22 @@ +// 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, +}); diff --git a/test/built-ins/Iterator/prototype/find/name.js b/test/built-ins/Iterator/prototype/find/name.js new file mode 100644 index 0000000000..4735b28c83 --- /dev/null +++ b/test/built-ins/Iterator/prototype/find/name.js @@ -0,0 +1,29 @@ +// 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, +}); diff --git a/test/built-ins/Iterator/prototype/find/next-method-returns-non-object.js b/test/built-ins/Iterator/prototype/find/next-method-returns-non-object.js new file mode 100644 index 0000000000..519c14a962 --- /dev/null +++ b/test/built-ins/Iterator/prototype/find/next-method-returns-non-object.js @@ -0,0 +1,23 @@ +// 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(() => {}); +}); diff --git a/test/built-ins/Iterator/prototype/find/next-method-returns-throwing-done.js b/test/built-ins/Iterator/prototype/find/next-method-returns-throwing-done.js new file mode 100644 index 0000000000..9a3e0a7d85 --- /dev/null +++ b/test/built-ins/Iterator/prototype/find/next-method-returns-throwing-done.js @@ -0,0 +1,31 @@ +// 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(() => {}); +}); diff --git a/test/built-ins/Iterator/prototype/find/next-method-returns-throwing-value-done.js b/test/built-ins/Iterator/prototype/find/next-method-returns-throwing-value-done.js new file mode 100644 index 0000000000..a03849a8e2 --- /dev/null +++ b/test/built-ins/Iterator/prototype/find/next-method-returns-throwing-value-done.js @@ -0,0 +1,28 @@ +// 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(() => {}); diff --git a/test/built-ins/Iterator/prototype/find/next-method-returns-throwing-value.js b/test/built-ins/Iterator/prototype/find/next-method-returns-throwing-value.js new file mode 100644 index 0000000000..9453b8c08f --- /dev/null +++ b/test/built-ins/Iterator/prototype/find/next-method-returns-throwing-value.js @@ -0,0 +1,31 @@ +// 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(() => {}); +}); diff --git a/test/built-ins/Iterator/prototype/find/next-method-throws.js b/test/built-ins/Iterator/prototype/find/next-method-throws.js new file mode 100644 index 0000000000..3a658321fd --- /dev/null +++ b/test/built-ins/Iterator/prototype/find/next-method-throws.js @@ -0,0 +1,23 @@ +// 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(() => {}); +}); diff --git a/test/built-ins/Iterator/prototype/find/non-callable-predicate.js b/test/built-ins/Iterator/prototype/find/non-callable-predicate.js new file mode 100644 index 0000000000..a2aa43c147 --- /dev/null +++ b/test/built-ins/Iterator/prototype/find/non-callable-predicate.js @@ -0,0 +1,20 @@ +// 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); +}); diff --git a/test/built-ins/Iterator/prototype/find/non-constructible.js b/test/built-ins/Iterator/prototype/find/non-constructible.js new file mode 100644 index 0000000000..df0eef60c9 --- /dev/null +++ b/test/built-ins/Iterator/prototype/find/non-constructible.js @@ -0,0 +1,28 @@ +// 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(() => {}); +}); diff --git a/test/built-ins/Iterator/prototype/find/predicate-args.js b/test/built-ins/Iterator/prototype/find/predicate-args.js new file mode 100644 index 0000000000..75a584874c --- /dev/null +++ b/test/built-ins/Iterator/prototype/find/predicate-args.js @@ -0,0 +1,41 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/find/predicate-returns-falsey-then-truthy.js b/test/built-ins/Iterator/prototype/find/predicate-returns-falsey-then-truthy.js new file mode 100644 index 0000000000..2732fba789 --- /dev/null +++ b/test/built-ins/Iterator/prototype/find/predicate-returns-falsey-then-truthy.js @@ -0,0 +1,32 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/find/predicate-returns-falsey.js b/test/built-ins/Iterator/prototype/find/predicate-returns-falsey.js new file mode 100644 index 0000000000..11d353b14c --- /dev/null +++ b/test/built-ins/Iterator/prototype/find/predicate-returns-falsey.js @@ -0,0 +1,21 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/find/predicate-returns-non-boolean.js b/test/built-ins/Iterator/prototype/find/predicate-returns-non-boolean.js new file mode 100644 index 0000000000..136fb4e83b --- /dev/null +++ b/test/built-ins/Iterator/prototype/find/predicate-returns-non-boolean.js @@ -0,0 +1,32 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/find/predicate-returns-truthy.js b/test/built-ins/Iterator/prototype/find/predicate-returns-truthy.js new file mode 100644 index 0000000000..a265869f42 --- /dev/null +++ b/test/built-ins/Iterator/prototype/find/predicate-returns-truthy.js @@ -0,0 +1,32 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/find/predicate-this.js b/test/built-ins/Iterator/prototype/find/predicate-this.js new file mode 100644 index 0000000000..84452f5369 --- /dev/null +++ b/test/built-ins/Iterator/prototype/find/predicate-this.js @@ -0,0 +1,31 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/find/predicate-throws-then-closing-iterator-also-throws.js b/test/built-ins/Iterator/prototype/find/predicate-throws-then-closing-iterator-also-throws.js new file mode 100644 index 0000000000..f070e00dd7 --- /dev/null +++ b/test/built-ins/Iterator/prototype/find/predicate-throws-then-closing-iterator-also-throws.js @@ -0,0 +1,36 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/find/predicate-throws.js b/test/built-ins/Iterator/prototype/find/predicate-throws.js new file mode 100644 index 0000000000..c031e43be8 --- /dev/null +++ b/test/built-ins/Iterator/prototype/find/predicate-throws.js @@ -0,0 +1,40 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/find/prop-desc.js b/test/built-ins/Iterator/prototype/find/prop-desc.js new file mode 100644 index 0000000000..c38c9508ea --- /dev/null +++ b/test/built-ins/Iterator/prototype/find/prop-desc.js @@ -0,0 +1,25 @@ +// 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, +}); diff --git a/test/built-ins/Iterator/prototype/find/proto.js b/test/built-ins/Iterator/prototype/find/proto.js new file mode 100644 index 0000000000..0d9ca00951 --- /dev/null +++ b/test/built-ins/Iterator/prototype/find/proto.js @@ -0,0 +1,11 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/find/this-non-callable-next.js b/test/built-ins/Iterator/prototype/find/this-non-callable-next.js new file mode 100644 index 0000000000..3168b25b79 --- /dev/null +++ b/test/built-ins/Iterator/prototype/find/this-non-callable-next.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.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); +}); diff --git a/test/built-ins/Iterator/prototype/find/this-non-object.js b/test/built-ins/Iterator/prototype/find/this-non-object.js new file mode 100644 index 0000000000..05b0c264c5 --- /dev/null +++ b/test/built-ins/Iterator/prototype/find/this-non-object.js @@ -0,0 +1,24 @@ +// 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, () => {}); +}); diff --git a/test/built-ins/Iterator/prototype/find/this-plain-iterator.js b/test/built-ins/Iterator/prototype/find/this-plain-iterator.js new file mode 100644 index 0000000000..4461ad137c --- /dev/null +++ b/test/built-ins/Iterator/prototype/find/this-plain-iterator.js @@ -0,0 +1,30 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/flatMap/argument-effect-order.js b/test/built-ins/Iterator/prototype/flatMap/argument-effect-order.js new file mode 100644 index 0000000000..4683a3024c --- /dev/null +++ b/test/built-ins/Iterator/prototype/flatMap/argument-effect-order.js @@ -0,0 +1,42 @@ +// 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, []); diff --git a/test/built-ins/Iterator/prototype/flatMap/callable.js b/test/built-ins/Iterator/prototype/flatMap/callable.js new file mode 100644 index 0000000000..0626011c7d --- /dev/null +++ b/test/built-ins/Iterator/prototype/flatMap/callable.js @@ -0,0 +1,13 @@ +// 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(() => []); diff --git a/test/built-ins/Iterator/prototype/flatMap/exhaustion-does-not-call-return.js b/test/built-ins/Iterator/prototype/flatMap/exhaustion-does-not-call-return.js new file mode 100644 index 0000000000..a33ef7ed16 --- /dev/null +++ b/test/built-ins/Iterator/prototype/flatMap/exhaustion-does-not-call-return.js @@ -0,0 +1,34 @@ +// 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(); diff --git a/test/built-ins/Iterator/prototype/flatMap/flattens-iterable.js b/test/built-ins/Iterator/prototype/flatMap/flattens-iterable.js new file mode 100644 index 0000000000..6668426d51 --- /dev/null +++ b/test/built-ins/Iterator/prototype/flatMap/flattens-iterable.js @@ -0,0 +1,30 @@ +// 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]); diff --git a/test/built-ins/Iterator/prototype/flatMap/flattens-iterator.js b/test/built-ins/Iterator/prototype/flatMap/flattens-iterator.js new file mode 100644 index 0000000000..da236b0fab --- /dev/null +++ b/test/built-ins/Iterator/prototype/flatMap/flattens-iterator.js @@ -0,0 +1,44 @@ +// 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]); diff --git a/test/built-ins/Iterator/prototype/flatMap/flattens-only-depth-1.js b/test/built-ins/Iterator/prototype/flatMap/flattens-only-depth-1.js new file mode 100644 index 0000000000..1ed5e8b52c --- /dev/null +++ b/test/built-ins/Iterator/prototype/flatMap/flattens-only-depth-1.js @@ -0,0 +1,34 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/flatMap/get-next-method-only-once.js b/test/built-ins/Iterator/prototype/flatMap/get-next-method-only-once.js new file mode 100644 index 0000000000..feb5c7094e --- /dev/null +++ b/test/built-ins/Iterator/prototype/flatMap/get-next-method-only-once.js @@ -0,0 +1,41 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/flatMap/get-next-method-throws.js b/test/built-ins/Iterator/prototype/flatMap/get-next-method-throws.js new file mode 100644 index 0000000000..a5ae5fabab --- /dev/null +++ b/test/built-ins/Iterator/prototype/flatMap/get-next-method-throws.js @@ -0,0 +1,25 @@ +// 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(() => []); +}); diff --git a/test/built-ins/Iterator/prototype/flatMap/get-return-method-throws.js b/test/built-ins/Iterator/prototype/flatMap/get-return-method-throws.js new file mode 100644 index 0000000000..e51b9e3336 --- /dev/null +++ b/test/built-ins/Iterator/prototype/flatMap/get-return-method-throws.js @@ -0,0 +1,30 @@ +// 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(); +}); diff --git a/test/built-ins/Iterator/prototype/flatMap/is-function.js b/test/built-ins/Iterator/prototype/flatMap/is-function.js new file mode 100644 index 0000000000..8d2ed6202a --- /dev/null +++ b/test/built-ins/Iterator/prototype/flatMap/is-function.js @@ -0,0 +1,10 @@ +// 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'); diff --git a/test/built-ins/Iterator/prototype/flatMap/iterable-primitives-are-not-flattened.js b/test/built-ins/Iterator/prototype/flatMap/iterable-primitives-are-not-flattened.js new file mode 100644 index 0000000000..e3eed45277 --- /dev/null +++ b/test/built-ins/Iterator/prototype/flatMap/iterable-primitives-are-not-flattened.js @@ -0,0 +1,37 @@ +// 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]); diff --git a/test/built-ins/Iterator/prototype/flatMap/iterable-to-iterator-fallback.js b/test/built-ins/Iterator/prototype/flatMap/iterable-to-iterator-fallback.js new file mode 100644 index 0000000000..0324025e68 --- /dev/null +++ b/test/built-ins/Iterator/prototype/flatMap/iterable-to-iterator-fallback.js @@ -0,0 +1,57 @@ +// 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]); diff --git a/test/built-ins/Iterator/prototype/flatMap/iterator-already-exhausted.js b/test/built-ins/Iterator/prototype/flatMap/iterator-already-exhausted.js new file mode 100644 index 0000000000..ef17517fe9 --- /dev/null +++ b/test/built-ins/Iterator/prototype/flatMap/iterator-already-exhausted.js @@ -0,0 +1,22 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/flatMap/iterator-return-method-throws.js b/test/built-ins/Iterator/prototype/flatMap/iterator-return-method-throws.js new file mode 100644 index 0000000000..5d8eb46291 --- /dev/null +++ b/test/built-ins/Iterator/prototype/flatMap/iterator-return-method-throws.js @@ -0,0 +1,29 @@ +// 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(); +}); diff --git a/test/built-ins/Iterator/prototype/flatMap/length.js b/test/built-ins/Iterator/prototype/flatMap/length.js new file mode 100644 index 0000000000..2f61836806 --- /dev/null +++ b/test/built-ins/Iterator/prototype/flatMap/length.js @@ -0,0 +1,22 @@ +// 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, +}); diff --git a/test/built-ins/Iterator/prototype/flatMap/mapper-args.js b/test/built-ins/Iterator/prototype/flatMap/mapper-args.js new file mode 100644 index 0000000000..07594d3ca8 --- /dev/null +++ b/test/built-ins/Iterator/prototype/flatMap/mapper-args.js @@ -0,0 +1,55 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/flatMap/mapper-returns-closed-iterator.js b/test/built-ins/Iterator/prototype/flatMap/mapper-returns-closed-iterator.js new file mode 100644 index 0000000000..e44010a733 --- /dev/null +++ b/test/built-ins/Iterator/prototype/flatMap/mapper-returns-closed-iterator.js @@ -0,0 +1,30 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/flatMap/mapper-returns-non-object.js b/test/built-ins/Iterator/prototype/flatMap/mapper-returns-non-object.js new file mode 100644 index 0000000000..c40ce55f83 --- /dev/null +++ b/test/built-ins/Iterator/prototype/flatMap/mapper-returns-non-object.js @@ -0,0 +1,34 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/flatMap/mapper-this.js b/test/built-ins/Iterator/prototype/flatMap/mapper-this.js new file mode 100644 index 0000000000..dee13a7208 --- /dev/null +++ b/test/built-ins/Iterator/prototype/flatMap/mapper-this.js @@ -0,0 +1,33 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/flatMap/mapper-throws-then-closing-iterator-also-throws.js b/test/built-ins/Iterator/prototype/flatMap/mapper-throws-then-closing-iterator-also-throws.js new file mode 100644 index 0000000000..41fd2e1204 --- /dev/null +++ b/test/built-ins/Iterator/prototype/flatMap/mapper-throws-then-closing-iterator-also-throws.js @@ -0,0 +1,40 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/flatMap/mapper-throws.js b/test/built-ins/Iterator/prototype/flatMap/mapper-throws.js new file mode 100644 index 0000000000..8e77c245df --- /dev/null +++ b/test/built-ins/Iterator/prototype/flatMap/mapper-throws.js @@ -0,0 +1,41 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/flatMap/name.js b/test/built-ins/Iterator/prototype/flatMap/name.js new file mode 100644 index 0000000000..d0a24e862f --- /dev/null +++ b/test/built-ins/Iterator/prototype/flatMap/name.js @@ -0,0 +1,29 @@ +// 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, +}); diff --git a/test/built-ins/Iterator/prototype/flatMap/next-method-returns-non-object.js b/test/built-ins/Iterator/prototype/flatMap/next-method-returns-non-object.js new file mode 100644 index 0000000000..3a427325cd --- /dev/null +++ b/test/built-ins/Iterator/prototype/flatMap/next-method-returns-non-object.js @@ -0,0 +1,23 @@ +// 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(); +}); diff --git a/test/built-ins/Iterator/prototype/flatMap/next-method-returns-throwing-done.js b/test/built-ins/Iterator/prototype/flatMap/next-method-returns-throwing-done.js new file mode 100644 index 0000000000..7dac1daa2e --- /dev/null +++ b/test/built-ins/Iterator/prototype/flatMap/next-method-returns-throwing-done.js @@ -0,0 +1,31 @@ +// 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(); +}); diff --git a/test/built-ins/Iterator/prototype/flatMap/next-method-returns-throwing-value-done.js b/test/built-ins/Iterator/prototype/flatMap/next-method-returns-throwing-value-done.js new file mode 100644 index 0000000000..ece5b2d777 --- /dev/null +++ b/test/built-ins/Iterator/prototype/flatMap/next-method-returns-throwing-value-done.js @@ -0,0 +1,28 @@ +// 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(); diff --git a/test/built-ins/Iterator/prototype/flatMap/next-method-returns-throwing-value.js b/test/built-ins/Iterator/prototype/flatMap/next-method-returns-throwing-value.js new file mode 100644 index 0000000000..c11cfacd6a --- /dev/null +++ b/test/built-ins/Iterator/prototype/flatMap/next-method-returns-throwing-value.js @@ -0,0 +1,31 @@ +// 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(); +}); diff --git a/test/built-ins/Iterator/prototype/flatMap/next-method-throws.js b/test/built-ins/Iterator/prototype/flatMap/next-method-throws.js new file mode 100644 index 0000000000..aef6861792 --- /dev/null +++ b/test/built-ins/Iterator/prototype/flatMap/next-method-throws.js @@ -0,0 +1,23 @@ +// 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(); +}); diff --git a/test/built-ins/Iterator/prototype/flatMap/non-callable-mapper.js b/test/built-ins/Iterator/prototype/flatMap/non-callable-mapper.js new file mode 100644 index 0000000000..b596288ec6 --- /dev/null +++ b/test/built-ins/Iterator/prototype/flatMap/non-callable-mapper.js @@ -0,0 +1,20 @@ +// 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); +}); diff --git a/test/built-ins/Iterator/prototype/flatMap/non-constructible.js b/test/built-ins/Iterator/prototype/flatMap/non-constructible.js new file mode 100644 index 0000000000..e2adfb4241 --- /dev/null +++ b/test/built-ins/Iterator/prototype/flatMap/non-constructible.js @@ -0,0 +1,28 @@ +// 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(() => []); +}); diff --git a/test/built-ins/Iterator/prototype/flatMap/prop-desc.js b/test/built-ins/Iterator/prototype/flatMap/prop-desc.js new file mode 100644 index 0000000000..97266ef53c --- /dev/null +++ b/test/built-ins/Iterator/prototype/flatMap/prop-desc.js @@ -0,0 +1,25 @@ +// 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, +}); diff --git a/test/built-ins/Iterator/prototype/flatMap/proto.js b/test/built-ins/Iterator/prototype/flatMap/proto.js new file mode 100644 index 0000000000..60feb748e4 --- /dev/null +++ b/test/built-ins/Iterator/prototype/flatMap/proto.js @@ -0,0 +1,11 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/flatMap/result-is-iterator.js b/test/built-ins/Iterator/prototype/flatMap/result-is-iterator.js new file mode 100644 index 0000000000..e85cf38aba --- /dev/null +++ b/test/built-ins/Iterator/prototype/flatMap/result-is-iterator.js @@ -0,0 +1,14 @@ +// 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' +); diff --git a/test/built-ins/Iterator/prototype/flatMap/return-is-forwarded-to-mapper-result.js b/test/built-ins/Iterator/prototype/flatMap/return-is-forwarded-to-mapper-result.js new file mode 100644 index 0000000000..004911659a --- /dev/null +++ b/test/built-ins/Iterator/prototype/flatMap/return-is-forwarded-to-mapper-result.js @@ -0,0 +1,45 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/flatMap/return-is-forwarded-to-underlying-iterator.js b/test/built-ins/Iterator/prototype/flatMap/return-is-forwarded-to-underlying-iterator.js new file mode 100644 index 0000000000..cf2a3a4755 --- /dev/null +++ b/test/built-ins/Iterator/prototype/flatMap/return-is-forwarded-to-underlying-iterator.js @@ -0,0 +1,33 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/flatMap/return-is-not-forwarded-after-exhaustion.js b/test/built-ins/Iterator/prototype/flatMap/return-is-not-forwarded-after-exhaustion.js new file mode 100644 index 0000000000..d970908da3 --- /dev/null +++ b/test/built-ins/Iterator/prototype/flatMap/return-is-not-forwarded-after-exhaustion.js @@ -0,0 +1,46 @@ +// 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(); diff --git a/test/built-ins/Iterator/prototype/flatMap/strings-are-not-flattened.js b/test/built-ins/Iterator/prototype/flatMap/strings-are-not-flattened.js new file mode 100644 index 0000000000..2584860766 --- /dev/null +++ b/test/built-ins/Iterator/prototype/flatMap/strings-are-not-flattened.js @@ -0,0 +1,26 @@ +// 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']); diff --git a/test/built-ins/Iterator/prototype/flatMap/this-non-callable-next.js b/test/built-ins/Iterator/prototype/flatMap/this-non-callable-next.js new file mode 100644 index 0000000000..871f6223f6 --- /dev/null +++ b/test/built-ins/Iterator/prototype/flatMap/this-non-callable-next.js @@ -0,0 +1,17 @@ +// 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(); +}); diff --git a/test/built-ins/Iterator/prototype/flatMap/this-non-object.js b/test/built-ins/Iterator/prototype/flatMap/this-non-object.js new file mode 100644 index 0000000000..8893a15046 --- /dev/null +++ b/test/built-ins/Iterator/prototype/flatMap/this-non-object.js @@ -0,0 +1,26 @@ +// 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, () => []); +}); diff --git a/test/built-ins/Iterator/prototype/flatMap/this-plain-iterator.js b/test/built-ins/Iterator/prototype/flatMap/this-plain-iterator.js new file mode 100644 index 0000000000..677d6adbcc --- /dev/null +++ b/test/built-ins/Iterator/prototype/flatMap/this-plain-iterator.js @@ -0,0 +1,31 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/flatMap/underlying-iterator-advanced-in-parallel.js b/test/built-ins/Iterator/prototype/flatMap/underlying-iterator-advanced-in-parallel.js new file mode 100644 index 0000000000..0d2f9f677e --- /dev/null +++ b/test/built-ins/Iterator/prototype/flatMap/underlying-iterator-advanced-in-parallel.js @@ -0,0 +1,42 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/flatMap/underlying-iterator-closed-in-parallel.js b/test/built-ins/Iterator/prototype/flatMap/underlying-iterator-closed-in-parallel.js new file mode 100644 index 0000000000..be65e4fba8 --- /dev/null +++ b/test/built-ins/Iterator/prototype/flatMap/underlying-iterator-closed-in-parallel.js @@ -0,0 +1,26 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/flatMap/underlying-iterator-closed.js b/test/built-ins/Iterator/prototype/flatMap/underlying-iterator-closed.js new file mode 100644 index 0000000000..9f54585ed8 --- /dev/null +++ b/test/built-ins/Iterator/prototype/flatMap/underlying-iterator-closed.js @@ -0,0 +1,26 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/forEach/argument-effect-order.js b/test/built-ins/Iterator/prototype/forEach/argument-effect-order.js new file mode 100644 index 0000000000..acf139d90c --- /dev/null +++ b/test/built-ins/Iterator/prototype/forEach/argument-effect-order.js @@ -0,0 +1,35 @@ +// 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, []); diff --git a/test/built-ins/Iterator/prototype/forEach/callable.js b/test/built-ins/Iterator/prototype/forEach/callable.js new file mode 100644 index 0000000000..344442e7ec --- /dev/null +++ b/test/built-ins/Iterator/prototype/forEach/callable.js @@ -0,0 +1,13 @@ +// 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(() => {}); diff --git a/test/built-ins/Iterator/prototype/forEach/fn-args.js b/test/built-ins/Iterator/prototype/forEach/fn-args.js new file mode 100644 index 0000000000..de5d875321 --- /dev/null +++ b/test/built-ins/Iterator/prototype/forEach/fn-args.js @@ -0,0 +1,40 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/forEach/fn-called-for-each-yielded-value.js b/test/built-ins/Iterator/prototype/forEach/fn-called-for-each-yielded-value.js new file mode 100644 index 0000000000..1df839d6a4 --- /dev/null +++ b/test/built-ins/Iterator/prototype/forEach/fn-called-for-each-yielded-value.js @@ -0,0 +1,28 @@ +// 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]); diff --git a/test/built-ins/Iterator/prototype/forEach/fn-this.js b/test/built-ins/Iterator/prototype/forEach/fn-this.js new file mode 100644 index 0000000000..eb0cb574b8 --- /dev/null +++ b/test/built-ins/Iterator/prototype/forEach/fn-this.js @@ -0,0 +1,30 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/forEach/fn-throws-then-closing-iterator-also-throws.js b/test/built-ins/Iterator/prototype/forEach/fn-throws-then-closing-iterator-also-throws.js new file mode 100644 index 0000000000..520f3ab590 --- /dev/null +++ b/test/built-ins/Iterator/prototype/forEach/fn-throws-then-closing-iterator-also-throws.js @@ -0,0 +1,36 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/forEach/fn-throws.js b/test/built-ins/Iterator/prototype/forEach/fn-throws.js new file mode 100644 index 0000000000..a860244d3a --- /dev/null +++ b/test/built-ins/Iterator/prototype/forEach/fn-throws.js @@ -0,0 +1,40 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/forEach/get-next-method-only-once.js b/test/built-ins/Iterator/prototype/forEach/get-next-method-only-once.js new file mode 100644 index 0000000000..ccb0db7da2 --- /dev/null +++ b/test/built-ins/Iterator/prototype/forEach/get-next-method-only-once.js @@ -0,0 +1,36 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/forEach/get-next-method-throws.js b/test/built-ins/Iterator/prototype/forEach/get-next-method-throws.js new file mode 100644 index 0000000000..17464a8457 --- /dev/null +++ b/test/built-ins/Iterator/prototype/forEach/get-next-method-throws.js @@ -0,0 +1,23 @@ +// 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(() => {}); +}); diff --git a/test/built-ins/Iterator/prototype/forEach/is-function.js b/test/built-ins/Iterator/prototype/forEach/is-function.js new file mode 100644 index 0000000000..28e16f80b2 --- /dev/null +++ b/test/built-ins/Iterator/prototype/forEach/is-function.js @@ -0,0 +1,10 @@ +// 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'); diff --git a/test/built-ins/Iterator/prototype/forEach/iterator-already-exhausted.js b/test/built-ins/Iterator/prototype/forEach/iterator-already-exhausted.js new file mode 100644 index 0000000000..521f120ad5 --- /dev/null +++ b/test/built-ins/Iterator/prototype/forEach/iterator-already-exhausted.js @@ -0,0 +1,22 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/forEach/length.js b/test/built-ins/Iterator/prototype/forEach/length.js new file mode 100644 index 0000000000..0bfeb8a1c3 --- /dev/null +++ b/test/built-ins/Iterator/prototype/forEach/length.js @@ -0,0 +1,22 @@ +// 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, +}); diff --git a/test/built-ins/Iterator/prototype/forEach/name.js b/test/built-ins/Iterator/prototype/forEach/name.js new file mode 100644 index 0000000000..780a73855e --- /dev/null +++ b/test/built-ins/Iterator/prototype/forEach/name.js @@ -0,0 +1,29 @@ +// 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, +}); diff --git a/test/built-ins/Iterator/prototype/forEach/next-method-returns-non-object.js b/test/built-ins/Iterator/prototype/forEach/next-method-returns-non-object.js new file mode 100644 index 0000000000..c8de66c3cf --- /dev/null +++ b/test/built-ins/Iterator/prototype/forEach/next-method-returns-non-object.js @@ -0,0 +1,23 @@ +// 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(() => {}); +}); diff --git a/test/built-ins/Iterator/prototype/forEach/next-method-returns-throwing-done.js b/test/built-ins/Iterator/prototype/forEach/next-method-returns-throwing-done.js new file mode 100644 index 0000000000..906c9d5287 --- /dev/null +++ b/test/built-ins/Iterator/prototype/forEach/next-method-returns-throwing-done.js @@ -0,0 +1,31 @@ +// 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(() => {}); +}); diff --git a/test/built-ins/Iterator/prototype/forEach/next-method-returns-throwing-value-done.js b/test/built-ins/Iterator/prototype/forEach/next-method-returns-throwing-value-done.js new file mode 100644 index 0000000000..e1a586fd3d --- /dev/null +++ b/test/built-ins/Iterator/prototype/forEach/next-method-returns-throwing-value-done.js @@ -0,0 +1,28 @@ +// 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(() => {}); diff --git a/test/built-ins/Iterator/prototype/forEach/next-method-returns-throwing-value.js b/test/built-ins/Iterator/prototype/forEach/next-method-returns-throwing-value.js new file mode 100644 index 0000000000..26c3cb04ea --- /dev/null +++ b/test/built-ins/Iterator/prototype/forEach/next-method-returns-throwing-value.js @@ -0,0 +1,31 @@ +// 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(() => {}); +}); diff --git a/test/built-ins/Iterator/prototype/forEach/next-method-throws.js b/test/built-ins/Iterator/prototype/forEach/next-method-throws.js new file mode 100644 index 0000000000..d6a79e8119 --- /dev/null +++ b/test/built-ins/Iterator/prototype/forEach/next-method-throws.js @@ -0,0 +1,23 @@ +// 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(() => {}); +}); diff --git a/test/built-ins/Iterator/prototype/forEach/non-callable-predicate.js b/test/built-ins/Iterator/prototype/forEach/non-callable-predicate.js new file mode 100644 index 0000000000..abfbfd3639 --- /dev/null +++ b/test/built-ins/Iterator/prototype/forEach/non-callable-predicate.js @@ -0,0 +1,20 @@ +// 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); +}); diff --git a/test/built-ins/Iterator/prototype/forEach/non-constructible.js b/test/built-ins/Iterator/prototype/forEach/non-constructible.js new file mode 100644 index 0000000000..65156cd462 --- /dev/null +++ b/test/built-ins/Iterator/prototype/forEach/non-constructible.js @@ -0,0 +1,28 @@ +// 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(() => {}); +}); diff --git a/test/built-ins/Iterator/prototype/forEach/prop-desc.js b/test/built-ins/Iterator/prototype/forEach/prop-desc.js new file mode 100644 index 0000000000..01ce3e9227 --- /dev/null +++ b/test/built-ins/Iterator/prototype/forEach/prop-desc.js @@ -0,0 +1,25 @@ +// 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, +}); diff --git a/test/built-ins/Iterator/prototype/forEach/proto.js b/test/built-ins/Iterator/prototype/forEach/proto.js new file mode 100644 index 0000000000..1b21d92222 --- /dev/null +++ b/test/built-ins/Iterator/prototype/forEach/proto.js @@ -0,0 +1,11 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/forEach/result-is-undefined.js b/test/built-ins/Iterator/prototype/forEach/result-is-undefined.js new file mode 100644 index 0000000000..bd7f7975b5 --- /dev/null +++ b/test/built-ins/Iterator/prototype/forEach/result-is-undefined.js @@ -0,0 +1,18 @@ +// 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 +); diff --git a/test/built-ins/Iterator/prototype/forEach/this-non-callable-next.js b/test/built-ins/Iterator/prototype/forEach/this-non-callable-next.js new file mode 100644 index 0000000000..10a4772e43 --- /dev/null +++ b/test/built-ins/Iterator/prototype/forEach/this-non-callable-next.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.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); +}); diff --git a/test/built-ins/Iterator/prototype/forEach/this-non-object.js b/test/built-ins/Iterator/prototype/forEach/this-non-object.js new file mode 100644 index 0000000000..6f2058845a --- /dev/null +++ b/test/built-ins/Iterator/prototype/forEach/this-non-object.js @@ -0,0 +1,24 @@ +// 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, () => {}); +}); diff --git a/test/built-ins/Iterator/prototype/forEach/this-plain-iterator.js b/test/built-ins/Iterator/prototype/forEach/this-plain-iterator.js new file mode 100644 index 0000000000..8ce4235b90 --- /dev/null +++ b/test/built-ins/Iterator/prototype/forEach/this-plain-iterator.js @@ -0,0 +1,29 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/initial-value.js b/test/built-ins/Iterator/prototype/initial-value.js new file mode 100644 index 0000000000..82ab6afe2f --- /dev/null +++ b/test/built-ins/Iterator/prototype/initial-value.js @@ -0,0 +1,23 @@ +// 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, +}); diff --git a/test/built-ins/Iterator/prototype/map/argument-effect-order.js b/test/built-ins/Iterator/prototype/map/argument-effect-order.js new file mode 100644 index 0000000000..76c6fc55a1 --- /dev/null +++ b/test/built-ins/Iterator/prototype/map/argument-effect-order.js @@ -0,0 +1,42 @@ +// 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, []); diff --git a/test/built-ins/Iterator/prototype/map/callable.js b/test/built-ins/Iterator/prototype/map/callable.js new file mode 100644 index 0000000000..fc70927b36 --- /dev/null +++ b/test/built-ins/Iterator/prototype/map/callable.js @@ -0,0 +1,13 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/map/exhaustion-does-not-call-return.js b/test/built-ins/Iterator/prototype/map/exhaustion-does-not-call-return.js new file mode 100644 index 0000000000..e93c945ebd --- /dev/null +++ b/test/built-ins/Iterator/prototype/map/exhaustion-does-not-call-return.js @@ -0,0 +1,34 @@ +// 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(); diff --git a/test/built-ins/Iterator/prototype/map/get-next-method-only-once.js b/test/built-ins/Iterator/prototype/map/get-next-method-only-once.js new file mode 100644 index 0000000000..4971dfed37 --- /dev/null +++ b/test/built-ins/Iterator/prototype/map/get-next-method-only-once.js @@ -0,0 +1,41 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/map/get-next-method-throws.js b/test/built-ins/Iterator/prototype/map/get-next-method-throws.js new file mode 100644 index 0000000000..d0884cba5e --- /dev/null +++ b/test/built-ins/Iterator/prototype/map/get-next-method-throws.js @@ -0,0 +1,25 @@ +// 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); +}); diff --git a/test/built-ins/Iterator/prototype/map/get-return-method-throws.js b/test/built-ins/Iterator/prototype/map/get-return-method-throws.js new file mode 100644 index 0000000000..4fc3299bba --- /dev/null +++ b/test/built-ins/Iterator/prototype/map/get-return-method-throws.js @@ -0,0 +1,30 @@ +// 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(); +}); diff --git a/test/built-ins/Iterator/prototype/map/is-function.js b/test/built-ins/Iterator/prototype/map/is-function.js new file mode 100644 index 0000000000..cbc51701ef --- /dev/null +++ b/test/built-ins/Iterator/prototype/map/is-function.js @@ -0,0 +1,10 @@ +// 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'); diff --git a/test/built-ins/Iterator/prototype/map/iterator-already-exhausted.js b/test/built-ins/Iterator/prototype/map/iterator-already-exhausted.js new file mode 100644 index 0000000000..05a0e70653 --- /dev/null +++ b/test/built-ins/Iterator/prototype/map/iterator-already-exhausted.js @@ -0,0 +1,22 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/map/iterator-return-method-throws.js b/test/built-ins/Iterator/prototype/map/iterator-return-method-throws.js new file mode 100644 index 0000000000..69b67a2794 --- /dev/null +++ b/test/built-ins/Iterator/prototype/map/iterator-return-method-throws.js @@ -0,0 +1,29 @@ +// 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(); +}); diff --git a/test/built-ins/Iterator/prototype/map/length.js b/test/built-ins/Iterator/prototype/map/length.js new file mode 100644 index 0000000000..b6d4258b1a --- /dev/null +++ b/test/built-ins/Iterator/prototype/map/length.js @@ -0,0 +1,22 @@ +// 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, +}); diff --git a/test/built-ins/Iterator/prototype/map/mapper-args.js b/test/built-ins/Iterator/prototype/map/mapper-args.js new file mode 100644 index 0000000000..25994834a1 --- /dev/null +++ b/test/built-ins/Iterator/prototype/map/mapper-args.js @@ -0,0 +1,55 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/map/mapper-this.js b/test/built-ins/Iterator/prototype/map/mapper-this.js new file mode 100644 index 0000000000..db3a611dea --- /dev/null +++ b/test/built-ins/Iterator/prototype/map/mapper-this.js @@ -0,0 +1,33 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/map/mapper-throws-then-closing-iterator-also-throws.js b/test/built-ins/Iterator/prototype/map/mapper-throws-then-closing-iterator-also-throws.js new file mode 100644 index 0000000000..9b0c772a23 --- /dev/null +++ b/test/built-ins/Iterator/prototype/map/mapper-throws-then-closing-iterator-also-throws.js @@ -0,0 +1,40 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/map/mapper-throws.js b/test/built-ins/Iterator/prototype/map/mapper-throws.js new file mode 100644 index 0000000000..e5142d0be2 --- /dev/null +++ b/test/built-ins/Iterator/prototype/map/mapper-throws.js @@ -0,0 +1,41 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/map/name.js b/test/built-ins/Iterator/prototype/map/name.js new file mode 100644 index 0000000000..6815e78998 --- /dev/null +++ b/test/built-ins/Iterator/prototype/map/name.js @@ -0,0 +1,29 @@ +// 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, +}); diff --git a/test/built-ins/Iterator/prototype/map/next-method-returns-non-object.js b/test/built-ins/Iterator/prototype/map/next-method-returns-non-object.js new file mode 100644 index 0000000000..21f969105e --- /dev/null +++ b/test/built-ins/Iterator/prototype/map/next-method-returns-non-object.js @@ -0,0 +1,23 @@ +// 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(); +}); diff --git a/test/built-ins/Iterator/prototype/map/next-method-returns-throwing-done.js b/test/built-ins/Iterator/prototype/map/next-method-returns-throwing-done.js new file mode 100644 index 0000000000..c9da2ef6cb --- /dev/null +++ b/test/built-ins/Iterator/prototype/map/next-method-returns-throwing-done.js @@ -0,0 +1,31 @@ +// 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(); +}); diff --git a/test/built-ins/Iterator/prototype/map/next-method-returns-throwing-value-done.js b/test/built-ins/Iterator/prototype/map/next-method-returns-throwing-value-done.js new file mode 100644 index 0000000000..d044cfb516 --- /dev/null +++ b/test/built-ins/Iterator/prototype/map/next-method-returns-throwing-value-done.js @@ -0,0 +1,28 @@ +// 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(); diff --git a/test/built-ins/Iterator/prototype/map/next-method-returns-throwing-value.js b/test/built-ins/Iterator/prototype/map/next-method-returns-throwing-value.js new file mode 100644 index 0000000000..a34de32a03 --- /dev/null +++ b/test/built-ins/Iterator/prototype/map/next-method-returns-throwing-value.js @@ -0,0 +1,31 @@ +// 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(); +}); diff --git a/test/built-ins/Iterator/prototype/map/next-method-throws.js b/test/built-ins/Iterator/prototype/map/next-method-throws.js new file mode 100644 index 0000000000..4a4480273c --- /dev/null +++ b/test/built-ins/Iterator/prototype/map/next-method-throws.js @@ -0,0 +1,23 @@ +// 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(); +}); diff --git a/test/built-ins/Iterator/prototype/map/non-callable-mapper.js b/test/built-ins/Iterator/prototype/map/non-callable-mapper.js new file mode 100644 index 0000000000..dfa0c618f2 --- /dev/null +++ b/test/built-ins/Iterator/prototype/map/non-callable-mapper.js @@ -0,0 +1,20 @@ +// 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); +}); diff --git a/test/built-ins/Iterator/prototype/map/non-constructible.js b/test/built-ins/Iterator/prototype/map/non-constructible.js new file mode 100644 index 0000000000..a6cb476430 --- /dev/null +++ b/test/built-ins/Iterator/prototype/map/non-constructible.js @@ -0,0 +1,28 @@ +// 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); +}); diff --git a/test/built-ins/Iterator/prototype/map/prop-desc.js b/test/built-ins/Iterator/prototype/map/prop-desc.js new file mode 100644 index 0000000000..9d58c5fb67 --- /dev/null +++ b/test/built-ins/Iterator/prototype/map/prop-desc.js @@ -0,0 +1,25 @@ +// 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, +}); diff --git a/test/built-ins/Iterator/prototype/map/proto.js b/test/built-ins/Iterator/prototype/map/proto.js new file mode 100644 index 0000000000..9d1851239c --- /dev/null +++ b/test/built-ins/Iterator/prototype/map/proto.js @@ -0,0 +1,11 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/map/result-is-iterator.js b/test/built-ins/Iterator/prototype/map/result-is-iterator.js new file mode 100644 index 0000000000..66fa0d10b1 --- /dev/null +++ b/test/built-ins/Iterator/prototype/map/result-is-iterator.js @@ -0,0 +1,11 @@ +// 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'); diff --git a/test/built-ins/Iterator/prototype/map/return-is-forwarded-to-underlying-iterator.js b/test/built-ins/Iterator/prototype/map/return-is-forwarded-to-underlying-iterator.js new file mode 100644 index 0000000000..a51ec50eb3 --- /dev/null +++ b/test/built-ins/Iterator/prototype/map/return-is-forwarded-to-underlying-iterator.js @@ -0,0 +1,33 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/map/return-is-not-forwarded-after-exhaustion.js b/test/built-ins/Iterator/prototype/map/return-is-not-forwarded-after-exhaustion.js new file mode 100644 index 0000000000..f3ca5fece9 --- /dev/null +++ b/test/built-ins/Iterator/prototype/map/return-is-not-forwarded-after-exhaustion.js @@ -0,0 +1,46 @@ +// 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(); diff --git a/test/built-ins/Iterator/prototype/map/returned-iterator-yields-mapper-return-values.js b/test/built-ins/Iterator/prototype/map/returned-iterator-yields-mapper-return-values.js new file mode 100644 index 0000000000..5565de995a --- /dev/null +++ b/test/built-ins/Iterator/prototype/map/returned-iterator-yields-mapper-return-values.js @@ -0,0 +1,36 @@ +// 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]); diff --git a/test/built-ins/Iterator/prototype/map/this-non-callable-next.js b/test/built-ins/Iterator/prototype/map/this-non-callable-next.js new file mode 100644 index 0000000000..db127cb4c3 --- /dev/null +++ b/test/built-ins/Iterator/prototype/map/this-non-callable-next.js @@ -0,0 +1,17 @@ +// 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(); +}); diff --git a/test/built-ins/Iterator/prototype/map/this-non-object.js b/test/built-ins/Iterator/prototype/map/this-non-object.js new file mode 100644 index 0000000000..e0d4480146 --- /dev/null +++ b/test/built-ins/Iterator/prototype/map/this-non-object.js @@ -0,0 +1,26 @@ +// 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); +}); diff --git a/test/built-ins/Iterator/prototype/map/this-plain-iterator.js b/test/built-ins/Iterator/prototype/map/this-plain-iterator.js new file mode 100644 index 0000000000..851eed8e2f --- /dev/null +++ b/test/built-ins/Iterator/prototype/map/this-plain-iterator.js @@ -0,0 +1,31 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/map/underlying-iterator-advanced-in-parallel.js b/test/built-ins/Iterator/prototype/map/underlying-iterator-advanced-in-parallel.js new file mode 100644 index 0000000000..bb95ca0765 --- /dev/null +++ b/test/built-ins/Iterator/prototype/map/underlying-iterator-advanced-in-parallel.js @@ -0,0 +1,42 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/map/underlying-iterator-closed-in-parallel.js b/test/built-ins/Iterator/prototype/map/underlying-iterator-closed-in-parallel.js new file mode 100644 index 0000000000..c83679632f --- /dev/null +++ b/test/built-ins/Iterator/prototype/map/underlying-iterator-closed-in-parallel.js @@ -0,0 +1,26 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/map/underlying-iterator-closed.js b/test/built-ins/Iterator/prototype/map/underlying-iterator-closed.js new file mode 100644 index 0000000000..b49c27b793 --- /dev/null +++ b/test/built-ins/Iterator/prototype/map/underlying-iterator-closed.js @@ -0,0 +1,26 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/reduce/argument-effect-order.js b/test/built-ins/Iterator/prototype/reduce/argument-effect-order.js new file mode 100644 index 0000000000..25d809a2ca --- /dev/null +++ b/test/built-ins/Iterator/prototype/reduce/argument-effect-order.js @@ -0,0 +1,58 @@ +// 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']); diff --git a/test/built-ins/Iterator/prototype/reduce/callable.js b/test/built-ins/Iterator/prototype/reduce/callable.js new file mode 100644 index 0000000000..c1a4c343e4 --- /dev/null +++ b/test/built-ins/Iterator/prototype/reduce/callable.js @@ -0,0 +1,13 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/reduce/get-next-method-only-once.js b/test/built-ins/Iterator/prototype/reduce/get-next-method-only-once.js new file mode 100644 index 0000000000..89c30adb4e --- /dev/null +++ b/test/built-ins/Iterator/prototype/reduce/get-next-method-only-once.js @@ -0,0 +1,36 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/reduce/get-next-method-throws.js b/test/built-ins/Iterator/prototype/reduce/get-next-method-throws.js new file mode 100644 index 0000000000..c3816f2651 --- /dev/null +++ b/test/built-ins/Iterator/prototype/reduce/get-next-method-throws.js @@ -0,0 +1,23 @@ +// 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(() => {}); +}); diff --git a/test/built-ins/Iterator/prototype/reduce/is-function.js b/test/built-ins/Iterator/prototype/reduce/is-function.js new file mode 100644 index 0000000000..4f144c5882 --- /dev/null +++ b/test/built-ins/Iterator/prototype/reduce/is-function.js @@ -0,0 +1,10 @@ +// 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'); diff --git a/test/built-ins/Iterator/prototype/reduce/iterator-already-exhausted-initial-value.js b/test/built-ins/Iterator/prototype/reduce/iterator-already-exhausted-initial-value.js new file mode 100644 index 0000000000..71f332cf16 --- /dev/null +++ b/test/built-ins/Iterator/prototype/reduce/iterator-already-exhausted-initial-value.js @@ -0,0 +1,21 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/reduce/iterator-already-exhausted-no-initial-value.js b/test/built-ins/Iterator/prototype/reduce/iterator-already-exhausted-no-initial-value.js new file mode 100644 index 0000000000..22dec14757 --- /dev/null +++ b/test/built-ins/Iterator/prototype/reduce/iterator-already-exhausted-no-initial-value.js @@ -0,0 +1,21 @@ +// 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(() => {}); +}); diff --git a/test/built-ins/Iterator/prototype/reduce/iterator-yields-once-initial-value.js b/test/built-ins/Iterator/prototype/reduce/iterator-yields-once-initial-value.js new file mode 100644 index 0000000000..5f936c4946 --- /dev/null +++ b/test/built-ins/Iterator/prototype/reduce/iterator-yields-once-initial-value.js @@ -0,0 +1,35 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/reduce/iterator-yields-once-no-initial-value.js b/test/built-ins/Iterator/prototype/reduce/iterator-yields-once-no-initial-value.js new file mode 100644 index 0000000000..38c4fdaaad --- /dev/null +++ b/test/built-ins/Iterator/prototype/reduce/iterator-yields-once-no-initial-value.js @@ -0,0 +1,26 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/reduce/length.js b/test/built-ins/Iterator/prototype/reduce/length.js new file mode 100644 index 0000000000..3b504529fe --- /dev/null +++ b/test/built-ins/Iterator/prototype/reduce/length.js @@ -0,0 +1,22 @@ +// 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, +}); diff --git a/test/built-ins/Iterator/prototype/reduce/name.js b/test/built-ins/Iterator/prototype/reduce/name.js new file mode 100644 index 0000000000..d79e858873 --- /dev/null +++ b/test/built-ins/Iterator/prototype/reduce/name.js @@ -0,0 +1,29 @@ +// 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, +}); diff --git a/test/built-ins/Iterator/prototype/reduce/next-method-returns-non-object.js b/test/built-ins/Iterator/prototype/reduce/next-method-returns-non-object.js new file mode 100644 index 0000000000..c23e1fd478 --- /dev/null +++ b/test/built-ins/Iterator/prototype/reduce/next-method-returns-non-object.js @@ -0,0 +1,23 @@ +// 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(() => {}); +}); diff --git a/test/built-ins/Iterator/prototype/reduce/next-method-returns-throwing-done.js b/test/built-ins/Iterator/prototype/reduce/next-method-returns-throwing-done.js new file mode 100644 index 0000000000..c855c5bc00 --- /dev/null +++ b/test/built-ins/Iterator/prototype/reduce/next-method-returns-throwing-done.js @@ -0,0 +1,31 @@ +// 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(() => {}); +}); diff --git a/test/built-ins/Iterator/prototype/reduce/next-method-returns-throwing-value-done.js b/test/built-ins/Iterator/prototype/reduce/next-method-returns-throwing-value-done.js new file mode 100644 index 0000000000..4682a6e2a8 --- /dev/null +++ b/test/built-ins/Iterator/prototype/reduce/next-method-returns-throwing-value-done.js @@ -0,0 +1,28 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/reduce/next-method-returns-throwing-value.js b/test/built-ins/Iterator/prototype/reduce/next-method-returns-throwing-value.js new file mode 100644 index 0000000000..900958e0a5 --- /dev/null +++ b/test/built-ins/Iterator/prototype/reduce/next-method-returns-throwing-value.js @@ -0,0 +1,31 @@ +// 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(() => {}); +}); diff --git a/test/built-ins/Iterator/prototype/reduce/next-method-throws.js b/test/built-ins/Iterator/prototype/reduce/next-method-throws.js new file mode 100644 index 0000000000..09cec5cdc4 --- /dev/null +++ b/test/built-ins/Iterator/prototype/reduce/next-method-throws.js @@ -0,0 +1,27 @@ +// 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); +}); diff --git a/test/built-ins/Iterator/prototype/reduce/non-callable-reducer.js b/test/built-ins/Iterator/prototype/reduce/non-callable-reducer.js new file mode 100644 index 0000000000..9a2cdd4810 --- /dev/null +++ b/test/built-ins/Iterator/prototype/reduce/non-callable-reducer.js @@ -0,0 +1,20 @@ +// 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); +}); diff --git a/test/built-ins/Iterator/prototype/reduce/non-constructible.js b/test/built-ins/Iterator/prototype/reduce/non-constructible.js new file mode 100644 index 0000000000..83f6882b73 --- /dev/null +++ b/test/built-ins/Iterator/prototype/reduce/non-constructible.js @@ -0,0 +1,32 @@ +// 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); +}); diff --git a/test/built-ins/Iterator/prototype/reduce/prop-desc.js b/test/built-ins/Iterator/prototype/reduce/prop-desc.js new file mode 100644 index 0000000000..1fca6a372a --- /dev/null +++ b/test/built-ins/Iterator/prototype/reduce/prop-desc.js @@ -0,0 +1,25 @@ +// 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, +}); diff --git a/test/built-ins/Iterator/prototype/reduce/proto.js b/test/built-ins/Iterator/prototype/reduce/proto.js new file mode 100644 index 0000000000..18f9123a56 --- /dev/null +++ b/test/built-ins/Iterator/prototype/reduce/proto.js @@ -0,0 +1,11 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/reduce/reducer-args-initial-value.js b/test/built-ins/Iterator/prototype/reduce/reducer-args-initial-value.js new file mode 100644 index 0000000000..1803917e81 --- /dev/null +++ b/test/built-ins/Iterator/prototype/reduce/reducer-args-initial-value.js @@ -0,0 +1,45 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/reduce/reducer-args-no-initial-value.js b/test/built-ins/Iterator/prototype/reduce/reducer-args-no-initial-value.js new file mode 100644 index 0000000000..c1dfc6c242 --- /dev/null +++ b/test/built-ins/Iterator/prototype/reduce/reducer-args-no-initial-value.js @@ -0,0 +1,41 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/reduce/reducer-memo-can-be-any-type.js b/test/built-ins/Iterator/prototype/reduce/reducer-memo-can-be-any-type.js new file mode 100644 index 0000000000..35a84a2152 --- /dev/null +++ b/test/built-ins/Iterator/prototype/reduce/reducer-memo-can-be-any-type.js @@ -0,0 +1,31 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/reduce/reducer-this.js b/test/built-ins/Iterator/prototype/reduce/reducer-this.js new file mode 100644 index 0000000000..9932713b0a --- /dev/null +++ b/test/built-ins/Iterator/prototype/reduce/reducer-this.js @@ -0,0 +1,32 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/reduce/reducer-throws-then-closing-iterator-also-throws.js b/test/built-ins/Iterator/prototype/reduce/reducer-throws-then-closing-iterator-also-throws.js new file mode 100644 index 0000000000..0eef70fa75 --- /dev/null +++ b/test/built-ins/Iterator/prototype/reduce/reducer-throws-then-closing-iterator-also-throws.js @@ -0,0 +1,36 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/reduce/reducer-throws.js b/test/built-ins/Iterator/prototype/reduce/reducer-throws.js new file mode 100644 index 0000000000..d1cd088241 --- /dev/null +++ b/test/built-ins/Iterator/prototype/reduce/reducer-throws.js @@ -0,0 +1,40 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/reduce/this-non-callable-next.js b/test/built-ins/Iterator/prototype/reduce/this-non-callable-next.js new file mode 100644 index 0000000000..48611726a2 --- /dev/null +++ b/test/built-ins/Iterator/prototype/reduce/this-non-callable-next.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.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); +}); diff --git a/test/built-ins/Iterator/prototype/reduce/this-non-object.js b/test/built-ins/Iterator/prototype/reduce/this-non-object.js new file mode 100644 index 0000000000..5d9143e675 --- /dev/null +++ b/test/built-ins/Iterator/prototype/reduce/this-non-object.js @@ -0,0 +1,33 @@ +// 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); +}); diff --git a/test/built-ins/Iterator/prototype/reduce/this-plain-iterator.js b/test/built-ins/Iterator/prototype/reduce/this-plain-iterator.js new file mode 100644 index 0000000000..2eddf1098a --- /dev/null +++ b/test/built-ins/Iterator/prototype/reduce/this-plain-iterator.js @@ -0,0 +1,32 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/some/argument-effect-order.js b/test/built-ins/Iterator/prototype/some/argument-effect-order.js new file mode 100644 index 0000000000..d45acefd84 --- /dev/null +++ b/test/built-ins/Iterator/prototype/some/argument-effect-order.js @@ -0,0 +1,30 @@ +// 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, []); diff --git a/test/built-ins/Iterator/prototype/some/callable.js b/test/built-ins/Iterator/prototype/some/callable.js new file mode 100644 index 0000000000..568bb60aff --- /dev/null +++ b/test/built-ins/Iterator/prototype/some/callable.js @@ -0,0 +1,13 @@ +// 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(() => {}); diff --git a/test/built-ins/Iterator/prototype/some/get-next-method-only-once.js b/test/built-ins/Iterator/prototype/some/get-next-method-only-once.js new file mode 100644 index 0000000000..9a0c940186 --- /dev/null +++ b/test/built-ins/Iterator/prototype/some/get-next-method-only-once.js @@ -0,0 +1,36 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/some/get-next-method-throws.js b/test/built-ins/Iterator/prototype/some/get-next-method-throws.js new file mode 100644 index 0000000000..6617aa659d --- /dev/null +++ b/test/built-ins/Iterator/prototype/some/get-next-method-throws.js @@ -0,0 +1,23 @@ +// 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(() => {}); +}); diff --git a/test/built-ins/Iterator/prototype/some/get-return-method-throws.js b/test/built-ins/Iterator/prototype/some/get-return-method-throws.js new file mode 100644 index 0000000000..cce312d59c --- /dev/null +++ b/test/built-ins/Iterator/prototype/some/get-return-method-throws.js @@ -0,0 +1,29 @@ +// 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); +}); diff --git a/test/built-ins/Iterator/prototype/some/is-function.js b/test/built-ins/Iterator/prototype/some/is-function.js new file mode 100644 index 0000000000..47de2a9339 --- /dev/null +++ b/test/built-ins/Iterator/prototype/some/is-function.js @@ -0,0 +1,10 @@ +// 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'); diff --git a/test/built-ins/Iterator/prototype/some/iterator-already-exhausted.js b/test/built-ins/Iterator/prototype/some/iterator-already-exhausted.js new file mode 100644 index 0000000000..d1172dfab9 --- /dev/null +++ b/test/built-ins/Iterator/prototype/some/iterator-already-exhausted.js @@ -0,0 +1,23 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/some/iterator-has-no-return.js b/test/built-ins/Iterator/prototype/some/iterator-has-no-return.js new file mode 100644 index 0000000000..28ed4c41b6 --- /dev/null +++ b/test/built-ins/Iterator/prototype/some/iterator-has-no-return.js @@ -0,0 +1,27 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/some/iterator-return-method-throws.js b/test/built-ins/Iterator/prototype/some/iterator-return-method-throws.js new file mode 100644 index 0000000000..d15240ebbf --- /dev/null +++ b/test/built-ins/Iterator/prototype/some/iterator-return-method-throws.js @@ -0,0 +1,29 @@ +// 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); +}); diff --git a/test/built-ins/Iterator/prototype/some/length.js b/test/built-ins/Iterator/prototype/some/length.js new file mode 100644 index 0000000000..8a790b22ca --- /dev/null +++ b/test/built-ins/Iterator/prototype/some/length.js @@ -0,0 +1,22 @@ +// 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, +}); diff --git a/test/built-ins/Iterator/prototype/some/name.js b/test/built-ins/Iterator/prototype/some/name.js new file mode 100644 index 0000000000..6cd820c5c4 --- /dev/null +++ b/test/built-ins/Iterator/prototype/some/name.js @@ -0,0 +1,29 @@ +// 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, +}); diff --git a/test/built-ins/Iterator/prototype/some/next-method-returns-non-object.js b/test/built-ins/Iterator/prototype/some/next-method-returns-non-object.js new file mode 100644 index 0000000000..6d1655a22d --- /dev/null +++ b/test/built-ins/Iterator/prototype/some/next-method-returns-non-object.js @@ -0,0 +1,23 @@ +// 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(() => {}); +}); diff --git a/test/built-ins/Iterator/prototype/some/next-method-returns-throwing-done.js b/test/built-ins/Iterator/prototype/some/next-method-returns-throwing-done.js new file mode 100644 index 0000000000..a87f60929d --- /dev/null +++ b/test/built-ins/Iterator/prototype/some/next-method-returns-throwing-done.js @@ -0,0 +1,31 @@ +// 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(() => {}); +}); diff --git a/test/built-ins/Iterator/prototype/some/next-method-returns-throwing-value-done.js b/test/built-ins/Iterator/prototype/some/next-method-returns-throwing-value-done.js new file mode 100644 index 0000000000..29cbded935 --- /dev/null +++ b/test/built-ins/Iterator/prototype/some/next-method-returns-throwing-value-done.js @@ -0,0 +1,28 @@ +// 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(() => {}); diff --git a/test/built-ins/Iterator/prototype/some/next-method-returns-throwing-value.js b/test/built-ins/Iterator/prototype/some/next-method-returns-throwing-value.js new file mode 100644 index 0000000000..6293c1d5be --- /dev/null +++ b/test/built-ins/Iterator/prototype/some/next-method-returns-throwing-value.js @@ -0,0 +1,31 @@ +// 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(() => {}); +}); diff --git a/test/built-ins/Iterator/prototype/some/next-method-throws.js b/test/built-ins/Iterator/prototype/some/next-method-throws.js new file mode 100644 index 0000000000..26b9623de9 --- /dev/null +++ b/test/built-ins/Iterator/prototype/some/next-method-throws.js @@ -0,0 +1,23 @@ +// 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(() => {}); +}); diff --git a/test/built-ins/Iterator/prototype/some/non-callable-predicate.js b/test/built-ins/Iterator/prototype/some/non-callable-predicate.js new file mode 100644 index 0000000000..3b9cf32fe6 --- /dev/null +++ b/test/built-ins/Iterator/prototype/some/non-callable-predicate.js @@ -0,0 +1,20 @@ +// 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); +}); diff --git a/test/built-ins/Iterator/prototype/some/non-constructible.js b/test/built-ins/Iterator/prototype/some/non-constructible.js new file mode 100644 index 0000000000..ca15f49095 --- /dev/null +++ b/test/built-ins/Iterator/prototype/some/non-constructible.js @@ -0,0 +1,28 @@ +// 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(() => {}); +}); diff --git a/test/built-ins/Iterator/prototype/some/predicate-args.js b/test/built-ins/Iterator/prototype/some/predicate-args.js new file mode 100644 index 0000000000..5868b375b5 --- /dev/null +++ b/test/built-ins/Iterator/prototype/some/predicate-args.js @@ -0,0 +1,41 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/some/predicate-returns-falsey-then-truthy.js b/test/built-ins/Iterator/prototype/some/predicate-returns-falsey-then-truthy.js new file mode 100644 index 0000000000..de62627f43 --- /dev/null +++ b/test/built-ins/Iterator/prototype/some/predicate-returns-falsey-then-truthy.js @@ -0,0 +1,32 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/some/predicate-returns-falsey.js b/test/built-ins/Iterator/prototype/some/predicate-returns-falsey.js new file mode 100644 index 0000000000..69f0b42e4d --- /dev/null +++ b/test/built-ins/Iterator/prototype/some/predicate-returns-falsey.js @@ -0,0 +1,21 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/some/predicate-returns-non-boolean.js b/test/built-ins/Iterator/prototype/some/predicate-returns-non-boolean.js new file mode 100644 index 0000000000..bd4e1d37c2 --- /dev/null +++ b/test/built-ins/Iterator/prototype/some/predicate-returns-non-boolean.js @@ -0,0 +1,32 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/some/predicate-returns-truthy.js b/test/built-ins/Iterator/prototype/some/predicate-returns-truthy.js new file mode 100644 index 0000000000..26484864c9 --- /dev/null +++ b/test/built-ins/Iterator/prototype/some/predicate-returns-truthy.js @@ -0,0 +1,32 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/some/predicate-this.js b/test/built-ins/Iterator/prototype/some/predicate-this.js new file mode 100644 index 0000000000..0574184fe0 --- /dev/null +++ b/test/built-ins/Iterator/prototype/some/predicate-this.js @@ -0,0 +1,31 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/some/predicate-throws-then-closing-iterator-also-throws.js b/test/built-ins/Iterator/prototype/some/predicate-throws-then-closing-iterator-also-throws.js new file mode 100644 index 0000000000..92bbda696f --- /dev/null +++ b/test/built-ins/Iterator/prototype/some/predicate-throws-then-closing-iterator-also-throws.js @@ -0,0 +1,36 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/some/predicate-throws.js b/test/built-ins/Iterator/prototype/some/predicate-throws.js new file mode 100644 index 0000000000..91cdd170ba --- /dev/null +++ b/test/built-ins/Iterator/prototype/some/predicate-throws.js @@ -0,0 +1,40 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/some/prop-desc.js b/test/built-ins/Iterator/prototype/some/prop-desc.js new file mode 100644 index 0000000000..80733f8f24 --- /dev/null +++ b/test/built-ins/Iterator/prototype/some/prop-desc.js @@ -0,0 +1,25 @@ +// 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, +}); diff --git a/test/built-ins/Iterator/prototype/some/proto.js b/test/built-ins/Iterator/prototype/some/proto.js new file mode 100644 index 0000000000..d32cc0cbe1 --- /dev/null +++ b/test/built-ins/Iterator/prototype/some/proto.js @@ -0,0 +1,11 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/some/result-is-boolean.js b/test/built-ins/Iterator/prototype/some/result-is-boolean.js new file mode 100644 index 0000000000..f4ae356641 --- /dev/null +++ b/test/built-ins/Iterator/prototype/some/result-is-boolean.js @@ -0,0 +1,11 @@ +// 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'); diff --git a/test/built-ins/Iterator/prototype/some/this-non-callable-next.js b/test/built-ins/Iterator/prototype/some/this-non-callable-next.js new file mode 100644 index 0000000000..ad46eafd16 --- /dev/null +++ b/test/built-ins/Iterator/prototype/some/this-non-callable-next.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 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); +}); diff --git a/test/built-ins/Iterator/prototype/some/this-non-object.js b/test/built-ins/Iterator/prototype/some/this-non-object.js new file mode 100644 index 0000000000..8ae3b60c78 --- /dev/null +++ b/test/built-ins/Iterator/prototype/some/this-non-object.js @@ -0,0 +1,24 @@ +// 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, () => {}); +}); diff --git a/test/built-ins/Iterator/prototype/some/this-plain-iterator.js b/test/built-ins/Iterator/prototype/some/this-plain-iterator.js new file mode 100644 index 0000000000..40038d4e4b --- /dev/null +++ b/test/built-ins/Iterator/prototype/some/this-plain-iterator.js @@ -0,0 +1,30 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/take/argument-effect-order.js b/test/built-ins/Iterator/prototype/take/argument-effect-order.js new file mode 100644 index 0000000000..d37557cd73 --- /dev/null +++ b/test/built-ins/Iterator/prototype/take/argument-effect-order.js @@ -0,0 +1,72 @@ +// 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, []); diff --git a/test/built-ins/Iterator/prototype/take/callable.js b/test/built-ins/Iterator/prototype/take/callable.js new file mode 100644 index 0000000000..75b1517a95 --- /dev/null +++ b/test/built-ins/Iterator/prototype/take/callable.js @@ -0,0 +1,13 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/take/exhaustion-calls-return.js b/test/built-ins/Iterator/prototype/take/exhaustion-calls-return.js new file mode 100644 index 0000000000..ae50a2a7dd --- /dev/null +++ b/test/built-ins/Iterator/prototype/take/exhaustion-calls-return.js @@ -0,0 +1,68 @@ +// 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(); diff --git a/test/built-ins/Iterator/prototype/take/get-next-method-only-once.js b/test/built-ins/Iterator/prototype/take/get-next-method-only-once.js new file mode 100644 index 0000000000..8a9b8ae335 --- /dev/null +++ b/test/built-ins/Iterator/prototype/take/get-next-method-only-once.js @@ -0,0 +1,41 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/take/get-next-method-throws.js b/test/built-ins/Iterator/prototype/take/get-next-method-throws.js new file mode 100644 index 0000000000..0a0abc9df7 --- /dev/null +++ b/test/built-ins/Iterator/prototype/take/get-next-method-throws.js @@ -0,0 +1,25 @@ +// 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); +}); diff --git a/test/built-ins/Iterator/prototype/take/get-return-method-throws.js b/test/built-ins/Iterator/prototype/take/get-return-method-throws.js new file mode 100644 index 0000000000..291a25beb6 --- /dev/null +++ b/test/built-ins/Iterator/prototype/take/get-return-method-throws.js @@ -0,0 +1,30 @@ +// 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(); +}); diff --git a/test/built-ins/Iterator/prototype/take/is-function.js b/test/built-ins/Iterator/prototype/take/is-function.js new file mode 100644 index 0000000000..5e3cacfc8e --- /dev/null +++ b/test/built-ins/Iterator/prototype/take/is-function.js @@ -0,0 +1,10 @@ +// 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'); diff --git a/test/built-ins/Iterator/prototype/take/length.js b/test/built-ins/Iterator/prototype/take/length.js new file mode 100644 index 0000000000..b7a0e29939 --- /dev/null +++ b/test/built-ins/Iterator/prototype/take/length.js @@ -0,0 +1,22 @@ +// 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, +}); diff --git a/test/built-ins/Iterator/prototype/take/limit-greater-than-or-equal-to-total.js b/test/built-ins/Iterator/prototype/take/limit-greater-than-or-equal-to-total.js new file mode 100644 index 0000000000..2fe3e77bf8 --- /dev/null +++ b/test/built-ins/Iterator/prototype/take/limit-greater-than-or-equal-to-total.js @@ -0,0 +1,27 @@ +// 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]); diff --git a/test/built-ins/Iterator/prototype/take/limit-less-than-total.js b/test/built-ins/Iterator/prototype/take/limit-less-than-total.js new file mode 100644 index 0000000000..d9a8689978 --- /dev/null +++ b/test/built-ins/Iterator/prototype/take/limit-less-than-total.js @@ -0,0 +1,28 @@ +// 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]); diff --git a/test/built-ins/Iterator/prototype/take/limit-rangeerror.js b/test/built-ins/Iterator/prototype/take/limit-rangeerror.js new file mode 100644 index 0000000000..f303d192d7 --- /dev/null +++ b/test/built-ins/Iterator/prototype/take/limit-rangeerror.js @@ -0,0 +1,36 @@ +// 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); +}); diff --git a/test/built-ins/Iterator/prototype/take/limit-tonumber-throws.js b/test/built-ins/Iterator/prototype/take/limit-tonumber-throws.js new file mode 100644 index 0000000000..1859590dea --- /dev/null +++ b/test/built-ins/Iterator/prototype/take/limit-tonumber-throws.js @@ -0,0 +1,22 @@ +// 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(); + }, + }); +}); diff --git a/test/built-ins/Iterator/prototype/take/limit-tonumber.js b/test/built-ins/Iterator/prototype/take/limit-tonumber.js new file mode 100644 index 0000000000..ad870abb63 --- /dev/null +++ b/test/built-ins/Iterator/prototype/take/limit-tonumber.js @@ -0,0 +1,61 @@ +// 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] +); diff --git a/test/built-ins/Iterator/prototype/take/name.js b/test/built-ins/Iterator/prototype/take/name.js new file mode 100644 index 0000000000..9b3dfe65eb --- /dev/null +++ b/test/built-ins/Iterator/prototype/take/name.js @@ -0,0 +1,29 @@ +// 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, +}); diff --git a/test/built-ins/Iterator/prototype/take/next-method-returns-non-object.js b/test/built-ins/Iterator/prototype/take/next-method-returns-non-object.js new file mode 100644 index 0000000000..d3535d6816 --- /dev/null +++ b/test/built-ins/Iterator/prototype/take/next-method-returns-non-object.js @@ -0,0 +1,29 @@ +// 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(); +}); diff --git a/test/built-ins/Iterator/prototype/take/next-method-returns-throwing-done.js b/test/built-ins/Iterator/prototype/take/next-method-returns-throwing-done.js new file mode 100644 index 0000000000..aedc223667 --- /dev/null +++ b/test/built-ins/Iterator/prototype/take/next-method-returns-throwing-done.js @@ -0,0 +1,42 @@ +// 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(); +}); diff --git a/test/built-ins/Iterator/prototype/take/next-method-returns-throwing-value-done.js b/test/built-ins/Iterator/prototype/take/next-method-returns-throwing-value-done.js new file mode 100644 index 0000000000..b464442756 --- /dev/null +++ b/test/built-ins/Iterator/prototype/take/next-method-returns-throwing-value-done.js @@ -0,0 +1,36 @@ +// 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(); diff --git a/test/built-ins/Iterator/prototype/take/next-method-returns-throwing-value.js b/test/built-ins/Iterator/prototype/take/next-method-returns-throwing-value.js new file mode 100644 index 0000000000..60d9509a3d --- /dev/null +++ b/test/built-ins/Iterator/prototype/take/next-method-returns-throwing-value.js @@ -0,0 +1,42 @@ +// 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(); +}); diff --git a/test/built-ins/Iterator/prototype/take/next-method-throws.js b/test/built-ins/Iterator/prototype/take/next-method-throws.js new file mode 100644 index 0000000000..8556583de0 --- /dev/null +++ b/test/built-ins/Iterator/prototype/take/next-method-throws.js @@ -0,0 +1,29 @@ +// 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(); +}); diff --git a/test/built-ins/Iterator/prototype/take/non-constructible.js b/test/built-ins/Iterator/prototype/take/non-constructible.js new file mode 100644 index 0000000000..6fb0a43e72 --- /dev/null +++ b/test/built-ins/Iterator/prototype/take/non-constructible.js @@ -0,0 +1,28 @@ +// 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); +}); diff --git a/test/built-ins/Iterator/prototype/take/prop-desc.js b/test/built-ins/Iterator/prototype/take/prop-desc.js new file mode 100644 index 0000000000..cd8f19f174 --- /dev/null +++ b/test/built-ins/Iterator/prototype/take/prop-desc.js @@ -0,0 +1,25 @@ +// 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, +}); diff --git a/test/built-ins/Iterator/prototype/take/proto.js b/test/built-ins/Iterator/prototype/take/proto.js new file mode 100644 index 0000000000..6e1e63dcce --- /dev/null +++ b/test/built-ins/Iterator/prototype/take/proto.js @@ -0,0 +1,11 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/take/result-is-iterator.js b/test/built-ins/Iterator/prototype/take/result-is-iterator.js new file mode 100644 index 0000000000..bc5cd4bf99 --- /dev/null +++ b/test/built-ins/Iterator/prototype/take/result-is-iterator.js @@ -0,0 +1,11 @@ +// 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'); diff --git a/test/built-ins/Iterator/prototype/take/return-is-forwarded.js b/test/built-ins/Iterator/prototype/take/return-is-forwarded.js new file mode 100644 index 0000000000..08e2506f1f --- /dev/null +++ b/test/built-ins/Iterator/prototype/take/return-is-forwarded.js @@ -0,0 +1,51 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/take/return-is-not-forwarded-after-exhaustion.js b/test/built-ins/Iterator/prototype/take/return-is-not-forwarded-after-exhaustion.js new file mode 100644 index 0000000000..77192e57fd --- /dev/null +++ b/test/built-ins/Iterator/prototype/take/return-is-not-forwarded-after-exhaustion.js @@ -0,0 +1,50 @@ +// 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(); diff --git a/test/built-ins/Iterator/prototype/take/this-non-callable-next.js b/test/built-ins/Iterator/prototype/take/this-non-callable-next.js new file mode 100644 index 0000000000..26b655fa01 --- /dev/null +++ b/test/built-ins/Iterator/prototype/take/this-non-callable-next.js @@ -0,0 +1,19 @@ +// 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(); +}); diff --git a/test/built-ins/Iterator/prototype/take/this-non-object.js b/test/built-ins/Iterator/prototype/take/this-non-object.js new file mode 100644 index 0000000000..e36b0e7bda --- /dev/null +++ b/test/built-ins/Iterator/prototype/take/this-non-object.js @@ -0,0 +1,34 @@ +// 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); +}); diff --git a/test/built-ins/Iterator/prototype/take/this-plain-iterator.js b/test/built-ins/Iterator/prototype/take/this-plain-iterator.js new file mode 100644 index 0000000000..b494b3d5eb --- /dev/null +++ b/test/built-ins/Iterator/prototype/take/this-plain-iterator.js @@ -0,0 +1,30 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/take/underlying-iterator-advanced-in-parallel.js b/test/built-ins/Iterator/prototype/take/underlying-iterator-advanced-in-parallel.js new file mode 100644 index 0000000000..2ef2a4dc3a --- /dev/null +++ b/test/built-ins/Iterator/prototype/take/underlying-iterator-advanced-in-parallel.js @@ -0,0 +1,39 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/take/underlying-iterator-closed-in-parallel.js b/test/built-ins/Iterator/prototype/take/underlying-iterator-closed-in-parallel.js new file mode 100644 index 0000000000..fc412d4013 --- /dev/null +++ b/test/built-ins/Iterator/prototype/take/underlying-iterator-closed-in-parallel.js @@ -0,0 +1,26 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/take/underlying-iterator-closed.js b/test/built-ins/Iterator/prototype/take/underlying-iterator-closed.js new file mode 100644 index 0000000000..dc3837bf86 --- /dev/null +++ b/test/built-ins/Iterator/prototype/take/underlying-iterator-closed.js @@ -0,0 +1,26 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/toArray/callable.js b/test/built-ins/Iterator/prototype/toArray/callable.js new file mode 100644 index 0000000000..819b92132e --- /dev/null +++ b/test/built-ins/Iterator/prototype/toArray/callable.js @@ -0,0 +1,13 @@ +// 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(); diff --git a/test/built-ins/Iterator/prototype/toArray/get-next-method-only-once.js b/test/built-ins/Iterator/prototype/toArray/get-next-method-only-once.js new file mode 100644 index 0000000000..15362c96d3 --- /dev/null +++ b/test/built-ins/Iterator/prototype/toArray/get-next-method-only-once.js @@ -0,0 +1,34 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/toArray/get-next-method-throws.js b/test/built-ins/Iterator/prototype/toArray/get-next-method-throws.js new file mode 100644 index 0000000000..06d7320638 --- /dev/null +++ b/test/built-ins/Iterator/prototype/toArray/get-next-method-throws.js @@ -0,0 +1,23 @@ +// 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(); +}); diff --git a/test/built-ins/Iterator/prototype/toArray/is-function.js b/test/built-ins/Iterator/prototype/toArray/is-function.js new file mode 100644 index 0000000000..0bede61973 --- /dev/null +++ b/test/built-ins/Iterator/prototype/toArray/is-function.js @@ -0,0 +1,10 @@ +// 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'); diff --git a/test/built-ins/Iterator/prototype/toArray/iterator-already-exhausted.js b/test/built-ins/Iterator/prototype/toArray/iterator-already-exhausted.js new file mode 100644 index 0000000000..9db33a71ac --- /dev/null +++ b/test/built-ins/Iterator/prototype/toArray/iterator-already-exhausted.js @@ -0,0 +1,24 @@ +// 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, []); diff --git a/test/built-ins/Iterator/prototype/toArray/length.js b/test/built-ins/Iterator/prototype/toArray/length.js new file mode 100644 index 0000000000..dadd069c5b --- /dev/null +++ b/test/built-ins/Iterator/prototype/toArray/length.js @@ -0,0 +1,22 @@ +// 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, +}); diff --git a/test/built-ins/Iterator/prototype/toArray/name.js b/test/built-ins/Iterator/prototype/toArray/name.js new file mode 100644 index 0000000000..fd970f676f --- /dev/null +++ b/test/built-ins/Iterator/prototype/toArray/name.js @@ -0,0 +1,29 @@ +// 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, +}); diff --git a/test/built-ins/Iterator/prototype/toArray/next-method-returns-non-object.js b/test/built-ins/Iterator/prototype/toArray/next-method-returns-non-object.js new file mode 100644 index 0000000000..22d08140f1 --- /dev/null +++ b/test/built-ins/Iterator/prototype/toArray/next-method-returns-non-object.js @@ -0,0 +1,23 @@ +// 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(); +}); diff --git a/test/built-ins/Iterator/prototype/toArray/next-method-returns-throwing-done.js b/test/built-ins/Iterator/prototype/toArray/next-method-returns-throwing-done.js new file mode 100644 index 0000000000..e725cf4049 --- /dev/null +++ b/test/built-ins/Iterator/prototype/toArray/next-method-returns-throwing-done.js @@ -0,0 +1,31 @@ +// 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(); +}); diff --git a/test/built-ins/Iterator/prototype/toArray/next-method-returns-throwing-value-done.js b/test/built-ins/Iterator/prototype/toArray/next-method-returns-throwing-value-done.js new file mode 100644 index 0000000000..15ca5ab334 --- /dev/null +++ b/test/built-ins/Iterator/prototype/toArray/next-method-returns-throwing-value-done.js @@ -0,0 +1,28 @@ +// 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(); diff --git a/test/built-ins/Iterator/prototype/toArray/next-method-returns-throwing-value.js b/test/built-ins/Iterator/prototype/toArray/next-method-returns-throwing-value.js new file mode 100644 index 0000000000..084158ddbd --- /dev/null +++ b/test/built-ins/Iterator/prototype/toArray/next-method-returns-throwing-value.js @@ -0,0 +1,31 @@ +// 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(); +}); diff --git a/test/built-ins/Iterator/prototype/toArray/next-method-throws.js b/test/built-ins/Iterator/prototype/toArray/next-method-throws.js new file mode 100644 index 0000000000..6473e8bb50 --- /dev/null +++ b/test/built-ins/Iterator/prototype/toArray/next-method-throws.js @@ -0,0 +1,23 @@ +// 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(); +}); diff --git a/test/built-ins/Iterator/prototype/toArray/non-constructible.js b/test/built-ins/Iterator/prototype/toArray/non-constructible.js new file mode 100644 index 0000000000..536deebdc9 --- /dev/null +++ b/test/built-ins/Iterator/prototype/toArray/non-constructible.js @@ -0,0 +1,24 @@ +// 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(); +}); diff --git a/test/built-ins/Iterator/prototype/toArray/prop-desc.js b/test/built-ins/Iterator/prototype/toArray/prop-desc.js new file mode 100644 index 0000000000..e6c487a3f2 --- /dev/null +++ b/test/built-ins/Iterator/prototype/toArray/prop-desc.js @@ -0,0 +1,25 @@ +// 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, +}); diff --git a/test/built-ins/Iterator/prototype/toArray/proto.js b/test/built-ins/Iterator/prototype/toArray/proto.js new file mode 100644 index 0000000000..142a82b4ae --- /dev/null +++ b/test/built-ins/Iterator/prototype/toArray/proto.js @@ -0,0 +1,11 @@ +// 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); diff --git a/test/built-ins/Iterator/prototype/toArray/this-non-callable-next.js b/test/built-ins/Iterator/prototype/toArray/this-non-callable-next.js new file mode 100644 index 0000000000..f0b2a56868 --- /dev/null +++ b/test/built-ins/Iterator/prototype/toArray/this-non-callable-next.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.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 }); +}); diff --git a/test/built-ins/Iterator/prototype/toArray/this-non-object.js b/test/built-ins/Iterator/prototype/toArray/this-non-object.js new file mode 100644 index 0000000000..d21723e98e --- /dev/null +++ b/test/built-ins/Iterator/prototype/toArray/this-non-object.js @@ -0,0 +1,24 @@ +// 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); +}); diff --git a/test/built-ins/Iterator/prototype/toArray/this-plain-iterator.js b/test/built-ins/Iterator/prototype/toArray/this-plain-iterator.js new file mode 100644 index 0000000000..765bc1e913 --- /dev/null +++ b/test/built-ins/Iterator/prototype/toArray/this-plain-iterator.js @@ -0,0 +1,25 @@ +// 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]); diff --git a/test/built-ins/Iterator/subclassable.js b/test/built-ins/Iterator/subclassable.js new file mode 100644 index 0000000000..4a07db8c04 --- /dev/null +++ b/test/built-ins/Iterator/subclassable.js @@ -0,0 +1,27 @@ +// 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' +); diff --git a/test/built-ins/Object/prototype/toString/symbol-tag-non-str-builtin.js b/test/built-ins/Object/prototype/toString/symbol-tag-non-str-builtin.js index 7e2ca775a8..02f9fcb667 100644 --- a/test/built-ins/Object/prototype/toString/symbol-tag-non-str-builtin.js +++ b/test/built-ins/Object/prototype/toString/symbol-tag-non-str-builtin.js @@ -26,7 +26,7 @@ var strIter = ''[Symbol.iterator](); var strIterProto = Object.getPrototypeOf(strIter); assert.sameValue(toString.call(strIter), '[object String Iterator]'); delete strIterProto[Symbol.toStringTag]; -assert.sameValue(toString.call(strIter), '[object Object]'); +assert.sameValue(toString.call(strIter), '[object Iterator]'); var arrIter = [][Symbol.iterator](); var arrIterProto = Object.getPrototypeOf(arrIter)