mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-06-11 02:13:56 +09:00
LibJS: Introduce AbstractOperations.{cpp,h} and move various AOs there
Value.{cpp,h} has become a dumping ground, let's change that. Things that are directly related to Values (e.g. bitwise/binary ops, equality related functions) can remain, but everything else that's not a Value or Object method and globally required (not just a static function somewhere) is being moved. Also convert to east-const while we're here. I haven't touched IteratorOperations.{cpp,h}, it seems fine to still have those separately.
This commit is contained in:
parent
c03a3dc5b7
commit
55db9539a5
Notes:
sideshowbarker
2024-07-18 11:59:42 +09:00
Author: https://github.com/linusg
Commit: 55db9539a5
Pull-request: https://github.com/SerenityOS/serenity/pull/8161
Reviewed-by: https://github.com/mattco98
18 changed files with 153 additions and 100 deletions
|
@ -22,6 +22,7 @@ set(SOURCES
|
|||
Lexer.cpp
|
||||
MarkupGenerator.cpp
|
||||
Parser.cpp
|
||||
Runtime/AbstractOperations.cpp
|
||||
Runtime/AggregateError.cpp
|
||||
Runtime/AggregateErrorConstructor.cpp
|
||||
Runtime/AggregateErrorPrototype.cpp
|
||||
|
|
115
Userland/Libraries/LibJS/Runtime/AbstractOperations.cpp
Normal file
115
Userland/Libraries/LibJS/Runtime/AbstractOperations.cpp
Normal file
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
* Copyright (c) 2020-2021, Linus Groh <linusg@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <AK/Function.h>
|
||||
#include <AK/Result.h>
|
||||
#include <LibJS/Runtime/AbstractOperations.h>
|
||||
#include <LibJS/Runtime/BoundFunction.h>
|
||||
#include <LibJS/Runtime/ErrorTypes.h>
|
||||
#include <LibJS/Runtime/Function.h>
|
||||
#include <LibJS/Runtime/GlobalObject.h>
|
||||
#include <LibJS/Runtime/Object.h>
|
||||
#include <LibJS/Runtime/PropertyName.h>
|
||||
|
||||
namespace JS {
|
||||
|
||||
// Used in various abstract operations to make it obvious when a non-optional return value must be discarded.
|
||||
static constexpr double INVALID { 0 };
|
||||
|
||||
// 7.2.1 RequireObjectCoercible ( argument ), https://tc39.es/ecma262/#sec-requireobjectcoercible
|
||||
Value require_object_coercible(GlobalObject& global_object, Value value)
|
||||
{
|
||||
auto& vm = global_object.vm();
|
||||
if (value.is_nullish()) {
|
||||
vm.throw_exception<TypeError>(global_object, ErrorType::NotObjectCoercible, value.to_string_without_side_effects());
|
||||
return {};
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
// 7.3.10 GetMethod ( V, P ), https://tc39.es/ecma262/#sec-getmethod
|
||||
Function* get_method(GlobalObject& global_object, Value value, PropertyName const& property_name)
|
||||
{
|
||||
auto& vm = global_object.vm();
|
||||
auto* object = value.to_object(global_object);
|
||||
if (vm.exception())
|
||||
return nullptr;
|
||||
auto property_value = object->get(property_name);
|
||||
if (vm.exception())
|
||||
return nullptr;
|
||||
if (property_value.is_empty() || property_value.is_nullish())
|
||||
return nullptr;
|
||||
if (!property_value.is_function()) {
|
||||
vm.throw_exception<TypeError>(global_object, ErrorType::NotAFunction, property_value.to_string_without_side_effects());
|
||||
return nullptr;
|
||||
}
|
||||
return &property_value.as_function();
|
||||
}
|
||||
|
||||
// 7.3.18 LengthOfArrayLike ( obj ), https://tc39.es/ecma262/#sec-lengthofarraylike
|
||||
size_t length_of_array_like(GlobalObject& global_object, Object const& object)
|
||||
{
|
||||
auto& vm = global_object.vm();
|
||||
auto result = object.get(vm.names.length).value_or(js_undefined());
|
||||
if (vm.exception())
|
||||
return INVALID;
|
||||
return result.to_length(global_object);
|
||||
}
|
||||
|
||||
// 7.3.19 CreateListFromArrayLike ( obj [ , elementTypes ] ), https://tc39.es/ecma262/#sec-createlistfromarraylike
|
||||
MarkedValueList create_list_from_array_like(GlobalObject& global_object, Value value, AK::Function<Result<void, ErrorType>(Value)> check_value)
|
||||
{
|
||||
auto& vm = global_object.vm();
|
||||
auto& heap = global_object.heap();
|
||||
if (!value.is_object()) {
|
||||
vm.throw_exception<TypeError>(global_object, ErrorType::NotAnObject, value.to_string_without_side_effects());
|
||||
return MarkedValueList { heap };
|
||||
}
|
||||
auto& array_like = value.as_object();
|
||||
auto length = length_of_array_like(global_object, array_like);
|
||||
if (vm.exception())
|
||||
return MarkedValueList { heap };
|
||||
auto list = MarkedValueList { heap };
|
||||
for (size_t i = 0; i < length; ++i) {
|
||||
auto index_name = String::number(i);
|
||||
auto next = array_like.get(index_name).value_or(js_undefined());
|
||||
if (vm.exception())
|
||||
return MarkedValueList { heap };
|
||||
if (check_value) {
|
||||
auto result = check_value(next);
|
||||
if (result.is_error()) {
|
||||
vm.throw_exception<TypeError>(global_object, result.release_error());
|
||||
return MarkedValueList { heap };
|
||||
}
|
||||
}
|
||||
list.append(next);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
// 7.3.22 SpeciesConstructor ( O, defaultConstructor ), https://tc39.es/ecma262/#sec-speciesconstructor
|
||||
Function* species_constructor(GlobalObject& global_object, Object const& object, Function& default_constructor)
|
||||
{
|
||||
auto& vm = global_object.vm();
|
||||
auto constructor = object.get(vm.names.constructor).value_or(js_undefined());
|
||||
if (vm.exception())
|
||||
return nullptr;
|
||||
if (constructor.is_undefined())
|
||||
return &default_constructor;
|
||||
if (!constructor.is_object()) {
|
||||
vm.throw_exception<TypeError>(global_object, ErrorType::NotAConstructor, constructor.to_string_without_side_effects());
|
||||
return nullptr;
|
||||
}
|
||||
auto species = constructor.as_object().get(vm.well_known_symbol_species()).value_or(js_undefined());
|
||||
if (species.is_nullish())
|
||||
return &default_constructor;
|
||||
if (species.is_constructor())
|
||||
return &species.as_function();
|
||||
vm.throw_exception<TypeError>(global_object, ErrorType::NotAConstructor, species.to_string_without_side_effects());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
}
|
21
Userland/Libraries/LibJS/Runtime/AbstractOperations.h
Normal file
21
Userland/Libraries/LibJS/Runtime/AbstractOperations.h
Normal file
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
* Copyright (c) 2020-2021, Linus Groh <linusg@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AK/Forward.h>
|
||||
#include <LibJS/Forward.h>
|
||||
#include <LibJS/Runtime/Value.h>
|
||||
|
||||
namespace JS {
|
||||
|
||||
Value require_object_coercible(GlobalObject&, Value);
|
||||
Function* get_method(GlobalObject& global_object, Value, PropertyName const&);
|
||||
size_t length_of_array_like(GlobalObject&, Object const&);
|
||||
MarkedValueList create_list_from_array_like(GlobalObject&, Value, AK::Function<Result<void, ErrorType>(Value)> = {});
|
||||
Function* species_constructor(GlobalObject&, Object const&, Function& default_constructor);
|
||||
|
||||
}
|
|
@ -6,6 +6,7 @@
|
|||
*/
|
||||
|
||||
#include <AK/Function.h>
|
||||
#include <LibJS/Runtime/AbstractOperations.h>
|
||||
#include <LibJS/Runtime/ArrayBuffer.h>
|
||||
#include <LibJS/Runtime/ArrayBufferConstructor.h>
|
||||
#include <LibJS/Runtime/ArrayBufferPrototype.h>
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include <AK/HashTable.h>
|
||||
#include <AK/ScopeGuard.h>
|
||||
#include <AK/StringBuilder.h>
|
||||
#include <LibJS/Runtime/AbstractOperations.h>
|
||||
#include <LibJS/Runtime/Array.h>
|
||||
#include <LibJS/Runtime/ArrayIterator.h>
|
||||
#include <LibJS/Runtime/ArrayPrototype.h>
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include <AK/StringBuilder.h>
|
||||
#include <LibJS/AST.h>
|
||||
#include <LibJS/Interpreter.h>
|
||||
#include <LibJS/Runtime/AbstractOperations.h>
|
||||
#include <LibJS/Runtime/BoundFunction.h>
|
||||
#include <LibJS/Runtime/Error.h>
|
||||
#include <LibJS/Runtime/Function.h>
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <LibJS/Runtime/AbstractOperations.h>
|
||||
#include <LibJS/Runtime/Error.h>
|
||||
#include <LibJS/Runtime/GlobalObject.h>
|
||||
#include <LibJS/Runtime/IteratorOperations.h>
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include <AK/JsonObject.h>
|
||||
#include <AK/JsonParser.h>
|
||||
#include <AK/StringBuilder.h>
|
||||
#include <LibJS/Runtime/AbstractOperations.h>
|
||||
#include <LibJS/Runtime/Array.h>
|
||||
#include <LibJS/Runtime/BigIntObject.h>
|
||||
#include <LibJS/Runtime/BooleanObject.h>
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
*/
|
||||
|
||||
#include <AK/Function.h>
|
||||
#include <LibJS/Runtime/AbstractOperations.h>
|
||||
#include <LibJS/Runtime/Array.h>
|
||||
#include <LibJS/Runtime/Error.h>
|
||||
#include <LibJS/Runtime/GlobalObject.h>
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include <AK/Function.h>
|
||||
#include <AK/String.h>
|
||||
#include <LibJS/Runtime/AbstractOperations.h>
|
||||
#include <LibJS/Runtime/Accessor.h>
|
||||
#include <LibJS/Runtime/BooleanObject.h>
|
||||
#include <LibJS/Runtime/Date.h>
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include <AK/Function.h>
|
||||
#include <LibJS/Interpreter.h>
|
||||
#include <LibJS/Runtime/AbstractOperations.h>
|
||||
#include <LibJS/Runtime/Error.h>
|
||||
#include <LibJS/Runtime/GlobalObject.h>
|
||||
#include <LibJS/Runtime/Promise.h>
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <LibJS/Runtime/AbstractOperations.h>
|
||||
#include <LibJS/Runtime/Accessor.h>
|
||||
#include <LibJS/Runtime/Array.h>
|
||||
#include <LibJS/Runtime/Error.h>
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
*/
|
||||
|
||||
#include <AK/Function.h>
|
||||
#include <LibJS/Runtime/AbstractOperations.h>
|
||||
#include <LibJS/Runtime/Array.h>
|
||||
#include <LibJS/Runtime/Error.h>
|
||||
#include <LibJS/Runtime/Function.h>
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
*/
|
||||
|
||||
#include <AK/Function.h>
|
||||
#include <LibJS/Runtime/AbstractOperations.h>
|
||||
#include <LibJS/Runtime/Array.h>
|
||||
#include <LibJS/Runtime/Error.h>
|
||||
#include <LibJS/Runtime/GlobalObject.h>
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include <AK/Function.h>
|
||||
#include <AK/StringBuilder.h>
|
||||
#include <LibJS/Heap/Heap.h>
|
||||
#include <LibJS/Runtime/AbstractOperations.h>
|
||||
#include <LibJS/Runtime/Array.h>
|
||||
#include <LibJS/Runtime/Error.h>
|
||||
#include <LibJS/Runtime/GlobalObject.h>
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
*/
|
||||
|
||||
#include <AK/Checked.h>
|
||||
#include <LibJS/Runtime/AbstractOperations.h>
|
||||
#include <LibJS/Runtime/ArrayBuffer.h>
|
||||
#include <LibJS/Runtime/GlobalObject.h>
|
||||
#include <LibJS/Runtime/IteratorOperations.h>
|
||||
|
|
|
@ -7,13 +7,13 @@
|
|||
|
||||
#include <AK/AllOf.h>
|
||||
#include <AK/FlyString.h>
|
||||
#include <AK/Result.h>
|
||||
#include <AK/String.h>
|
||||
#include <AK/StringBuilder.h>
|
||||
#include <AK/Utf8View.h>
|
||||
#include <LibCrypto/BigInt/SignedBigInteger.h>
|
||||
#include <LibCrypto/NumberTheory/ModularFunctions.h>
|
||||
#include <LibJS/Heap/Heap.h>
|
||||
#include <LibJS/Runtime/AbstractOperations.h>
|
||||
#include <LibJS/Runtime/Accessor.h>
|
||||
#include <LibJS/Runtime/Array.h>
|
||||
#include <LibJS/Runtime/BigInt.h>
|
||||
|
@ -38,7 +38,7 @@
|
|||
namespace JS {
|
||||
|
||||
// Used in various abstract operations to make it obvious when a non-optional return value must be discarded.
|
||||
static const double INVALID { 0 };
|
||||
static constexpr double INVALID { 0 };
|
||||
|
||||
static inline bool same_type_for_equality(const Value& lhs, const Value& rhs)
|
||||
{
|
||||
|
@ -1495,97 +1495,4 @@ TriState abstract_relation(GlobalObject& global_object, bool left_first, Value l
|
|||
return TriState::False;
|
||||
}
|
||||
|
||||
// 7.3.10 GetMethod ( V, P ), https://tc39.es/ecma262/#sec-getmethod
|
||||
Function* get_method(GlobalObject& global_object, Value value, const PropertyName& property_name)
|
||||
{
|
||||
auto& vm = global_object.vm();
|
||||
auto* object = value.to_object(global_object);
|
||||
if (vm.exception())
|
||||
return nullptr;
|
||||
auto property_value = object->get(property_name);
|
||||
if (vm.exception())
|
||||
return nullptr;
|
||||
if (property_value.is_empty() || property_value.is_nullish())
|
||||
return nullptr;
|
||||
if (!property_value.is_function()) {
|
||||
vm.throw_exception<TypeError>(global_object, ErrorType::NotAFunction, property_value.to_string_without_side_effects());
|
||||
return nullptr;
|
||||
}
|
||||
return &property_value.as_function();
|
||||
}
|
||||
|
||||
// 7.3.18 LengthOfArrayLike ( obj ), https://tc39.es/ecma262/#sec-lengthofarraylike
|
||||
size_t length_of_array_like(GlobalObject& global_object, const Object& object)
|
||||
{
|
||||
auto& vm = global_object.vm();
|
||||
auto result = object.get(vm.names.length).value_or(js_undefined());
|
||||
if (vm.exception())
|
||||
return INVALID;
|
||||
return result.to_length(global_object);
|
||||
}
|
||||
|
||||
// 7.3.22 SpeciesConstructor ( O, defaultConstructor ), https://tc39.es/ecma262/#sec-speciesconstructor
|
||||
Function* species_constructor(GlobalObject& global_object, const Object& object, Function& default_constructor)
|
||||
{
|
||||
auto& vm = global_object.vm();
|
||||
auto constructor = object.get(vm.names.constructor).value_or(js_undefined());
|
||||
if (vm.exception())
|
||||
return nullptr;
|
||||
if (constructor.is_undefined())
|
||||
return &default_constructor;
|
||||
if (!constructor.is_object()) {
|
||||
vm.throw_exception<TypeError>(global_object, ErrorType::NotAConstructor, constructor.to_string_without_side_effects());
|
||||
return nullptr;
|
||||
}
|
||||
auto species = constructor.as_object().get(vm.well_known_symbol_species()).value_or(js_undefined());
|
||||
if (species.is_nullish())
|
||||
return &default_constructor;
|
||||
if (species.is_constructor())
|
||||
return &species.as_function();
|
||||
vm.throw_exception<TypeError>(global_object, ErrorType::NotAConstructor, species.to_string_without_side_effects());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// 7.2.1 RequireObjectCoercible ( argument ), https://tc39.es/ecma262/#sec-requireobjectcoercible
|
||||
Value require_object_coercible(GlobalObject& global_object, Value value)
|
||||
{
|
||||
auto& vm = global_object.vm();
|
||||
if (value.is_nullish()) {
|
||||
vm.throw_exception<TypeError>(global_object, ErrorType::NotObjectCoercible, value.to_string_without_side_effects());
|
||||
return {};
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
// 7.3.19 CreateListFromArrayLike ( obj [ , elementTypes ] ), https://tc39.es/ecma262/#sec-createlistfromarraylike
|
||||
MarkedValueList create_list_from_array_like(GlobalObject& global_object, Value value, AK::Function<Result<void, ErrorType>(Value)> check_value)
|
||||
{
|
||||
auto& vm = global_object.vm();
|
||||
auto& heap = global_object.heap();
|
||||
if (!value.is_object()) {
|
||||
vm.throw_exception<TypeError>(global_object, ErrorType::NotAnObject, value.to_string_without_side_effects());
|
||||
return MarkedValueList { heap };
|
||||
}
|
||||
auto& array_like = value.as_object();
|
||||
auto length = length_of_array_like(global_object, array_like);
|
||||
if (vm.exception())
|
||||
return MarkedValueList { heap };
|
||||
auto list = MarkedValueList { heap };
|
||||
for (size_t i = 0; i < length; ++i) {
|
||||
auto index_name = String::number(i);
|
||||
auto next = array_like.get(index_name).value_or(js_undefined());
|
||||
if (vm.exception())
|
||||
return MarkedValueList { heap };
|
||||
if (check_value) {
|
||||
auto result = check_value(next);
|
||||
if (result.is_error()) {
|
||||
vm.throw_exception<TypeError>(global_object, result.release_error());
|
||||
return MarkedValueList { heap };
|
||||
}
|
||||
}
|
||||
list.append(next);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include <AK/Types.h>
|
||||
#include <LibJS/Forward.h>
|
||||
#include <LibJS/Runtime/BigInt.h>
|
||||
#include <LibJS/Runtime/PrimitiveString.h>
|
||||
#include <math.h>
|
||||
|
||||
// 2 ** 53 - 1
|
||||
|
@ -378,11 +379,6 @@ bool same_value(Value lhs, Value rhs);
|
|||
bool same_value_zero(Value lhs, Value rhs);
|
||||
bool same_value_non_numeric(Value lhs, Value rhs);
|
||||
TriState abstract_relation(GlobalObject&, bool left_first, Value lhs, Value rhs);
|
||||
Function* get_method(GlobalObject& global_object, Value, const PropertyName&);
|
||||
size_t length_of_array_like(GlobalObject&, const Object&);
|
||||
Function* species_constructor(GlobalObject&, const Object&, Function& default_constructor);
|
||||
Value require_object_coercible(GlobalObject&, Value);
|
||||
MarkedValueList create_list_from_array_like(GlobalObject&, Value, AK::Function<Result<void, ErrorType>(Value)> = {});
|
||||
|
||||
struct ValueTraits : public Traits<Value> {
|
||||
static unsigned hash(Value value)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue