diff options
author | Idan Horowitz <idan.horowitz@gmail.com> | 2021-06-12 05:28:30 +0300 |
---|---|---|
committer | Linus Groh <mail@linusgroh.de> | 2021-06-12 10:44:28 +0100 |
commit | 39554f3787eae7e52094cab16a966e62f00dea22 (patch) | |
tree | e0b331375290b09230da1bf69e0fab913070956d /Userland/Libraries/LibJS/Runtime | |
parent | 1a8ee5d8d74da5a261c5347662dc543cb283ad5a (diff) | |
download | serenity-39554f3787eae7e52094cab16a966e62f00dea22.zip |
LibJS: Add the WeakMap built-in object
Diffstat (limited to 'Userland/Libraries/LibJS/Runtime')
-rw-r--r-- | Userland/Libraries/LibJS/Runtime/GlobalObject.cpp | 3 | ||||
-rw-r--r-- | Userland/Libraries/LibJS/Runtime/WeakMap.cpp | 32 | ||||
-rw-r--r-- | Userland/Libraries/LibJS/Runtime/WeakMap.h | 36 | ||||
-rw-r--r-- | Userland/Libraries/LibJS/Runtime/WeakMapConstructor.cpp | 74 | ||||
-rw-r--r-- | Userland/Libraries/LibJS/Runtime/WeakMapConstructor.h | 28 | ||||
-rw-r--r-- | Userland/Libraries/LibJS/Runtime/WeakMapPrototype.cpp | 41 | ||||
-rw-r--r-- | Userland/Libraries/LibJS/Runtime/WeakMapPrototype.h | 25 |
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&); +}; + +} |