LibIDL+WrapperGenerator: Make it easier to work with IDL::Type classes
Track the kind of Type it is, and use that to provide some convenient `is_foo()` / `as_foo()` methods. While I was at it, made these all classes instead of structs and made their data private.
This commit is contained in:
parent
c4668053d1
commit
7c8ef79898
Notes:
sideshowbarker
2024-07-17 06:53:48 +09:00
Author: https://github.com/AtkinsSJ Commit: https://github.com/SerenityOS/serenity/commit/7c8ef79898 Pull-request: https://github.com/SerenityOS/serenity/pull/15170
6 changed files with 288 additions and 217 deletions
|
@ -16,47 +16,48 @@ Vector<StringView> s_header_search_paths;
|
|||
|
||||
namespace IDL {
|
||||
|
||||
// FIXME: Generate this automatically somehow.
|
||||
static bool is_wrappable_type(Type const& type)
|
||||
{
|
||||
if (type.name == "EventTarget")
|
||||
if (type.name() == "EventTarget")
|
||||
return true;
|
||||
if (type.name == "Node")
|
||||
if (type.name() == "Node")
|
||||
return true;
|
||||
if (type.name == "Document")
|
||||
if (type.name() == "Document")
|
||||
return true;
|
||||
if (type.name == "Text")
|
||||
if (type.name() == "Text")
|
||||
return true;
|
||||
if (type.name == "DocumentType")
|
||||
if (type.name() == "DocumentType")
|
||||
return true;
|
||||
if (type.name.ends_with("Element"sv))
|
||||
if (type.name().ends_with("Element"sv))
|
||||
return true;
|
||||
if (type.name.ends_with("Event"sv))
|
||||
if (type.name().ends_with("Event"sv))
|
||||
return true;
|
||||
if (type.name == "ImageData")
|
||||
if (type.name() == "ImageData")
|
||||
return true;
|
||||
if (type.name == "Window")
|
||||
if (type.name() == "Window")
|
||||
return true;
|
||||
if (type.name == "Range")
|
||||
if (type.name() == "Range")
|
||||
return true;
|
||||
if (type.name == "Selection")
|
||||
if (type.name() == "Selection")
|
||||
return true;
|
||||
if (type.name == "Attribute")
|
||||
if (type.name() == "Attribute")
|
||||
return true;
|
||||
if (type.name == "NamedNodeMap")
|
||||
if (type.name() == "NamedNodeMap")
|
||||
return true;
|
||||
if (type.name == "TextMetrics")
|
||||
if (type.name() == "TextMetrics")
|
||||
return true;
|
||||
if (type.name == "AbortSignal")
|
||||
if (type.name() == "AbortSignal")
|
||||
return true;
|
||||
if (type.name == "CanvasRenderingContext2D")
|
||||
if (type.name() == "CanvasRenderingContext2D")
|
||||
return true;
|
||||
if (type.name == "WebGLRenderingContext")
|
||||
if (type.name() == "WebGLRenderingContext")
|
||||
return true;
|
||||
if (type.name == "URLSearchParams")
|
||||
if (type.name() == "URLSearchParams")
|
||||
return true;
|
||||
if (type.name == "Blob")
|
||||
if (type.name() == "Blob")
|
||||
return true;
|
||||
if (type.name == "Path2D")
|
||||
if (type.name() == "Path2D")
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
@ -75,99 +76,99 @@ static StringView sequence_storage_type_to_cpp_storage_type_name(SequenceStorage
|
|||
|
||||
static bool impl_is_wrapper(Type const& type)
|
||||
{
|
||||
if (type.name == "StyleSheet"sv)
|
||||
if (type.name() == "StyleSheet"sv)
|
||||
return true;
|
||||
|
||||
if (type.name == "CSSStyleSheet"sv)
|
||||
if (type.name() == "CSSStyleSheet"sv)
|
||||
return true;
|
||||
|
||||
if (type.name == "StyleSheetList"sv)
|
||||
if (type.name() == "StyleSheetList"sv)
|
||||
return true;
|
||||
|
||||
if (type.name == "CSSRuleList"sv)
|
||||
if (type.name() == "CSSRuleList"sv)
|
||||
return true;
|
||||
|
||||
if (type.name == "CSSRule"sv)
|
||||
if (type.name() == "CSSRule"sv)
|
||||
return true;
|
||||
|
||||
if (type.name == "CSSStyleRule"sv)
|
||||
if (type.name() == "CSSStyleRule"sv)
|
||||
return true;
|
||||
|
||||
if (type.name == "CSSFontFaceRule"sv)
|
||||
if (type.name() == "CSSFontFaceRule"sv)
|
||||
return true;
|
||||
|
||||
if (type.name == "CSSConditionRule"sv)
|
||||
if (type.name() == "CSSConditionRule"sv)
|
||||
return true;
|
||||
|
||||
if (type.name == "CSSGroupingRule"sv)
|
||||
if (type.name() == "CSSGroupingRule"sv)
|
||||
return true;
|
||||
|
||||
if (type.name == "CSSMediaRule"sv)
|
||||
if (type.name() == "CSSMediaRule"sv)
|
||||
return true;
|
||||
|
||||
if (type.name == "CSSImportRule"sv)
|
||||
if (type.name() == "CSSImportRule"sv)
|
||||
return true;
|
||||
|
||||
if (type.name == "EventTarget"sv)
|
||||
if (type.name() == "EventTarget"sv)
|
||||
return true;
|
||||
|
||||
if (type.name == "Node"sv)
|
||||
if (type.name() == "Node"sv)
|
||||
return true;
|
||||
if (type.name == "ShadowRoot"sv)
|
||||
if (type.name() == "ShadowRoot"sv)
|
||||
return true;
|
||||
if (type.name == "DocumentTemporary"sv)
|
||||
if (type.name() == "DocumentTemporary"sv)
|
||||
return true;
|
||||
if (type.name == "Text"sv)
|
||||
if (type.name() == "Text"sv)
|
||||
return true;
|
||||
if (type.name == "Document"sv)
|
||||
if (type.name() == "Document"sv)
|
||||
return true;
|
||||
if (type.name == "DocumentType"sv)
|
||||
if (type.name() == "DocumentType"sv)
|
||||
return true;
|
||||
if (type.name.ends_with("Element"sv))
|
||||
if (type.name().ends_with("Element"sv))
|
||||
return true;
|
||||
if (type.name == "XMLHttpRequest"sv)
|
||||
if (type.name() == "XMLHttpRequest"sv)
|
||||
return true;
|
||||
if (type.name == "XMLHttpRequestEventTarget"sv)
|
||||
if (type.name() == "XMLHttpRequestEventTarget"sv)
|
||||
return true;
|
||||
if (type.name == "AbortSignal"sv)
|
||||
if (type.name() == "AbortSignal"sv)
|
||||
return true;
|
||||
if (type.name == "WebSocket"sv)
|
||||
if (type.name() == "WebSocket"sv)
|
||||
return true;
|
||||
if (type.name == "Worker"sv)
|
||||
if (type.name() == "Worker"sv)
|
||||
return true;
|
||||
if (type.name == "NodeIterator"sv)
|
||||
if (type.name() == "NodeIterator"sv)
|
||||
return true;
|
||||
if (type.name == "TreeWalker"sv)
|
||||
if (type.name() == "TreeWalker"sv)
|
||||
return true;
|
||||
if (type.name == "MediaQueryList"sv)
|
||||
if (type.name() == "MediaQueryList"sv)
|
||||
return true;
|
||||
if (type.name == "MessagePort"sv)
|
||||
if (type.name() == "MessagePort"sv)
|
||||
return true;
|
||||
if (type.name == "NodeFilter"sv)
|
||||
if (type.name() == "NodeFilter"sv)
|
||||
return true;
|
||||
if (type.name == "DOMTokenList"sv)
|
||||
if (type.name() == "DOMTokenList"sv)
|
||||
return true;
|
||||
if (type.name == "DOMStringMap"sv)
|
||||
if (type.name() == "DOMStringMap"sv)
|
||||
return true;
|
||||
if (type.name == "MutationRecord"sv)
|
||||
if (type.name() == "MutationRecord"sv)
|
||||
return true;
|
||||
if (type.name == "CanvasRenderingContext2D"sv)
|
||||
if (type.name() == "CanvasRenderingContext2D"sv)
|
||||
return true;
|
||||
if (type.name == "WebGLRenderingContext"sv)
|
||||
if (type.name() == "WebGLRenderingContext"sv)
|
||||
return true;
|
||||
if (type.name == "Path2D"sv)
|
||||
if (type.name() == "Path2D"sv)
|
||||
return true;
|
||||
if (type.name == "Storage"sv)
|
||||
if (type.name() == "Storage"sv)
|
||||
return true;
|
||||
if (type.name == "File"sv)
|
||||
if (type.name() == "File"sv)
|
||||
return true;
|
||||
if (type.name == "Blob"sv)
|
||||
if (type.name() == "Blob"sv)
|
||||
return true;
|
||||
if (type.name == "URL"sv)
|
||||
if (type.name() == "URL"sv)
|
||||
return true;
|
||||
if (type.name == "URLSearchParams"sv)
|
||||
if (type.name() == "URLSearchParams"sv)
|
||||
return true;
|
||||
if (type.name == "DOMException"sv)
|
||||
if (type.name() == "DOMException"sv)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
|
@ -202,51 +203,51 @@ CppType idl_type_name_to_cpp_type(Type const& type, Interface const& interface)
|
|||
{
|
||||
if (is_wrappable_type(type)) {
|
||||
if (impl_is_wrapper(type)) {
|
||||
return { .name = String::formatted("JS::Handle<{}>", type.name), .sequence_storage_type = SequenceStorageType::MarkedVector };
|
||||
return { .name = String::formatted("JS::Handle<{}>", type.name()), .sequence_storage_type = SequenceStorageType::MarkedVector };
|
||||
}
|
||||
|
||||
if (type.nullable)
|
||||
return { .name = String::formatted("RefPtr<{}>", type.name), .sequence_storage_type = SequenceStorageType::Vector };
|
||||
if (type.is_nullable())
|
||||
return { .name = String::formatted("RefPtr<{}>", type.name()), .sequence_storage_type = SequenceStorageType::Vector };
|
||||
|
||||
return { .name = String::formatted("NonnullRefPtr<{}>", type.name), .sequence_storage_type = SequenceStorageType::Vector };
|
||||
return { .name = String::formatted("NonnullRefPtr<{}>", type.name()), .sequence_storage_type = SequenceStorageType::Vector };
|
||||
}
|
||||
|
||||
if (type.is_string())
|
||||
return { .name = "String", .sequence_storage_type = SequenceStorageType::Vector };
|
||||
|
||||
if (type.name == "double" && !type.nullable)
|
||||
if (type.name() == "double" && !type.is_nullable())
|
||||
return { .name = "double", .sequence_storage_type = SequenceStorageType::Vector };
|
||||
|
||||
if (type.name == "float" && !type.nullable)
|
||||
if (type.name() == "float" && !type.is_nullable())
|
||||
return { .name = "float", .sequence_storage_type = SequenceStorageType::Vector };
|
||||
|
||||
if (type.name == "boolean" && !type.nullable)
|
||||
if (type.name() == "boolean" && !type.is_nullable())
|
||||
return { .name = "bool", .sequence_storage_type = SequenceStorageType::Vector };
|
||||
|
||||
if (type.name == "unsigned long" && !type.nullable)
|
||||
if (type.name() == "unsigned long" && !type.is_nullable())
|
||||
return { .name = "u32", .sequence_storage_type = SequenceStorageType::Vector };
|
||||
|
||||
if (type.name == "unsigned short" && !type.nullable)
|
||||
if (type.name() == "unsigned short" && !type.is_nullable())
|
||||
return { .name = "u16", .sequence_storage_type = SequenceStorageType::Vector };
|
||||
|
||||
if (type.name == "long long" && !type.nullable)
|
||||
if (type.name() == "long long" && !type.is_nullable())
|
||||
return { .name = "i64", .sequence_storage_type = SequenceStorageType::Vector };
|
||||
|
||||
if (type.name == "unsigned long long" && !type.nullable)
|
||||
if (type.name() == "unsigned long long" && !type.is_nullable())
|
||||
return { .name = "u64", .sequence_storage_type = SequenceStorageType::Vector };
|
||||
|
||||
if (type.name == "long" && !type.nullable)
|
||||
if (type.name() == "long" && !type.is_nullable())
|
||||
return { .name = "i32", .sequence_storage_type = SequenceStorageType::Vector };
|
||||
|
||||
if (type.name == "any")
|
||||
if (type.name() == "any")
|
||||
return { .name = "JS::Value", .sequence_storage_type = SequenceStorageType::MarkedVector };
|
||||
|
||||
if (type.name == "BufferSource")
|
||||
if (type.name() == "BufferSource")
|
||||
return { .name = "JS::Handle<JS::Object>", .sequence_storage_type = SequenceStorageType::MarkedVector };
|
||||
|
||||
if (type.name == "sequence") {
|
||||
if (type.name() == "sequence") {
|
||||
auto& parameterized_type = verify_cast<ParameterizedType>(type);
|
||||
auto& sequence_type = parameterized_type.parameters.first();
|
||||
auto& sequence_type = parameterized_type.parameters().first();
|
||||
auto sequence_cpp_type = idl_type_name_to_cpp_type(sequence_type, interface);
|
||||
auto storage_type_name = sequence_storage_type_to_cpp_storage_type_name(sequence_cpp_type.sequence_storage_type);
|
||||
|
||||
|
@ -256,10 +257,10 @@ CppType idl_type_name_to_cpp_type(Type const& type, Interface const& interface)
|
|||
return { .name = String::formatted("{}<{}>", storage_type_name, sequence_cpp_type.name), .sequence_storage_type = SequenceStorageType::Vector };
|
||||
}
|
||||
|
||||
if (type.name == "record") {
|
||||
if (type.name() == "record") {
|
||||
auto& parameterized_type = verify_cast<ParameterizedType>(type);
|
||||
auto& record_key_type = parameterized_type.parameters[0];
|
||||
auto& record_value_type = parameterized_type.parameters[1];
|
||||
auto& record_key_type = parameterized_type.parameters()[0];
|
||||
auto& record_value_type = parameterized_type.parameters()[1];
|
||||
auto record_key_cpp_type = idl_type_name_to_cpp_type(record_key_type, interface);
|
||||
auto record_value_cpp_type = idl_type_name_to_cpp_type(record_value_type, interface);
|
||||
|
||||
|
@ -271,14 +272,14 @@ CppType idl_type_name_to_cpp_type(Type const& type, Interface const& interface)
|
|||
return { .name = union_type_to_variant(union_type, interface), .sequence_storage_type = SequenceStorageType::Vector };
|
||||
}
|
||||
|
||||
if (!type.nullable) {
|
||||
if (!type.is_nullable()) {
|
||||
for (auto& dictionary : interface.dictionaries) {
|
||||
if (type.name == dictionary.key)
|
||||
return { .name = type.name, .sequence_storage_type = SequenceStorageType::Vector };
|
||||
if (type.name() == dictionary.key)
|
||||
return { .name = type.name(), .sequence_storage_type = SequenceStorageType::Vector };
|
||||
}
|
||||
}
|
||||
|
||||
dbgln("Unimplemented type for idl_type_name_to_cpp_type: {}{}", type.name, type.nullable ? "?" : "");
|
||||
dbgln("Unimplemented type for idl_type_name_to_cpp_type: {}{}", type.name(), type.is_nullable() ? "?" : "");
|
||||
TODO();
|
||||
}
|
||||
|
||||
|
@ -366,11 +367,11 @@ static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter
|
|||
scoped_generator.set("js_name", js_name);
|
||||
scoped_generator.set("js_suffix", js_suffix);
|
||||
scoped_generator.set("legacy_null_to_empty_string", legacy_null_to_empty_string ? "true" : "false");
|
||||
scoped_generator.set("parameter.type.name", parameter.type->name);
|
||||
if (parameter.type->name == "Window")
|
||||
scoped_generator.set("parameter.type.name", parameter.type->name());
|
||||
if (parameter.type->name() == "Window")
|
||||
scoped_generator.set("wrapper_name", "HTML::Window");
|
||||
else {
|
||||
scoped_generator.set("wrapper_name", String::formatted("{}Wrapper", parameter.type->name));
|
||||
scoped_generator.set("wrapper_name", String::formatted("{}Wrapper", parameter.type->name()));
|
||||
}
|
||||
|
||||
if (optional_default_value.has_value())
|
||||
|
@ -389,7 +390,7 @@ static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter
|
|||
}
|
||||
)~~~");
|
||||
} else if (!optional) {
|
||||
if (!parameter.type->nullable) {
|
||||
if (!parameter.type->is_nullable()) {
|
||||
scoped_generator.append(R"~~~(
|
||||
String @cpp_name@;
|
||||
if (@js_name@@js_suffix@.is_null() && @legacy_null_to_empty_string@) {
|
||||
|
@ -414,7 +415,7 @@ static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter
|
|||
else
|
||||
@cpp_name@ = TRY(@js_name@@js_suffix@.to_string(vm));
|
||||
})~~~");
|
||||
if (optional_default_value.has_value() && (!parameter.type->nullable || optional_default_value.value() != "null")) {
|
||||
if (optional_default_value.has_value() && (!parameter.type->is_nullable() || optional_default_value.value() != "null")) {
|
||||
scoped_generator.append(R"~~~( else {
|
||||
@cpp_name@ = @parameter.optional_default_value@;
|
||||
}
|
||||
|
@ -424,15 +425,15 @@ static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter
|
|||
)~~~");
|
||||
}
|
||||
}
|
||||
} else if (parameter.type->name.is_one_of("EventListener", "NodeFilter")) {
|
||||
} else if (parameter.type->name().is_one_of("EventListener", "NodeFilter")) {
|
||||
// FIXME: Replace this with support for callback interfaces. https://heycam.github.io/webidl/#idl-callback-interface
|
||||
|
||||
if (parameter.type->name == "EventListener")
|
||||
if (parameter.type->name() == "EventListener")
|
||||
scoped_generator.set("cpp_type", "IDLEventListener");
|
||||
else
|
||||
scoped_generator.set("cpp_type", parameter.type->name);
|
||||
scoped_generator.set("cpp_type", parameter.type->name());
|
||||
|
||||
if (parameter.type->nullable) {
|
||||
if (parameter.type->is_nullable()) {
|
||||
scoped_generator.append(R"~~~(
|
||||
@cpp_type@* @cpp_name@ = nullptr;
|
||||
if (!@js_name@@js_suffix@.is_nullish()) {
|
||||
|
@ -453,7 +454,7 @@ static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter
|
|||
)~~~");
|
||||
}
|
||||
} else if (IDL::is_wrappable_type(*parameter.type)) {
|
||||
if (!parameter.type->nullable) {
|
||||
if (!parameter.type->is_nullable()) {
|
||||
if (!optional) {
|
||||
scoped_generator.append(R"~~~(
|
||||
if (!@js_name@@js_suffix@.is_object() || !is<@wrapper_name@>(@js_name@@js_suffix@.as_object()))
|
||||
|
@ -483,7 +484,7 @@ static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter
|
|||
}
|
||||
)~~~");
|
||||
}
|
||||
} else if (parameter.type->name == "double" || parameter.type->name == "float") {
|
||||
} else if (parameter.type->name() == "double" || parameter.type->name() == "float") {
|
||||
if (!optional) {
|
||||
scoped_generator.append(R"~~~(
|
||||
@parameter.type.name@ @cpp_name@ = TRY(@js_name@@js_suffix@.to_double(vm));
|
||||
|
@ -512,7 +513,7 @@ static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter
|
|||
)~~~");
|
||||
}
|
||||
}
|
||||
} else if (parameter.type->name == "boolean") {
|
||||
} else if (parameter.type->name() == "boolean") {
|
||||
if (!optional || optional_default_value.has_value()) {
|
||||
scoped_generator.append(R"~~~(
|
||||
bool @cpp_name@;
|
||||
|
@ -536,7 +537,7 @@ static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter
|
|||
@cpp_name@ = @parameter.optional_default_value@;
|
||||
)~~~");
|
||||
}
|
||||
} else if (parameter.type->name == "unsigned long") {
|
||||
} else if (parameter.type->name() == "unsigned long") {
|
||||
if (!optional || optional_default_value.has_value()) {
|
||||
scoped_generator.append(R"~~~(
|
||||
u32 @cpp_name@;
|
||||
|
@ -560,7 +561,7 @@ static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter
|
|||
@cpp_name@ = @parameter.optional_default_value@UL;
|
||||
)~~~");
|
||||
}
|
||||
} else if (parameter.type->name == "unsigned short") {
|
||||
} else if (parameter.type->name() == "unsigned short") {
|
||||
if (!optional || optional_default_value.has_value()) {
|
||||
scoped_generator.append(R"~~~(
|
||||
u16 @cpp_name@;
|
||||
|
@ -584,7 +585,7 @@ static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter
|
|||
@cpp_name@ = @parameter.optional_default_value@;
|
||||
)~~~");
|
||||
}
|
||||
} else if (parameter.type->name == "long") {
|
||||
} else if (parameter.type->name() == "long") {
|
||||
if (!optional || optional_default_value.has_value()) {
|
||||
scoped_generator.append(R"~~~(
|
||||
i32 @cpp_name@;
|
||||
|
@ -608,7 +609,7 @@ static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter
|
|||
@cpp_name@ = @parameter.optional_default_value@L;
|
||||
)~~~");
|
||||
}
|
||||
} else if (parameter.type->name == "long long") {
|
||||
} else if (parameter.type->name() == "long long") {
|
||||
if (!optional || optional_default_value.has_value()) {
|
||||
scoped_generator.append(R"~~~(
|
||||
i64 @cpp_name@;
|
||||
|
@ -632,7 +633,7 @@ static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter
|
|||
@cpp_name@ = @parameter.optional_default_value@L;
|
||||
)~~~");
|
||||
}
|
||||
} else if (parameter.type->name == "Promise") {
|
||||
} else if (parameter.type->name() == "Promise") {
|
||||
// NOTE: It's not clear to me where the implicit wrapping of non-Promise values in a resolved
|
||||
// Promise is defined in the spec; https://webidl.spec.whatwg.org/#idl-promise doesn't say
|
||||
// anything of this sort. Both Gecko and Blink do it, however, so I'm sure it's correct.
|
||||
|
@ -644,7 +645,7 @@ static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter
|
|||
}
|
||||
auto @cpp_name@ = JS::make_handle(&static_cast<JS::Promise&>(@js_name@@js_suffix@.as_object()));
|
||||
)~~~");
|
||||
} else if (parameter.type->name == "BufferSource") {
|
||||
} else if (parameter.type->name() == "BufferSource") {
|
||||
scoped_generator.append(R"~~~(
|
||||
if (!@js_name@@js_suffix@.is_object() || !(is<JS::TypedArrayBase>(@js_name@@js_suffix@.as_object()) || is<JS::ArrayBuffer>(@js_name@@js_suffix@.as_object()) || is<JS::DataView>(@js_name@@js_suffix@.as_object())))
|
||||
return vm.throw_completion<JS::TypeError>(JS::ErrorType::NotAnObjectOfType, "@parameter.type.name@");
|
||||
|
@ -652,7 +653,7 @@ static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter
|
|||
// TODO: Should we make this a Variant?
|
||||
auto @cpp_name@ = JS::make_handle(&@js_name@@js_suffix@.as_object());
|
||||
)~~~");
|
||||
} else if (parameter.type->name == "any") {
|
||||
} else if (parameter.type->name() == "any") {
|
||||
if (!optional) {
|
||||
scoped_generator.append(R"~~~(
|
||||
auto @cpp_name@ = @js_name@@js_suffix@;
|
||||
|
@ -679,9 +680,9 @@ static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter
|
|||
}
|
||||
}
|
||||
}
|
||||
} else if (interface.enumerations.contains(parameter.type->name)) {
|
||||
} else if (interface.enumerations.contains(parameter.type->name())) {
|
||||
auto enum_generator = scoped_generator.fork();
|
||||
auto& enumeration = interface.enumerations.find(parameter.type->name)->value;
|
||||
auto& enumeration = interface.enumerations.find(parameter.type->name())->value;
|
||||
StringView enum_member_name;
|
||||
if (optional_default_value.has_value()) {
|
||||
VERIFY(optional_default_value->length() >= 2 && (*optional_default_value)[0] == '"' && (*optional_default_value)[optional_default_value->length() - 1] == '"');
|
||||
|
@ -737,7 +738,7 @@ static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter
|
|||
}
|
||||
)~~~");
|
||||
}
|
||||
} else if (interface.dictionaries.contains(parameter.type->name)) {
|
||||
} else if (interface.dictionaries.contains(parameter.type->name())) {
|
||||
if (optional_default_value.has_value() && optional_default_value != "{}")
|
||||
TODO();
|
||||
auto dictionary_generator = scoped_generator.fork();
|
||||
|
@ -747,7 +748,7 @@ static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter
|
|||
|
||||
@parameter.type.name@ @cpp_name@ {};
|
||||
)~~~");
|
||||
auto* current_dictionary = &interface.dictionaries.find(parameter.type->name)->value;
|
||||
auto* current_dictionary = &interface.dictionaries.find(parameter.type->name())->value;
|
||||
while (true) {
|
||||
for (auto& member : current_dictionary->members) {
|
||||
dictionary_generator.set("member_key", member.name);
|
||||
|
@ -780,11 +781,11 @@ static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter
|
|||
VERIFY(interface.dictionaries.contains(current_dictionary->parent_name));
|
||||
current_dictionary = &interface.dictionaries.find(current_dictionary->parent_name)->value;
|
||||
}
|
||||
} else if (interface.callback_functions.contains(parameter.type->name)) {
|
||||
} else if (interface.callback_functions.contains(parameter.type->name())) {
|
||||
// https://webidl.spec.whatwg.org/#es-callback-function
|
||||
|
||||
auto callback_function_generator = scoped_generator.fork();
|
||||
auto& callback_function = interface.callback_functions.find(parameter.type->name)->value;
|
||||
auto& callback_function = interface.callback_functions.find(parameter.type->name())->value;
|
||||
|
||||
// An ECMAScript value V is converted to an IDL callback function type value by running the following algorithm:
|
||||
// 1. If the result of calling IsCallable(V) is false and the conversion to an IDL value is not being performed due to V being assigned to an attribute whose type is a nullable callback function that is annotated with [LegacyTreatNonObjectAsNull], then throw a TypeError.
|
||||
|
@ -806,7 +807,7 @@ static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter
|
|||
auto @cpp_name@ = vm.heap().allocate_without_realm<CallbackType>(@js_name@@js_suffix@.as_object(), HTML::incumbent_settings_object());
|
||||
)~~~");
|
||||
}
|
||||
} else if (parameter.type->name == "sequence") {
|
||||
} else if (parameter.type->name() == "sequence") {
|
||||
// https://webidl.spec.whatwg.org/#es-sequence
|
||||
|
||||
auto sequence_generator = scoped_generator.fork();
|
||||
|
@ -820,7 +821,7 @@ static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter
|
|||
// 4. Return the result of creating a sequence from V and method.
|
||||
|
||||
if (optional) {
|
||||
auto sequence_cpp_type = idl_type_name_to_cpp_type(parameterized_type.parameters.first(), interface);
|
||||
auto sequence_cpp_type = idl_type_name_to_cpp_type(parameterized_type.parameters().first(), interface);
|
||||
sequence_generator.set("sequence.type", sequence_cpp_type.name);
|
||||
sequence_generator.set("sequence.storage_type", sequence_storage_type_to_cpp_storage_type_name(sequence_cpp_type.sequence_storage_type));
|
||||
|
||||
|
@ -871,7 +872,7 @@ static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter
|
|||
}
|
||||
)~~~");
|
||||
}
|
||||
} else if (parameter.type->name == "record") {
|
||||
} else if (parameter.type->name() == "record") {
|
||||
// https://webidl.spec.whatwg.org/#es-record
|
||||
|
||||
auto record_generator = scoped_generator.fork();
|
||||
|
@ -879,10 +880,10 @@ static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter
|
|||
record_generator.set("recursion_depth", String::number(recursion_depth));
|
||||
|
||||
// A record can only have two types: key type and value type.
|
||||
VERIFY(parameterized_type.parameters.size() == 2);
|
||||
VERIFY(parameterized_type.parameters().size() == 2);
|
||||
|
||||
// A record only allows the key to be a string.
|
||||
VERIFY(parameterized_type.parameters[0].is_string());
|
||||
VERIFY(parameterized_type.parameters()[0].is_string());
|
||||
|
||||
// An ECMAScript value O is converted to an IDL record<K, V> value as follows:
|
||||
// 1. If Type(O) is not Object, throw a TypeError.
|
||||
|
@ -925,7 +926,7 @@ static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter
|
|||
continue;
|
||||
)~~~");
|
||||
|
||||
IDL::Parameter key_parameter { .type = parameterized_type.parameters[0], .name = acceptable_cpp_name, .optional_default_value = {}, .extended_attributes = {} };
|
||||
IDL::Parameter key_parameter { .type = parameterized_type.parameters()[0], .name = acceptable_cpp_name, .optional_default_value = {}, .extended_attributes = {} };
|
||||
generate_to_cpp(record_generator, key_parameter, "key", String::number(recursion_depth), String::formatted("typed_key{}", recursion_depth), interface, false, false, {}, false, recursion_depth + 1);
|
||||
|
||||
record_generator.append(R"~~~(
|
||||
|
@ -933,7 +934,7 @@ static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter
|
|||
)~~~");
|
||||
|
||||
// FIXME: Record value types should be TypeWithExtendedAttributes, which would allow us to get [LegacyNullToEmptyString] here.
|
||||
IDL::Parameter value_parameter { .type = parameterized_type.parameters[1], .name = acceptable_cpp_name, .optional_default_value = {}, .extended_attributes = {} };
|
||||
IDL::Parameter value_parameter { .type = parameterized_type.parameters()[1], .name = acceptable_cpp_name, .optional_default_value = {}, .extended_attributes = {} };
|
||||
generate_to_cpp(record_generator, value_parameter, "value", String::number(recursion_depth), String::formatted("typed_value{}", recursion_depth), interface, false, false, {}, false, recursion_depth + 1);
|
||||
|
||||
record_generator.append(R"~~~(
|
||||
|
@ -956,7 +957,7 @@ static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter
|
|||
RefPtr<Type> dictionary_type;
|
||||
for (auto& dictionary : interface.dictionaries) {
|
||||
for (auto& type : types) {
|
||||
if (type.name == dictionary.key) {
|
||||
if (type.name() == dictionary.key) {
|
||||
dictionary_type = type;
|
||||
break;
|
||||
}
|
||||
|
@ -968,7 +969,7 @@ static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter
|
|||
|
||||
if (dictionary_type) {
|
||||
auto dictionary_generator = union_generator.fork();
|
||||
dictionary_generator.set("dictionary.type", dictionary_type->name);
|
||||
dictionary_generator.set("dictionary.type", dictionary_type->name());
|
||||
|
||||
// The lambda must take the JS::Value to convert as a parameter instead of capturing it in order to support union types being variadic.
|
||||
dictionary_generator.append(R"~~~(
|
||||
|
@ -1030,7 +1031,7 @@ static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter
|
|||
|
||||
bool includes_object = false;
|
||||
for (auto& type : types) {
|
||||
if (type.name == "object") {
|
||||
if (type.name() == "object") {
|
||||
includes_object = true;
|
||||
break;
|
||||
}
|
||||
|
@ -1062,7 +1063,7 @@ static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter
|
|||
continue;
|
||||
|
||||
auto union_platform_object_type_generator = union_generator.fork();
|
||||
union_platform_object_type_generator.set("platform_object_type", String::formatted("{}Wrapper", type.name));
|
||||
union_platform_object_type_generator.set("platform_object_type", String::formatted("{}Wrapper", type.name()));
|
||||
auto cpp_type = IDL::idl_type_name_to_cpp_type(type, interface);
|
||||
union_platform_object_type_generator.set("refptr_type", cpp_type.name);
|
||||
|
||||
|
@ -1087,7 +1088,7 @@ static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter
|
|||
// 6. If Type(V) is Object and V has an [[ArrayBufferData]] internal slot, then
|
||||
// 1. If types includes ArrayBuffer, then return the result of converting V to ArrayBuffer.
|
||||
for (auto& type : types) {
|
||||
if (type.name == "BufferSource") {
|
||||
if (type.name() == "BufferSource") {
|
||||
union_generator.append(R"~~~(
|
||||
if (is<JS::ArrayBuffer>(@js_name@@js_suffix@_object))
|
||||
return JS::make_handle(@js_name@@js_suffix@_object);
|
||||
|
@ -1117,7 +1118,7 @@ static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter
|
|||
// 1. If types includes a sequence type, then:
|
||||
RefPtr<IDL::ParameterizedType> sequence_type;
|
||||
for (auto& type : types) {
|
||||
if (type.name == "sequence") {
|
||||
if (type.name() == "sequence") {
|
||||
sequence_type = verify_cast<IDL::ParameterizedType>(type);
|
||||
break;
|
||||
}
|
||||
|
@ -1157,7 +1158,7 @@ static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter
|
|||
// 4. If types includes a record type, then return the result of converting V to that record type.
|
||||
RefPtr<IDL::ParameterizedType> record_type;
|
||||
for (auto& type : types) {
|
||||
if (type.name == "record") {
|
||||
if (type.name() == "record") {
|
||||
record_type = verify_cast<IDL::ParameterizedType>(type);
|
||||
break;
|
||||
}
|
||||
|
@ -1190,7 +1191,7 @@ static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter
|
|||
// 1. If types includes boolean, then return the result of converting V to boolean.
|
||||
bool includes_boolean = false;
|
||||
for (auto& type : types) {
|
||||
if (type.name == "boolean") {
|
||||
if (type.name() == "boolean") {
|
||||
includes_boolean = true;
|
||||
break;
|
||||
}
|
||||
|
@ -1232,7 +1233,7 @@ static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter
|
|||
// 1. If types includes bigint, then return the result of converting V to bigint
|
||||
bool includes_bigint = false;
|
||||
for (auto& type : types) {
|
||||
if (type.name == "bigint") {
|
||||
if (type.name() == "bigint") {
|
||||
includes_bigint = true;
|
||||
break;
|
||||
}
|
||||
|
@ -1367,7 +1368,7 @@ static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter
|
|||
)~~~");
|
||||
}
|
||||
} else {
|
||||
dbgln("Unimplemented JS-to-C++ conversion: {}", parameter.type->name);
|
||||
dbgln("Unimplemented JS-to-C++ conversion: {}", parameter.type->name());
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
}
|
||||
|
@ -1427,7 +1428,7 @@ void IDL::ParameterizedType::generate_sequence_from_iterable(SourceGenerator& ge
|
|||
sequence_generator.set("iterable_cpp_name", iterable_cpp_name);
|
||||
sequence_generator.set("iterator_method_cpp_name", iterator_method_cpp_name);
|
||||
sequence_generator.set("recursion_depth", String::number(recursion_depth));
|
||||
auto sequence_cpp_type = idl_type_name_to_cpp_type(parameters.first(), interface);
|
||||
auto sequence_cpp_type = idl_type_name_to_cpp_type(parameters().first(), interface);
|
||||
sequence_generator.set("sequence.type", sequence_cpp_type.name);
|
||||
sequence_generator.set("sequence.storage_type", sequence_storage_type_to_cpp_storage_type_name(sequence_cpp_type.sequence_storage_type));
|
||||
|
||||
|
@ -1465,7 +1466,7 @@ void IDL::ParameterizedType::generate_sequence_from_iterable(SourceGenerator& ge
|
|||
)~~~");
|
||||
|
||||
// FIXME: Sequences types should be TypeWithExtendedAttributes, which would allow us to get [LegacyNullToEmptyString] here.
|
||||
IDL::Parameter parameter { .type = parameters.first(), .name = iterable_cpp_name, .optional_default_value = {}, .extended_attributes = {} };
|
||||
IDL::Parameter parameter { .type = parameters().first(), .name = iterable_cpp_name, .optional_default_value = {}, .extended_attributes = {} };
|
||||
generate_to_cpp(sequence_generator, parameter, "next_item", String::number(recursion_depth), String::formatted("sequence_item{}", recursion_depth), interface, false, false, {}, false, recursion_depth);
|
||||
|
||||
sequence_generator.append(R"~~~(
|
||||
|
@ -1483,25 +1484,25 @@ static void generate_wrap_statement(SourceGenerator& generator, String const& va
|
|||
{
|
||||
auto scoped_generator = generator.fork();
|
||||
scoped_generator.set("value", value);
|
||||
scoped_generator.set("type", type.name);
|
||||
scoped_generator.set("type", type.name());
|
||||
scoped_generator.set("result_expression", result_expression);
|
||||
scoped_generator.set("recursion_depth", String::number(recursion_depth));
|
||||
|
||||
if (type.name == "undefined") {
|
||||
if (type.name() == "undefined") {
|
||||
scoped_generator.append(R"~~~(
|
||||
@result_expression@ JS::js_undefined();
|
||||
)~~~");
|
||||
return;
|
||||
}
|
||||
|
||||
if (type.nullable && !is<UnionType>(type)) {
|
||||
if (type.is_nullable() && !is<UnionType>(type)) {
|
||||
if (type.is_string()) {
|
||||
scoped_generator.append(R"~~~(
|
||||
if (@value@.is_null()) {
|
||||
@result_expression@ JS::js_null();
|
||||
} else {
|
||||
)~~~");
|
||||
} else if (type.name == "sequence") {
|
||||
} else if (type.name() == "sequence") {
|
||||
scoped_generator.append(R"~~~(
|
||||
if (!@value@.has_value()) {
|
||||
@result_expression@ JS::js_null();
|
||||
|
@ -1520,7 +1521,7 @@ static void generate_wrap_statement(SourceGenerator& generator, String const& va
|
|||
scoped_generator.append(R"~~~(
|
||||
@result_expression@ JS::js_string(vm, @value@);
|
||||
)~~~");
|
||||
} else if (type.name == "sequence") {
|
||||
} else if (type.name() == "sequence") {
|
||||
// https://webidl.spec.whatwg.org/#es-sequence
|
||||
auto& sequence_generic_type = verify_cast<IDL::ParameterizedType>(type);
|
||||
|
||||
|
@ -1528,7 +1529,7 @@ static void generate_wrap_statement(SourceGenerator& generator, String const& va
|
|||
auto* new_array@recursion_depth@ = MUST(JS::Array::create(realm, 0));
|
||||
)~~~");
|
||||
|
||||
if (!type.nullable) {
|
||||
if (!type.is_nullable()) {
|
||||
scoped_generator.append(R"~~~(
|
||||
for (size_t i@recursion_depth@ = 0; i@recursion_depth@ < @value@.size(); ++i@recursion_depth@) {
|
||||
auto& element@recursion_depth@ = @value@.at(i@recursion_depth@);
|
||||
|
@ -1541,12 +1542,12 @@ static void generate_wrap_statement(SourceGenerator& generator, String const& va
|
|||
)~~~");
|
||||
}
|
||||
|
||||
if (impl_is_wrapper(sequence_generic_type.parameters.first())) {
|
||||
if (impl_is_wrapper(sequence_generic_type.parameters().first())) {
|
||||
scoped_generator.append(R"~~~(
|
||||
auto* wrapped_element@recursion_depth@ = &(*element@recursion_depth@);
|
||||
)~~~");
|
||||
} else {
|
||||
generate_wrap_statement(scoped_generator, String::formatted("element{}", recursion_depth), sequence_generic_type.parameters.first(), interface, String::formatted("auto wrapped_element{} =", recursion_depth), WrappingReference::Yes, recursion_depth + 1);
|
||||
generate_wrap_statement(scoped_generator, String::formatted("element{}", recursion_depth), sequence_generic_type.parameters().first(), interface, String::formatted("auto wrapped_element{} =", recursion_depth), WrappingReference::Yes, recursion_depth + 1);
|
||||
}
|
||||
|
||||
scoped_generator.append(R"~~~(
|
||||
|
@ -1556,27 +1557,27 @@ static void generate_wrap_statement(SourceGenerator& generator, String const& va
|
|||
|
||||
@result_expression@ new_array@recursion_depth@;
|
||||
)~~~");
|
||||
} else if (type.name == "boolean" || type.name == "double" || type.name == "float") {
|
||||
} else if (type.name() == "boolean" || type.name() == "double" || type.name() == "float") {
|
||||
scoped_generator.append(R"~~~(
|
||||
@result_expression@ JS::Value(@value@);
|
||||
)~~~");
|
||||
} else if (type.name == "short" || type.name == "long" || type.name == "unsigned short") {
|
||||
} else if (type.name() == "short" || type.name() == "long" || type.name() == "unsigned short") {
|
||||
scoped_generator.append(R"~~~(
|
||||
@result_expression@ JS::Value((i32)@value@);
|
||||
)~~~");
|
||||
} else if (type.name == "unsigned long") {
|
||||
} else if (type.name() == "unsigned long") {
|
||||
scoped_generator.append(R"~~~(
|
||||
@result_expression@ JS::Value((u32)@value@);
|
||||
)~~~");
|
||||
} else if (type.name == "long long") {
|
||||
} else if (type.name() == "long long") {
|
||||
scoped_generator.append(R"~~~(
|
||||
@result_expression@ JS::Value((double)@value@);
|
||||
)~~~");
|
||||
} else if (type.name == "unsigned long long") {
|
||||
} else if (type.name() == "unsigned long long") {
|
||||
scoped_generator.append(R"~~~(
|
||||
@result_expression@ JS::Value((double)@value@);
|
||||
)~~~");
|
||||
} else if (type.name == "Location" || type.name == "Promise" || type.name == "Uint8Array" || type.name == "Uint8ClampedArray" || type.name == "any") {
|
||||
} else if (type.name() == "Location" || type.name() == "Promise" || type.name() == "Uint8Array" || type.name() == "Uint8ClampedArray" || type.name() == "any") {
|
||||
scoped_generator.append(R"~~~(
|
||||
@result_expression@ @value@;
|
||||
)~~~");
|
||||
|
@ -1605,7 +1606,7 @@ static void generate_wrap_statement(SourceGenerator& generator, String const& va
|
|||
|
||||
// End of current visit lambda.
|
||||
// The last lambda cannot have a trailing comma on the closing brace, unless the type is nullable, where an extra lambda will be generated for the Empty case.
|
||||
if (current_union_type_index != union_types.size() - 1 || type.nullable) {
|
||||
if (current_union_type_index != union_types.size() - 1 || type.is_nullable()) {
|
||||
union_generator.append(R"~~~(
|
||||
},
|
||||
)~~~");
|
||||
|
@ -1616,7 +1617,7 @@ static void generate_wrap_statement(SourceGenerator& generator, String const& va
|
|||
}
|
||||
}
|
||||
|
||||
if (type.nullable) {
|
||||
if (type.is_nullable()) {
|
||||
union_generator.append(R"~~~(
|
||||
[](Empty) -> JS::Value {
|
||||
return JS::js_null();
|
||||
|
@ -1628,18 +1629,18 @@ static void generate_wrap_statement(SourceGenerator& generator, String const& va
|
|||
union_generator.append(R"~~~(
|
||||
);
|
||||
)~~~");
|
||||
} else if (interface.enumerations.contains(type.name)) {
|
||||
} else if (interface.enumerations.contains(type.name())) {
|
||||
scoped_generator.append(R"~~~(
|
||||
@result_expression@ JS::js_string(vm, Bindings::idl_enum_to_string(@value@));
|
||||
)~~~");
|
||||
} else if (interface.callback_functions.contains(type.name)) {
|
||||
} else if (interface.callback_functions.contains(type.name())) {
|
||||
// https://webidl.spec.whatwg.org/#es-callback-function
|
||||
|
||||
auto& callback_function = interface.callback_functions.find(type.name)->value;
|
||||
auto& callback_function = interface.callback_functions.find(type.name())->value;
|
||||
|
||||
// The result of converting an IDL callback function type value to an ECMAScript value is a reference to the same object that the IDL callback function type value represents.
|
||||
|
||||
if (callback_function.is_legacy_treat_non_object_as_null && !type.nullable) {
|
||||
if (callback_function.is_legacy_treat_non_object_as_null && !type.is_nullable()) {
|
||||
scoped_generator.append(R"~~~(
|
||||
if (!@value@) {
|
||||
@result_expression@ JS::js_null();
|
||||
|
@ -1652,7 +1653,7 @@ static void generate_wrap_statement(SourceGenerator& generator, String const& va
|
|||
@result_expression@ &@value@->callback;
|
||||
)~~~");
|
||||
}
|
||||
} else if (interface.dictionaries.contains(type.name)) {
|
||||
} else if (interface.dictionaries.contains(type.name())) {
|
||||
// https://webidl.spec.whatwg.org/#es-dictionary
|
||||
auto dictionary_generator = scoped_generator.fork();
|
||||
|
||||
|
@ -1660,7 +1661,7 @@ static void generate_wrap_statement(SourceGenerator& generator, String const& va
|
|||
auto* dictionary_object@recursion_depth@ = JS::Object::create(realm, realm.intrinsics().object_prototype());
|
||||
)~~~");
|
||||
|
||||
auto* current_dictionary = &interface.dictionaries.find(type.name)->value;
|
||||
auto* current_dictionary = &interface.dictionaries.find(type.name())->value;
|
||||
while (true) {
|
||||
for (auto& member : current_dictionary->members) {
|
||||
dictionary_generator.set("member_key", member.name);
|
||||
|
@ -1687,7 +1688,7 @@ static void generate_wrap_statement(SourceGenerator& generator, String const& va
|
|||
dictionary_generator.append(R"~~~(
|
||||
@result_expression@ dictionary_object@recursion_depth@;
|
||||
)~~~");
|
||||
} else if (type.name == "object") {
|
||||
} else if (type.name() == "object") {
|
||||
scoped_generator.append(R"~~~(
|
||||
@result_expression@ JS::Value(const_cast<JS::Object*>(@value@));
|
||||
)~~~");
|
||||
|
@ -1703,7 +1704,7 @@ static void generate_wrap_statement(SourceGenerator& generator, String const& va
|
|||
}
|
||||
}
|
||||
|
||||
if (type.nullable && !is<UnionType>(type)) {
|
||||
if (type.is_nullable() && !is<UnionType>(type)) {
|
||||
scoped_generator.append(R"~~~(
|
||||
}
|
||||
)~~~");
|
||||
|
@ -1794,7 +1795,7 @@ static Optional<String> generate_arguments_match_check_for_count(Vector<IDL::Par
|
|||
auto argument = String::formatted("arg{}", i);
|
||||
StringBuilder condition;
|
||||
condition.append('(');
|
||||
if (parameter.type->nullable)
|
||||
if (parameter.type->is_nullable())
|
||||
condition.appendff("{}.is_nullish() || ", argument);
|
||||
else if (parameter.optional)
|
||||
condition.appendff("{}.is_undefined() || ", argument);
|
||||
|
@ -2558,7 +2559,7 @@ JS_DEFINE_NATIVE_FUNCTION(@prototype_class@::@attribute.getter_callback@)
|
|||
)~~~");
|
||||
|
||||
if (attribute.extended_attributes.contains("Reflect")) {
|
||||
if (attribute.type->name != "boolean") {
|
||||
if (attribute.type->name() != "boolean") {
|
||||
attribute_generator.append(R"~~~(
|
||||
auto retval = impl->attribute(HTML::AttributeNames::@attribute.reflect_name@);
|
||||
)~~~");
|
||||
|
@ -2592,7 +2593,7 @@ JS_DEFINE_NATIVE_FUNCTION(@prototype_class@::@attribute.setter_callback@)
|
|||
generate_to_cpp(generator, attribute, "value", "", "cpp_value", interface, attribute.extended_attributes.contains("LegacyNullToEmptyString"));
|
||||
|
||||
if (attribute.extended_attributes.contains("Reflect")) {
|
||||
if (attribute.type->name != "boolean") {
|
||||
if (attribute.type->name() != "boolean") {
|
||||
attribute_generator.append(R"~~~(
|
||||
impl->set_attribute(HTML::AttributeNames::@attribute.reflect_name@, cpp_value);
|
||||
)~~~");
|
||||
|
|
|
@ -112,21 +112,21 @@ int main(int argc, char** argv)
|
|||
for (auto& attribute : interface.attributes) {
|
||||
dbgln(" {}{}{} {}",
|
||||
attribute.readonly ? "readonly " : "",
|
||||
attribute.type->name,
|
||||
attribute.type->nullable ? "?" : "",
|
||||
attribute.type->name(),
|
||||
attribute.type->is_nullable() ? "?" : "",
|
||||
attribute.name);
|
||||
}
|
||||
|
||||
dbgln("Functions:");
|
||||
for (auto& function : interface.functions) {
|
||||
dbgln(" {}{} {}",
|
||||
function.return_type->name,
|
||||
function.return_type->nullable ? "?" : "",
|
||||
function.return_type->name(),
|
||||
function.return_type->is_nullable() ? "?" : "",
|
||||
function.name);
|
||||
for (auto& parameter : function.parameters) {
|
||||
dbgln(" {}{} {}",
|
||||
parameter.type->name,
|
||||
parameter.type->nullable ? "?" : "",
|
||||
parameter.type->name(),
|
||||
parameter.type->is_nullable() ? "?" : "",
|
||||
parameter.name);
|
||||
}
|
||||
}
|
||||
|
@ -134,13 +134,13 @@ int main(int argc, char** argv)
|
|||
dbgln("Static Functions:");
|
||||
for (auto& function : interface.static_functions) {
|
||||
dbgln(" static {}{} {}",
|
||||
function.return_type->name,
|
||||
function.return_type->nullable ? "?" : "",
|
||||
function.return_type->name(),
|
||||
function.return_type->is_nullable() ? "?" : "",
|
||||
function.name);
|
||||
for (auto& parameter : function.parameters) {
|
||||
dbgln(" {}{} {}",
|
||||
parameter.type->name,
|
||||
parameter.type->nullable ? "?" : "",
|
||||
parameter.type->name(),
|
||||
parameter.type->is_nullable() ? "?" : "",
|
||||
parameter.name);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
set(SOURCES
|
||||
IDLParser.cpp
|
||||
Types.cpp
|
||||
)
|
||||
|
||||
serenity_lib(LibIDL idl)
|
||||
|
|
|
@ -403,7 +403,7 @@ void Parser::parse_getter(HashMap<String, String>& extended_attributes, Interfac
|
|||
|
||||
auto& identifier = function.parameters.first();
|
||||
|
||||
if (identifier.type->nullable)
|
||||
if (identifier.type->is_nullable())
|
||||
report_parsing_error("identifier's type must not be nullable."sv, filename, input, lexer.tell());
|
||||
|
||||
if (identifier.optional)
|
||||
|
@ -411,18 +411,18 @@ void Parser::parse_getter(HashMap<String, String>& extended_attributes, Interfac
|
|||
|
||||
// FIXME: Disallow variadic functions once they're supported.
|
||||
|
||||
if (identifier.type->name == "DOMString") {
|
||||
if (identifier.type->name() == "DOMString") {
|
||||
if (interface.named_property_getter.has_value())
|
||||
report_parsing_error("An interface can only have one named property getter."sv, filename, input, lexer.tell());
|
||||
|
||||
interface.named_property_getter = move(function);
|
||||
} else if (identifier.type->name == "unsigned long") {
|
||||
} else if (identifier.type->name() == "unsigned long") {
|
||||
if (interface.indexed_property_getter.has_value())
|
||||
report_parsing_error("An interface can only have one indexed property getter."sv, filename, input, lexer.tell());
|
||||
|
||||
interface.indexed_property_getter = move(function);
|
||||
} else {
|
||||
report_parsing_error(String::formatted("Named/indexed property getter's identifier's type must be either 'DOMString' or 'unsigned long', got '{}'.", identifier.type->name), filename, input, lexer.tell());
|
||||
report_parsing_error(String::formatted("Named/indexed property getter's identifier's type must be either 'DOMString' or 'unsigned long', got '{}'.", identifier.type->name()), filename, input, lexer.tell());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -437,7 +437,7 @@ void Parser::parse_setter(HashMap<String, String>& extended_attributes, Interfac
|
|||
|
||||
auto& identifier = function.parameters.first();
|
||||
|
||||
if (identifier.type->nullable)
|
||||
if (identifier.type->is_nullable())
|
||||
report_parsing_error("identifier's type must not be nullable."sv, filename, input, lexer.tell());
|
||||
|
||||
if (identifier.optional)
|
||||
|
@ -445,7 +445,7 @@ void Parser::parse_setter(HashMap<String, String>& extended_attributes, Interfac
|
|||
|
||||
// FIXME: Disallow variadic functions once they're supported.
|
||||
|
||||
if (identifier.type->name == "DOMString") {
|
||||
if (identifier.type->name() == "DOMString") {
|
||||
if (interface.named_property_setter.has_value())
|
||||
report_parsing_error("An interface can only have one named property setter."sv, filename, input, lexer.tell());
|
||||
|
||||
|
@ -453,7 +453,7 @@ void Parser::parse_setter(HashMap<String, String>& extended_attributes, Interfac
|
|||
report_parsing_error("A named property setter must be accompanied by a named property getter."sv, filename, input, lexer.tell());
|
||||
|
||||
interface.named_property_setter = move(function);
|
||||
} else if (identifier.type->name == "unsigned long") {
|
||||
} else if (identifier.type->name() == "unsigned long") {
|
||||
if (interface.indexed_property_setter.has_value())
|
||||
report_parsing_error("An interface can only have one indexed property setter."sv, filename, input, lexer.tell());
|
||||
|
||||
|
@ -462,7 +462,7 @@ void Parser::parse_setter(HashMap<String, String>& extended_attributes, Interfac
|
|||
|
||||
interface.indexed_property_setter = move(function);
|
||||
} else {
|
||||
report_parsing_error(String::formatted("Named/indexed property setter's identifier's type must be either 'DOMString' or 'unsigned long', got '{}'.", identifier.type->name), filename, input, lexer.tell());
|
||||
report_parsing_error(String::formatted("Named/indexed property setter's identifier's type must be either 'DOMString' or 'unsigned long', got '{}'.", identifier.type->name()), filename, input, lexer.tell());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -477,7 +477,7 @@ void Parser::parse_deleter(HashMap<String, String>& extended_attributes, Interfa
|
|||
|
||||
auto& identifier = function.parameters.first();
|
||||
|
||||
if (identifier.type->nullable)
|
||||
if (identifier.type->is_nullable())
|
||||
report_parsing_error("identifier's type must not be nullable."sv, filename, input, lexer.tell());
|
||||
|
||||
if (identifier.optional)
|
||||
|
@ -485,7 +485,7 @@ void Parser::parse_deleter(HashMap<String, String>& extended_attributes, Interfa
|
|||
|
||||
// FIXME: Disallow variadic functions once they're supported.
|
||||
|
||||
if (identifier.type->name == "DOMString") {
|
||||
if (identifier.type->name() == "DOMString") {
|
||||
if (interface.named_property_deleter.has_value())
|
||||
report_parsing_error("An interface can only have one named property deleter."sv, filename, input, lexer.tell());
|
||||
|
||||
|
@ -494,7 +494,7 @@ void Parser::parse_deleter(HashMap<String, String>& extended_attributes, Interfa
|
|||
|
||||
interface.named_property_deleter = move(function);
|
||||
} else {
|
||||
report_parsing_error(String::formatted("Named property deleter's identifier's type must be 'DOMString', got '{}'.", identifier.type->name), filename, input, lexer.tell());
|
||||
report_parsing_error(String::formatted("Named property deleter's identifier's type must be 'DOMString', got '{}'.", identifier.type->name()), filename, input, lexer.tell());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -809,18 +809,18 @@ static void resolve_typedef(Interface& interface, NonnullRefPtr<Type>& type, Has
|
|||
{
|
||||
if (is<ParameterizedType>(*type)) {
|
||||
auto parameterized_type = static_ptr_cast<ParameterizedType>(type);
|
||||
auto& parameters = static_cast<Vector<NonnullRefPtr<Type>>&>(parameterized_type->parameters);
|
||||
auto& parameters = static_cast<Vector<NonnullRefPtr<Type>>&>(parameterized_type->parameters());
|
||||
for (auto& parameter : parameters)
|
||||
resolve_typedef(interface, parameter);
|
||||
return;
|
||||
}
|
||||
|
||||
auto it = interface.typedefs.find(type->name);
|
||||
auto it = interface.typedefs.find(type->name());
|
||||
if (it == interface.typedefs.end())
|
||||
return;
|
||||
bool is_nullable = type->nullable;
|
||||
bool nullable = type->is_nullable();
|
||||
type = it->value.type;
|
||||
type->nullable = is_nullable;
|
||||
type->set_nullable(nullable);
|
||||
if (!extended_attributes)
|
||||
return;
|
||||
for (auto& attribute : it->value.extended_attributes)
|
||||
|
|
31
Userland/Libraries/LibIDL/Types.cpp
Normal file
31
Userland/Libraries/LibIDL/Types.cpp
Normal file
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Copyright (c) 2022, Sam Atkins <atkinssj@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#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);
|
||||
}
|
||||
|
||||
}
|
|
@ -3,6 +3,7 @@
|
|||
* 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
|
||||
*/
|
||||
|
@ -41,29 +42,63 @@ struct CppType {
|
|||
SequenceStorageType sequence_storage_type;
|
||||
};
|
||||
|
||||
struct Type : public RefCounted<Type> {
|
||||
Type() = default;
|
||||
class ParameterizedType;
|
||||
class UnionType;
|
||||
|
||||
class Type : public RefCounted<Type> {
|
||||
public:
|
||||
enum class Kind {
|
||||
Plain, // AKA, Type.
|
||||
Parameterized,
|
||||
Union,
|
||||
};
|
||||
|
||||
Type(String name, bool nullable)
|
||||
: name(move(name))
|
||||
, nullable(nullable)
|
||||
: m_kind(Kind::Plain)
|
||||
, m_name(move(name))
|
||||
, m_nullable(nullable)
|
||||
{
|
||||
}
|
||||
|
||||
Type(Kind kind, String name, bool nullable)
|
||||
: m_kind(kind)
|
||||
, m_name(move(name))
|
||||
, m_nullable(nullable)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~Type() = default;
|
||||
|
||||
String name;
|
||||
bool nullable { false };
|
||||
bool is_string() const { return name.is_one_of("ByteString", "CSSOMString", "DOMString", "USVString"); }
|
||||
Kind kind() const { return m_kind; }
|
||||
|
||||
String const& name() const { return m_name; }
|
||||
|
||||
bool is_nullable() const { return m_nullable; }
|
||||
void set_nullable(bool value) { m_nullable = value; }
|
||||
|
||||
bool is_string() const { return m_name.is_one_of("ByteString", "CSSOMString", "DOMString", "USVString"); }
|
||||
|
||||
// https://webidl.spec.whatwg.org/#dfn-integer-type
|
||||
bool is_integer() const { return name.is_one_of("byte", "octet", "short", "unsigned short", "long", "unsigned long", "long long", "unsigned long long"); }
|
||||
bool is_integer() const { return 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_integer() || name.is_one_of("float", "unrestricted float", "double", "unrestricted double"); }
|
||||
bool is_numeric() const { return is_integer() || m_name.is_one_of("float", "unrestricted float", "double", "unrestricted double"); }
|
||||
|
||||
// https://webidl.spec.whatwg.org/#dfn-primitive-type
|
||||
bool is_primitive() const { return is_numeric() || name.is_one_of("bigint", "boolean"); }
|
||||
bool is_primitive() const { return is_numeric() || m_name.is_one_of("bigint", "boolean"); }
|
||||
|
||||
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();
|
||||
|
||||
private:
|
||||
Kind m_kind;
|
||||
String m_name;
|
||||
bool m_nullable { false };
|
||||
};
|
||||
|
||||
struct Parameter {
|
||||
|
@ -143,20 +178,23 @@ struct CallbackFunction {
|
|||
|
||||
class Interface;
|
||||
|
||||
struct ParameterizedType : public Type {
|
||||
ParameterizedType() = default;
|
||||
|
||||
class ParameterizedType : public Type {
|
||||
public:
|
||||
ParameterizedType(String name, bool nullable, NonnullRefPtrVector<Type> parameters)
|
||||
: Type(move(name), nullable)
|
||||
, parameters(move(parameters))
|
||||
: Type(Kind::Parameterized, move(name), nullable)
|
||||
, m_parameters(move(parameters))
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~ParameterizedType() override = default;
|
||||
|
||||
NonnullRefPtrVector<Type> parameters;
|
||||
|
||||
void generate_sequence_from_iterable(SourceGenerator& generator, String const& cpp_name, String const& iterable_cpp_name, String const& iterator_method_cpp_name, IDL::Interface const&, size_t recursion_depth) const;
|
||||
|
||||
NonnullRefPtrVector<Type> const& parameters() const { return m_parameters; }
|
||||
NonnullRefPtrVector<Type>& parameters() { return m_parameters; }
|
||||
|
||||
private:
|
||||
NonnullRefPtrVector<Type> m_parameters;
|
||||
};
|
||||
|
||||
static inline size_t get_shortest_function_length(Vector<Function&> const& overload_set)
|
||||
|
@ -238,18 +276,18 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
struct UnionType : public Type {
|
||||
UnionType() = default;
|
||||
|
||||
class UnionType : public Type {
|
||||
public:
|
||||
UnionType(String name, bool nullable, NonnullRefPtrVector<Type> member_types)
|
||||
: Type(move(name), nullable)
|
||||
, member_types(move(member_types))
|
||||
: Type(Kind::Union, move(name), nullable)
|
||||
, m_member_types(move(member_types))
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~UnionType() override = default;
|
||||
|
||||
NonnullRefPtrVector<Type> member_types;
|
||||
NonnullRefPtrVector<Type> const& member_types() const { return m_member_types; }
|
||||
NonnullRefPtrVector<Type>& member_types() { return m_member_types; }
|
||||
|
||||
// https://webidl.spec.whatwg.org/#dfn-flattened-union-member-types
|
||||
NonnullRefPtrVector<Type> flattened_member_types() const
|
||||
|
@ -260,14 +298,14 @@ struct UnionType : public Type {
|
|||
NonnullRefPtrVector<Type> types;
|
||||
|
||||
// 3. For each member type U of T:
|
||||
for (auto& type : member_types) {
|
||||
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 (is<UnionType>(type)) {
|
||||
auto& union_member_type = verify_cast<UnionType>(type);
|
||||
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.
|
||||
|
@ -288,9 +326,9 @@ struct UnionType : public Type {
|
|||
size_t num_nullable_member_types = 0;
|
||||
|
||||
// 3. For each member type U of T:
|
||||
for (auto& type : member_types) {
|
||||
for (auto& type : m_member_types) {
|
||||
// 1. If U is a nullable type, then:
|
||||
if (type.nullable) {
|
||||
if (type.is_nullable()) {
|
||||
// 1. Set n to n + 1.
|
||||
++num_nullable_member_types;
|
||||
|
||||
|
@ -298,8 +336,8 @@ struct UnionType : public Type {
|
|||
}
|
||||
|
||||
// 2. If U is a union type, then:
|
||||
if (is<UnionType>(type)) {
|
||||
auto& union_member_type = verify_cast<UnionType>(type);
|
||||
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.
|
||||
|
@ -322,18 +360,18 @@ struct UnionType : public Type {
|
|||
bool includes_undefined() const
|
||||
{
|
||||
// -> the type is a union type and one of its member types includes undefined.
|
||||
for (auto& type : member_types) {
|
||||
if (is<UnionType>(type)) {
|
||||
auto& union_type = verify_cast<UnionType>(type);
|
||||
if (union_type.includes_undefined())
|
||||
return true;
|
||||
}
|
||||
for (auto& type : m_member_types) {
|
||||
if (type.is_union() && type.as_union().includes_undefined())
|
||||
return true;
|
||||
|
||||
if (type.name == "undefined"sv)
|
||||
if (type.name() == "undefined"sv)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
NonnullRefPtrVector<Type> m_member_types;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue