/src/serenity/Userland/Libraries/LibJS/Runtime/WeakSetConstructor.cpp
Line | Count | Source |
1 | | /* |
2 | | * Copyright (c) 2021, Idan Horowitz <idan.horowitz@serenityos.org> |
3 | | * |
4 | | * SPDX-License-Identifier: BSD-2-Clause |
5 | | */ |
6 | | |
7 | | #include <LibJS/Runtime/AbstractOperations.h> |
8 | | #include <LibJS/Runtime/Error.h> |
9 | | #include <LibJS/Runtime/GlobalObject.h> |
10 | | #include <LibJS/Runtime/Iterator.h> |
11 | | #include <LibJS/Runtime/WeakSet.h> |
12 | | #include <LibJS/Runtime/WeakSetConstructor.h> |
13 | | |
14 | | namespace JS { |
15 | | |
16 | | JS_DEFINE_ALLOCATOR(WeakSetConstructor); |
17 | | |
18 | | WeakSetConstructor::WeakSetConstructor(Realm& realm) |
19 | 0 | : NativeFunction(realm.vm().names.WeakSet.as_string(), realm.intrinsics().function_prototype()) |
20 | 0 | { |
21 | 0 | } |
22 | | |
23 | | void WeakSetConstructor::initialize(Realm& realm) |
24 | 0 | { |
25 | 0 | auto& vm = this->vm(); |
26 | 0 | Base::initialize(realm); |
27 | | |
28 | | // 24.4.2.1 WeakSet.prototype, https://tc39.es/ecma262/#sec-weakset.prototype |
29 | 0 | define_direct_property(vm.names.prototype, realm.intrinsics().weak_set_prototype(), 0); |
30 | |
|
31 | 0 | define_direct_property(vm.names.length, Value(0), Attribute::Configurable); |
32 | 0 | } |
33 | | |
34 | | // 24.4.1.1 WeakSet ( [ iterable ] ), https://tc39.es/ecma262/#sec-weakset-iterable |
35 | | ThrowCompletionOr<Value> WeakSetConstructor::call() |
36 | 0 | { |
37 | 0 | auto& vm = this->vm(); |
38 | | |
39 | | // 1. If NewTarget is undefined, throw a TypeError exception. |
40 | 0 | return vm.throw_completion<TypeError>(ErrorType::ConstructorWithoutNew, vm.names.WeakSet); |
41 | 0 | } |
42 | | |
43 | | // 24.4.1.1 WeakSet ( [ iterable ] ), https://tc39.es/ecma262/#sec-weakset-iterable |
44 | | ThrowCompletionOr<NonnullGCPtr<Object>> WeakSetConstructor::construct(FunctionObject& new_target) |
45 | 0 | { |
46 | 0 | auto& vm = this->vm(); |
47 | 0 | auto iterable = vm.argument(0); |
48 | | |
49 | | // 2. Let set be ? OrdinaryCreateFromConstructor(NewTarget, "%WeakSet.prototype%", « [[WeakSetData]] »). |
50 | | // 3. Set set.[[WeakSetData]] to a new empty List. |
51 | 0 | auto set = TRY(ordinary_create_from_constructor<WeakSet>(vm, new_target, &Intrinsics::weak_set_prototype)); |
52 | | |
53 | | // 4. If iterable is either undefined or null, return set. |
54 | 0 | if (iterable.is_nullish()) |
55 | 0 | return set; |
56 | | |
57 | | // 5. Let adder be ? Get(set, "add"). |
58 | 0 | auto adder = TRY(set->get(vm.names.add)); |
59 | | |
60 | | // 6. If IsCallable(adder) is false, throw a TypeError exception. |
61 | 0 | if (!adder.is_function()) |
62 | 0 | return vm.throw_completion<TypeError>(ErrorType::NotAFunction, "'add' property of WeakSet"); |
63 | | |
64 | | // 7. Let iteratorRecord be ? GetIterator(iterable, sync). |
65 | | // 8. Repeat, |
66 | 0 | (void)TRY(get_iterator_values(vm, iterable, [&](Value next) -> Optional<Completion> { |
67 | | // a. Let next be ? IteratorStepValue(iteratorRecord). |
68 | | // c. If next is DONE, return set. |
69 | | // c. Let status be Completion(Call(adder, set, « nextValue »)). |
70 | | // d. IfAbruptCloseIterator(status, iteratorRecord). |
71 | 0 | TRY(JS::call(vm, adder.as_function(), set, next)); |
72 | 0 | return {}; |
73 | 0 | })); |
74 | | |
75 | | // b. If next is false, return set. |
76 | 0 | return set; |
77 | 0 | } |
78 | | |
79 | | } |