From aa32bfa4481f6298c99846025394b7bc415ca621 Mon Sep 17 00:00:00 2001 From: Shannon Booth Date: Wed, 7 Aug 2024 18:42:14 +1200 Subject: [PATCH] LibWeb: Implement USVString scalar value handling USVString is defined in the IDL spec as: > The USVString type corresponds to scalar value strings. Depending on > the context, these can be treated as sequences of either 16-bit > unsigned integer code units or scalar values. This means we need to account for surrogate code points by using the replacement character. This fixes the last test in https://wpt.live/url/url-constructor.any.html --- .../BindingsGenerator/IDLGenerators.cpp | 13 +++++++---- Tests/LibWeb/Text/expected/URL/url.txt | 22 +++++++++++++++++++ Tests/LibWeb/Text/input/URL/url.html | 1 + 3 files changed, 32 insertions(+), 4 deletions(-) diff --git a/Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/IDLGenerators.cpp b/Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/IDLGenerators.cpp index e61b86a50c9..c4d17d65352 100644 --- a/Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/IDLGenerators.cpp +++ b/Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/IDLGenerators.cpp @@ -332,6 +332,11 @@ static void emit_includes_for_all_imports(auto& interface, auto& generator, bool template static void generate_to_string(SourceGenerator& scoped_generator, ParameterType const& parameter, bool variadic, bool optional, Optional const& optional_default_value) { + if (parameter.type->name() == "USVString") + scoped_generator.set("to_string", "to_well_formed_string"sv); + else + scoped_generator.set("to_string", "to_string"sv); + if (variadic) { scoped_generator.append(R"~~~( Vector @cpp_name@; @@ -340,7 +345,7 @@ static void generate_to_string(SourceGenerator& scoped_generator, ParameterType @cpp_name@.ensure_capacity(vm.argument_count() - @js_suffix@); for (size_t i = @js_suffix@; i < vm.argument_count(); ++i) { - auto to_string_result = TRY(vm.argument(i).to_string(vm)); + auto to_string_result = TRY(vm.argument(i).@to_string@(vm)); @cpp_name@.unchecked_append(move(to_string_result)); } } @@ -350,14 +355,14 @@ static void generate_to_string(SourceGenerator& scoped_generator, ParameterType scoped_generator.append(R"~~~( @string_type@ @cpp_name@; if (!@legacy_null_to_empty_string@ || !@js_name@@js_suffix@.is_null()) { - @cpp_name@ = TRY(@js_name@@js_suffix@.to_string(vm)); + @cpp_name@ = TRY(@js_name@@js_suffix@.@to_string@(vm)); } )~~~"); } else { scoped_generator.append(R"~~~( Optional<@string_type@> @cpp_name@; if (!@js_name@@js_suffix@.is_nullish()) - @cpp_name@ = TRY(@js_name@@js_suffix@.to_string(vm)); + @cpp_name@ = TRY(@js_name@@js_suffix@.@to_string@(vm)); )~~~"); } } else { @@ -375,7 +380,7 @@ static void generate_to_string(SourceGenerator& scoped_generator, ParameterType scoped_generator.append(R"~~~( if (!@js_name@@js_suffix@.is_undefined()) { if (!@legacy_null_to_empty_string@ || !@js_name@@js_suffix@.is_null()) - @cpp_name@ = TRY(@js_name@@js_suffix@.to_string(vm)); + @cpp_name@ = TRY(@js_name@@js_suffix@.@to_string@(vm)); })~~~"); if (!may_be_null) { scoped_generator.append(R"~~~( else { diff --git a/Tests/LibWeb/Text/expected/URL/url.txt b/Tests/LibWeb/Text/expected/URL/url.txt index 2cc4f366a23..6401c140e70 100644 --- a/Tests/LibWeb/Text/expected/URL/url.txt +++ b/Tests/LibWeb/Text/expected/URL/url.txt @@ -163,6 +163,17 @@ pathname => '/foo/bar' search => '??a=b&c=d' searchParams => '%3Fa=b&c=d' hash => '' +new URL('http://example.com/𐟾﷐﷏﷯ﷰ￾￿?𐟾﷐﷏﷯ﷰ￾￿', undefined) +protocol => 'http:' +username => '' +password => '' +host => 'example.com' +hostname => 'example.com' +port => '' +pathname => '/%EF%BF%BD%F0%90%9F%BE%EF%BF%BD%EF%B7%90%EF%B7%8F%EF%B7%AF%EF%B7%B0%EF%BF%BE%EF%BF%BF' +search => '?%EF%BF%BD%F0%90%9F%BE%EF%BF%BD%EF%B7%90%EF%B7%8F%EF%B7%AF%EF%B7%B0%EF%BF%BE%EF%BF%BF' +searchParams => '%EF%BF%BD%F0%90%9F%BE%EF%BF%BD%EF%B7%90%EF%B7%8F%EF%B7%AF%EF%B7%B0%EF%BF%BE%EF%BF%BF=' +hash => '' ========================================= URL.parse('ftp://serenityos.org:21', undefined) protocol => 'ftp:' @@ -329,3 +340,14 @@ pathname => '/foo/bar' search => '??a=b&c=d' searchParams => '%3Fa=b&c=d' hash => '' +URL.parse('http://example.com/𐟾﷐﷏﷯ﷰ￾￿?𐟾﷐﷏﷯ﷰ￾￿', undefined) +protocol => 'http:' +username => '' +password => '' +host => 'example.com' +hostname => 'example.com' +port => '' +pathname => '/%EF%BF%BD%F0%90%9F%BE%EF%BF%BD%EF%B7%90%EF%B7%8F%EF%B7%AF%EF%B7%B0%EF%BF%BE%EF%BF%BF' +search => '?%EF%BF%BD%F0%90%9F%BE%EF%BF%BD%EF%B7%90%EF%B7%8F%EF%B7%AF%EF%B7%B0%EF%BF%BE%EF%BF%BF' +searchParams => '%EF%BF%BD%F0%90%9F%BE%EF%BF%BD%EF%B7%90%EF%B7%8F%EF%B7%AF%EF%B7%B0%EF%BF%BE%EF%BF%BF=' +hash => '' diff --git a/Tests/LibWeb/Text/input/URL/url.html b/Tests/LibWeb/Text/input/URL/url.html index ebcaece3b3d..77c79fafff6 100644 --- a/Tests/LibWeb/Text/input/URL/url.html +++ b/Tests/LibWeb/Text/input/URL/url.html @@ -37,6 +37,7 @@ { input: '/c:/foo/bar', base: 'file:///c:/baz/qux' }, { input: '', base: 'file:///test?test#test' }, { input: '??a=b&c=d', base: 'http://example.org/foo/bar' }, + { input: 'http://example.com/\uD800\uD801\uDFFE\uDFFF\uFDD0\uFDCF\uFDEF\uFDF0\uFFFE\uFFFF?\uD800\uD801\uDFFE\uDFFF\uFDD0\uFDCF\uFDEF\uFDF0\uFFFE\uFFFF' }, ]; for (url of urls) {