summaryrefslogtreecommitdiff
path: root/Userland/Libraries/LibJS/Runtime
diff options
context:
space:
mode:
authorIdan Horowitz <idan.horowitz@gmail.com>2021-06-12 05:28:30 +0300
committerLinus Groh <mail@linusgroh.de>2021-06-12 10:44:28 +0100
commit39554f3787eae7e52094cab16a966e62f00dea22 (patch)
treee0b331375290b09230da1bf69e0fab913070956d /Userland/Libraries/LibJS/Runtime
parent1a8ee5d8d74da5a261c5347662dc543cb283ad5a (diff)
downloadserenity-39554f3787eae7e52094cab16a966e62f00dea22.zip
LibJS: Add the WeakMap built-in object
Diffstat (limited to 'Userland/Libraries/LibJS/Runtime')
-rw-r--r--Userland/Libraries/LibJS/Runtime/GlobalObject.cpp3
-rw-r--r--Userland/Libraries/LibJS/Runtime/WeakMap.cpp32
-rw-r--r--Userland/Libraries/LibJS/Runtime/WeakMap.h36
-rw-r--r--Userland/Libraries/LibJS/Runtime/WeakMapConstructor.cpp74
-rw-r--r--Userland/Libraries/LibJS/Runtime/WeakMapConstructor.h28
-rw-r--r--Userland/Libraries/LibJS/Runtime/WeakMapPrototype.cpp41
-rw-r--r--Userland/Libraries/LibJS/Runtime/WeakMapPrototype.h25
7 files changed, 239 insertions, 0 deletions
diff --git a/Userland/Libraries/LibJS/Runtime/GlobalObject.cpp b/Userland/Libraries/LibJS/Runtime/GlobalObject.cpp
index 6a7bd4ff7a..246cbc25ec 100644
--- a/Userland/Libraries/LibJS/Runtime/GlobalObject.cpp
+++ b/Userland/Libraries/LibJS/Runtime/GlobalObject.cpp
@@ -62,6 +62,8 @@
#include <LibJS/Runtime/TypedArrayConstructor.h>
#include <LibJS/Runtime/TypedArrayPrototype.h>
#include <LibJS/Runtime/Value.h>
+#include <LibJS/Runtime/WeakMapConstructor.h>
+#include <LibJS/Runtime/WeakMapPrototype.h>
#include <LibJS/Runtime/WeakSetConstructor.h>
#include <LibJS/Runtime/WeakSetPrototype.h>
@@ -154,6 +156,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.WeakMap, m_weak_map_constructor, m_weak_map_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/WeakMap.cpp b/Userland/Libraries/LibJS/Runtime/WeakMap.cpp
new file mode 100644
index 0000000000..00cff84e51
--- /dev/null
+++ b/Userland/Libraries/LibJS/Runtime/WeakMap.cpp
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2021, Idan Horowitz <idan.horowitz@serenityos.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <LibJS/Runtime/WeakMap.h>
+
+namespace JS {
+
+WeakMap* WeakMap::create(GlobalObject& global_object)
+{
+ return global_object.heap().allocate<WeakMap>(global_object, *global_object.weak_map_prototype());
+}
+
+WeakMap::WeakMap(Object& prototype)
+ : Object(prototype)
+ , WeakContainer(heap())
+{
+}
+
+WeakMap::~WeakMap()
+{
+}
+
+void WeakMap::remove_sweeped_cells(Badge<Heap>, Vector<Cell*>& cells)
+{
+ for (auto* cell : cells)
+ m_values.remove(cell);
+}
+
+}
diff --git a/Userland/Libraries/LibJS/Runtime/WeakMap.h b/Userland/Libraries/LibJS/Runtime/WeakMap.h
new file mode 100644
index 0000000000..e067327978
--- /dev/null
+++ b/Userland/Libraries/LibJS/Runtime/WeakMap.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2021, Idan Horowitz <idan.horowitz@serenityos.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#pragma once
+
+#include <AK/HashMap.h>
+#include <LibJS/Runtime/GlobalObject.h>
+#include <LibJS/Runtime/Object.h>
+#include <LibJS/Runtime/WeakContainer.h>
+
+namespace JS {
+
+class WeakMap final
+ : public Object
+ , public WeakContainer {
+ JS_OBJECT(WeakMap, Object);
+
+public:
+ static WeakMap* create(GlobalObject&);
+
+ explicit WeakMap(Object& prototype);
+ virtual ~WeakMap() override;
+
+ HashMap<Cell*, Value> const& values() const { return m_values; };
+ HashMap<Cell*, Value>& values() { return m_values; };
+
+ virtual void remove_sweeped_cells(Badge<Heap>, Vector<Cell*>&) override;
+
+private:
+ HashMap<Cell*, Value> m_values; // This stores Cell pointers instead of Object pointers to aide with sweeping
+};
+
+}
diff --git a/Userland/Libraries/LibJS/Runtime/WeakMapConstructor.cpp b/Userland/Libraries/LibJS/Runtime/WeakMapConstructor.cpp
new file mode 100644
index 0000000000..5ef3121fb7
--- /dev/null
+++ b/Userland/Libraries/LibJS/Runtime/WeakMapConstructor.cpp
@@ -0,0 +1,74 @@
+/*
+ * 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/WeakMap.h>
+#include <LibJS/Runtime/WeakMapConstructor.h>
+
+namespace JS {
+
+WeakMapConstructor::WeakMapConstructor(GlobalObject& global_object)
+ : NativeFunction(vm().names.WeakMap, *global_object.function_prototype())
+{
+}
+
+void WeakMapConstructor::initialize(GlobalObject& global_object)
+{
+ auto& vm = this->vm();
+ NativeFunction::initialize(global_object);
+ define_property(vm.names.prototype, global_object.weak_map_prototype(), 0);
+ define_property(vm.names.length, Value(0), Attribute::Configurable);
+}
+
+WeakMapConstructor::~WeakMapConstructor()
+{
+}
+
+Value WeakMapConstructor::call()
+{
+ auto& vm = this->vm();
+ vm.throw_exception<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, vm.names.WeakMap);
+ return {};
+}
+
+Value WeakMapConstructor::construct(Function&)
+{
+ auto& vm = this->vm();
+ if (vm.argument(0).is_nullish())
+ return WeakMap::create(global_object());
+
+ auto* weak_map = WeakMap::create(global_object());
+ auto adder = weak_map->get(vm.names.set);
+ if (vm.exception())
+ return {};
+ if (!adder.is_function()) {
+ vm.throw_exception<TypeError>(global_object(), ErrorType::NotAFunction, "'set' property of WeakMap");
+ return {};
+ }
+ get_iterator_values(global_object(), vm.argument(0), [&](Value iterator_value) {
+ if (vm.exception())
+ return IterationDecision::Break;
+ if (!iterator_value.is_object()) {
+ vm.throw_exception<TypeError>(global_object(), ErrorType::NotAnObject, String::formatted("Iterator value {}", iterator_value.to_string_without_side_effects()));
+ return IterationDecision::Break;
+ }
+ auto key = iterator_value.as_object().get(0);
+ if (vm.exception())
+ return IterationDecision::Break;
+ auto value = iterator_value.as_object().get(1);
+ if (vm.exception())
+ return IterationDecision::Break;
+ (void)vm.call(adder.as_function(), Value(weak_map), key, value);
+ return vm.exception() ? IterationDecision::Break : IterationDecision::Continue;
+ });
+ if (vm.exception())
+ return {};
+ return weak_map;
+}
+
+}
diff --git a/Userland/Libraries/LibJS/Runtime/WeakMapConstructor.h b/Userland/Libraries/LibJS/Runtime/WeakMapConstructor.h
new file mode 100644
index 0000000000..42d47eadad
--- /dev/null
+++ b/Userland/Libraries/LibJS/Runtime/WeakMapConstructor.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 WeakMapConstructor final : public NativeFunction {
+ JS_OBJECT(WeakMapConstructor, NativeFunction);
+
+public:
+ explicit WeakMapConstructor(GlobalObject&);
+ virtual void initialize(GlobalObject&) override;
+ virtual ~WeakMapConstructor() 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/WeakMapPrototype.cpp b/Userland/Libraries/LibJS/Runtime/WeakMapPrototype.cpp
new file mode 100644
index 0000000000..892b1c14b6
--- /dev/null
+++ b/Userland/Libraries/LibJS/Runtime/WeakMapPrototype.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/WeakMapPrototype.h>
+
+namespace JS {
+
+WeakMapPrototype::WeakMapPrototype(GlobalObject& global_object)
+ : Object(*global_object.object_prototype())
+{
+}
+
+void WeakMapPrototype::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.WeakMap), Attribute::Configurable);
+}
+
+WeakMapPrototype::~WeakMapPrototype()
+{
+}
+
+WeakMap* WeakMapPrototype::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<WeakMap>(this_object)) {
+ vm.throw_exception<TypeError>(global_object, ErrorType::NotA, "WeakMap");
+ return nullptr;
+ }
+ return static_cast<WeakMap*>(this_object);
+}
+
+}
diff --git a/Userland/Libraries/LibJS/Runtime/WeakMapPrototype.h b/Userland/Libraries/LibJS/Runtime/WeakMapPrototype.h
new file mode 100644
index 0000000000..267ddeb689
--- /dev/null
+++ b/Userland/Libraries/LibJS/Runtime/WeakMapPrototype.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2021, Idan Horowitz <idan.horowitz@serenityos.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#pragma once
+
+#include <LibJS/Runtime/WeakMap.h>
+
+namespace JS {
+
+class WeakMapPrototype final : public Object {
+ JS_OBJECT(WeakMapPrototype, Object);
+
+public:
+ WeakMapPrototype(GlobalObject&);
+ virtual void initialize(GlobalObject&) override;
+ virtual ~WeakMapPrototype() override;
+
+private:
+ static WeakMap* typed_this(VM&, GlobalObject&);
+};
+
+}