mirror of
https://github.com/RGBCube/serenity
synced 2025-05-15 06:44:58 +00:00
LibJS: Add the Set built-in object
This commit is contained in:
parent
b17a282b4b
commit
670be04c81
15 changed files with 359 additions and 30 deletions
|
@ -1,31 +1,31 @@
|
||||||
set(SOURCES
|
set(SOURCES
|
||||||
AST.cpp
|
AST.cpp
|
||||||
Bytecode/ASTCodegen.cpp
|
Bytecode/ASTCodegen.cpp
|
||||||
Bytecode/BasicBlock.cpp
|
Bytecode/BasicBlock.cpp
|
||||||
Bytecode/Generator.cpp
|
Bytecode/Generator.cpp
|
||||||
Bytecode/Instruction.cpp
|
Bytecode/Instruction.cpp
|
||||||
Bytecode/Interpreter.cpp
|
Bytecode/Interpreter.cpp
|
||||||
Bytecode/Op.cpp
|
Bytecode/Op.cpp
|
||||||
Console.cpp
|
Console.cpp
|
||||||
Heap/CellAllocator.cpp
|
Heap/CellAllocator.cpp
|
||||||
Heap/BlockAllocator.cpp
|
Heap/BlockAllocator.cpp
|
||||||
Heap/Handle.cpp
|
Heap/Handle.cpp
|
||||||
Heap/HeapBlock.cpp
|
Heap/HeapBlock.cpp
|
||||||
Heap/Heap.cpp
|
Heap/Heap.cpp
|
||||||
Interpreter.cpp
|
Interpreter.cpp
|
||||||
Lexer.cpp
|
Lexer.cpp
|
||||||
MarkupGenerator.cpp
|
MarkupGenerator.cpp
|
||||||
Parser.cpp
|
Parser.cpp
|
||||||
Runtime/Array.cpp
|
Runtime/Array.cpp
|
||||||
Runtime/ArrayBuffer.cpp
|
Runtime/ArrayBuffer.cpp
|
||||||
Runtime/ArrayBufferConstructor.cpp
|
Runtime/ArrayBufferConstructor.cpp
|
||||||
Runtime/ArrayBufferPrototype.cpp
|
Runtime/ArrayBufferPrototype.cpp
|
||||||
Runtime/ArrayConstructor.cpp
|
Runtime/ArrayConstructor.cpp
|
||||||
Runtime/ArrayIterator.cpp
|
Runtime/ArrayIterator.cpp
|
||||||
Runtime/ArrayIteratorPrototype.cpp
|
Runtime/ArrayIteratorPrototype.cpp
|
||||||
Runtime/ArrayPrototype.cpp
|
Runtime/ArrayPrototype.cpp
|
||||||
Runtime/BigInt.cpp
|
Runtime/BigInt.cpp
|
||||||
Runtime/BigIntConstructor.cpp
|
Runtime/BigIntConstructor.cpp
|
||||||
Runtime/BigIntObject.cpp
|
Runtime/BigIntObject.cpp
|
||||||
Runtime/BigIntPrototype.cpp
|
Runtime/BigIntPrototype.cpp
|
||||||
Runtime/BooleanConstructor.cpp
|
Runtime/BooleanConstructor.cpp
|
||||||
|
@ -76,6 +76,9 @@ set(SOURCES
|
||||||
Runtime/RegExpPrototype.cpp
|
Runtime/RegExpPrototype.cpp
|
||||||
Runtime/ScopeObject.cpp
|
Runtime/ScopeObject.cpp
|
||||||
Runtime/ScriptFunction.cpp
|
Runtime/ScriptFunction.cpp
|
||||||
|
Runtime/Set.cpp
|
||||||
|
Runtime/SetConstructor.cpp
|
||||||
|
Runtime/SetPrototype.cpp
|
||||||
Runtime/Shape.cpp
|
Runtime/Shape.cpp
|
||||||
Runtime/StringConstructor.cpp
|
Runtime/StringConstructor.cpp
|
||||||
Runtime/StringIterator.cpp
|
Runtime/StringIterator.cpp
|
||||||
|
|
|
@ -37,6 +37,7 @@
|
||||||
__JS_ENUMERATE(Object, object, ObjectPrototype, ObjectConstructor, void) \
|
__JS_ENUMERATE(Object, object, ObjectPrototype, ObjectConstructor, void) \
|
||||||
__JS_ENUMERATE(Promise, promise, PromisePrototype, PromiseConstructor, void) \
|
__JS_ENUMERATE(Promise, promise, PromisePrototype, PromiseConstructor, void) \
|
||||||
__JS_ENUMERATE(RegExpObject, regexp, RegExpPrototype, RegExpConstructor, void) \
|
__JS_ENUMERATE(RegExpObject, regexp, RegExpPrototype, RegExpConstructor, 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)
|
||||||
|
|
||||||
|
|
|
@ -239,6 +239,7 @@ namespace JS {
|
||||||
P(sign) \
|
P(sign) \
|
||||||
P(sin) \
|
P(sin) \
|
||||||
P(sinh) \
|
P(sinh) \
|
||||||
|
P(size) \
|
||||||
P(slice) \
|
P(slice) \
|
||||||
P(small) \
|
P(small) \
|
||||||
P(some) \
|
P(some) \
|
||||||
|
|
|
@ -47,6 +47,8 @@
|
||||||
#include <LibJS/Runtime/ReflectObject.h>
|
#include <LibJS/Runtime/ReflectObject.h>
|
||||||
#include <LibJS/Runtime/RegExpConstructor.h>
|
#include <LibJS/Runtime/RegExpConstructor.h>
|
||||||
#include <LibJS/Runtime/RegExpPrototype.h>
|
#include <LibJS/Runtime/RegExpPrototype.h>
|
||||||
|
#include <LibJS/Runtime/SetConstructor.h>
|
||||||
|
#include <LibJS/Runtime/SetPrototype.h>
|
||||||
#include <LibJS/Runtime/Shape.h>
|
#include <LibJS/Runtime/Shape.h>
|
||||||
#include <LibJS/Runtime/StringConstructor.h>
|
#include <LibJS/Runtime/StringConstructor.h>
|
||||||
#include <LibJS/Runtime/StringIteratorPrototype.h>
|
#include <LibJS/Runtime/StringIteratorPrototype.h>
|
||||||
|
@ -87,7 +89,7 @@ void GlobalObject::initialize_global_object()
|
||||||
static_cast<FunctionPrototype*>(m_function_prototype)->initialize(*this);
|
static_cast<FunctionPrototype*>(m_function_prototype)->initialize(*this);
|
||||||
static_cast<ObjectPrototype*>(m_object_prototype)->initialize(*this);
|
static_cast<ObjectPrototype*>(m_object_prototype)->initialize(*this);
|
||||||
|
|
||||||
set_prototype(m_object_prototype);
|
Object::set_prototype(m_object_prototype);
|
||||||
|
|
||||||
#define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName, ArrayType) \
|
#define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName, ArrayType) \
|
||||||
if (!m_##snake_name##_prototype) \
|
if (!m_##snake_name##_prototype) \
|
||||||
|
@ -137,6 +139,7 @@ void GlobalObject::initialize_global_object()
|
||||||
add_constructor(vm.names.Promise, m_promise_constructor, m_promise_prototype);
|
add_constructor(vm.names.Promise, m_promise_constructor, m_promise_prototype);
|
||||||
add_constructor(vm.names.Proxy, m_proxy_constructor, nullptr);
|
add_constructor(vm.names.Proxy, m_proxy_constructor, nullptr);
|
||||||
add_constructor(vm.names.RegExp, m_regexp_constructor, m_regexp_prototype);
|
add_constructor(vm.names.RegExp, m_regexp_constructor, m_regexp_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);
|
||||||
|
|
||||||
|
|
37
Userland/Libraries/LibJS/Runtime/Set.cpp
Normal file
37
Userland/Libraries/LibJS/Runtime/Set.cpp
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021, Idan Horowitz <idan.horowitz@serenityos.org>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <LibJS/Runtime/Set.h>
|
||||||
|
|
||||||
|
namespace JS {
|
||||||
|
|
||||||
|
Set* Set::create(GlobalObject& global_object)
|
||||||
|
{
|
||||||
|
return global_object.heap().allocate<Set>(global_object, *global_object.set_prototype());
|
||||||
|
}
|
||||||
|
|
||||||
|
Set::Set(Object& prototype)
|
||||||
|
: Object(prototype)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Set::~Set()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Set* Set::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<Set>(this_object)) {
|
||||||
|
vm.throw_exception<TypeError>(global_object, ErrorType::NotA, "Set");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return static_cast<Set*>(this_object);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
53
Userland/Libraries/LibJS/Runtime/Set.h
Normal file
53
Userland/Libraries/LibJS/Runtime/Set.h
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021, Idan Horowitz <idan.horowitz@serenityos.org>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <AK/HashTable.h>
|
||||||
|
#include <LibJS/Runtime/BigInt.h>
|
||||||
|
#include <LibJS/Runtime/GlobalObject.h>
|
||||||
|
#include <LibJS/Runtime/Object.h>
|
||||||
|
#include <LibJS/Runtime/Value.h>
|
||||||
|
|
||||||
|
namespace JS {
|
||||||
|
|
||||||
|
struct ValueTraits : public Traits<Value> {
|
||||||
|
static unsigned hash(Value value)
|
||||||
|
{
|
||||||
|
VERIFY(!value.is_empty());
|
||||||
|
if (value.is_string())
|
||||||
|
return value.as_string().string().hash();
|
||||||
|
|
||||||
|
if (value.is_bigint())
|
||||||
|
return value.as_bigint().big_integer().hash();
|
||||||
|
|
||||||
|
return u64_hash(value.encoded()); // FIXME: Is this the best way to hash pointers, doubles & ints?
|
||||||
|
}
|
||||||
|
static bool equals(const Value a, const Value b)
|
||||||
|
{
|
||||||
|
return same_value_zero(a, b);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class Set : public Object {
|
||||||
|
JS_OBJECT(Set, Object);
|
||||||
|
|
||||||
|
public:
|
||||||
|
static Set* create(GlobalObject&);
|
||||||
|
|
||||||
|
explicit Set(Object& prototype);
|
||||||
|
virtual ~Set() override;
|
||||||
|
|
||||||
|
static Set* typed_this(VM&, GlobalObject&);
|
||||||
|
|
||||||
|
HashTable<Value, ValueTraits> const& values() const { return m_values; };
|
||||||
|
HashTable<Value, ValueTraits>& values() { return m_values; };
|
||||||
|
|
||||||
|
private:
|
||||||
|
HashTable<Value, ValueTraits> m_values; // FIXME: Replace with a HashTable that maintains a linked list of insertion order for correct iteration order
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
71
Userland/Libraries/LibJS/Runtime/SetConstructor.cpp
Normal file
71
Userland/Libraries/LibJS/Runtime/SetConstructor.cpp
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
/*
|
||||||
|
* 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/Set.h>
|
||||||
|
#include <LibJS/Runtime/SetConstructor.h>
|
||||||
|
|
||||||
|
namespace JS {
|
||||||
|
|
||||||
|
SetConstructor::SetConstructor(GlobalObject& global_object)
|
||||||
|
: NativeFunction(vm().names.Set, *global_object.function_prototype())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetConstructor::initialize(GlobalObject& global_object)
|
||||||
|
{
|
||||||
|
auto& vm = this->vm();
|
||||||
|
NativeFunction::initialize(global_object);
|
||||||
|
define_property(vm.names.prototype, global_object.set_prototype(), 0);
|
||||||
|
define_property(vm.names.length, Value(0), Attribute::Configurable);
|
||||||
|
|
||||||
|
define_native_property(vm.well_known_symbol_species(), symbol_species_getter, {}, Attribute::Configurable);
|
||||||
|
}
|
||||||
|
|
||||||
|
SetConstructor::~SetConstructor()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Value SetConstructor::call()
|
||||||
|
{
|
||||||
|
auto& vm = this->vm();
|
||||||
|
vm.throw_exception<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, vm.names.Set);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
Value SetConstructor::construct(Function&)
|
||||||
|
{
|
||||||
|
auto& vm = this->vm();
|
||||||
|
if (vm.argument(0).is_nullish())
|
||||||
|
return Set::create(global_object());
|
||||||
|
|
||||||
|
auto* set = Set::create(global_object());
|
||||||
|
auto adder = set->get(vm.names.add);
|
||||||
|
if (vm.exception())
|
||||||
|
return {};
|
||||||
|
if (!adder.is_function()) {
|
||||||
|
vm.throw_exception<TypeError>(global_object(), ErrorType::NotAFunction, "'add' property of Set");
|
||||||
|
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(set), iterator_value);
|
||||||
|
return vm.exception() ? IterationDecision::Break : IterationDecision::Continue;
|
||||||
|
});
|
||||||
|
if (vm.exception())
|
||||||
|
return {};
|
||||||
|
return set;
|
||||||
|
}
|
||||||
|
|
||||||
|
JS_DEFINE_NATIVE_GETTER(SetConstructor::symbol_species_getter)
|
||||||
|
{
|
||||||
|
return vm.this_value(global_object);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
30
Userland/Libraries/LibJS/Runtime/SetConstructor.h
Normal file
30
Userland/Libraries/LibJS/Runtime/SetConstructor.h
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
/*
|
||||||
|
* 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 SetConstructor final : public NativeFunction {
|
||||||
|
JS_OBJECT(SetConstructor, NativeFunction);
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit SetConstructor(GlobalObject&);
|
||||||
|
virtual void initialize(GlobalObject&) override;
|
||||||
|
virtual ~SetConstructor() override;
|
||||||
|
|
||||||
|
virtual Value call() override;
|
||||||
|
virtual Value construct(Function&) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
virtual bool has_constructor() const override { return true; }
|
||||||
|
|
||||||
|
JS_DECLARE_NATIVE_GETTER(symbol_species_getter);
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
40
Userland/Libraries/LibJS/Runtime/SetPrototype.cpp
Normal file
40
Userland/Libraries/LibJS/Runtime/SetPrototype.cpp
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021, Idan Horowitz <idan.horowitz@serenityos.org>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <AK/HashTable.h>
|
||||||
|
#include <LibJS/Runtime/SetPrototype.h>
|
||||||
|
|
||||||
|
namespace JS {
|
||||||
|
|
||||||
|
SetPrototype::SetPrototype(GlobalObject& global_object)
|
||||||
|
: Set(*global_object.object_prototype())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetPrototype::initialize(GlobalObject& global_object)
|
||||||
|
{
|
||||||
|
auto& vm = this->vm();
|
||||||
|
Set::initialize(global_object);
|
||||||
|
u8 attr = Attribute::Writable | Attribute::Configurable;
|
||||||
|
|
||||||
|
define_native_property(vm.names.size, size_getter, {}, attr);
|
||||||
|
|
||||||
|
define_property(vm.well_known_symbol_to_string_tag(), js_string(global_object.heap(), vm.names.Set), Attribute::Configurable);
|
||||||
|
}
|
||||||
|
|
||||||
|
SetPrototype::~SetPrototype()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
JS_DEFINE_NATIVE_GETTER(SetPrototype::size_getter)
|
||||||
|
{
|
||||||
|
auto* set = typed_this(vm, global_object);
|
||||||
|
if (!set)
|
||||||
|
return {};
|
||||||
|
return Value(set->values().size());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
25
Userland/Libraries/LibJS/Runtime/SetPrototype.h
Normal file
25
Userland/Libraries/LibJS/Runtime/SetPrototype.h
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021, Idan Horowitz <idan.horowitz@serenityos.org>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <LibJS/Runtime/Set.h>
|
||||||
|
|
||||||
|
namespace JS {
|
||||||
|
|
||||||
|
class SetPrototype final : public Set {
|
||||||
|
JS_OBJECT(SetPrototype, Set);
|
||||||
|
|
||||||
|
public:
|
||||||
|
SetPrototype(GlobalObject&);
|
||||||
|
virtual void initialize(GlobalObject&) override;
|
||||||
|
virtual ~SetPrototype() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
JS_DECLARE_NATIVE_GETTER(size_getter);
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -253,6 +253,8 @@ public:
|
||||||
i32 as_i32() const;
|
i32 as_i32() const;
|
||||||
u32 as_u32() const;
|
u32 as_u32() const;
|
||||||
|
|
||||||
|
u64 encoded() const { return m_value.encoded; }
|
||||||
|
|
||||||
String to_string(GlobalObject&, bool legacy_null_to_empty_string = false) const;
|
String to_string(GlobalObject&, bool legacy_null_to_empty_string = false) const;
|
||||||
PrimitiveString* to_primitive_string(GlobalObject&);
|
PrimitiveString* to_primitive_string(GlobalObject&);
|
||||||
Value to_primitive(GlobalObject&, PreferredType preferred_type = PreferredType::Default) const;
|
Value to_primitive(GlobalObject&, PreferredType preferred_type = PreferredType::Default) const;
|
||||||
|
@ -301,7 +303,9 @@ private:
|
||||||
Accessor* as_accessor;
|
Accessor* as_accessor;
|
||||||
BigInt* as_bigint;
|
BigInt* as_bigint;
|
||||||
NativeProperty* as_native_property;
|
NativeProperty* as_native_property;
|
||||||
} m_value;
|
|
||||||
|
u64 encoded;
|
||||||
|
} m_value { .encoded = 0 };
|
||||||
};
|
};
|
||||||
|
|
||||||
inline Value js_undefined()
|
inline Value js_undefined()
|
||||||
|
|
31
Userland/Libraries/LibJS/Tests/builtins/Set/Set.js
Normal file
31
Userland/Libraries/LibJS/Tests/builtins/Set/Set.js
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
test("constructor properties", () => {
|
||||||
|
expect(Set).toHaveLength(0);
|
||||||
|
expect(Set.name).toBe("Set");
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("errors", () => {
|
||||||
|
test("invalid array iterators", () => {
|
||||||
|
[-100, Infinity, NaN, {}, 152n].forEach(value => {
|
||||||
|
expect(() => {
|
||||||
|
new Set(value);
|
||||||
|
}).toThrowWithMessage(TypeError, "is not iterable");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
test("called without new", () => {
|
||||||
|
expect(() => {
|
||||||
|
Set();
|
||||||
|
}).toThrowWithMessage(TypeError, "Set constructor must be called with 'new'");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("normal behavior", () => {
|
||||||
|
test("typeof", () => {
|
||||||
|
expect(typeof new Set()).toBe("object");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("constructor with single array argument", () => {
|
||||||
|
var a = new Set([0, 1, 2]);
|
||||||
|
expect(a instanceof Set).toBeTrue();
|
||||||
|
expect(a).toHaveSize(3);
|
||||||
|
});
|
||||||
|
});
|
|
@ -97,6 +97,17 @@ class ExpectationError extends Error {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toHaveSize(size) {
|
||||||
|
this.__expect(
|
||||||
|
typeof this.target.size === "number",
|
||||||
|
() => "toHaveSize: target.size not of type number"
|
||||||
|
);
|
||||||
|
|
||||||
|
this.__doMatcher(() => {
|
||||||
|
this.__expect(Object.is(this.target.size, size));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
toHaveProperty(property, value) {
|
toHaveProperty(property, value) {
|
||||||
this.__doMatcher(() => {
|
this.__doMatcher(() => {
|
||||||
let object = this.target;
|
let object = this.target;
|
||||||
|
|
|
@ -43,7 +43,7 @@ void WindowObject::initialize_global_object()
|
||||||
{
|
{
|
||||||
Base::initialize_global_object();
|
Base::initialize_global_object();
|
||||||
|
|
||||||
set_prototype(&ensure_web_prototype<EventTargetPrototype>("EventTarget"));
|
Object::set_prototype(&ensure_web_prototype<EventTargetPrototype>("EventTarget"));
|
||||||
|
|
||||||
define_property("window", this, JS::Attribute::Enumerable);
|
define_property("window", this, JS::Attribute::Enumerable);
|
||||||
define_property("frames", this, JS::Attribute::Enumerable);
|
define_property("frames", this, JS::Attribute::Enumerable);
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
#include <LibJS/Runtime/ProxyObject.h>
|
#include <LibJS/Runtime/ProxyObject.h>
|
||||||
#include <LibJS/Runtime/RegExpObject.h>
|
#include <LibJS/Runtime/RegExpObject.h>
|
||||||
#include <LibJS/Runtime/ScriptFunction.h>
|
#include <LibJS/Runtime/ScriptFunction.h>
|
||||||
|
#include <LibJS/Runtime/Set.h>
|
||||||
#include <LibJS/Runtime/Shape.h>
|
#include <LibJS/Runtime/Shape.h>
|
||||||
#include <LibJS/Runtime/StringObject.h>
|
#include <LibJS/Runtime/StringObject.h>
|
||||||
#include <LibJS/Runtime/TypedArray.h>
|
#include <LibJS/Runtime/TypedArray.h>
|
||||||
|
@ -277,6 +278,22 @@ static void print_proxy_object(const JS::Object& object, HashTable<JS::Object*>&
|
||||||
print_value(&proxy_object.handler(), seen_objects);
|
print_value(&proxy_object.handler(), seen_objects);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void print_set(const JS::Object& object, HashTable<JS::Object*>& seen_objects)
|
||||||
|
{
|
||||||
|
auto& set = static_cast<const JS::Set&>(object);
|
||||||
|
auto& values = set.values();
|
||||||
|
print_type("Set");
|
||||||
|
out(" {{");
|
||||||
|
bool first = true;
|
||||||
|
for (auto& value : values) {
|
||||||
|
print_separator(first);
|
||||||
|
print_value(value, seen_objects);
|
||||||
|
}
|
||||||
|
if (!first)
|
||||||
|
out(" ");
|
||||||
|
out("}}");
|
||||||
|
}
|
||||||
|
|
||||||
static void print_promise(const JS::Object& object, HashTable<JS::Object*>& seen_objects)
|
static void print_promise(const JS::Object& object, HashTable<JS::Object*>& seen_objects)
|
||||||
{
|
{
|
||||||
auto& promise = static_cast<const JS::Promise&>(object);
|
auto& promise = static_cast<const JS::Promise&>(object);
|
||||||
|
@ -398,6 +415,8 @@ static void print_value(JS::Value value, HashTable<JS::Object*>& seen_objects)
|
||||||
return print_error(object, seen_objects);
|
return print_error(object, seen_objects);
|
||||||
if (is<JS::RegExpObject>(object))
|
if (is<JS::RegExpObject>(object))
|
||||||
return print_regexp_object(object, seen_objects);
|
return print_regexp_object(object, seen_objects);
|
||||||
|
if (is<JS::Set>(object))
|
||||||
|
return print_set(object, seen_objects);
|
||||||
if (is<JS::ProxyObject>(object))
|
if (is<JS::ProxyObject>(object))
|
||||||
return print_proxy_object(object, seen_objects);
|
return print_proxy_object(object, seen_objects);
|
||||||
if (is<JS::Promise>(object))
|
if (is<JS::Promise>(object))
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue