mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-06-09 09:34:57 +09:00
Everywhere: Hoist the Libraries folder to the top-level
This commit is contained in:
parent
950e819ee7
commit
93712b24bf
Notes:
github-actions[bot]
2024-11-10 11:51:52 +00:00
Author: https://github.com/trflynn89
Commit: 93712b24bf
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/2256
Reviewed-by: https://github.com/sideshowbarker
4547 changed files with 104 additions and 113 deletions
7
Libraries/LibIDL/CMakeLists.txt
Normal file
7
Libraries/LibIDL/CMakeLists.txt
Normal file
|
@ -0,0 +1,7 @@
|
|||
set(SOURCES
|
||||
IDLParser.cpp
|
||||
Types.cpp
|
||||
)
|
||||
|
||||
serenity_lib(LibIDL idl)
|
||||
target_link_libraries(LibIDL PRIVATE LibCoreMinimal LibFileSystem)
|
1271
Libraries/LibIDL/IDLParser.cpp
Normal file
1271
Libraries/LibIDL/IDLParser.cpp
Normal file
File diff suppressed because it is too large
Load diff
84
Libraries/LibIDL/IDLParser.h
Normal file
84
Libraries/LibIDL/IDLParser.h
Normal file
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* Copyright (c) 2020-2023, Andreas Kling <andreas@ladybird.org>
|
||||
* Copyright (c) 2021, Linus Groh <linusg@serenityos.org>
|
||||
* Copyright (c) 2021, Luke Wilde <lukew@serenityos.org>
|
||||
* Copyright (c) 2022, Ali Mohammad Pur <mpfard@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AK/CharacterTypes.h>
|
||||
#include <AK/GenericLexer.h>
|
||||
#include <LibIDL/Types.h>
|
||||
|
||||
namespace IDL {
|
||||
|
||||
class Parser {
|
||||
public:
|
||||
Parser(ByteString filename, StringView contents, ByteString import_base_path);
|
||||
Interface& parse();
|
||||
|
||||
Vector<ByteString> imported_files() const;
|
||||
|
||||
private:
|
||||
// https://webidl.spec.whatwg.org/#dfn-special-operation
|
||||
// A special operation is a getter, setter or deleter.
|
||||
enum class IsSpecialOperation {
|
||||
No,
|
||||
Yes,
|
||||
};
|
||||
|
||||
enum class IsStatic {
|
||||
No,
|
||||
Yes,
|
||||
};
|
||||
|
||||
Parser(Parser* parent, ByteString filename, StringView contents, ByteString import_base_path);
|
||||
|
||||
void assert_specific(char ch);
|
||||
void assert_string(StringView expected);
|
||||
void consume_whitespace();
|
||||
Optional<Interface&> resolve_import(auto path);
|
||||
|
||||
HashMap<ByteString, ByteString> parse_extended_attributes();
|
||||
void parse_attribute(HashMap<ByteString, ByteString>& extended_attributes, Interface&, IsStatic is_static = IsStatic::No);
|
||||
void parse_interface(Interface&);
|
||||
void parse_namespace(Interface&);
|
||||
void parse_non_interface_entities(bool allow_interface, Interface&);
|
||||
void parse_enumeration(HashMap<ByteString, ByteString>, Interface&);
|
||||
void parse_typedef(Interface&);
|
||||
void parse_interface_mixin(Interface&);
|
||||
void parse_dictionary(Interface&);
|
||||
void parse_callback_function(HashMap<ByteString, ByteString>& extended_attributes, Interface&);
|
||||
void parse_constructor(HashMap<ByteString, ByteString>& extended_attributes, Interface&);
|
||||
void parse_getter(HashMap<ByteString, ByteString>& extended_attributes, Interface&);
|
||||
void parse_setter(HashMap<ByteString, ByteString>& extended_attributes, Interface&);
|
||||
void parse_deleter(HashMap<ByteString, ByteString>& extended_attributes, Interface&);
|
||||
void parse_stringifier(HashMap<ByteString, ByteString>& extended_attributes, Interface&);
|
||||
void parse_iterable(Interface&);
|
||||
void parse_setlike(Interface&, bool is_readonly);
|
||||
Function parse_function(HashMap<ByteString, ByteString>& extended_attributes, Interface&, IsStatic is_static = IsStatic::No, IsSpecialOperation is_special_operation = IsSpecialOperation::No);
|
||||
Vector<Parameter> parse_parameters();
|
||||
NonnullRefPtr<Type const> parse_type();
|
||||
void parse_constant(Interface&);
|
||||
ByteString parse_identifier_until(AK::Function<bool(char)> predicate);
|
||||
ByteString parse_identifier_ending_with(auto... possible_terminating_characters);
|
||||
ByteString parse_identifier_ending_with_space();
|
||||
ByteString parse_identifier_ending_with_space_or(auto... possible_terminating_characters);
|
||||
|
||||
ByteString import_base_path;
|
||||
ByteString filename;
|
||||
StringView input;
|
||||
LineTrackingLexer lexer;
|
||||
|
||||
HashTable<NonnullOwnPtr<Interface>>& top_level_interfaces();
|
||||
HashTable<NonnullOwnPtr<Interface>> interfaces;
|
||||
HashMap<ByteString, Interface*>& top_level_resolved_imports();
|
||||
HashMap<ByteString, Interface*> resolved_imports;
|
||||
Parser* top_level_parser();
|
||||
Parser* parent = nullptr;
|
||||
};
|
||||
|
||||
}
|
308
Libraries/LibIDL/Types.cpp
Normal file
308
Libraries/LibIDL/Types.cpp
Normal file
|
@ -0,0 +1,308 @@
|
|||
/*
|
||||
* Copyright (c) 2022, Sam Atkins <atkinssj@serenityos.org>
|
||||
* Copyright (c) 2023, Luke Wilde <lukew@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <AK/Debug.h>
|
||||
#include <LibIDL/Types.h>
|
||||
|
||||
namespace IDL {
|
||||
|
||||
ParameterizedType const& Type::as_parameterized() const
|
||||
{
|
||||
return verify_cast<ParameterizedType const>(*this);
|
||||
}
|
||||
|
||||
ParameterizedType& Type::as_parameterized()
|
||||
{
|
||||
return verify_cast<ParameterizedType>(*this);
|
||||
}
|
||||
|
||||
UnionType const& Type::as_union() const
|
||||
{
|
||||
return verify_cast<UnionType const>(*this);
|
||||
}
|
||||
|
||||
UnionType& Type::as_union()
|
||||
{
|
||||
return verify_cast<UnionType>(*this);
|
||||
}
|
||||
|
||||
// https://webidl.spec.whatwg.org/#dfn-includes-a-nullable-type
|
||||
bool Type::includes_nullable_type() const
|
||||
{
|
||||
// A type includes a nullable type if:
|
||||
// - the type is a nullable type, or
|
||||
if (is_nullable())
|
||||
return true;
|
||||
|
||||
// FIXME: - the type is an annotated type and its inner type is a nullable type, or
|
||||
|
||||
// - the type is a union type and its number of nullable member types is 1.
|
||||
if (is_union() && as_union().number_of_nullable_member_types() == 1)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// https://webidl.spec.whatwg.org/#dfn-includes-undefined
|
||||
bool Type::includes_undefined() const
|
||||
{
|
||||
// A type includes undefined if:
|
||||
// - the type is undefined, or
|
||||
if (is_undefined())
|
||||
return true;
|
||||
|
||||
// - the type is a nullable type and its inner type includes undefined, or
|
||||
// NOTE: We don't treat nullable as its own type, so this is handled by the other cases.
|
||||
|
||||
// FIXME: - the type is an annotated type and its inner type includes undefined, or
|
||||
|
||||
// - the type is a union type and one of its member types includes undefined.
|
||||
if (is_union()) {
|
||||
for (auto& type : as_union().member_types()) {
|
||||
if (type->includes_undefined())
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// https://webidl.spec.whatwg.org/#dfn-distinguishable
|
||||
bool Type::is_distinguishable_from(IDL::Interface const& interface, IDL::Type const& other) const
|
||||
{
|
||||
// 1. If one type includes a nullable type and the other type either includes a nullable type,
|
||||
// is a union type with flattened member types including a dictionary type, or is a dictionary type,
|
||||
// return false.
|
||||
if (includes_nullable_type() && (other.includes_nullable_type() || (other.is_union() && any_of(other.as_union().flattened_member_types(), [&interface](auto const& type) { return interface.dictionaries.contains(type->name()); })) || interface.dictionaries.contains(other.name())))
|
||||
return false;
|
||||
|
||||
// 2. If both types are either a union type or nullable union type, return true if each member type
|
||||
// of the one is distinguishable with each member type of the other, or false otherwise.
|
||||
if (is_union() && other.is_union()) {
|
||||
auto const& this_union = as_union();
|
||||
auto const& other_union = other.as_union();
|
||||
|
||||
for (auto& this_member_type : this_union.member_types()) {
|
||||
for (auto& other_member_type : other_union.member_types()) {
|
||||
if (!this_member_type->is_distinguishable_from(interface, other_member_type))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// 3. If one type is a union type or nullable union type, return true if each member type of the union
|
||||
// type is distinguishable with the non-union type, or false otherwise.
|
||||
if (is_union() || other.is_union()) {
|
||||
auto const& the_union = is_union() ? as_union() : other.as_union();
|
||||
auto const& non_union = is_union() ? other : *this;
|
||||
|
||||
for (auto& member_type : the_union.member_types()) {
|
||||
if (!non_union.is_distinguishable_from(interface, member_type))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// 4. Consider the two "innermost" types derived by taking each type’s inner type if it is an annotated type,
|
||||
// and then taking its inner type inner type if the result is a nullable type. If these two innermost types
|
||||
// appear or are in categories appearing in the following table and there is a “●” mark in the corresponding
|
||||
// entry or there is a letter in the corresponding entry and the designated additional requirement below the
|
||||
// table is satisfied, then return true. Otherwise return false.
|
||||
auto const& this_innermost_type = innermost_type();
|
||||
auto const& other_innermost_type = other.innermost_type();
|
||||
|
||||
enum class DistinguishabilityCategory {
|
||||
Undefined,
|
||||
Boolean,
|
||||
Numeric,
|
||||
BigInt,
|
||||
String,
|
||||
Object,
|
||||
Symbol,
|
||||
InterfaceLike,
|
||||
CallbackFunction,
|
||||
DictionaryLike,
|
||||
SequenceLike,
|
||||
__Count
|
||||
};
|
||||
|
||||
// See https://webidl.spec.whatwg.org/#distinguishable-table
|
||||
// clang-format off
|
||||
static constexpr bool table[to_underlying(DistinguishabilityCategory::__Count)][to_underlying(DistinguishabilityCategory::__Count)] {
|
||||
{false, true, true, true, true, true, true, true, true, false, true},
|
||||
{ true, false, true, true, true, true, true, true, true, true, true},
|
||||
{ true, true, false, true, true, true, true, true, true, true, true},
|
||||
{ true, true, true, false, true, true, true, true, true, true, true},
|
||||
{ true, true, true, true, false, true, true, true, true, true, true},
|
||||
{ true, true, true, true, true, false, true, false, false, false, false},
|
||||
{ true, true, true, true, true, true, false, true, true, true, true},
|
||||
{ true, true, true, true, true, false, true, false, true, true, true},
|
||||
{ true, true, true, true, true, false, true, true, false, false, true},
|
||||
{false, true, true, true, true, false, true, true, false, false, true},
|
||||
{ true, true, true, true, true, false, true, true, true, true, false},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
auto determine_category = [&interface](Type const& type) -> DistinguishabilityCategory {
|
||||
if (type.is_undefined())
|
||||
return DistinguishabilityCategory::Undefined;
|
||||
if (type.is_boolean())
|
||||
return DistinguishabilityCategory::Boolean;
|
||||
if (type.is_numeric())
|
||||
return DistinguishabilityCategory::Numeric;
|
||||
if (type.is_bigint())
|
||||
return DistinguishabilityCategory::BigInt;
|
||||
if (type.is_string())
|
||||
return DistinguishabilityCategory::String;
|
||||
if (type.is_object())
|
||||
return DistinguishabilityCategory::Object;
|
||||
if (type.is_symbol())
|
||||
return DistinguishabilityCategory::Symbol;
|
||||
// FIXME: InterfaceLike - see below
|
||||
// FIXME: CallbackFunction
|
||||
// DictionaryLike
|
||||
// * Dictionary Types
|
||||
// * Record Types
|
||||
// FIXME: * Callback Interface Types
|
||||
if (interface.dictionaries.contains(type.name()) || (type.is_parameterized() && type.name() == "record"sv))
|
||||
return DistinguishabilityCategory::DictionaryLike;
|
||||
// FIXME: Frozen array types are included in "sequence-like"
|
||||
if (type.is_sequence())
|
||||
return DistinguishabilityCategory::SequenceLike;
|
||||
|
||||
// FIXME: For lack of a better way of determining if something is an interface type, this just assumes anything we don't recognise is one.
|
||||
dbgln_if(IDL_DEBUG, "Unable to determine category for type named '{}', assuming it's an interface type.", type.name());
|
||||
return DistinguishabilityCategory::InterfaceLike;
|
||||
};
|
||||
|
||||
auto this_distinguishability = determine_category(this_innermost_type);
|
||||
auto other_distinguishability = determine_category(other_innermost_type);
|
||||
|
||||
if (this_distinguishability == DistinguishabilityCategory::InterfaceLike && other_distinguishability == DistinguishabilityCategory::InterfaceLike) {
|
||||
// The two identified interface-like types are not the same, and
|
||||
// FIXME: no single platform object implements both interface-like types.
|
||||
return this_innermost_type.name() != other_innermost_type.name();
|
||||
}
|
||||
|
||||
return table[to_underlying(this_distinguishability)][to_underlying(other_distinguishability)];
|
||||
}
|
||||
|
||||
// https://webidl.spec.whatwg.org/#dfn-json-types
|
||||
bool Type::is_json(Interface const& interface) const
|
||||
{
|
||||
// The JSON types are:
|
||||
// - numeric types,
|
||||
if (is_numeric())
|
||||
return true;
|
||||
|
||||
// - boolean,
|
||||
if (is_boolean())
|
||||
return true;
|
||||
|
||||
// - string types,
|
||||
if (is_string() || interface.enumerations.find(m_name) != interface.enumerations.end())
|
||||
return true;
|
||||
|
||||
// - object,
|
||||
if (is_object())
|
||||
return true;
|
||||
|
||||
// - nullable types whose inner type is a JSON type,
|
||||
// - annotated types whose inner type is a JSON type,
|
||||
// NOTE: We don't separate nullable and annotated into separate types.
|
||||
|
||||
// - union types whose member types are JSON types,
|
||||
if (is_union()) {
|
||||
auto const& union_type = as_union();
|
||||
|
||||
for (auto const& type : union_type.member_types()) {
|
||||
if (!type->is_json(interface))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// - typedefs whose type being given a new name is a JSON type,
|
||||
auto typedef_iterator = interface.typedefs.find(m_name);
|
||||
if (typedef_iterator != interface.typedefs.end())
|
||||
return typedef_iterator->value.type->is_json(interface);
|
||||
|
||||
// - sequence types whose parameterized type is a JSON type,
|
||||
// - frozen array types whose parameterized type is a JSON type,
|
||||
// - records where all of their values are JSON types,
|
||||
if (is_parameterized() && m_name.is_one_of("sequence", "FrozenArray", "record")) {
|
||||
auto const& parameterized_type = as_parameterized();
|
||||
|
||||
for (auto const& parameter : parameterized_type.parameters()) {
|
||||
if (!parameter->is_json(interface))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// - dictionary types where the types of all members declared on the dictionary and all its inherited dictionaries are JSON types,
|
||||
auto dictionary_iterator = interface.dictionaries.find(m_name);
|
||||
if (dictionary_iterator != interface.dictionaries.end()) {
|
||||
auto const& dictionary = dictionary_iterator->value;
|
||||
for (auto const& member : dictionary.members) {
|
||||
if (!member.type->is_json(interface))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// - interface types that have a toJSON operation declared on themselves or one of their inherited interfaces.
|
||||
Optional<Interface const&> current_interface_for_to_json;
|
||||
if (m_name == interface.name) {
|
||||
current_interface_for_to_json = interface;
|
||||
} else {
|
||||
// NOTE: Interface types must have the IDL file of their interface imported.
|
||||
// Though the type name may not refer to an interface, so we don't assert this here.
|
||||
auto imported_interface_iterator = interface.imported_modules.find_if([this](IDL::Interface const& imported_interface) {
|
||||
return imported_interface.name == m_name;
|
||||
});
|
||||
|
||||
if (imported_interface_iterator != interface.imported_modules.end())
|
||||
current_interface_for_to_json = *imported_interface_iterator;
|
||||
}
|
||||
|
||||
while (current_interface_for_to_json.has_value()) {
|
||||
auto to_json_iterator = current_interface_for_to_json->functions.find_if([](IDL::Function const& function) {
|
||||
return function.name == "toJSON"sv;
|
||||
});
|
||||
|
||||
if (to_json_iterator != current_interface_for_to_json->functions.end())
|
||||
return true;
|
||||
|
||||
if (current_interface_for_to_json->parent_name.is_empty())
|
||||
break;
|
||||
|
||||
auto imported_interface_iterator = current_interface_for_to_json->imported_modules.find_if([¤t_interface_for_to_json](IDL::Interface const& imported_interface) {
|
||||
return imported_interface.name == current_interface_for_to_json->parent_name;
|
||||
});
|
||||
|
||||
// Inherited interfaces must have their IDL files imported.
|
||||
VERIFY(imported_interface_iterator != interface.imported_modules.end());
|
||||
|
||||
current_interface_for_to_json = *imported_interface_iterator;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void EffectiveOverloadSet::remove_all_other_entries()
|
||||
{
|
||||
Vector<Item> new_items;
|
||||
new_items.append(m_items[*m_last_matching_item_index]);
|
||||
m_items = move(new_items);
|
||||
}
|
||||
|
||||
}
|
473
Libraries/LibIDL/Types.h
Normal file
473
Libraries/LibIDL/Types.h
Normal file
|
@ -0,0 +1,473 @@
|
|||
/*
|
||||
* Copyright (c) 2020-2023, Andreas Kling <andreas@ladybird.org>
|
||||
* Copyright (c) 2021, Linus Groh <linusg@serenityos.org>
|
||||
* Copyright (c) 2021, Luke Wilde <lukew@serenityos.org>
|
||||
* Copyright (c) 2022, Ali Mohammad Pur <mpfard@serenityos.org>
|
||||
* Copyright (c) 2022, Sam Atkins <atkinssj@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AK/ByteString.h>
|
||||
#include <AK/HashMap.h>
|
||||
#include <AK/NonnullRefPtr.h>
|
||||
#include <AK/SourceGenerator.h>
|
||||
#include <AK/StringBuilder.h>
|
||||
#include <AK/Tuple.h>
|
||||
#include <AK/TypeCasts.h>
|
||||
|
||||
namespace IDL {
|
||||
|
||||
template<typename FunctionType>
|
||||
static size_t get_function_shortest_length(FunctionType& function)
|
||||
{
|
||||
size_t length = 0;
|
||||
for (auto& parameter : function.parameters) {
|
||||
if (!parameter.optional && !parameter.variadic)
|
||||
length++;
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
enum class SequenceStorageType {
|
||||
Vector, // Used to safely store non-JS values
|
||||
MarkedVector, // Used to safely store JS::Value and anything that inherits JS::Cell, e.g. JS::Object
|
||||
};
|
||||
|
||||
struct CppType {
|
||||
ByteString name;
|
||||
SequenceStorageType sequence_storage_type;
|
||||
};
|
||||
|
||||
class ParameterizedType;
|
||||
class UnionType;
|
||||
class Interface;
|
||||
|
||||
class Type : public RefCounted<Type> {
|
||||
public:
|
||||
enum class Kind {
|
||||
Plain, // AKA, Type.
|
||||
Parameterized,
|
||||
Union,
|
||||
};
|
||||
|
||||
Type(ByteString name, bool nullable)
|
||||
: m_kind(Kind::Plain)
|
||||
, m_name(move(name))
|
||||
, m_nullable(nullable)
|
||||
{
|
||||
}
|
||||
|
||||
Type(Kind kind, ByteString name, bool nullable)
|
||||
: m_kind(kind)
|
||||
, m_name(move(name))
|
||||
, m_nullable(nullable)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~Type() = default;
|
||||
|
||||
Kind kind() const { return m_kind; }
|
||||
|
||||
bool is_plain() const { return m_kind == Kind::Plain; }
|
||||
|
||||
bool is_parameterized() const { return m_kind == Kind::Parameterized; }
|
||||
ParameterizedType const& as_parameterized() const;
|
||||
ParameterizedType& as_parameterized();
|
||||
|
||||
bool is_union() const { return m_kind == Kind::Union; }
|
||||
UnionType const& as_union() const;
|
||||
UnionType& as_union();
|
||||
|
||||
ByteString const& name() const { return m_name; }
|
||||
|
||||
bool is_nullable() const { return m_nullable; }
|
||||
void set_nullable(bool value) { m_nullable = value; }
|
||||
|
||||
// https://webidl.spec.whatwg.org/#dfn-includes-a-nullable-type
|
||||
bool includes_nullable_type() const;
|
||||
|
||||
// -> https://webidl.spec.whatwg.org/#dfn-includes-undefined
|
||||
bool includes_undefined() const;
|
||||
|
||||
Type const& innermost_type() const
|
||||
{
|
||||
// From step 4 of https://webidl.spec.whatwg.org/#dfn-distinguishable
|
||||
// "Consider the two "innermost" types derived by taking each type’s inner type if it is an annotated type, and then taking its inner type inner type if the result is a nullable type."
|
||||
// FIXME: Annotated types.
|
||||
VERIFY(!is_union());
|
||||
return *this;
|
||||
}
|
||||
|
||||
// https://webidl.spec.whatwg.org/#idl-any
|
||||
bool is_any() const { return is_plain() && m_name == "any"; }
|
||||
|
||||
// https://webidl.spec.whatwg.org/#idl-undefined
|
||||
bool is_undefined() const { return is_plain() && m_name == "undefined"; }
|
||||
|
||||
// https://webidl.spec.whatwg.org/#idl-boolean
|
||||
bool is_boolean() const { return is_plain() && m_name == "boolean"; }
|
||||
|
||||
// https://webidl.spec.whatwg.org/#idl-bigint
|
||||
bool is_bigint() const { return is_plain() && m_name == "bigint"; }
|
||||
|
||||
// https://webidl.spec.whatwg.org/#idl-object
|
||||
bool is_object() const { return is_plain() && m_name == "object"; }
|
||||
|
||||
// https://webidl.spec.whatwg.org/#idl-symbol
|
||||
bool is_symbol() const { return is_plain() && m_name == "symbol"; }
|
||||
|
||||
bool is_string() const { return is_plain() && m_name.is_one_of("ByteString", "CSSOMString", "DOMString", "USVString"); }
|
||||
|
||||
// https://webidl.spec.whatwg.org/#dfn-integer-type
|
||||
bool is_integer() const { return is_plain() && m_name.is_one_of("byte", "octet", "short", "unsigned short", "long", "unsigned long", "long long", "unsigned long long"); }
|
||||
|
||||
// https://webidl.spec.whatwg.org/#dfn-numeric-type
|
||||
bool is_numeric() const { return is_plain() && (is_integer() || is_floating_point()); }
|
||||
|
||||
// https://webidl.spec.whatwg.org/#dfn-primitive-type
|
||||
bool is_primitive() const { return is_plain() && (is_numeric() || is_boolean() || m_name == "bigint"); }
|
||||
|
||||
// https://webidl.spec.whatwg.org/#idl-sequence
|
||||
bool is_sequence() const { return is_parameterized() && m_name == "sequence"; }
|
||||
|
||||
// https://webidl.spec.whatwg.org/#dfn-distinguishable
|
||||
bool is_distinguishable_from(Interface const&, Type const& other) const;
|
||||
|
||||
bool is_json(Interface const&) const;
|
||||
|
||||
bool is_restricted_floating_point() const { return m_name.is_one_of("float", "double"); }
|
||||
bool is_unrestricted_floating_point() const { return m_name.is_one_of("unrestricted float", "unrestricted double"); }
|
||||
bool is_floating_point() const { return is_restricted_floating_point() || is_unrestricted_floating_point(); }
|
||||
|
||||
private:
|
||||
Kind m_kind;
|
||||
ByteString m_name;
|
||||
bool m_nullable { false };
|
||||
};
|
||||
|
||||
struct Parameter {
|
||||
NonnullRefPtr<Type const> type;
|
||||
ByteString name;
|
||||
bool optional { false };
|
||||
Optional<ByteString> optional_default_value;
|
||||
HashMap<ByteString, ByteString> extended_attributes;
|
||||
bool variadic { false };
|
||||
};
|
||||
|
||||
struct Function {
|
||||
NonnullRefPtr<Type const> return_type;
|
||||
ByteString name;
|
||||
Vector<Parameter> parameters;
|
||||
HashMap<ByteString, ByteString> extended_attributes;
|
||||
LineTrackingLexer::Position source_position;
|
||||
size_t overload_index { 0 };
|
||||
bool is_overloaded { false };
|
||||
|
||||
size_t shortest_length() const { return get_function_shortest_length(*this); }
|
||||
};
|
||||
|
||||
struct Constructor {
|
||||
ByteString name;
|
||||
Vector<Parameter> parameters;
|
||||
HashMap<ByteString, ByteString> extended_attributes;
|
||||
size_t overload_index { 0 };
|
||||
bool is_overloaded { false };
|
||||
|
||||
size_t shortest_length() const { return get_function_shortest_length(*this); }
|
||||
};
|
||||
|
||||
struct Constant {
|
||||
NonnullRefPtr<Type const> type;
|
||||
ByteString name;
|
||||
ByteString value;
|
||||
};
|
||||
|
||||
struct Attribute {
|
||||
bool inherit { false };
|
||||
bool readonly { false };
|
||||
NonnullRefPtr<Type const> type;
|
||||
ByteString name;
|
||||
HashMap<ByteString, ByteString> extended_attributes;
|
||||
|
||||
// Added for convenience after parsing
|
||||
ByteString getter_callback_name;
|
||||
ByteString setter_callback_name;
|
||||
};
|
||||
|
||||
struct DictionaryMember {
|
||||
bool required { false };
|
||||
NonnullRefPtr<Type const> type;
|
||||
ByteString name;
|
||||
HashMap<ByteString, ByteString> extended_attributes;
|
||||
Optional<ByteString> default_value;
|
||||
};
|
||||
|
||||
struct Dictionary {
|
||||
ByteString parent_name;
|
||||
Vector<DictionaryMember> members;
|
||||
};
|
||||
|
||||
struct Typedef {
|
||||
HashMap<ByteString, ByteString> extended_attributes;
|
||||
NonnullRefPtr<Type const> type;
|
||||
};
|
||||
|
||||
struct Enumeration {
|
||||
OrderedHashTable<ByteString> values;
|
||||
OrderedHashMap<ByteString, ByteString> translated_cpp_names;
|
||||
HashMap<ByteString, ByteString> extended_attributes;
|
||||
ByteString first_member;
|
||||
bool is_original_definition { true };
|
||||
};
|
||||
|
||||
struct CallbackFunction {
|
||||
NonnullRefPtr<Type const> return_type;
|
||||
Vector<Parameter> parameters;
|
||||
bool is_legacy_treat_non_object_as_null { false };
|
||||
};
|
||||
|
||||
class ParameterizedType : public Type {
|
||||
public:
|
||||
ParameterizedType(ByteString name, bool nullable, Vector<NonnullRefPtr<Type const>> parameters)
|
||||
: Type(Kind::Parameterized, move(name), nullable)
|
||||
, m_parameters(move(parameters))
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~ParameterizedType() override = default;
|
||||
|
||||
void generate_sequence_from_iterable(SourceGenerator& generator, ByteString const& cpp_name, ByteString const& iterable_cpp_name, ByteString const& iterator_method_cpp_name, IDL::Interface const&, size_t recursion_depth) const;
|
||||
|
||||
Vector<NonnullRefPtr<Type const>> const& parameters() const { return m_parameters; }
|
||||
Vector<NonnullRefPtr<Type const>>& parameters() { return m_parameters; }
|
||||
|
||||
private:
|
||||
Vector<NonnullRefPtr<Type const>> m_parameters;
|
||||
};
|
||||
|
||||
static inline size_t get_shortest_function_length(Vector<Function&> const& overload_set)
|
||||
{
|
||||
size_t shortest_length = SIZE_MAX;
|
||||
for (auto const& function : overload_set)
|
||||
shortest_length = min(function.shortest_length(), shortest_length);
|
||||
return shortest_length;
|
||||
}
|
||||
|
||||
class Interface {
|
||||
AK_MAKE_NONCOPYABLE(Interface);
|
||||
AK_MAKE_NONMOVABLE(Interface);
|
||||
|
||||
public:
|
||||
explicit Interface() = default;
|
||||
|
||||
ByteString name;
|
||||
ByteString parent_name;
|
||||
ByteString namespaced_name;
|
||||
ByteString implemented_name;
|
||||
|
||||
bool is_namespace { false };
|
||||
bool is_mixin { false };
|
||||
|
||||
HashMap<ByteString, ByteString> extended_attributes;
|
||||
|
||||
Vector<Attribute> attributes;
|
||||
Vector<Attribute> static_attributes;
|
||||
Vector<Constant> constants;
|
||||
Vector<Constructor> constructors;
|
||||
Vector<Function> functions;
|
||||
Vector<Function> static_functions;
|
||||
bool has_stringifier { false };
|
||||
Optional<ByteString> stringifier_attribute;
|
||||
bool has_unscopable_member { false };
|
||||
|
||||
Optional<NonnullRefPtr<Type const>> value_iterator_type;
|
||||
Optional<Tuple<NonnullRefPtr<Type const>, NonnullRefPtr<Type const>>> pair_iterator_types;
|
||||
Optional<NonnullRefPtr<Type const>> set_entry_type;
|
||||
bool is_set_readonly { false };
|
||||
|
||||
Optional<Function> named_property_getter;
|
||||
Optional<Function> named_property_setter;
|
||||
|
||||
Optional<Function> indexed_property_getter;
|
||||
Optional<Function> indexed_property_setter;
|
||||
|
||||
Optional<Function> named_property_deleter;
|
||||
|
||||
HashMap<ByteString, Dictionary> dictionaries;
|
||||
HashMap<ByteString, Enumeration> enumerations;
|
||||
HashMap<ByteString, Typedef> typedefs;
|
||||
HashMap<ByteString, Interface*> mixins;
|
||||
HashMap<ByteString, CallbackFunction> callback_functions;
|
||||
|
||||
// Added for convenience after parsing
|
||||
ByteString fully_qualified_name;
|
||||
ByteString constructor_class;
|
||||
ByteString prototype_class;
|
||||
ByteString prototype_base_class;
|
||||
ByteString namespace_class;
|
||||
ByteString global_mixin_class;
|
||||
HashMap<ByteString, HashTable<ByteString>> included_mixins;
|
||||
|
||||
ByteString module_own_path;
|
||||
Vector<Interface&> imported_modules;
|
||||
|
||||
HashMap<ByteString, Vector<Function&>> overload_sets;
|
||||
HashMap<ByteString, Vector<Function&>> static_overload_sets;
|
||||
HashMap<ByteString, Vector<Constructor&>> constructor_overload_sets;
|
||||
|
||||
// https://webidl.spec.whatwg.org/#dfn-support-indexed-properties
|
||||
bool supports_indexed_properties() const { return indexed_property_getter.has_value(); }
|
||||
|
||||
// https://webidl.spec.whatwg.org/#dfn-support-named-properties
|
||||
bool supports_named_properties() const { return named_property_getter.has_value(); }
|
||||
|
||||
// https://webidl.spec.whatwg.org/#dfn-legacy-platform-object
|
||||
bool is_legacy_platform_object() const { return !extended_attributes.contains("Global") && (supports_indexed_properties() || supports_named_properties()); }
|
||||
|
||||
bool will_generate_code() const
|
||||
{
|
||||
return !name.is_empty() || any_of(enumerations, [](auto& entry) { return entry.value.is_original_definition; });
|
||||
}
|
||||
};
|
||||
|
||||
class UnionType : public Type {
|
||||
public:
|
||||
UnionType(ByteString name, bool nullable, Vector<NonnullRefPtr<Type const>> member_types)
|
||||
: Type(Kind::Union, move(name), nullable)
|
||||
, m_member_types(move(member_types))
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~UnionType() override = default;
|
||||
|
||||
Vector<NonnullRefPtr<Type const>> const& member_types() const { return m_member_types; }
|
||||
Vector<NonnullRefPtr<Type const>>& member_types() { return m_member_types; }
|
||||
|
||||
// https://webidl.spec.whatwg.org/#dfn-flattened-union-member-types
|
||||
Vector<NonnullRefPtr<Type const>> flattened_member_types() const
|
||||
{
|
||||
// 1. Let T be the union type.
|
||||
|
||||
// 2. Initialize S to ∅.
|
||||
Vector<NonnullRefPtr<Type const>> types;
|
||||
|
||||
// 3. For each member type U of T:
|
||||
for (auto& type : m_member_types) {
|
||||
// FIXME: 1. If U is an annotated type, then set U to be the inner type of U.
|
||||
|
||||
// 2. If U is a nullable type, then set U to be the inner type of U. (NOTE: Not necessary as nullable is stored with Type and not as a separate struct)
|
||||
|
||||
// 3. If U is a union type, then add to S the flattened member types of U.
|
||||
if (type->is_union()) {
|
||||
auto& union_member_type = type->as_union();
|
||||
types.extend(union_member_type.flattened_member_types());
|
||||
} else {
|
||||
// 4. Otherwise, U is not a union type. Add U to S.
|
||||
types.append(type);
|
||||
}
|
||||
}
|
||||
|
||||
// 4. Return S.
|
||||
return types;
|
||||
}
|
||||
|
||||
// https://webidl.spec.whatwg.org/#dfn-number-of-nullable-member-types
|
||||
size_t number_of_nullable_member_types() const
|
||||
{
|
||||
// 1. Let T be the union type.
|
||||
|
||||
// 2. Initialize n to 0.
|
||||
size_t num_nullable_member_types = 0;
|
||||
|
||||
// 3. For each member type U of T:
|
||||
for (auto& type : m_member_types) {
|
||||
// 1. If U is a nullable type, then:
|
||||
if (type->is_nullable()) {
|
||||
// 1. Set n to n + 1.
|
||||
++num_nullable_member_types;
|
||||
|
||||
// 2. Set U to be the inner type of U. (NOTE: Not necessary as nullable is stored with Type and not as a separate struct)
|
||||
}
|
||||
|
||||
// 2. If U is a union type, then:
|
||||
if (type->is_union()) {
|
||||
auto& union_member_type = type->as_union();
|
||||
|
||||
// 1. Let m be the number of nullable member types of U.
|
||||
// 2. Set n to n + m.
|
||||
num_nullable_member_types += union_member_type.number_of_nullable_member_types();
|
||||
}
|
||||
}
|
||||
|
||||
// 4. Return n.
|
||||
return num_nullable_member_types;
|
||||
}
|
||||
|
||||
private:
|
||||
Vector<NonnullRefPtr<Type const>> m_member_types;
|
||||
};
|
||||
|
||||
// https://webidl.spec.whatwg.org/#dfn-optionality-value
|
||||
enum class Optionality {
|
||||
Required,
|
||||
Optional,
|
||||
Variadic,
|
||||
};
|
||||
|
||||
// https://webidl.spec.whatwg.org/#dfn-effective-overload-set
|
||||
class EffectiveOverloadSet {
|
||||
public:
|
||||
struct Item {
|
||||
int callable_id;
|
||||
Vector<NonnullRefPtr<Type const>> types;
|
||||
Vector<Optionality> optionality_values;
|
||||
};
|
||||
|
||||
EffectiveOverloadSet(Vector<Item> items, size_t distinguishing_argument_index)
|
||||
: m_items(move(items))
|
||||
, m_distinguishing_argument_index(distinguishing_argument_index)
|
||||
{
|
||||
}
|
||||
|
||||
Vector<Item>& items() { return m_items; }
|
||||
Vector<Item> const& items() const { return m_items; }
|
||||
|
||||
Item const& only_item() const
|
||||
{
|
||||
VERIFY(m_items.size() == 1);
|
||||
return m_items[0];
|
||||
}
|
||||
|
||||
bool is_empty() const { return m_items.is_empty(); }
|
||||
size_t size() const { return m_items.size(); }
|
||||
|
||||
size_t distinguishing_argument_index() const { return m_distinguishing_argument_index; }
|
||||
|
||||
template<typename Matches>
|
||||
bool has_overload_with_matching_argument_at_index(size_t index, Matches matches)
|
||||
{
|
||||
for (size_t i = 0; i < m_items.size(); ++i) {
|
||||
auto const& item = m_items[i];
|
||||
if (matches(item.types[index], item.optionality_values[index])) {
|
||||
m_last_matching_item_index = i;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
m_last_matching_item_index = {};
|
||||
return false;
|
||||
}
|
||||
|
||||
void remove_all_other_entries();
|
||||
|
||||
private:
|
||||
// FIXME: This should be an "ordered set".
|
||||
Vector<Item> m_items;
|
||||
size_t m_distinguishing_argument_index { 0 };
|
||||
|
||||
Optional<size_t> m_last_matching_item_index;
|
||||
};
|
||||
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue