summaryrefslogtreecommitdiff
path: root/Userland/Libraries
diff options
context:
space:
mode:
authorIdan Horowitz <idan.horowitz@gmail.com>2021-06-09 19:23:04 +0300
committerLinus Groh <mail@linusgroh.de>2021-06-09 21:52:25 +0100
commit8b6beac5ce5e1ca5f4e0befa3a48d6d6923f648e (patch)
treeb08fa9d9a02be2d1ba27e511927ee1ade10cfd69 /Userland/Libraries
parentee9fe288b2d9182e83185b07a925df095289ddb2 (diff)
downloadserenity-8b6beac5ce5e1ca5f4e0befa3a48d6d6923f648e.zip
LibJS: Add the WeakSet built-in object
Diffstat (limited to 'Userland/Libraries')
-rw-r--r--Userland/Libraries/LibJS/CMakeLists.txt3
-rw-r--r--Userland/Libraries/LibJS/Forward.h3
-rw-r--r--Userland/Libraries/LibJS/Runtime/GlobalObject.cpp3
-rw-r--r--Userland/Libraries/LibJS/Runtime/WeakSet.cpp25
-rw-r--r--Userland/Libraries/LibJS/Runtime/WeakSet.h31
-rw-r--r--Userland/Libraries/LibJS/Runtime/WeakSetConstructor.cpp64
-rw-r--r--Userland/Libraries/LibJS/Runtime/WeakSetConstructor.h28
-rw-r--r--Userland/Libraries/LibJS/Runtime/WeakSetPrototype.cpp41
-rw-r--r--Userland/Libraries/LibJS/Runtime/WeakSetPrototype.h23
-rw-r--r--Userland/Libraries/LibJS/Tests/builtins/WeakSet/WeakSet.js30
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();
+ });
+});