From 661dd32432d90651a59da5e820b075edfeff26e1 Mon Sep 17 00:00:00 2001 From: Linus Groh Date: Mon, 11 Oct 2021 12:56:44 +0100 Subject: [PATCH] LibWeb: Add support for the Promise IDL type to WrapperGenerator This includes parsing parameterized types (foo) as well as generating the appropriate code in generate_wrap_statement() and generate_to_cpp(). --- .../LibWeb/WrapperGenerator.cpp | 33 ++++++++++++++----- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/Meta/Lagom/Tools/CodeGenerators/LibWeb/WrapperGenerator.cpp b/Meta/Lagom/Tools/CodeGenerators/LibWeb/WrapperGenerator.cpp index e093743be5..248731c1b4 100644 --- a/Meta/Lagom/Tools/CodeGenerators/LibWeb/WrapperGenerator.cpp +++ b/Meta/Lagom/Tools/CodeGenerators/LibWeb/WrapperGenerator.cpp @@ -83,6 +83,7 @@ static size_t get_function_length(FunctionType& function) struct Type { String name; + Vector parameters; bool nullable { false }; bool is_string() const { return name.is_one_of("ByteString", "CSSOMString", "DOMString", "USVString"); } }; @@ -259,16 +260,25 @@ static NonnullOwnPtr parse_interface(StringView filename, StringView interface->extended_attributes = parse_extended_attributes(); auto parse_type = [&] { + auto consume_name = [&] { + return lexer.consume_until([](auto ch) { return !isalnum(ch) && ch != '_'; }); + }; bool unsigned_ = lexer.consume_specific("unsigned"); if (unsigned_) consume_whitespace(); - auto name = lexer.consume_until([](auto ch) { return !isalnum(ch) && ch != '_'; }); + auto name = consume_name(); + Vector parameters; + if (lexer.consume_specific('<')) { + // TODO: Parse multiple parameters if necessary + parameters.append(consume_name()); + lexer.consume_specific('>'); + } auto nullable = lexer.consume_specific('?'); StringBuilder builder; if (unsigned_) builder.append("unsigned "); builder.append(name); - return Type { builder.to_string(), nullable }; + return Type { builder.to_string(), parameters, nullable }; }; auto parse_attribute = [&](HashMap& extended_attributes) { @@ -1071,6 +1081,18 @@ static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter } else { return JS::js_undefined(); } +)~~~"); + } 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. + scoped_generator.append(R"~~~( + if (!@js_name@@js_suffix@.is_object() || !is(@js_name@@js_suffix@.as_object())) { + auto* new_promise = JS::Promise::create(global_object); + new_promise->fulfill(@js_name@@js_suffix@); + @js_name@@js_suffix@ = new_promise; + } + auto @cpp_name@ = JS::make_handle(&static_cast(@js_name@@js_suffix@.as_object())); )~~~"); } else if (parameter.type.name == "any") { if (!optional) { @@ -1247,7 +1269,7 @@ static void generate_wrap_statement(SourceGenerator& generator, String const& va scoped_generator.append(R"~~~( @result_expression@ JS::Value((i32)@value@); )~~~"); - } else if (type.name == "Uint8ClampedArray" || type.name == "any") { + } else if (type.name == "Location" || type.name == "Promise" || type.name == "Uint8ClampedArray" || type.name == "any") { scoped_generator.append(R"~~~( @result_expression@ @value@; )~~~"); @@ -1257,11 +1279,6 @@ static void generate_wrap_statement(SourceGenerator& generator, String const& va @result_expression@ JS::js_null(); else @result_expression@ @value@.callback.cell(); -)~~~"); - } else if (type.name == "Location") { - // Location is special cased as it is already a JS::Object. - scoped_generator.append(R"~~~( - @result_expression@ JS::Value(@value@); )~~~"); } else { scoped_generator.append(R"~~~(