Iterator.cpp 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. /*
  2. * Copyright (c) 2023, Tim Flynn <trflynn89@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <LibJS/Runtime/AbstractOperations.h>
  7. #include <LibJS/Runtime/Iterator.h>
  8. #include <LibJS/Runtime/VM.h>
  9. namespace JS {
  10. ThrowCompletionOr<NonnullGCPtr<Iterator>> Iterator::create(Realm& realm, Object& prototype, IteratorRecord iterated)
  11. {
  12. return MUST_OR_THROW_OOM(realm.heap().allocate<Iterator>(realm, prototype, move(iterated)));
  13. }
  14. Iterator::Iterator(Object& prototype, IteratorRecord iterated)
  15. : Object(ConstructWithPrototypeTag::Tag, prototype)
  16. , m_iterated(move(iterated))
  17. {
  18. }
  19. Iterator::Iterator(Object& prototype)
  20. : Iterator(prototype, {})
  21. {
  22. }
  23. // 2.1.1 GetIteratorDirect ( obj ), https://tc39.es/proposal-iterator-helpers/#sec-getiteratorflattenable
  24. ThrowCompletionOr<IteratorRecord> get_iterator_direct(VM& vm, Object& object)
  25. {
  26. // 1. Let nextMethod be ? Get(obj, "next").
  27. auto next_method = TRY(object.get(vm.names.next));
  28. // 2. Let iteratorRecord be Record { [[Iterator]]: obj, [[NextMethod]]: nextMethod, [[Done]]: false }.
  29. IteratorRecord iterator_record { .iterator = object, .next_method = next_method, .done = false };
  30. // 3. Return iteratorRecord.
  31. return iterator_record;
  32. }
  33. ThrowCompletionOr<IteratorRecord> get_iterator_flattenable(VM& vm, Value object)
  34. {
  35. // 1. If obj is not an Object, throw a TypeError exception.
  36. if (!object.is_object())
  37. return vm.throw_completion<TypeError>(ErrorType::NotAnObject, "obj"sv);
  38. // 2. Let method be ? GetMethod(obj, @@iterator).
  39. auto method = TRY(object.get_method(vm, vm.well_known_symbol_iterator()));
  40. Value iterator;
  41. // 3. If method is undefined, then
  42. if (!method) {
  43. // a. Let iterator be obj.
  44. iterator = object;
  45. }
  46. // 4. Else,
  47. else {
  48. // a. Let iterator be ? Call(method, obj).
  49. iterator = TRY(call(vm, method, object));
  50. }
  51. // 5. If iterator is not an Object, throw a TypeError exception.
  52. if (!iterator.is_object())
  53. return vm.throw_completion<TypeError>(ErrorType::NotAnObject, "iterator"sv);
  54. // 6. Return ? GetIteratorDirect(iterator).
  55. return TRY(get_iterator_direct(vm, iterator.as_object()));
  56. }
  57. }