mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 07:17:35 +00:00
LibJS: Add the WeakSet built-in object
This commit is contained in:
parent
ee9fe288b2
commit
8b6beac5ce
10 changed files with 250 additions and 1 deletions
|
@ -97,6 +97,9 @@ set(SOURCES
|
||||||
Runtime/TypedArrayPrototype.cpp
|
Runtime/TypedArrayPrototype.cpp
|
||||||
Runtime/VM.cpp
|
Runtime/VM.cpp
|
||||||
Runtime/Value.cpp
|
Runtime/Value.cpp
|
||||||
|
Runtime/WeakSet.cpp
|
||||||
|
Runtime/WeakSetConstructor.cpp
|
||||||
|
Runtime/WeakSetPrototype.cpp
|
||||||
Runtime/WithScope.cpp
|
Runtime/WithScope.cpp
|
||||||
SyntaxHighlighter.cpp
|
SyntaxHighlighter.cpp
|
||||||
Token.cpp
|
Token.cpp
|
||||||
|
|
|
@ -39,7 +39,8 @@
|
||||||
__JS_ENUMERATE(RegExpObject, regexp, RegExpPrototype, RegExpConstructor, void) \
|
__JS_ENUMERATE(RegExpObject, regexp, RegExpPrototype, RegExpConstructor, void) \
|
||||||
__JS_ENUMERATE(Set, set, SetPrototype, SetConstructor, void) \
|
__JS_ENUMERATE(Set, set, SetPrototype, SetConstructor, void) \
|
||||||
__JS_ENUMERATE(StringObject, string, StringPrototype, StringConstructor, 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 \
|
#define JS_ENUMERATE_NATIVE_OBJECTS \
|
||||||
JS_ENUMERATE_NATIVE_OBJECTS_EXCLUDING_TEMPLATES \
|
JS_ENUMERATE_NATIVE_OBJECTS_EXCLUDING_TEMPLATES \
|
||||||
|
|
|
@ -60,6 +60,8 @@
|
||||||
#include <LibJS/Runtime/TypedArrayConstructor.h>
|
#include <LibJS/Runtime/TypedArrayConstructor.h>
|
||||||
#include <LibJS/Runtime/TypedArrayPrototype.h>
|
#include <LibJS/Runtime/TypedArrayPrototype.h>
|
||||||
#include <LibJS/Runtime/Value.h>
|
#include <LibJS/Runtime/Value.h>
|
||||||
|
#include <LibJS/Runtime/WeakSetConstructor.h>
|
||||||
|
#include <LibJS/Runtime/WeakSetPrototype.h>
|
||||||
|
|
||||||
namespace JS {
|
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.Set, m_set_constructor, m_set_prototype);
|
||||||
add_constructor(vm.names.String, m_string_constructor, m_string_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.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);
|
initialize_constructor(vm.names.TypedArray, m_typed_array_constructor, m_typed_array_prototype);
|
||||||
|
|
||||||
|
|
25
Userland/Libraries/LibJS/Runtime/WeakSet.cpp
Normal file
25
Userland/Libraries/LibJS/Runtime/WeakSet.cpp
Normal file
|
@ -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()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
31
Userland/Libraries/LibJS/Runtime/WeakSet.h
Normal file
31
Userland/Libraries/LibJS/Runtime/WeakSet.h
Normal file
|
@ -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;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
64
Userland/Libraries/LibJS/Runtime/WeakSetConstructor.cpp
Normal file
64
Userland/Libraries/LibJS/Runtime/WeakSetConstructor.cpp
Normal file
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
28
Userland/Libraries/LibJS/Runtime/WeakSetConstructor.h
Normal file
28
Userland/Libraries/LibJS/Runtime/WeakSetConstructor.h
Normal file
|
@ -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; }
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
41
Userland/Libraries/LibJS/Runtime/WeakSetPrototype.cpp
Normal file
41
Userland/Libraries/LibJS/Runtime/WeakSetPrototype.cpp
Normal file
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
23
Userland/Libraries/LibJS/Runtime/WeakSetPrototype.h
Normal file
23
Userland/Libraries/LibJS/Runtime/WeakSetPrototype.h
Normal file
|
@ -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&);
|
||||||
|
}
|
30
Userland/Libraries/LibJS/Tests/builtins/WeakSet/WeakSet.js
Normal file
30
Userland/Libraries/LibJS/Tests/builtins/WeakSet/WeakSet.js
Normal file
|
@ -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();
|
||||||
|
});
|
||||||
|
});
|
Loading…
Add table
Add a link
Reference in a new issue