mirror of
https://github.com/RGBCube/serenity
synced 2025-05-15 05:04:59 +00:00

Rather than splitting the Iterator type and its AOs into two files, let's combine them into one file to match every other JS runtime object that we have.
79 lines
2.7 KiB
C++
79 lines
2.7 KiB
C++
/*
|
|
* Copyright (c) 2021, Idan Horowitz <idan.horowitz@serenityos.org>
|
|
*
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*/
|
|
|
|
#include <LibJS/Runtime/AbstractOperations.h>
|
|
#include <LibJS/Runtime/Error.h>
|
|
#include <LibJS/Runtime/GlobalObject.h>
|
|
#include <LibJS/Runtime/Iterator.h>
|
|
#include <LibJS/Runtime/WeakSet.h>
|
|
#include <LibJS/Runtime/WeakSetConstructor.h>
|
|
|
|
namespace JS {
|
|
|
|
WeakSetConstructor::WeakSetConstructor(Realm& realm)
|
|
: NativeFunction(realm.vm().names.WeakSet.as_string(), realm.intrinsics().function_prototype())
|
|
{
|
|
}
|
|
|
|
ThrowCompletionOr<void> WeakSetConstructor::initialize(Realm& realm)
|
|
{
|
|
auto& vm = this->vm();
|
|
MUST_OR_THROW_OOM(NativeFunction::initialize(realm));
|
|
|
|
// 24.4.2.1 WeakSet.prototype, https://tc39.es/ecma262/#sec-weakset.prototype
|
|
define_direct_property(vm.names.prototype, realm.intrinsics().weak_set_prototype(), 0);
|
|
|
|
define_direct_property(vm.names.length, Value(0), Attribute::Configurable);
|
|
|
|
return {};
|
|
}
|
|
|
|
// 24.4.1.1 WeakSet ( [ iterable ] ), https://tc39.es/ecma262/#sec-weakset-iterable
|
|
ThrowCompletionOr<Value> WeakSetConstructor::call()
|
|
{
|
|
auto& vm = this->vm();
|
|
|
|
// 1. If NewTarget is undefined, throw a TypeError exception.
|
|
return vm.throw_completion<TypeError>(ErrorType::ConstructorWithoutNew, vm.names.WeakSet);
|
|
}
|
|
|
|
// 24.4.1.1 WeakSet ( [ iterable ] ), https://tc39.es/ecma262/#sec-weakset-iterable
|
|
ThrowCompletionOr<NonnullGCPtr<Object>> WeakSetConstructor::construct(FunctionObject& new_target)
|
|
{
|
|
auto& vm = this->vm();
|
|
auto iterable = vm.argument(0);
|
|
|
|
// 2. Let set be ? OrdinaryCreateFromConstructor(NewTarget, "%WeakSet.prototype%", « [[WeakSetData]] »).
|
|
// 3. Set set.[[WeakSetData]] to a new empty List.
|
|
auto set = TRY(ordinary_create_from_constructor<WeakSet>(vm, new_target, &Intrinsics::weak_set_prototype));
|
|
|
|
// 4. If iterable is either undefined or null, return set.
|
|
if (iterable.is_nullish())
|
|
return set;
|
|
|
|
// 5. Let adder be ? Get(set, "add").
|
|
auto adder = TRY(set->get(vm.names.add));
|
|
|
|
// 6. If IsCallable(adder) is false, throw a TypeError exception.
|
|
if (!adder.is_function())
|
|
return vm.throw_completion<TypeError>(ErrorType::NotAFunction, "'add' property of WeakSet");
|
|
|
|
// 7. Let iteratorRecord be ? GetIterator(iterable, sync).
|
|
// 8. Repeat,
|
|
// a. Let next be ? IteratorStep(iteratorRecord).
|
|
// c. Let nextValue be ? IteratorValue(next).
|
|
(void)TRY(get_iterator_values(vm, iterable, [&](Value next_value) -> Optional<Completion> {
|
|
// d. Let status be Completion(Call(adder, set, « nextValue »)).
|
|
// e. IfAbruptCloseIterator(status, iteratorRecord).
|
|
TRY(JS::call(vm, adder.as_function(), set, next_value));
|
|
return {};
|
|
}));
|
|
|
|
// b. If next is false, return set.
|
|
return set;
|
|
}
|
|
|
|
}
|