1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-27 10:47:35 +00:00

LibJS: Implement AggregateError

This commit is contained in:
Linus Groh 2021-06-11 18:06:20 +01:00
parent 2f03eb8628
commit cbd7437d40
13 changed files with 301 additions and 15 deletions

View file

@ -0,0 +1,29 @@
/*
* Copyright (c) 2021, Linus Groh <linusg@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibJS/Runtime/AggregateError.h>
#include <LibJS/Runtime/Array.h>
#include <LibJS/Runtime/GlobalObject.h>
namespace JS {
AggregateError* AggregateError::create(GlobalObject& global_object, String const& message, Vector<Value> const& errors)
{
auto& vm = global_object.vm();
auto* error = global_object.heap().allocate<AggregateError>(global_object, *global_object.aggregate_error_prototype());
u8 attr = Attribute::Writable | Attribute::Configurable;
if (!message.is_null())
error->define_property(vm.names.message, js_string(vm, message), attr);
error->define_property(vm.names.errors, Array::create_from(global_object, errors), attr);
return error;
}
AggregateError::AggregateError(Object& prototype)
: Object(prototype)
{
}
}

View file

@ -0,0 +1,23 @@
/*
* Copyright (c) 2021, Linus Groh <linusg@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <LibJS/Runtime/Object.h>
namespace JS {
class AggregateError : public Object {
JS_OBJECT(Error, Object);
public:
static AggregateError* create(GlobalObject&, String const& message, Vector<Value> const& errors);
explicit AggregateError(Object& prototype);
virtual ~AggregateError() override = default;
};
}

View file

@ -0,0 +1,50 @@
/*
* Copyright (c) 2021, Linus Groh <linusg@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibJS/Runtime/AggregateError.h>
#include <LibJS/Runtime/AggregateErrorConstructor.h>
#include <LibJS/Runtime/ErrorConstructor.h>
#include <LibJS/Runtime/GlobalObject.h>
#include <LibJS/Runtime/IteratorOperations.h>
namespace JS {
AggregateErrorConstructor::AggregateErrorConstructor(GlobalObject& global_object)
: NativeFunction(*static_cast<Object*>(global_object.error_constructor()))
{
}
void AggregateErrorConstructor::initialize(GlobalObject& global_object)
{
auto& vm = this->vm();
NativeFunction::initialize(global_object);
define_property(vm.names.prototype, global_object.aggregate_error_prototype(), 0);
define_property(vm.names.length, Value(2), Attribute::Configurable);
}
Value AggregateErrorConstructor::call()
{
return construct(*this);
}
// 20.5.7.1 The AggregateError Constructor, https://tc39.es/ecma262/#sec-aggregate-error-constructor
Value AggregateErrorConstructor::construct(Function&)
{
auto& vm = this->vm();
String message;
if (!vm.argument(1).is_undefined()) {
message = vm.argument(1).to_string(global_object());
if (vm.exception())
return {};
}
auto errors_list = iterable_to_list(global_object(), vm.argument(0));
if (vm.exception())
return {};
// FIXME: 2. Let O be ? OrdinaryCreateFromConstructor(newTarget, "%AggregateError.prototype%", « [[ErrorData]] »).
return AggregateError::create(global_object(), message, errors_list);
}
}

View file

@ -0,0 +1,28 @@
/*
* Copyright (c) 2021, Linus Groh <linusg@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <LibJS/Runtime/NativeFunction.h>
namespace JS {
class AggregateErrorConstructor final : public NativeFunction {
JS_OBJECT(AggregateErrorConstructor, NativeFunction);
public:
explicit AggregateErrorConstructor(GlobalObject&);
virtual void initialize(GlobalObject&) override;
virtual ~AggregateErrorConstructor() override = default;
virtual Value call() override;
virtual Value construct(Function& new_target) override;
private:
virtual bool has_constructor() const override { return true; }
};
}

View file

@ -0,0 +1,27 @@
/*
* Copyright (c) 2021, Linus Groh <linusg@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibJS/Runtime/AggregateErrorPrototype.h>
#include <LibJS/Runtime/GlobalObject.h>
#include <LibJS/Runtime/PrimitiveString.h>
namespace JS {
AggregateErrorPrototype::AggregateErrorPrototype(GlobalObject& global_object)
: Object(*global_object.error_prototype())
{
}
void AggregateErrorPrototype::initialize(GlobalObject& global_object)
{
auto& vm = this->vm();
Object::initialize(global_object);
u8 attr = Attribute::Writable | Attribute::Configurable;
define_property(vm.names.name, js_string(vm, "AggregateError"), attr);
define_property(vm.names.message, js_string(vm, ""), attr);
}
}

View file

@ -0,0 +1,22 @@
/*
* Copyright (c) 2021, Linus Groh <linusg@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <LibJS/Runtime/Object.h>
namespace JS {
class AggregateErrorPrototype final : public Object {
JS_OBJECT(AggregateErrorPrototype, Object);
public:
explicit AggregateErrorPrototype(GlobalObject&);
virtual void initialize(GlobalObject&) override;
virtual ~AggregateErrorPrototype() override = default;
};
}

View file

@ -100,6 +100,7 @@ namespace JS {
P(entries) \
P(enumerable) \
P(error) \
P(errors) \
P(escape) \
P(eval) \
P(every) \

View file

@ -15,6 +15,8 @@
#include <LibJS/Interpreter.h>
#include <LibJS/Lexer.h>
#include <LibJS/Parser.h>
#include <LibJS/Runtime/AggregateErrorConstructor.h>
#include <LibJS/Runtime/AggregateErrorPrototype.h>
#include <LibJS/Runtime/ArrayBufferConstructor.h>
#include <LibJS/Runtime/ArrayBufferPrototype.h>
#include <LibJS/Runtime/ArrayConstructor.h>
@ -94,6 +96,9 @@ void GlobalObject::initialize_global_object()
Object::set_prototype(m_object_prototype);
// This must be initialized before allocating AggregateErrorPrototype, which uses ErrorPrototype as its prototype.
m_error_prototype = heap().allocate<ErrorPrototype>(*this, *this);
#define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName, ArrayType) \
if (!m_##snake_name##_prototype) \
m_##snake_name##_prototype = heap().allocate<PrototypeName>(*this, *this);
@ -130,6 +135,10 @@ void GlobalObject::initialize_global_object()
define_property(vm.names.JSON, heap().allocate<JSONObject>(*this, *this), attr);
define_property(vm.names.Reflect, heap().allocate<ReflectObject>(*this, *this), attr);
// This must be initialized before allocating AggregateErrorConstructor, which uses ErrorConstructor as its prototype.
initialize_constructor(vm.names.Error, m_error_constructor, m_error_prototype);
add_constructor(vm.names.AggregateError, m_aggregate_error_constructor, m_aggregate_error_prototype);
add_constructor(vm.names.Array, m_array_constructor, m_array_prototype);
add_constructor(vm.names.ArrayBuffer, m_array_buffer_constructor, m_array_buffer_prototype);
add_constructor(vm.names.BigInt, m_bigint_constructor, m_bigint_prototype);