2022-02-16 22:30:43 +00:00
/*
2024-10-04 11:19:50 +00:00
* Copyright ( c ) 2020 - 2023 , Andreas Kling < andreas @ ladybird . org >
2022-02-16 22:30:43 +00:00
* 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 >
2022-08-24 16:22:09 +00:00
* Copyright ( c ) 2022 , Sam Atkins < atkinssj @ serenityos . org >
2022-02-16 22:30:43 +00:00
*
* SPDX - License - Identifier : BSD - 2 - Clause
*/
# pragma once
2023-12-16 14:19:34 +00:00
# include <AK/ByteString.h>
2022-02-16 22:30:43 +00:00
# include <AK/HashMap.h>
2022-04-01 18:43:02 +00:00
# include <AK/NonnullRefPtr.h>
2022-02-16 22:30:43 +00:00
# include <AK/SourceGenerator.h>
# include <AK/StringBuilder.h>
# include <AK/Tuple.h>
# include <AK/TypeCasts.h>
namespace IDL {
template < typename FunctionType >
2022-08-22 13:14:32 +00:00
static size_t get_function_shortest_length ( FunctionType & function )
2022-02-16 22:30:43 +00:00
{
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 {
2023-12-16 14:19:34 +00:00
ByteString name ;
2022-02-16 22:30:43 +00:00
SequenceStorageType sequence_storage_type ;
} ;
2022-08-24 16:22:09 +00:00
class ParameterizedType ;
class UnionType ;
2023-03-23 16:41:16 +00:00
class Interface ;
2022-08-24 16:22:09 +00:00
class Type : public RefCounted < Type > {
public :
enum class Kind {
Plain , // AKA, Type.
Parameterized ,
Union ,
} ;
2022-02-16 22:30:43 +00:00
2023-12-16 14:19:34 +00:00
Type ( ByteString name , bool nullable )
2022-08-24 16:22:09 +00:00
: m_kind ( Kind : : Plain )
, m_name ( move ( name ) )
, m_nullable ( nullable )
{
}
2023-12-16 14:19:34 +00:00
Type ( Kind kind , ByteString name , bool nullable )
2022-08-24 16:22:09 +00:00
: m_kind ( kind )
, m_name ( move ( name ) )
, m_nullable ( nullable )
2022-02-16 22:30:43 +00:00
{
}
virtual ~ Type ( ) = default ;
2022-08-24 16:22:09 +00:00
Kind kind ( ) const { return m_kind ; }
2022-09-07 14:27:08 +00:00
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 ( ) ;
2023-12-16 14:19:34 +00:00
ByteString const & name ( ) const { return m_name ; }
2022-08-24 16:22:09 +00:00
bool is_nullable ( ) const { return m_nullable ; }
void set_nullable ( bool value ) { m_nullable = value ; }
2022-09-07 14:27:08 +00:00
// 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 " ) ; }
2022-02-16 22:30:43 +00:00
// https://webidl.spec.whatwg.org/#dfn-integer-type
2022-09-07 14:27:08 +00:00
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 " ) ; }
2022-02-16 22:30:43 +00:00
// https://webidl.spec.whatwg.org/#dfn-numeric-type
2024-05-27 15:04:58 +00:00
bool is_numeric ( ) const { return is_plain ( ) & & ( is_integer ( ) | | is_floating_point ( ) ) ; }
2022-04-03 16:21:29 +00:00
// https://webidl.spec.whatwg.org/#dfn-primitive-type
2022-09-07 14:27:08 +00:00
bool is_primitive ( ) const { return is_plain ( ) & & ( is_numeric ( ) | | is_boolean ( ) | | m_name = = " bigint " ) ; }
2022-08-24 16:22:09 +00:00
2022-09-07 14:27:08 +00:00
// https://webidl.spec.whatwg.org/#idl-sequence
bool is_sequence ( ) const { return is_parameterized ( ) & & m_name = = " sequence " ; }
2022-08-24 16:22:09 +00:00
2022-09-07 14:27:08 +00:00
// https://webidl.spec.whatwg.org/#dfn-distinguishable
2023-11-10 21:47:18 +00:00
bool is_distinguishable_from ( Interface const & , Type const & other ) const ;
2022-08-24 16:22:09 +00:00
2023-03-23 16:41:16 +00:00
bool is_json ( Interface const & ) const ;
2024-05-27 15:04:58 +00:00
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 ( ) ; }
2022-08-24 16:22:09 +00:00
private :
Kind m_kind ;
2023-12-16 14:19:34 +00:00
ByteString m_name ;
2022-08-24 16:22:09 +00:00
bool m_nullable { false } ;
2022-02-16 22:30:43 +00:00
} ;
struct Parameter {
2023-02-20 17:56:08 +00:00
NonnullRefPtr < Type const > type ;
2023-12-16 14:19:34 +00:00
ByteString name ;
2022-02-16 22:30:43 +00:00
bool optional { false } ;
2023-12-16 14:19:34 +00:00
Optional < ByteString > optional_default_value ;
HashMap < ByteString , ByteString > extended_attributes ;
2022-02-16 22:30:43 +00:00
bool variadic { false } ;
} ;
struct Function {
2023-02-20 17:56:08 +00:00
NonnullRefPtr < Type const > return_type ;
2023-12-16 14:19:34 +00:00
ByteString name ;
2022-02-16 22:30:43 +00:00
Vector < Parameter > parameters ;
2023-12-16 14:19:34 +00:00
HashMap < ByteString , ByteString > extended_attributes ;
2024-02-16 01:27:03 +00:00
LineTrackingLexer : : Position source_position ;
2022-03-05 18:51:17 +00:00
size_t overload_index { 0 } ;
bool is_overloaded { false } ;
2022-02-16 22:30:43 +00:00
2022-08-22 13:14:32 +00:00
size_t shortest_length ( ) const { return get_function_shortest_length ( * this ) ; }
2022-02-16 22:30:43 +00:00
} ;
struct Constructor {
2023-12-16 14:19:34 +00:00
ByteString name ;
2022-02-16 22:30:43 +00:00
Vector < Parameter > parameters ;
2023-12-16 14:19:34 +00:00
HashMap < ByteString , ByteString > extended_attributes ;
2024-03-26 13:15:38 +00:00
size_t overload_index { 0 } ;
bool is_overloaded { false } ;
2022-02-16 22:30:43 +00:00
2022-08-22 13:14:32 +00:00
size_t shortest_length ( ) const { return get_function_shortest_length ( * this ) ; }
2022-02-16 22:30:43 +00:00
} ;
struct Constant {
2023-02-20 17:56:08 +00:00
NonnullRefPtr < Type const > type ;
2023-12-16 14:19:34 +00:00
ByteString name ;
ByteString value ;
2022-02-16 22:30:43 +00:00
} ;
struct Attribute {
2022-04-05 15:09:42 +00:00
bool inherit { false } ;
2022-02-16 22:30:43 +00:00
bool readonly { false } ;
2023-02-20 17:56:08 +00:00
NonnullRefPtr < Type const > type ;
2023-12-16 14:19:34 +00:00
ByteString name ;
HashMap < ByteString , ByteString > extended_attributes ;
2022-02-16 22:30:43 +00:00
// Added for convenience after parsing
2023-12-16 14:19:34 +00:00
ByteString getter_callback_name ;
ByteString setter_callback_name ;
2022-02-16 22:30:43 +00:00
} ;
struct DictionaryMember {
bool required { false } ;
2023-02-20 17:56:08 +00:00
NonnullRefPtr < Type const > type ;
2023-12-16 14:19:34 +00:00
ByteString name ;
HashMap < ByteString , ByteString > extended_attributes ;
Optional < ByteString > default_value ;
2022-02-16 22:30:43 +00:00
} ;
struct Dictionary {
2023-12-16 14:19:34 +00:00
ByteString parent_name ;
2022-02-16 22:30:43 +00:00
Vector < DictionaryMember > members ;
} ;
2022-03-30 20:32:44 +00:00
struct Typedef {
2023-12-16 14:19:34 +00:00
HashMap < ByteString , ByteString > extended_attributes ;
2023-02-20 17:56:08 +00:00
NonnullRefPtr < Type const > type ;
2022-03-30 20:32:44 +00:00
} ;
2022-02-16 22:30:43 +00:00
struct Enumeration {
2023-12-16 14:19:34 +00:00
OrderedHashTable < ByteString > values ;
OrderedHashMap < ByteString , ByteString > translated_cpp_names ;
HashMap < ByteString , ByteString > extended_attributes ;
ByteString first_member ;
2022-02-16 22:30:43 +00:00
bool is_original_definition { true } ;
} ;
2022-03-30 20:35:13 +00:00
struct CallbackFunction {
2023-02-20 17:56:08 +00:00
NonnullRefPtr < Type const > return_type ;
2022-03-30 20:35:13 +00:00
Vector < Parameter > parameters ;
bool is_legacy_treat_non_object_as_null { false } ;
} ;
2022-08-24 16:22:09 +00:00
class ParameterizedType : public Type {
public :
2023-12-16 14:19:34 +00:00
ParameterizedType ( ByteString name , bool nullable , Vector < NonnullRefPtr < Type const > > parameters )
2022-08-24 16:22:09 +00:00
: Type ( Kind : : Parameterized , move ( name ) , nullable )
, m_parameters ( move ( parameters ) )
2022-02-16 22:30:43 +00:00
{
}
virtual ~ ParameterizedType ( ) override = default ;
2023-12-16 14:19:34 +00:00
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 ;
2022-08-24 16:22:09 +00:00
2023-03-06 13:17:01 +00:00
Vector < NonnullRefPtr < Type const > > const & parameters ( ) const { return m_parameters ; }
Vector < NonnullRefPtr < Type const > > & parameters ( ) { return m_parameters ; }
2022-08-24 16:22:09 +00:00
private :
2023-03-06 13:17:01 +00:00
Vector < NonnullRefPtr < Type const > > m_parameters ;
2022-02-16 22:30:43 +00:00
} ;
2022-03-05 18:51:17 +00:00
static inline size_t get_shortest_function_length ( Vector < Function & > const & overload_set )
{
2022-08-12 11:08:23 +00:00
size_t shortest_length = SIZE_MAX ;
2022-03-05 18:51:17 +00:00
for ( auto const & function : overload_set )
2022-08-22 13:14:32 +00:00
shortest_length = min ( function . shortest_length ( ) , shortest_length ) ;
2022-08-12 11:08:23 +00:00
return shortest_length ;
2022-03-05 18:51:17 +00:00
}
2022-04-30 17:27:50 +00:00
class Interface {
AK_MAKE_NONCOPYABLE ( Interface ) ;
AK_MAKE_NONMOVABLE ( Interface ) ;
public :
explicit Interface ( ) = default ;
2023-12-16 14:19:34 +00:00
ByteString name ;
ByteString parent_name ;
ByteString namespaced_name ;
2024-02-11 06:48:29 +00:00
ByteString implemented_name ;
2022-02-16 22:30:43 +00:00
2023-03-15 13:55:49 +00:00
bool is_namespace { false } ;
2022-02-16 23:45:57 +00:00
bool is_mixin { false } ;
2023-12-16 14:19:34 +00:00
HashMap < ByteString , ByteString > extended_attributes ;
2022-02-16 22:30:43 +00:00
Vector < Attribute > attributes ;
2024-04-01 13:03:41 +00:00
Vector < Attribute > static_attributes ;
2022-02-16 22:30:43 +00:00
Vector < Constant > constants ;
Vector < Constructor > constructors ;
Vector < Function > functions ;
Vector < Function > static_functions ;
bool has_stringifier { false } ;
2023-12-16 14:19:34 +00:00
Optional < ByteString > stringifier_attribute ;
2022-02-16 22:30:43 +00:00
bool has_unscopable_member { false } ;
2023-02-20 17:56:08 +00:00
Optional < NonnullRefPtr < Type const > > value_iterator_type ;
Optional < Tuple < NonnullRefPtr < Type const > , NonnullRefPtr < Type const > > > pair_iterator_types ;
2024-05-22 02:17:16 +00:00
Optional < NonnullRefPtr < Type const > > set_entry_type ;
bool is_set_readonly { false } ;
2022-02-16 22:30:43 +00:00
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 ;
2023-12-16 14:19:34 +00:00
HashMap < ByteString , Dictionary > dictionaries ;
HashMap < ByteString , Enumeration > enumerations ;
HashMap < ByteString , Typedef > typedefs ;
HashMap < ByteString , Interface * > mixins ;
HashMap < ByteString , CallbackFunction > callback_functions ;
2022-02-16 22:30:43 +00:00
// Added for convenience after parsing
2023-12-16 14:19:34 +00:00
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 ;
2022-04-30 17:27:50 +00:00
Vector < Interface & > imported_modules ;
2022-02-16 22:30:43 +00:00
2023-12-16 14:19:34 +00:00
HashMap < ByteString , Vector < Function & > > overload_sets ;
HashMap < ByteString , Vector < Function & > > static_overload_sets ;
2024-03-26 13:15:38 +00:00
HashMap < ByteString , Vector < Constructor & > > constructor_overload_sets ;
2022-03-05 18:51:17 +00:00
2022-02-16 22:30:43 +00:00
// 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 ( ) ) ; }
2022-03-30 20:30:12 +00:00
bool will_generate_code ( ) const
{
return ! name . is_empty ( ) | | any_of ( enumerations , [ ] ( auto & entry ) { return entry . value . is_original_definition ; } ) ;
}
2022-02-16 22:30:43 +00:00
} ;
2022-08-24 16:22:09 +00:00
class UnionType : public Type {
public :
2023-12-16 14:19:34 +00:00
UnionType ( ByteString name , bool nullable , Vector < NonnullRefPtr < Type const > > member_types )
2022-08-24 16:22:09 +00:00
: Type ( Kind : : Union , move ( name ) , nullable )
, m_member_types ( move ( member_types ) )
2022-02-19 21:57:34 +00:00
{
}
virtual ~ UnionType ( ) override = default ;
2023-03-06 13:17:01 +00:00
Vector < NonnullRefPtr < Type const > > const & member_types ( ) const { return m_member_types ; }
Vector < NonnullRefPtr < Type const > > & member_types ( ) { return m_member_types ; }
2022-02-19 21:57:34 +00:00
// https://webidl.spec.whatwg.org/#dfn-flattened-union-member-types
2023-03-06 13:17:01 +00:00
Vector < NonnullRefPtr < Type const > > flattened_member_types ( ) const
2022-02-19 21:57:34 +00:00
{
// 1. Let T be the union type.
// 2. Initialize S to ∅.
2023-03-06 13:17:01 +00:00
Vector < NonnullRefPtr < Type const > > types ;
2022-02-19 21:57:34 +00:00
// 3. For each member type U of T:
2022-08-24 16:22:09 +00:00
for ( auto & type : m_member_types ) {
2022-02-19 21:57:34 +00:00
// 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.
2023-03-06 13:17:01 +00:00
if ( type - > is_union ( ) ) {
auto & union_member_type = type - > as_union ( ) ;
2022-02-19 21:57:34 +00:00
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:
2022-08-24 16:22:09 +00:00
for ( auto & type : m_member_types ) {
2022-02-19 21:57:34 +00:00
// 1. If U is a nullable type, then:
2023-03-06 13:17:01 +00:00
if ( type - > is_nullable ( ) ) {
2022-02-19 21:57:34 +00:00
// 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:
2023-03-06 13:17:01 +00:00
if ( type - > is_union ( ) ) {
auto & union_member_type = type - > as_union ( ) ;
2022-02-19 21:57:34 +00:00
// 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 ;
}
2022-08-24 16:22:09 +00:00
private :
2023-03-06 13:17:01 +00:00
Vector < NonnullRefPtr < Type const > > m_member_types ;
2022-02-19 21:57:34 +00:00
} ;
2022-09-08 16:19:14 +00:00
// 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 ;
2023-03-06 13:17:01 +00:00
Vector < NonnullRefPtr < Type const > > types ;
2022-09-08 16:19:14 +00:00
Vector < Optionality > optionality_values ;
} ;
2023-11-10 21:38:59 +00:00
EffectiveOverloadSet ( Vector < Item > items , size_t distinguishing_argument_index )
2022-09-08 16:19:14 +00:00
: m_items ( move ( items ) )
2023-11-10 21:38:59 +00:00
, m_distinguishing_argument_index ( distinguishing_argument_index )
2022-09-08 16:19:14 +00:00
{
}
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 ( ) ; }
2023-11-10 21:38:59 +00:00
size_t distinguishing_argument_index ( ) const { return m_distinguishing_argument_index ; }
2022-09-08 16:19:14 +00:00
template < typename Matches >
bool has_overload_with_matching_argument_at_index ( size_t index , Matches matches )
{
2022-11-29 13:40:05 +00:00
for ( size_t i = 0 ; i < m_items . size ( ) ; + + i ) {
auto const & item = m_items [ i ] ;
2022-09-08 16:19:14 +00:00
if ( matches ( item . types [ index ] , item . optionality_values [ index ] ) ) {
2022-11-29 13:40:05 +00:00
m_last_matching_item_index = i ;
2022-09-08 16:19:14 +00:00
return true ;
}
}
2022-11-29 13:40:05 +00:00
m_last_matching_item_index = { } ;
2022-09-08 16:19:14 +00:00
return false ;
}
void remove_all_other_entries ( ) ;
private :
// FIXME: This should be an "ordered set".
Vector < Item > m_items ;
2023-11-10 21:38:59 +00:00
size_t m_distinguishing_argument_index { 0 } ;
2022-09-08 16:19:14 +00:00
2022-11-29 13:40:05 +00:00
Optional < size_t > m_last_matching_item_index ;
2022-09-08 16:19:14 +00:00
} ;
2022-02-16 22:30:43 +00:00
}