/src/serenity/Userland/Libraries/LibJS/Runtime/WeakMapConstructor.cpp
Line | Count | Source (jump to first uncovered line) |
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/WeakMap.h> |
12 | | #include <LibJS/Runtime/WeakMapConstructor.h> |
13 | | |
14 | | namespace JS { |
15 | | |
16 | | JS_DEFINE_ALLOCATOR(WeakMapConstructor); |
17 | | |
18 | | WeakMapConstructor::WeakMapConstructor(Realm& realm) |
19 | 0 | : NativeFunction(realm.vm().names.WeakMap.as_string(), realm.intrinsics().function_prototype()) |
20 | 0 | { |
21 | 0 | } |
22 | | |
23 | | void WeakMapConstructor::initialize(Realm& realm) |
24 | 0 | { |
25 | 0 | auto& vm = this->vm(); |
26 | 0 | Base::initialize(realm); |
27 | | |
28 | | // 24.3.2.1 WeakMap.prototype, https://tc39.es/ecma262/#sec-weakmap.prototype |
29 | 0 | define_direct_property(vm.names.prototype, realm.intrinsics().weak_map_prototype(), 0); |
30 | |
|
31 | 0 | define_direct_property(vm.names.length, Value(0), Attribute::Configurable); |
32 | 0 | } |
33 | | |
34 | | // 24.3.1.1 WeakMap ( [ iterable ] ), https://tc39.es/ecma262/#sec-weakmap-iterable |
35 | | ThrowCompletionOr<Value> WeakMapConstructor::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.WeakMap); |
41 | 0 | } |
42 | | |
43 | | // 24.3.1.1 WeakMap ( [ iterable ] ), https://tc39.es/ecma262/#sec-weakmap-iterable |
44 | | ThrowCompletionOr<NonnullGCPtr<Object>> WeakMapConstructor::construct(FunctionObject& new_target) |
45 | 0 | { |
46 | 0 | auto& vm = this->vm(); |
47 | 0 | auto iterable = vm.argument(0); |
48 | | |
49 | | // 2. Let map be ? OrdinaryCreateFromConstructor(NewTarget, "%WeakMap.prototype%", « [[WeakMapData]] »). |
50 | | // 3. Set map.[[WeakMapData]] to a new empty List. |
51 | 0 | auto map = TRY(ordinary_create_from_constructor<WeakMap>(vm, new_target, &Intrinsics::weak_map_prototype)); |
52 | | |
53 | | // 4. If iterable is either undefined or null, return map. |
54 | 0 | if (iterable.is_nullish()) |
55 | 0 | return map; |
56 | | |
57 | | // 5. Let adder be ? Get(map, "set"). |
58 | 0 | auto adder = TRY(map->get(vm.names.set)); |
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, "'set' property of WeakMap"); |
63 | | |
64 | | // 7. Return ? AddEntriesFromIterable(map, iterable, adder). |
65 | 0 | (void)TRY(get_iterator_values(vm, iterable, [&](Value iterator_value) -> Optional<Completion> { |
66 | 0 | if (!iterator_value.is_object()) |
67 | 0 | return vm.throw_completion<TypeError>(ErrorType::NotAnObject, ByteString::formatted("Iterator value {}", iterator_value.to_string_without_side_effects())); |
68 | |
|
69 | 0 | auto key = TRY(iterator_value.as_object().get(0)); |
70 | 0 | auto value = TRY(iterator_value.as_object().get(1)); |
71 | 0 | TRY(JS::call(vm, adder.as_function(), map, key, value)); |
72 | |
|
73 | 0 | return {}; |
74 | 0 | })); |
75 | | |
76 | 0 | return map; |
77 | 0 | } |
78 | | |
79 | | } |