diff options
author | Idan Horowitz <idan.horowitz@gmail.com> | 2021-06-09 19:23:04 +0300 |
---|---|---|
committer | Linus Groh <mail@linusgroh.de> | 2021-06-09 21:52:25 +0100 |
commit | 8b6beac5ce5e1ca5f4e0befa3a48d6d6923f648e (patch) | |
tree | b08fa9d9a02be2d1ba27e511927ee1ade10cfd69 /Userland/Libraries | |
parent | ee9fe288b2d9182e83185b07a925df095289ddb2 (diff) | |
download | serenity-8b6beac5ce5e1ca5f4e0befa3a48d6d6923f648e.zip |
LibJS: Add the WeakSet built-in object
Diffstat (limited to 'Userland/Libraries')
-rw-r--r-- | Userland/Libraries/LibJS/CMakeLists.txt | 3 | ||||
-rw-r--r-- | Userland/Libraries/LibJS/Forward.h | 3 | ||||
-rw-r--r-- | Userland/Libraries/LibJS/Runtime/GlobalObject.cpp | 3 | ||||
-rw-r--r-- | Userland/Libraries/LibJS/Runtime/WeakSet.cpp | 25 | ||||
-rw-r--r-- | Userland/Libraries/LibJS/Runtime/WeakSet.h | 31 | ||||
-rw-r--r-- | Userland/Libraries/LibJS/Runtime/WeakSetConstructor.cpp | 64 | ||||
-rw-r--r-- | Userland/Libraries/LibJS/Runtime/WeakSetConstructor.h | 28 | ||||
-rw-r--r-- | Userland/Libraries/LibJS/Runtime/WeakSetPrototype.cpp | 41 | ||||
-rw-r--r-- | Userland/Libraries/LibJS/Runtime/WeakSetPrototype.h | 23 | ||||
-rw-r--r-- | Userland/Libraries/LibJS/Tests/builtins/WeakSet/WeakSet.js | 30 |
10 files changed, 250 insertions, 1 deletions
diff --git a/Userland/Libraries/LibJS/CMakeLists.txt b/Userland/Libraries/LibJS/CMakeLists.txt index d28e72c016..ffcba7b6a1 100644 --- a/Userland/Libraries/LibJS/CMakeLists.txt +++ b/Userland/Libraries/LibJS/CMakeLists.txt @@ -97,6 +97,9 @@ set(SOURCES Runtime/TypedArrayPrototype.cpp Runtime/VM.cpp Runtime/Value.cpp + Runtime/WeakSet.cpp + Runtime/WeakSetConstructor.cpp + Runtime/WeakSetPrototype.cpp Runtime/WithScope.cpp SyntaxHighlighter.cpp Token.cpp diff --git a/Userland/Libraries/LibJS/Forward.h b/Userland/Libraries/LibJS/Forward.h index 9e0a6058ce..2af2650c1c 100644 --- a/Userland/Libraries/LibJS/Forward.h +++ b/Userland/Libraries/LibJS/Forward.h @@ -39,7 +39,8 @@ __JS_ENUMERATE(RegExpObject, regexp, RegExpPrototype, RegExpConstructor, void) \ __JS_ENUMERATE(Set, set, SetPrototype, SetConstructor, void) \ __JS_ENUMERATE(StringObject, string, StringPrototype, StringConstructor, void) \ - __JS_ENUMERATE(SymbolObject, symbol, SymbolPrototype, SymbolConstructor, void) + __JS_ENUMERATE(SymbolObject, symbol, SymbolPrototype, SymbolConstructor, void) \ + __JS_ENUMERATE(WeakSet, weak_set, WeakSetPrototype, WeakSetConstructor, void) #define JS_ENUMERATE_NATIVE_OBJECTS \ JS_ENUMERATE_NATIVE_OBJECTS_EXCLUDING_TEMPLATES \ diff --git a/Userland/Libraries/LibJS/Runtime/GlobalObject.cpp b/Userland/Libraries/LibJS/Runtime/GlobalObject.cpp index f168a11d24..8d162b2f15 100644 --- a/Userland/Libraries/LibJS/Runtime/GlobalObject.cpp +++ b/Userland/Libraries/LibJS/Runtime/GlobalObject.cpp @@ -60,6 +60,8 @@ #include <LibJS/Runtime/TypedArrayConstructor.h> #include <LibJS/Runtime/TypedArrayPrototype.h> #include <LibJS/Runtime/Value.h> +#include <LibJS/Runtime/WeakSetConstructor.h> +#include <LibJS/Runtime/WeakSetPrototype.h> namespace JS { @@ -143,6 +145,7 @@ void GlobalObject::initialize_global_object() add_constructor(vm.names.Set, m_set_constructor, m_set_prototype); add_constructor(vm.names.String, m_string_constructor, m_string_prototype); add_constructor(vm.names.Symbol, m_symbol_constructor, m_symbol_prototype); + add_constructor(vm.names.WeakSet, m_weak_set_constructor, m_weak_set_prototype); initialize_constructor(vm.names.TypedArray, m_typed_array_constructor, m_typed_array_prototype); diff --git a/Userland/Libraries/LibJS/Runtime/WeakSet.cpp b/Userland/Libraries/LibJS/Runtime/WeakSet.cpp new file mode 100644 index 0000000000..50bf41c0ba --- /dev/null +++ b/Userland/Libraries/LibJS/Runtime/WeakSet.cpp @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2021, Idan Horowitz <idan.horowitz@serenityos.org> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include <LibJS/Runtime/WeakSet.h> + +namespace JS { + +WeakSet* WeakSet::create(GlobalObject& global_object) +{ + return global_object.heap().allocate<WeakSet>(global_object, *global_object.weak_set_prototype()); +} + +WeakSet::WeakSet(Object& prototype) + : Object(prototype) +{ +} + +WeakSet::~WeakSet() +{ +} + +} diff --git a/Userland/Libraries/LibJS/Runtime/WeakSet.h b/Userland/Libraries/LibJS/Runtime/WeakSet.h new file mode 100644 index 0000000000..f8c06ad017 --- /dev/null +++ b/Userland/Libraries/LibJS/Runtime/WeakSet.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2021, Idan Horowitz <idan.horowitz@serenityos.org> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include <AK/HashTable.h> +#include <LibJS/Runtime/GlobalObject.h> +#include <LibJS/Runtime/Object.h> + +namespace JS { + +class WeakSet : public Object { + JS_OBJECT(WeakSet, Object); + +public: + static WeakSet* create(GlobalObject&); + + explicit WeakSet(Object& prototype); + virtual ~WeakSet() override; + + HashTable<Object*> const& values() const { return m_values; }; + HashTable<Object*>& values() { return m_values; }; + +private: + HashTable<Object*> m_values; +}; + +} diff --git a/Userland/Libraries/LibJS/Runtime/WeakSetConstructor.cpp b/Userland/Libraries/LibJS/Runtime/WeakSetConstructor.cpp new file mode 100644 index 0000000000..e42bee40ab --- /dev/null +++ b/Userland/Libraries/LibJS/Runtime/WeakSetConstructor.cpp @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2021, Idan Horowitz <idan.horowitz@serenityos.org> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include <LibJS/Runtime/Error.h> +#include <LibJS/Runtime/GlobalObject.h> +#include <LibJS/Runtime/IteratorOperations.h> +#include <LibJS/Runtime/WeakSet.h> +#include <LibJS/Runtime/WeakSetConstructor.h> + +namespace JS { + +WeakSetConstructor::WeakSetConstructor(GlobalObject& global_object) + : NativeFunction(vm().names.WeakSet, *global_object.function_prototype()) +{ +} + +void WeakSetConstructor::initialize(GlobalObject& global_object) +{ + auto& vm = this->vm(); + NativeFunction::initialize(global_object); + define_property(vm.names.prototype, global_object.weak_set_prototype(), 0); + define_property(vm.names.length, Value(0), Attribute::Configurable); +} + +WeakSetConstructor::~WeakSetConstructor() +{ +} + +Value WeakSetConstructor::call() +{ + auto& vm = this->vm(); + vm.throw_exception<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, vm.names.WeakSet); + return {}; +} + +Value WeakSetConstructor::construct(Function&) +{ + auto& vm = this->vm(); + if (vm.argument(0).is_nullish()) + return WeakSet::create(global_object()); + + auto* weak_set = WeakSet::create(global_object()); + auto adder = weak_set->get(vm.names.add); + if (vm.exception()) + return {}; + if (!adder.is_function()) { + vm.throw_exception<TypeError>(global_object(), ErrorType::NotAFunction, "'add' property of WeakSet"); + return {}; + } + get_iterator_values(global_object(), vm.argument(0), [&](Value iterator_value) { + if (vm.exception()) + return IterationDecision::Break; + (void)vm.call(adder.as_function(), Value(weak_set), iterator_value); + return vm.exception() ? IterationDecision::Break : IterationDecision::Continue; + }); + if (vm.exception()) + return {}; + return weak_set; +} + +} diff --git a/Userland/Libraries/LibJS/Runtime/WeakSetConstructor.h b/Userland/Libraries/LibJS/Runtime/WeakSetConstructor.h new file mode 100644 index 0000000000..0e3c5838ab --- /dev/null +++ b/Userland/Libraries/LibJS/Runtime/WeakSetConstructor.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2021, Idan Horowitz <idan.horowitz@serenityos.org> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include <LibJS/Runtime/NativeFunction.h> + +namespace JS { + +class WeakSetConstructor final : public NativeFunction { + JS_OBJECT(WeakSetConstructor, NativeFunction); + +public: + explicit WeakSetConstructor(GlobalObject&); + virtual void initialize(GlobalObject&) override; + virtual ~WeakSetConstructor() override; + + virtual Value call() override; + virtual Value construct(Function&) override; + +private: + virtual bool has_constructor() const override { return true; } +}; + +} diff --git a/Userland/Libraries/LibJS/Runtime/WeakSetPrototype.cpp b/Userland/Libraries/LibJS/Runtime/WeakSetPrototype.cpp new file mode 100644 index 0000000000..8058621a4d --- /dev/null +++ b/Userland/Libraries/LibJS/Runtime/WeakSetPrototype.cpp @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2021, Idan Horowitz <idan.horowitz@serenityos.org> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include <AK/HashTable.h> +#include <LibJS/Runtime/WeakSetPrototype.h> + +namespace JS { + +WeakSetPrototype::WeakSetPrototype(GlobalObject& global_object) + : Object(*global_object.object_prototype()) +{ +} + +void WeakSetPrototype::initialize(GlobalObject& global_object) +{ + auto& vm = this->vm(); + Object::initialize(global_object); + + define_property(vm.well_known_symbol_to_string_tag(), js_string(global_object.heap(), vm.names.WeakSet), Attribute::Configurable); +} + +WeakSetPrototype::~WeakSetPrototype() +{ +} + +WeakSet* WeakSetPrototype::typed_this(VM& vm, GlobalObject& global_object) +{ + auto* this_object = vm.this_value(global_object).to_object(global_object); + if (!this_object) + return {}; + if (!is<WeakSet>(this_object)) { + vm.throw_exception<TypeError>(global_object, ErrorType::NotA, "WeakSet"); + return nullptr; + } + return static_cast<WeakSet*>(this_object); +} + +} diff --git a/Userland/Libraries/LibJS/Runtime/WeakSetPrototype.h b/Userland/Libraries/LibJS/Runtime/WeakSetPrototype.h new file mode 100644 index 0000000000..31a6a2cf96 --- /dev/null +++ b/Userland/Libraries/LibJS/Runtime/WeakSetPrototype.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2021, Idan Horowitz <idan.horowitz@serenityos.org> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include <LibJS/Runtime/WeakSet.h> + +namespace JS { + +class WeakSetPrototype final : public Object { + JS_OBJECT(WeakSetPrototype, Object); + +public: + WeakSetPrototype(GlobalObject&); + virtual void initialize(GlobalObject&) override; + virtual ~WeakSetPrototype() override; + +private: + static WeakSet* typed_this(VM&, GlobalObject&); +} diff --git a/Userland/Libraries/LibJS/Tests/builtins/WeakSet/WeakSet.js b/Userland/Libraries/LibJS/Tests/builtins/WeakSet/WeakSet.js new file mode 100644 index 0000000000..61400a048d --- /dev/null +++ b/Userland/Libraries/LibJS/Tests/builtins/WeakSet/WeakSet.js @@ -0,0 +1,30 @@ +test("constructor properties", () => { + expect(WeakSet).toHaveLength(0); + expect(WeakSet.name).toBe("WeakSet"); +}); + +describe("errors", () => { + test("invalid array iterators", () => { + [-100, Infinity, NaN, {}, 152n].forEach(value => { + expect(() => { + new WeakSet(value); + }).toThrowWithMessage(TypeError, "is not iterable"); + }); + }); + test("called without new", () => { + expect(() => { + WeakSet(); + }).toThrowWithMessage(TypeError, "WeakSet constructor must be called with 'new'"); + }); +}); + +describe("normal behavior", () => { + test("typeof", () => { + expect(typeof new WeakSet()).toBe("object"); + }); + + test("constructor with single array argument", () => { + var a = new WeakSet([{ a: 1 }, { a: 2 }, { a: 3 }]); + expect(a instanceof WeakSet).toBeTrue(); + }); +}); |