Types.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. /*
  2. * Copyright (c) 2022, Sam Atkins <atkinssj@serenityos.org>
  3. * Copyright (c) 2023, Luke Wilde <lukew@serenityos.org>
  4. *
  5. * SPDX-License-Identifier: BSD-2-Clause
  6. */
  7. #include <AK/Debug.h>
  8. #include <LibIDL/Types.h>
  9. namespace IDL {
  10. ParameterizedType const& Type::as_parameterized() const
  11. {
  12. return verify_cast<ParameterizedType const>(*this);
  13. }
  14. ParameterizedType& Type::as_parameterized()
  15. {
  16. return verify_cast<ParameterizedType>(*this);
  17. }
  18. UnionType const& Type::as_union() const
  19. {
  20. return verify_cast<UnionType const>(*this);
  21. }
  22. UnionType& Type::as_union()
  23. {
  24. return verify_cast<UnionType>(*this);
  25. }
  26. // https://webidl.spec.whatwg.org/#dfn-includes-a-nullable-type
  27. bool Type::includes_nullable_type() const
  28. {
  29. // A type includes a nullable type if:
  30. // - the type is a nullable type, or
  31. if (is_nullable())
  32. return true;
  33. // FIXME: - the type is an annotated type and its inner type is a nullable type, or
  34. // - the type is a union type and its number of nullable member types is 1.
  35. if (is_union() && as_union().number_of_nullable_member_types() == 1)
  36. return true;
  37. return false;
  38. }
  39. // https://webidl.spec.whatwg.org/#dfn-includes-undefined
  40. bool Type::includes_undefined() const
  41. {
  42. // A type includes undefined if:
  43. // - the type is undefined, or
  44. if (is_undefined())
  45. return true;
  46. // - the type is a nullable type and its inner type includes undefined, or
  47. // NOTE: We don't treat nullable as its own type, so this is handled by the other cases.
  48. // FIXME: - the type is an annotated type and its inner type includes undefined, or
  49. // - the type is a union type and one of its member types includes undefined.
  50. if (is_union()) {
  51. for (auto& type : as_union().member_types()) {
  52. if (type->includes_undefined())
  53. return true;
  54. }
  55. }
  56. return false;
  57. }
  58. // https://webidl.spec.whatwg.org/#dfn-distinguishable
  59. bool Type::is_distinguishable_from(IDL::Interface const& interface, IDL::Type const& other) const
  60. {
  61. // 1. If one type includes a nullable type and the other type either includes a nullable type,
  62. // is a union type with flattened member types including a dictionary type, or is a dictionary type,
  63. // return false.
  64. 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())))
  65. return false;
  66. // 2. If both types are either a union type or nullable union type, return true if each member type
  67. // of the one is distinguishable with each member type of the other, or false otherwise.
  68. if (is_union() && other.is_union()) {
  69. auto const& this_union = as_union();
  70. auto const& other_union = other.as_union();
  71. for (auto& this_member_type : this_union.member_types()) {
  72. for (auto& other_member_type : other_union.member_types()) {
  73. if (!this_member_type->is_distinguishable_from(interface, other_member_type))
  74. return false;
  75. }
  76. }
  77. return true;
  78. }
  79. // 3. If one type is a union type or nullable union type, return true if each member type of the union
  80. // type is distinguishable with the non-union type, or false otherwise.
  81. if (is_union() || other.is_union()) {
  82. auto const& the_union = is_union() ? as_union() : other.as_union();
  83. auto const& non_union = is_union() ? other : *this;
  84. for (auto& member_type : the_union.member_types()) {
  85. if (!non_union.is_distinguishable_from(interface, member_type))
  86. return false;
  87. }
  88. return true;
  89. }
  90. // 4. Consider the two "innermost" types derived by taking each type’s inner type if it is an annotated type,
  91. // and then taking its inner type inner type if the result is a nullable type. If these two innermost types
  92. // appear or are in categories appearing in the following table and there is a “●” mark in the corresponding
  93. // entry or there is a letter in the corresponding entry and the designated additional requirement below the
  94. // table is satisfied, then return true. Otherwise return false.
  95. auto const& this_innermost_type = innermost_type();
  96. auto const& other_innermost_type = other.innermost_type();
  97. enum class DistinguishabilityCategory {
  98. Undefined,
  99. Boolean,
  100. Numeric,
  101. BigInt,
  102. String,
  103. Object,
  104. Symbol,
  105. InterfaceLike,
  106. CallbackFunction,
  107. DictionaryLike,
  108. SequenceLike,
  109. __Count
  110. };
  111. // See https://webidl.spec.whatwg.org/#distinguishable-table
  112. // clang-format off
  113. static constexpr bool table[to_underlying(DistinguishabilityCategory::__Count)][to_underlying(DistinguishabilityCategory::__Count)] {
  114. {false, true, true, true, true, true, true, true, true, false, true},
  115. { true, false, true, true, true, true, true, true, true, true, true},
  116. { true, true, false, true, true, true, true, true, true, true, true},
  117. { true, true, true, false, true, true, true, true, true, true, true},
  118. { true, true, true, true, false, true, true, true, true, true, true},
  119. { true, true, true, true, true, false, true, false, false, false, false},
  120. { true, true, true, true, true, true, false, true, true, true, true},
  121. { true, true, true, true, true, false, true, false, true, true, true},
  122. { true, true, true, true, true, false, true, true, false, false, true},
  123. {false, true, true, true, true, false, true, true, false, false, true},
  124. { true, true, true, true, true, false, true, true, true, true, false},
  125. };
  126. // clang-format on
  127. auto determine_category = [&interface](Type const& type) -> DistinguishabilityCategory {
  128. if (type.is_undefined())
  129. return DistinguishabilityCategory::Undefined;
  130. if (type.is_boolean())
  131. return DistinguishabilityCategory::Boolean;
  132. if (type.is_numeric())
  133. return DistinguishabilityCategory::Numeric;
  134. if (type.is_bigint())
  135. return DistinguishabilityCategory::BigInt;
  136. if (type.is_string())
  137. return DistinguishabilityCategory::String;
  138. if (type.is_object())
  139. return DistinguishabilityCategory::Object;
  140. if (type.is_symbol())
  141. return DistinguishabilityCategory::Symbol;
  142. // FIXME: InterfaceLike - see below
  143. // FIXME: CallbackFunction
  144. // DictionaryLike
  145. // * Dictionary Types
  146. // * Record Types
  147. // FIXME: * Callback Interface Types
  148. if (interface.dictionaries.contains(type.name()) || (type.is_parameterized() && type.name() == "record"sv))
  149. return DistinguishabilityCategory::DictionaryLike;
  150. // FIXME: Frozen array types are included in "sequence-like"
  151. if (type.is_sequence())
  152. return DistinguishabilityCategory::SequenceLike;
  153. // 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.
  154. dbgln_if(IDL_DEBUG, "Unable to determine category for type named '{}', assuming it's an interface type.", type.name());
  155. return DistinguishabilityCategory::InterfaceLike;
  156. };
  157. auto this_distinguishability = determine_category(this_innermost_type);
  158. auto other_distinguishability = determine_category(other_innermost_type);
  159. if (this_distinguishability == DistinguishabilityCategory::InterfaceLike && other_distinguishability == DistinguishabilityCategory::InterfaceLike) {
  160. // The two identified interface-like types are not the same, and
  161. // FIXME: no single platform object implements both interface-like types.
  162. return this_innermost_type.name() != other_innermost_type.name();
  163. }
  164. return table[to_underlying(this_distinguishability)][to_underlying(other_distinguishability)];
  165. }
  166. // https://webidl.spec.whatwg.org/#dfn-json-types
  167. bool Type::is_json(Interface const& interface) const
  168. {
  169. // The JSON types are:
  170. // - numeric types,
  171. if (is_numeric())
  172. return true;
  173. // - boolean,
  174. if (is_boolean())
  175. return true;
  176. // - string types,
  177. if (is_string() || interface.enumerations.find(m_name) != interface.enumerations.end())
  178. return true;
  179. // - object,
  180. if (is_object())
  181. return true;
  182. // - nullable types whose inner type is a JSON type,
  183. // - annotated types whose inner type is a JSON type,
  184. // NOTE: We don't separate nullable and annotated into separate types.
  185. // - union types whose member types are JSON types,
  186. if (is_union()) {
  187. auto const& union_type = as_union();
  188. for (auto const& type : union_type.member_types()) {
  189. if (!type->is_json(interface))
  190. return false;
  191. }
  192. return true;
  193. }
  194. // - typedefs whose type being given a new name is a JSON type,
  195. auto typedef_iterator = interface.typedefs.find(m_name);
  196. if (typedef_iterator != interface.typedefs.end())
  197. return typedef_iterator->value.type->is_json(interface);
  198. // - sequence types whose parameterized type is a JSON type,
  199. // - frozen array types whose parameterized type is a JSON type,
  200. // - records where all of their values are JSON types,
  201. if (is_parameterized() && m_name.is_one_of("sequence", "FrozenArray", "record")) {
  202. auto const& parameterized_type = as_parameterized();
  203. for (auto const& parameter : parameterized_type.parameters()) {
  204. if (!parameter->is_json(interface))
  205. return false;
  206. }
  207. return true;
  208. }
  209. // - dictionary types where the types of all members declared on the dictionary and all its inherited dictionaries are JSON types,
  210. auto dictionary_iterator = interface.dictionaries.find(m_name);
  211. if (dictionary_iterator != interface.dictionaries.end()) {
  212. auto const& dictionary = dictionary_iterator->value;
  213. for (auto const& member : dictionary.members) {
  214. if (!member.type->is_json(interface))
  215. return false;
  216. }
  217. return true;
  218. }
  219. // - interface types that have a toJSON operation declared on themselves or one of their inherited interfaces.
  220. Optional<Interface const&> current_interface_for_to_json;
  221. if (m_name == interface.name) {
  222. current_interface_for_to_json = interface;
  223. } else {
  224. // NOTE: Interface types must have the IDL file of their interface imported.
  225. // Though the type name may not refer to an interface, so we don't assert this here.
  226. auto imported_interface_iterator = interface.imported_modules.find_if([this](IDL::Interface const& imported_interface) {
  227. return imported_interface.name == m_name;
  228. });
  229. if (imported_interface_iterator != interface.imported_modules.end())
  230. current_interface_for_to_json = *imported_interface_iterator;
  231. }
  232. while (current_interface_for_to_json.has_value()) {
  233. auto to_json_iterator = current_interface_for_to_json->functions.find_if([](IDL::Function const& function) {
  234. return function.name == "toJSON"sv;
  235. });
  236. if (to_json_iterator != current_interface_for_to_json->functions.end())
  237. return true;
  238. if (current_interface_for_to_json->parent_name.is_empty())
  239. break;
  240. auto imported_interface_iterator = current_interface_for_to_json->imported_modules.find_if([&current_interface_for_to_json](IDL::Interface const& imported_interface) {
  241. return imported_interface.name == current_interface_for_to_json->parent_name;
  242. });
  243. // Inherited interfaces must have their IDL files imported.
  244. VERIFY(imported_interface_iterator != interface.imported_modules.end());
  245. current_interface_for_to_json = *imported_interface_iterator;
  246. }
  247. return false;
  248. }
  249. void EffectiveOverloadSet::remove_all_other_entries()
  250. {
  251. Vector<Item> new_items;
  252. new_items.append(m_items[*m_last_matching_item_index]);
  253. m_items = move(new_items);
  254. }
  255. }