mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-08-30 06:06:48 +00:00
LibWeb: Port the FormAssociatedElement value to UTF-16
Some checks are pending
CI / macOS, arm64, Sanitizer, Clang (push) Waiting to run
CI / Linux, x86_64, Fuzzers, Clang (push) Waiting to run
CI / Linux, x86_64, Sanitizer, GNU (push) Waiting to run
CI / Linux, x86_64, Sanitizer, Clang (push) Waiting to run
Package the js repl as a binary artifact / Linux, arm64 (push) Waiting to run
Package the js repl as a binary artifact / macOS, arm64 (push) Waiting to run
Package the js repl as a binary artifact / Linux, x86_64 (push) Waiting to run
Run test262 and test-wasm / run_and_update_results (push) Waiting to run
Lint Code / lint (push) Waiting to run
Label PRs with merge conflicts / auto-labeler (push) Waiting to run
Push notes / build (push) Waiting to run
Some checks are pending
CI / macOS, arm64, Sanitizer, Clang (push) Waiting to run
CI / Linux, x86_64, Fuzzers, Clang (push) Waiting to run
CI / Linux, x86_64, Sanitizer, GNU (push) Waiting to run
CI / Linux, x86_64, Sanitizer, Clang (push) Waiting to run
Package the js repl as a binary artifact / Linux, arm64 (push) Waiting to run
Package the js repl as a binary artifact / macOS, arm64 (push) Waiting to run
Package the js repl as a binary artifact / Linux, x86_64 (push) Waiting to run
Run test262 and test-wasm / run_and_update_results (push) Waiting to run
Lint Code / lint (push) Waiting to run
Label PRs with merge conflicts / auto-labeler (push) Waiting to run
Push notes / build (push) Waiting to run
This porting effort makes it pretty clear we will want a UTF-16-aware GenericLexer. But for now, we can actually make ASCII assumptions about what we are parsing, and act accordingly.
This commit is contained in:
parent
e7b08cf291
commit
c8888609f4
Notes:
github-actions[bot]
2025-07-28 10:26:29 +00:00
Author: https://github.com/trflynn89
Commit: c8888609f4
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/5610
30 changed files with 444 additions and 333 deletions
|
@ -3600,7 +3600,7 @@ Optional<Element::Directionality> Element::auto_directionality() const
|
||||||
|
|
||||||
// 1. If element's value contains a character of bidirectional character type AL or R,
|
// 1. If element's value contains a character of bidirectional character type AL or R,
|
||||||
// and there is no character of bidirectional character type L anywhere before it in the element's value, then return 'rtl'.
|
// and there is no character of bidirectional character type L anywhere before it in the element's value, then return 'rtl'.
|
||||||
for (auto code_point : Utf8View(value)) {
|
for (auto code_point : value) {
|
||||||
auto bidi_class = Unicode::bidirectional_class(code_point);
|
auto bidi_class = Unicode::bidirectional_class(code_point);
|
||||||
if (bidi_class == Unicode::BidiClass::LeftToRight)
|
if (bidi_class == Unicode::BidiClass::LeftToRight)
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -33,30 +33,33 @@ u32 week_number_of_the_last_day(u64 year)
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#valid-week-string
|
// https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#valid-week-string
|
||||||
bool is_valid_week_string(StringView value)
|
bool is_valid_week_string(Utf16View const& value)
|
||||||
{
|
{
|
||||||
// A string is a valid week string representing a week-year year and week week if it consists of the following components in the given order:
|
// A string is a valid week string representing a week-year year and week week if it consists of the following components in the given order:
|
||||||
|
|
||||||
// 1. Four or more ASCII digits, representing year, where year > 0
|
// 1. Four or more ASCII digits, representing year, where year > 0
|
||||||
// 2. A U+002D HYPHEN-MINUS character (-)
|
// 2. A U+002D HYPHEN-MINUS character (-)
|
||||||
// 3. A U+0057 LATIN CAPITAL LETTER W character (W)
|
// 3. A U+0057 LATIN CAPITAL LETTER W character (W)
|
||||||
// 4. Two ASCII digits, representing the week week, in the range 1 ≤ week ≤ maxweek, where maxweek is the week number of the last day of week-year year
|
// 4. Two ASCII digits, representing the week week, in the range 1 ≤ week ≤ maxweek, where maxweek is the week number
|
||||||
|
// of the last day of week-year year
|
||||||
auto parts = value.split_view('-', SplitBehavior::KeepEmpty);
|
auto parts = value.split_view('-', SplitBehavior::KeepEmpty);
|
||||||
if (parts.size() != 2)
|
if (parts.size() != 2)
|
||||||
return false;
|
return false;
|
||||||
if (parts[0].length() < 4)
|
|
||||||
|
if (parts[0].length_in_code_units() < 4)
|
||||||
return false;
|
return false;
|
||||||
|
if (parts[1].length_in_code_units() != 3)
|
||||||
|
return false;
|
||||||
|
|
||||||
for (auto digit : parts[0])
|
for (auto digit : parts[0])
|
||||||
if (!is_ascii_digit(digit))
|
if (!is_ascii_digit(digit))
|
||||||
return false;
|
return false;
|
||||||
if (parts[1].length() != 3)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!parts[1].starts_with('W'))
|
if (!parts[1].starts_with("W"sv))
|
||||||
return false;
|
return false;
|
||||||
if (!is_ascii_digit(parts[1][1]))
|
if (!is_ascii_digit(parts[1].code_unit_at(1)))
|
||||||
return false;
|
return false;
|
||||||
if (!is_ascii_digit(parts[1][2]))
|
if (!is_ascii_digit(parts[1].code_unit_at(2)))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
u64 year = 0;
|
u64 year = 0;
|
||||||
|
@ -64,13 +67,13 @@ bool is_valid_week_string(StringView value)
|
||||||
year *= 10;
|
year *= 10;
|
||||||
year += parse_ascii_digit(d);
|
year += parse_ascii_digit(d);
|
||||||
}
|
}
|
||||||
auto week = (parse_ascii_digit(parts[1][1]) * 10) + parse_ascii_digit(parts[1][2]);
|
|
||||||
|
|
||||||
|
auto week = (parse_ascii_digit(parts[1].code_unit_at(1)) * 10) + parse_ascii_digit(parts[1].code_unit_at(2));
|
||||||
return week >= 1 && week <= week_number_of_the_last_day(year);
|
return week >= 1 && week <= week_number_of_the_last_day(year);
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#valid-month-string
|
// https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#valid-month-string
|
||||||
bool is_valid_month_string(StringView value)
|
bool is_valid_month_string(Utf16View const& value)
|
||||||
{
|
{
|
||||||
// A string is a valid month string representing a year year and month month if it consists of the following components in the given order:
|
// A string is a valid month string representing a year year and month month if it consists of the following components in the given order:
|
||||||
|
|
||||||
|
@ -82,40 +85,42 @@ bool is_valid_month_string(StringView value)
|
||||||
if (parts.size() != 2)
|
if (parts.size() != 2)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (parts[0].length() < 4)
|
if (parts[0].length_in_code_units() < 4)
|
||||||
return false;
|
return false;
|
||||||
|
if (parts[1].length_in_code_units() != 2)
|
||||||
|
return false;
|
||||||
|
|
||||||
for (auto digit : parts[0])
|
for (auto digit : parts[0])
|
||||||
if (!is_ascii_digit(digit))
|
if (!is_ascii_digit(digit))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (parts[1].length() != 2)
|
if (!is_ascii_digit(parts[1].code_unit_at(0)))
|
||||||
|
return false;
|
||||||
|
if (!is_ascii_digit(parts[1].code_unit_at(1)))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!is_ascii_digit(parts[1][0]))
|
auto month = (parse_ascii_digit(parts[1].code_unit_at(0)) * 10) + parse_ascii_digit(parts[1].code_unit_at(1));
|
||||||
return false;
|
|
||||||
if (!is_ascii_digit(parts[1][1]))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
auto month = (parse_ascii_digit(parts[1][0]) * 10) + parse_ascii_digit(parts[1][1]);
|
|
||||||
return month >= 1 && month <= 12;
|
return month >= 1 && month <= 12;
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#valid-date-string
|
// https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#valid-date-string
|
||||||
bool is_valid_date_string(StringView value)
|
bool is_valid_date_string(Utf16View const& value)
|
||||||
{
|
{
|
||||||
// A string is a valid date string representing a year year, month month, and day day if it consists of the following components in the given order:
|
// A string is a valid date string representing a year year, month month, and day day if it consists of the following components in the given order:
|
||||||
|
|
||||||
// 1. A valid month string, representing year and month
|
// 1. A valid month string, representing year and month
|
||||||
// 2. A U+002D HYPHEN-MINUS character (-)
|
// 2. A U+002D HYPHEN-MINUS character (-)
|
||||||
// 3. Two ASCII digits, representing day, in the range 1 ≤ day ≤ maxday where maxday is the number of days in the month month and year year
|
// 3. Two ASCII digits, representing day, in the range 1 ≤ day ≤ maxday where maxday is the number of days in the
|
||||||
|
// month month and year year
|
||||||
auto parts = value.split_view('-', SplitBehavior::KeepEmpty);
|
auto parts = value.split_view('-', SplitBehavior::KeepEmpty);
|
||||||
if (parts.size() != 3)
|
if (parts.size() != 3)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!is_valid_month_string(ByteString::formatted("{}-{}", parts[0], parts[1])))
|
auto month_string = value.substring_view(0, parts[0].length_in_code_units() + 1 + parts[1].length_in_code_units());
|
||||||
|
if (!is_valid_month_string(month_string))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (parts[2].length() != 2)
|
if (parts[2].length_in_code_units() != 2)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
i64 year = 0;
|
i64 year = 0;
|
||||||
|
@ -123,18 +128,20 @@ bool is_valid_date_string(StringView value)
|
||||||
year *= 10;
|
year *= 10;
|
||||||
year += parse_ascii_digit(d);
|
year += parse_ascii_digit(d);
|
||||||
}
|
}
|
||||||
auto month = (parse_ascii_digit(parts[1][0]) * 10) + parse_ascii_digit(parts[1][1]);
|
|
||||||
i64 day = (parse_ascii_digit(parts[2][0]) * 10) + parse_ascii_digit(parts[2][1]);
|
auto month = (parse_ascii_digit(parts[1].code_unit_at(0)) * 10) + parse_ascii_digit(parts[1].code_unit_at(1));
|
||||||
|
i64 day = (parse_ascii_digit(parts[2].code_unit_at(0)) * 10) + parse_ascii_digit(parts[2].code_unit_at(1));
|
||||||
|
|
||||||
return day >= 1 && day <= AK::days_in_month(year, month);
|
return day >= 1 && day <= AK::days_in_month(year, month);
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#valid-local-date-and-time-string
|
// https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#valid-local-date-and-time-string
|
||||||
bool is_valid_local_date_and_time_string(StringView value)
|
bool is_valid_local_date_and_time_string(Utf16View const& value)
|
||||||
{
|
{
|
||||||
auto parts_split_by_T = value.split_view('T', SplitBehavior::KeepEmpty);
|
auto parts_split_by_T = value.split_view('T', SplitBehavior::KeepEmpty);
|
||||||
if (parts_split_by_T.size() == 2)
|
if (parts_split_by_T.size() == 2)
|
||||||
return is_valid_date_string(parts_split_by_T[0]) && is_valid_time_string(parts_split_by_T[1]);
|
return is_valid_date_string(parts_split_by_T[0]) && is_valid_time_string(parts_split_by_T[1]);
|
||||||
|
|
||||||
auto parts_split_by_space = value.split_view(' ', SplitBehavior::KeepEmpty);
|
auto parts_split_by_space = value.split_view(' ', SplitBehavior::KeepEmpty);
|
||||||
if (parts_split_by_space.size() == 2)
|
if (parts_split_by_space.size() == 2)
|
||||||
return is_valid_date_string(parts_split_by_space[0]) && is_valid_time_string(parts_split_by_space[1]);
|
return is_valid_date_string(parts_split_by_space[0]) && is_valid_time_string(parts_split_by_space[1]);
|
||||||
|
@ -143,11 +150,11 @@ bool is_valid_local_date_and_time_string(StringView value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#valid-normalised-local-date-and-time-string
|
// https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#valid-normalised-local-date-and-time-string
|
||||||
String normalize_local_date_and_time_string(String const& value)
|
Utf16String normalize_local_date_and_time_string(Utf16String const& value)
|
||||||
{
|
{
|
||||||
if (auto spaces = value.count(" "sv); spaces > 0) {
|
if (auto spaces = value.count(" "sv); spaces > 0) {
|
||||||
VERIFY(spaces == 1);
|
VERIFY(spaces == 1);
|
||||||
return MUST(value.replace(" "sv, "T"sv, ReplaceMode::FirstOnly));
|
return value.replace(" "sv, "T"sv, ReplaceMode::FirstOnly);
|
||||||
}
|
}
|
||||||
|
|
||||||
VERIFY(value.count("T"sv) == 1);
|
VERIFY(value.count("T"sv) == 1);
|
||||||
|
@ -155,7 +162,7 @@ String normalize_local_date_and_time_string(String const& value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#valid-time-string
|
// https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#valid-time-string
|
||||||
bool is_valid_time_string(StringView value)
|
bool is_valid_time_string(Utf16View const& value)
|
||||||
{
|
{
|
||||||
// A string is a valid time string representing an hour hour, a minute minute, and a second second if it consists of the following components in the given order:
|
// A string is a valid time string representing an hour hour, a minute minute, and a second second if it consists of the following components in the given order:
|
||||||
|
|
||||||
|
@ -171,40 +178,50 @@ bool is_valid_time_string(StringView value)
|
||||||
auto parts = value.split_view(':', SplitBehavior::KeepEmpty);
|
auto parts = value.split_view(':', SplitBehavior::KeepEmpty);
|
||||||
if (parts.size() != 2 && parts.size() != 3)
|
if (parts.size() != 2 && parts.size() != 3)
|
||||||
return false;
|
return false;
|
||||||
if (parts[0].length() != 2)
|
|
||||||
|
if (parts[0].length_in_code_units() != 2)
|
||||||
return false;
|
return false;
|
||||||
if (!(is_ascii_digit(parts[0][0]) && is_ascii_digit(parts[0][1])))
|
if (parts[1].length_in_code_units() != 2)
|
||||||
return false;
|
return false;
|
||||||
auto hour = (parse_ascii_digit(parts[0][0]) * 10) + parse_ascii_digit(parts[0][1]);
|
|
||||||
|
if (!is_ascii_digit(parts[0].code_unit_at(0)) || !is_ascii_digit(parts[0].code_unit_at(1)))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
auto hour = (parse_ascii_digit(parts[0].code_unit_at(0)) * 10) + parse_ascii_digit(parts[0].code_unit_at(1));
|
||||||
if (hour > 23)
|
if (hour > 23)
|
||||||
return false;
|
return false;
|
||||||
if (parts[1].length() != 2)
|
|
||||||
|
if (!is_ascii_digit(parts[1].code_unit_at(0)) || !is_ascii_digit(parts[1].code_unit_at(1)))
|
||||||
return false;
|
return false;
|
||||||
if (!(is_ascii_digit(parts[1][0]) && is_ascii_digit(parts[1][1])))
|
|
||||||
return false;
|
auto minute = (parse_ascii_digit(parts[1].code_unit_at(0)) * 10) + parse_ascii_digit(parts[1].code_unit_at(1));
|
||||||
auto minute = (parse_ascii_digit(parts[1][0]) * 10) + parse_ascii_digit(parts[1][1]);
|
|
||||||
if (minute > 59)
|
if (minute > 59)
|
||||||
return false;
|
return false;
|
||||||
if (parts.size() == 2)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
if (parts[2].length() < 2)
|
if (parts.size() == 3) {
|
||||||
|
if (parts[2].length_in_code_units() < 2)
|
||||||
return false;
|
return false;
|
||||||
if (!(is_ascii_digit(parts[2][0]) && is_ascii_digit(parts[2][1])))
|
|
||||||
|
if (!is_ascii_digit(parts[2].code_unit_at(0)) || !is_ascii_digit(parts[2].code_unit_at(1)))
|
||||||
return false;
|
return false;
|
||||||
auto second = (parse_ascii_digit(parts[2][0]) * 10) + parse_ascii_digit(parts[2][1]);
|
|
||||||
|
auto second = (parse_ascii_digit(parts[2].code_unit_at(0)) * 10) + parse_ascii_digit(parts[2].code_unit_at(1));
|
||||||
if (second > 59)
|
if (second > 59)
|
||||||
return false;
|
return false;
|
||||||
if (parts[2].length() == 2)
|
|
||||||
return true;
|
if (parts[2].length_in_code_units() > 2) {
|
||||||
auto second_parts = parts[2].split_view('.', SplitBehavior::KeepEmpty);
|
auto fractional = parts[2].split_view('.', SplitBehavior::KeepEmpty);
|
||||||
if (second_parts.size() != 2)
|
if (fractional.size() != 2)
|
||||||
return false;
|
return false;
|
||||||
if (second_parts[1].length() < 1 || second_parts[1].length() > 3)
|
|
||||||
|
if (fractional[1].length_in_code_units() < 1 || fractional[1].length_in_code_units() > 3)
|
||||||
return false;
|
return false;
|
||||||
for (auto digit : second_parts[1])
|
|
||||||
|
for (auto digit : fractional[1])
|
||||||
if (!is_ascii_digit(digit))
|
if (!is_ascii_digit(digit))
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,19 +7,19 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <AK/Forward.h>
|
#include <AK/Forward.h>
|
||||||
#include <AK/String.h>
|
#include <AK/Utf16String.h>
|
||||||
#include <LibJS/Runtime/Date.h>
|
#include <LibJS/Runtime/Date.h>
|
||||||
#include <LibWeb/WebIDL/ExceptionOr.h>
|
#include <LibWeb/WebIDL/ExceptionOr.h>
|
||||||
|
|
||||||
namespace Web::HTML {
|
namespace Web::HTML {
|
||||||
|
|
||||||
u32 week_number_of_the_last_day(u64 year);
|
u32 week_number_of_the_last_day(u64 year);
|
||||||
bool is_valid_week_string(StringView value);
|
bool is_valid_week_string(Utf16View const& value);
|
||||||
bool is_valid_month_string(StringView value);
|
bool is_valid_month_string(Utf16View const& value);
|
||||||
bool is_valid_date_string(StringView value);
|
bool is_valid_date_string(Utf16View const& value);
|
||||||
bool is_valid_local_date_and_time_string(StringView value);
|
bool is_valid_local_date_and_time_string(Utf16View const& value);
|
||||||
String normalize_local_date_and_time_string(String const& value);
|
Utf16String normalize_local_date_and_time_string(Utf16String const& value);
|
||||||
bool is_valid_time_string(StringView value);
|
bool is_valid_time_string(Utf16View const& value);
|
||||||
WebIDL::ExceptionOr<GC::Ref<JS::Date>> parse_time_string(JS::Realm& realm, StringView value);
|
WebIDL::ExceptionOr<GC::Ref<JS::Date>> parse_time_string(JS::Realm& realm, StringView value);
|
||||||
|
|
||||||
struct YearAndMonth {
|
struct YearAndMonth {
|
||||||
|
|
|
@ -125,7 +125,7 @@ public:
|
||||||
virtual bool suffering_from_bad_input() const { return false; }
|
virtual bool suffering_from_bad_input() const { return false; }
|
||||||
bool suffering_from_a_custom_error() const;
|
bool suffering_from_a_custom_error() const;
|
||||||
|
|
||||||
virtual String value() const { return String {}; }
|
virtual Utf16String value() const { return {}; }
|
||||||
virtual Optional<String> optional_value() const { VERIFY_NOT_REACHED(); }
|
virtual Optional<String> optional_value() const { VERIFY_NOT_REACHED(); }
|
||||||
|
|
||||||
virtual HTMLElement& form_associated_element_to_html_element() = 0;
|
virtual HTMLElement& form_associated_element_to_html_element() = 0;
|
||||||
|
|
|
@ -144,7 +144,7 @@ WebIDL::ExceptionOr<Optional<Vector<XHR::FormDataEntry>>> construct_entry_list(J
|
||||||
if (auto* select_element = dynamic_cast<HTML::HTMLSelectElement*>(control.ptr())) {
|
if (auto* select_element = dynamic_cast<HTML::HTMLSelectElement*>(control.ptr())) {
|
||||||
for (auto const& option_element : select_element->list_of_options()) {
|
for (auto const& option_element : select_element->list_of_options()) {
|
||||||
if (option_element->selected() && !option_element->disabled()) {
|
if (option_element->selected() && !option_element->disabled()) {
|
||||||
entry_list.append(TRY(create_entry(realm, name.to_string(), option_element->value())));
|
entry_list.append(TRY(create_entry(realm, name.to_string(), option_element->value().to_utf8_but_should_be_ported_to_utf16())));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -153,11 +153,11 @@ WebIDL::ExceptionOr<Optional<Vector<XHR::FormDataEntry>>> construct_entry_list(J
|
||||||
// 1. If the field element has a value attribute specified, then let value be the value of that attribute; otherwise, let value be the string "on".
|
// 1. If the field element has a value attribute specified, then let value be the value of that attribute; otherwise, let value be the string "on".
|
||||||
auto value = checkbox_or_radio_element->value();
|
auto value = checkbox_or_radio_element->value();
|
||||||
if (value.is_empty())
|
if (value.is_empty())
|
||||||
value = "on"_string;
|
value = "on"_utf16;
|
||||||
|
|
||||||
// 2. Create an entry with name and value, and append it to entry list.
|
// 2. Create an entry with name and value, and append it to entry list.
|
||||||
auto checkbox_or_radio_element_name = checkbox_or_radio_element->name();
|
auto checkbox_or_radio_element_name = checkbox_or_radio_element->name();
|
||||||
entry_list.append(TRY(create_entry(realm, checkbox_or_radio_element_name->to_string(), value)));
|
entry_list.append(TRY(create_entry(realm, checkbox_or_radio_element_name->to_string(), value.to_utf8_but_should_be_ported_to_utf16())));
|
||||||
}
|
}
|
||||||
// 8. Otherwise, if the field element is an input element whose type attribute is in the File Upload state, then:
|
// 8. Otherwise, if the field element is an input element whose type attribute is in the File Upload state, then:
|
||||||
else if (auto* file_element = dynamic_cast<HTML::HTMLInputElement*>(control.ptr()); file_element && file_element->type_state() == HTMLInputElement::TypeAttributeState::FileUpload) {
|
else if (auto* file_element = dynamic_cast<HTML::HTMLInputElement*>(control.ptr()); file_element && file_element->type_state() == HTMLInputElement::TypeAttributeState::FileUpload) {
|
||||||
|
@ -186,7 +186,7 @@ WebIDL::ExceptionOr<Optional<Vector<XHR::FormDataEntry>>> construct_entry_list(J
|
||||||
}
|
}
|
||||||
// 10. Otherwise, create an entry with name and the value of the field element, and append it to entry list.
|
// 10. Otherwise, create an entry with name and the value of the field element, and append it to entry list.
|
||||||
else {
|
else {
|
||||||
entry_list.append(TRY(create_entry(realm, name.to_string(), control_as_form_associated_element->value())));
|
entry_list.append(TRY(create_entry(realm, name.to_string(), control_as_form_associated_element->value().to_utf8_but_should_be_ported_to_utf16())));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 11. If the element has a dirname attribute, and that attribute's value is not the empty string, then:
|
// 11. If the element has a dirname attribute, and that attribute's value is not the empty string, then:
|
||||||
|
|
|
@ -117,10 +117,10 @@ bool HTMLButtonElement::is_submit_button() const
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/form-elements.html#the-button-element:concept-fe-value
|
// https://html.spec.whatwg.org/multipage/form-elements.html#the-button-element:concept-fe-value
|
||||||
String HTMLButtonElement::value() const
|
Utf16String HTMLButtonElement::value() const
|
||||||
{
|
{
|
||||||
// The element's value is the value of the element's value attribute, if there is one; otherwise the empty string.
|
// The element's value is the value of the element's value attribute, if there is one; otherwise the empty string.
|
||||||
return attribute(AttributeNames::value).value_or(String {});
|
return Utf16String::from_utf8(attribute(AttributeNames::value).value_or(String {}));
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/form-elements.html#the-button-element:concept-fe-optional-value
|
// https://html.spec.whatwg.org/multipage/form-elements.html#the-button-element:concept-fe-optional-value
|
||||||
|
|
|
@ -75,7 +75,7 @@ public:
|
||||||
// https://www.w3.org/TR/html-aria/#el-button
|
// https://www.w3.org/TR/html-aria/#el-button
|
||||||
virtual Optional<ARIA::Role> default_role() const override { return ARIA::Role::button; }
|
virtual Optional<ARIA::Role> default_role() const override { return ARIA::Role::button; }
|
||||||
|
|
||||||
virtual String value() const override;
|
virtual Utf16String value() const override;
|
||||||
virtual Optional<String> optional_value() const override;
|
virtual Optional<String> optional_value() const override;
|
||||||
|
|
||||||
virtual bool has_activation_behavior() const override;
|
virtual bool has_activation_behavior() const override;
|
||||||
|
|
|
@ -26,7 +26,7 @@ interface HTMLButtonElement : HTMLElement {
|
||||||
[CEReactions, Reflect=formtarget] attribute DOMString formTarget;
|
[CEReactions, Reflect=formtarget] attribute DOMString formTarget;
|
||||||
[CEReactions, Reflect] attribute DOMString name;
|
[CEReactions, Reflect] attribute DOMString name;
|
||||||
[CEReactions, ImplementedAs=type_for_bindings, Enumerated=ButtonTypeState] attribute DOMString type;
|
[CEReactions, ImplementedAs=type_for_bindings, Enumerated=ButtonTypeState] attribute DOMString type;
|
||||||
[CEReactions, Reflect] attribute DOMString value;
|
[CEReactions, Reflect] attribute Utf16DOMString value;
|
||||||
|
|
||||||
readonly attribute boolean willValidate;
|
readonly attribute boolean willValidate;
|
||||||
readonly attribute ValidityState validity;
|
readonly attribute ValidityState validity;
|
||||||
|
|
|
@ -404,7 +404,7 @@ static void show_the_picker_if_applicable(HTMLInputElement& element)
|
||||||
if (element.type_state() == HTMLInputElement::TypeAttributeState::Color) {
|
if (element.type_state() == HTMLInputElement::TypeAttributeState::Color) {
|
||||||
auto weak_element = element.make_weak_ptr<HTMLInputElement>();
|
auto weak_element = element.make_weak_ptr<HTMLInputElement>();
|
||||||
element.set_is_open(true);
|
element.set_is_open(true);
|
||||||
element.document().browsing_context()->top_level_browsing_context()->page().did_request_color_picker(weak_element, Color::from_string(element.value()).value_or(Color(0, 0, 0)));
|
element.document().browsing_context()->top_level_browsing_context()->page().did_request_color_picker(weak_element, Color::from_utf16_string(element.value()).value_or(Color(0, 0, 0)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -530,7 +530,7 @@ void HTMLInputElement::did_edit_text_node()
|
||||||
{
|
{
|
||||||
// An input element's dirty value flag must be set to true whenever the user interacts with the control in a way that changes the value.
|
// An input element's dirty value flag must be set to true whenever the user interacts with the control in a way that changes the value.
|
||||||
auto old_value = move(m_value);
|
auto old_value = move(m_value);
|
||||||
m_value = value_sanitization_algorithm(m_text_node->data().to_utf8_but_should_be_ported_to_utf16());
|
m_value = value_sanitization_algorithm(m_text_node->data());
|
||||||
m_dirty_value = true;
|
m_dirty_value = true;
|
||||||
|
|
||||||
m_has_uncommitted_changes = true;
|
m_has_uncommitted_changes = true;
|
||||||
|
@ -547,7 +547,7 @@ void HTMLInputElement::did_pick_color(Optional<Color> picked_color, ColorPickerU
|
||||||
{
|
{
|
||||||
if (type_state() == TypeAttributeState::Color && picked_color.has_value()) {
|
if (type_state() == TypeAttributeState::Color && picked_color.has_value()) {
|
||||||
// then when the user changes the element's value
|
// then when the user changes the element's value
|
||||||
m_value = value_sanitization_algorithm(picked_color.value().to_string_without_alpha());
|
m_value = value_sanitization_algorithm(picked_color->to_utf16_string_without_alpha());
|
||||||
m_dirty_value = true;
|
m_dirty_value = true;
|
||||||
|
|
||||||
update_color_well_element();
|
update_color_well_element();
|
||||||
|
@ -630,7 +630,7 @@ void HTMLInputElement::did_select_files(Span<SelectedFile> selected_files, Multi
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
String HTMLInputElement::value() const
|
Utf16String HTMLInputElement::value() const
|
||||||
{
|
{
|
||||||
switch (value_attribute_mode()) {
|
switch (value_attribute_mode()) {
|
||||||
// https://html.spec.whatwg.org/multipage/input.html#dom-input-value-value
|
// https://html.spec.whatwg.org/multipage/input.html#dom-input-value-value
|
||||||
|
@ -642,21 +642,23 @@ String HTMLInputElement::value() const
|
||||||
case ValueAttributeMode::Default:
|
case ValueAttributeMode::Default:
|
||||||
// On getting, if the element has a value content attribute, return that attribute's value; otherwise, return
|
// On getting, if the element has a value content attribute, return that attribute's value; otherwise, return
|
||||||
// the empty string.
|
// the empty string.
|
||||||
return get_attribute_value(AttributeNames::value);
|
return Utf16String::from_utf8(get_attribute_value(AttributeNames::value));
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/input.html#dom-input-value-default-on
|
// https://html.spec.whatwg.org/multipage/input.html#dom-input-value-default-on
|
||||||
case ValueAttributeMode::DefaultOn:
|
case ValueAttributeMode::DefaultOn:
|
||||||
// On getting, if the element has a value content attribute, return that attribute's value; otherwise, return
|
// On getting, if the element has a value content attribute, return that attribute's value; otherwise, return
|
||||||
// the string "on".
|
// the string "on".
|
||||||
return get_attribute(AttributeNames::value).value_or("on"_string);
|
if (auto value = get_attribute(AttributeNames::value); value.has_value())
|
||||||
|
return Utf16String::from_utf8(*value);
|
||||||
|
return "on"_utf16;
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/input.html#dom-input-value-filename
|
// https://html.spec.whatwg.org/multipage/input.html#dom-input-value-filename
|
||||||
case ValueAttributeMode::Filename:
|
case ValueAttributeMode::Filename:
|
||||||
// On getting, return the string "C:\fakepath\" followed by the name of the first file in the list of selected
|
// On getting, return the string "C:\fakepath\" followed by the name of the first file in the list of selected
|
||||||
// files, if any, or the empty string if the list is empty.
|
// files, if any, or the empty string if the list is empty.
|
||||||
if (m_selected_files && m_selected_files->item(0))
|
if (m_selected_files && m_selected_files->item(0))
|
||||||
return MUST(String::formatted("C:\\fakepath\\{}", m_selected_files->item(0)->name()));
|
return Utf16String::formatted("C:\\fakepath\\{}", m_selected_files->item(0)->name());
|
||||||
return String {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
VERIFY_NOT_REACHED();
|
VERIFY_NOT_REACHED();
|
||||||
|
@ -674,7 +676,7 @@ Optional<String> HTMLInputElement::optional_value() const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
WebIDL::ExceptionOr<void> HTMLInputElement::set_value(String const& value)
|
WebIDL::ExceptionOr<void> HTMLInputElement::set_value(Utf16String const& value)
|
||||||
{
|
{
|
||||||
auto& realm = this->realm();
|
auto& realm = this->realm();
|
||||||
|
|
||||||
|
@ -700,7 +702,7 @@ WebIDL::ExceptionOr<void> HTMLInputElement::set_value(String const& value)
|
||||||
relevant_value_was_changed();
|
relevant_value_was_changed();
|
||||||
|
|
||||||
if (m_text_node) {
|
if (m_text_node) {
|
||||||
m_text_node->set_data(Utf16String::from_utf8(m_value));
|
m_text_node->set_data(m_value);
|
||||||
update_placeholder_visibility();
|
update_placeholder_visibility();
|
||||||
|
|
||||||
set_the_selection_range(m_text_node->length(), m_text_node->length());
|
set_the_selection_range(m_text_node->length(), m_text_node->length());
|
||||||
|
@ -796,21 +798,21 @@ void HTMLInputElement::update_placeholder_visibility()
|
||||||
m_placeholder_element->set_inline_style(placeholder_style_when_hidden());
|
m_placeholder_element->set_inline_style(placeholder_style_when_hidden());
|
||||||
}
|
}
|
||||||
|
|
||||||
void HTMLInputElement::update_button_input_shadow_tree()
|
Utf16String HTMLInputElement::button_label() const
|
||||||
{
|
{
|
||||||
if (m_text_node) {
|
auto label = get_attribute(HTML::AttributeNames::value).map([](auto const& label) { return Utf16String::from_utf8(label); });
|
||||||
Optional<String> label = get_attribute(HTML::AttributeNames::value);
|
|
||||||
if (!label.has_value()) {
|
if (!label.has_value()) {
|
||||||
if (type_state() == TypeAttributeState::ResetButton) {
|
if (type_state() == TypeAttributeState::ResetButton) {
|
||||||
// https://html.spec.whatwg.org/multipage/input.html#reset-button-state-(type=reset)
|
// https://html.spec.whatwg.org/multipage/input.html#reset-button-state-(type=reset)
|
||||||
// If the element has a value attribute, the button's label must be the value of that attribute;
|
// If the element has a value attribute, the button's label must be the value of that attribute;
|
||||||
// otherwise, it must be an implementation-defined string that means "Reset" or some such.
|
// otherwise, it must be an implementation-defined string that means "Reset" or some such.
|
||||||
label = "Reset"_string;
|
label = "Reset"_utf16;
|
||||||
} else if (type_state() == TypeAttributeState::SubmitButton) {
|
} else if (type_state() == TypeAttributeState::SubmitButton) {
|
||||||
// https://html.spec.whatwg.org/multipage/input.html#submit-button-state-(type=submit)
|
// https://html.spec.whatwg.org/multipage/input.html#submit-button-state-(type=submit)
|
||||||
// If the element has a value attribute, the button's label must be the value of that attribute;
|
// If the element has a value attribute, the button's label must be the value of that attribute;
|
||||||
// otherwise, it must be an implementation-defined string that means "Submit" or some such.
|
// otherwise, it must be an implementation-defined string that means "Submit" or some such.
|
||||||
label = "Submit"_string;
|
label = "Submit"_utf16;
|
||||||
} else {
|
} else {
|
||||||
// https://html.spec.whatwg.org/multipage/input.html#button-state-(type=button)
|
// https://html.spec.whatwg.org/multipage/input.html#button-state-(type=button)
|
||||||
// If the element has a value attribute, the button's label must be the value of that attribute;
|
// If the element has a value attribute, the button's label must be the value of that attribute;
|
||||||
|
@ -819,7 +821,13 @@ void HTMLInputElement::update_button_input_shadow_tree()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_text_node->set_data(Utf16String::from_utf8(label.value()));
|
return label.release_value();
|
||||||
|
}
|
||||||
|
|
||||||
|
void HTMLInputElement::update_button_input_shadow_tree()
|
||||||
|
{
|
||||||
|
if (m_text_node) {
|
||||||
|
m_text_node->set_data(button_label());
|
||||||
update_placeholder_visibility();
|
update_placeholder_visibility();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -827,7 +835,7 @@ void HTMLInputElement::update_button_input_shadow_tree()
|
||||||
void HTMLInputElement::update_text_input_shadow_tree()
|
void HTMLInputElement::update_text_input_shadow_tree()
|
||||||
{
|
{
|
||||||
if (m_text_node) {
|
if (m_text_node) {
|
||||||
m_text_node->set_data(Utf16String::from_utf8(m_value));
|
m_text_node->set_data(m_value);
|
||||||
update_placeholder_visibility();
|
update_placeholder_visibility();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -999,26 +1007,8 @@ void HTMLInputElement::create_button_input_shadow_tree()
|
||||||
set_shadow_root(shadow_root);
|
set_shadow_root(shadow_root);
|
||||||
auto text_container = MUST(DOM::create_element(document(), HTML::TagNames::span, Namespace::HTML));
|
auto text_container = MUST(DOM::create_element(document(), HTML::TagNames::span, Namespace::HTML));
|
||||||
MUST(text_container->set_attribute(HTML::AttributeNames::style, "display: inline-block; pointer-events: none;"_string));
|
MUST(text_container->set_attribute(HTML::AttributeNames::style, "display: inline-block; pointer-events: none;"_string));
|
||||||
Optional<String> label = get_attribute(HTML::AttributeNames::value);
|
|
||||||
if (!label.has_value()) {
|
m_text_node = realm().create<DOM::Text>(document(), button_label());
|
||||||
if (type_state() == TypeAttributeState::ResetButton) {
|
|
||||||
// https://html.spec.whatwg.org/multipage/input.html#reset-button-state-(type=reset)
|
|
||||||
// If the element has a value attribute, the button's label must be the value of that attribute;
|
|
||||||
// otherwise, it must be an implementation-defined string that means "Reset" or some such.
|
|
||||||
label = "Reset"_string;
|
|
||||||
} else if (type_state() == TypeAttributeState::SubmitButton) {
|
|
||||||
// https://html.spec.whatwg.org/multipage/input.html#submit-button-state-(type=submit)
|
|
||||||
// If the element has a value attribute, the button's label must be the value of that attribute;
|
|
||||||
// otherwise, it must be an implementation-defined string that means "Submit" or some such.
|
|
||||||
label = "Submit"_string;
|
|
||||||
} else {
|
|
||||||
// https://html.spec.whatwg.org/multipage/input.html#button-state-(type=button)
|
|
||||||
// If the element has a value attribute, the button's label must be the value of that attribute;
|
|
||||||
// otherwise, it must be the empty string.
|
|
||||||
label = value();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m_text_node = realm().create<DOM::Text>(document(), Utf16String::from_utf8(label.value()));
|
|
||||||
MUST(text_container->append_child(*m_text_node));
|
MUST(text_container->append_child(*m_text_node));
|
||||||
MUST(shadow_root->append_child(*text_container));
|
MUST(shadow_root->append_child(*text_container));
|
||||||
}
|
}
|
||||||
|
@ -1074,7 +1064,7 @@ void HTMLInputElement::create_text_input_shadow_tree()
|
||||||
}
|
}
|
||||||
MUST(element->append_child(*m_inner_text_element));
|
MUST(element->append_child(*m_inner_text_element));
|
||||||
|
|
||||||
m_text_node = realm().create<DOM::Text>(document(), Utf16String::from_utf8(initial_value));
|
m_text_node = realm().create<DOM::Text>(document(), move(initial_value));
|
||||||
handle_readonly_attribute(attribute(HTML::AttributeNames::readonly));
|
handle_readonly_attribute(attribute(HTML::AttributeNames::readonly));
|
||||||
if (type_state() == TypeAttributeState::Password)
|
if (type_state() == TypeAttributeState::Password)
|
||||||
m_text_node->set_is_password_input({}, true);
|
m_text_node->set_is_password_input({}, true);
|
||||||
|
@ -1163,7 +1153,7 @@ void HTMLInputElement::create_color_input_shadow_tree()
|
||||||
border: 1px solid ButtonBorder;
|
border: 1px solid ButtonBorder;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
)~~~"_string));
|
)~~~"_string));
|
||||||
MUST(m_color_well_element->style_for_bindings()->set_property(CSS::PropertyID::BackgroundColor, color));
|
MUST(m_color_well_element->style_for_bindings()->set_property(CSS::PropertyID::BackgroundColor, color.to_utf8_but_should_be_ported_to_utf16()));
|
||||||
|
|
||||||
MUST(border->append_child(*m_color_well_element));
|
MUST(border->append_child(*m_color_well_element));
|
||||||
MUST(shadow_root->append_child(border));
|
MUST(shadow_root->append_child(border));
|
||||||
|
@ -1175,7 +1165,7 @@ void HTMLInputElement::update_color_well_element()
|
||||||
if (!m_color_well_element)
|
if (!m_color_well_element)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
MUST(m_color_well_element->style_for_bindings()->set_property(CSS::PropertyID::BackgroundColor, m_value));
|
MUST(m_color_well_element->style_for_bindings()->set_property(CSS::PropertyID::BackgroundColor, m_value.to_utf8_but_should_be_ported_to_utf16()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void HTMLInputElement::create_file_input_shadow_tree()
|
void HTMLInputElement::create_file_input_shadow_tree()
|
||||||
|
@ -1407,11 +1397,11 @@ void HTMLInputElement::form_associated_element_attribute_changed(FlyString const
|
||||||
} else if (name == HTML::AttributeNames::value) {
|
} else if (name == HTML::AttributeNames::value) {
|
||||||
if (!m_dirty_value) {
|
if (!m_dirty_value) {
|
||||||
auto old_value = move(m_value);
|
auto old_value = move(m_value);
|
||||||
if (!value.has_value()) {
|
|
||||||
m_value = String {};
|
if (value.has_value())
|
||||||
} else {
|
m_value = value_sanitization_algorithm(Utf16String::from_utf8(*value));
|
||||||
m_value = value_sanitization_algorithm(*value);
|
else
|
||||||
}
|
m_value = {};
|
||||||
|
|
||||||
if (m_value != old_value)
|
if (m_value != old_value)
|
||||||
relevant_value_was_changed();
|
relevant_value_was_changed();
|
||||||
|
@ -1458,7 +1448,7 @@ void HTMLInputElement::type_attribute_changed(TypeAttributeState old_state, Type
|
||||||
// then set the value of the element to the value of the value content attribute, if there is one, or the empty string
|
// then set the value of the element to the value of the value content attribute, if there is one, or the empty string
|
||||||
// otherwise, and then set the control's dirty value flag to false.
|
// otherwise, and then set the control's dirty value flag to false.
|
||||||
else if (old_value_attribute_mode != ValueAttributeMode::Value && new_value_attribute_mode == ValueAttributeMode::Value) {
|
else if (old_value_attribute_mode != ValueAttributeMode::Value && new_value_attribute_mode == ValueAttributeMode::Value) {
|
||||||
m_value = attribute(HTML::AttributeNames::value).value_or({});
|
m_value = Utf16String::from_utf8(attribute(HTML::AttributeNames::value).value_or({}));
|
||||||
m_dirty_value = false;
|
m_dirty_value = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1466,7 +1456,7 @@ void HTMLInputElement::type_attribute_changed(TypeAttributeState old_state, Type
|
||||||
// than the filename mode, and the new state of the element's type attribute puts the value IDL attribute in the filename mode,
|
// than the filename mode, and the new state of the element's type attribute puts the value IDL attribute in the filename mode,
|
||||||
// then set the value of the element to the empty string.
|
// then set the value of the element to the empty string.
|
||||||
else if (old_value_attribute_mode != ValueAttributeMode::Filename && new_value_attribute_mode == ValueAttributeMode::Filename) {
|
else if (old_value_attribute_mode != ValueAttributeMode::Filename && new_value_attribute_mode == ValueAttributeMode::Filename) {
|
||||||
m_value = String {};
|
m_value = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4. Update the element's rendering and behavior to the new state's.
|
// 4. Update the element's rendering and behavior to the new state's.
|
||||||
|
@ -1618,129 +1608,147 @@ bool HTMLInputElement::can_have_text_editing_cursor() const
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#valid-simple-colour
|
// https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#valid-simple-colour
|
||||||
static bool is_valid_simple_color(StringView value)
|
static bool is_valid_simple_color(Utf16View const& value)
|
||||||
{
|
{
|
||||||
// if it is exactly seven characters long,
|
// if it is exactly seven characters long,
|
||||||
if (value.length() != 7)
|
if (value.length_in_code_units() != 7)
|
||||||
return false;
|
return false;
|
||||||
// and the first character is a U+0023 NUMBER SIGN character (#),
|
// and the first character is a U+0023 NUMBER SIGN character (#),
|
||||||
if (!value.starts_with('#'))
|
if (!value.starts_with("#"sv))
|
||||||
return false;
|
return false;
|
||||||
// and the remaining six characters are all ASCII hex digits
|
// and the remaining six characters are all ASCII hex digits
|
||||||
for (size_t i = 1; i < value.length(); i++)
|
for (size_t i = 1; i < value.length_in_code_units(); i++)
|
||||||
if (!is_ascii_hex_digit(value[i]))
|
if (!is_ascii_hex_digit(value.code_unit_at(i)))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/input.html#value-sanitization-algorithm
|
// https://html.spec.whatwg.org/multipage/input.html#value-sanitization-algorithm
|
||||||
String HTMLInputElement::value_sanitization_algorithm(String const& value) const
|
Utf16String HTMLInputElement::value_sanitization_algorithm(Utf16String const& value) const
|
||||||
{
|
{
|
||||||
if (type_state() == HTMLInputElement::TypeAttributeState::Text || type_state() == HTMLInputElement::TypeAttributeState::Search || type_state() == HTMLInputElement::TypeAttributeState::Telephone || type_state() == HTMLInputElement::TypeAttributeState::Password) {
|
auto strip_newlines = [&]() {
|
||||||
|
if (!value.contains('\r') && !value.contains('\n'))
|
||||||
|
return value;
|
||||||
|
|
||||||
|
StringBuilder builder(StringBuilder::Mode::UTF16);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < value.length_in_code_units(); ++i) {
|
||||||
|
auto code_unit = value.code_unit_at(i);
|
||||||
|
if (code_unit != '\r' && code_unit != '\n')
|
||||||
|
builder.append_code_unit(code_unit);
|
||||||
|
}
|
||||||
|
|
||||||
|
return builder.to_utf16_string();
|
||||||
|
};
|
||||||
|
|
||||||
|
auto strip_newlines_and_trim = [&]() {
|
||||||
|
auto value_without_newlines = strip_newlines();
|
||||||
|
return Utf16String::from_utf16_without_validation(value_without_newlines.utf16_view().trim(Infra::ASCII_WHITESPACE));
|
||||||
|
};
|
||||||
|
|
||||||
|
// https://html.spec.whatwg.org/multipage/input.html#text-(type=text)-state-and-search-state-(type=search):value-sanitization-algorithm
|
||||||
|
// https://html.spec.whatwg.org/multipage/input.html#telephone-state-(type=tel):value-sanitization-algorithm
|
||||||
|
// https://html.spec.whatwg.org/multipage/input.html#password-state-(type=password):value-sanitization-algorithm
|
||||||
|
if (first_is_one_of(type_state(), HTMLInputElement::TypeAttributeState::Text, HTMLInputElement::TypeAttributeState::Search, HTMLInputElement::TypeAttributeState::Telephone, HTMLInputElement::TypeAttributeState::Password)) {
|
||||||
// Strip newlines from the value.
|
// Strip newlines from the value.
|
||||||
if (value.bytes_as_string_view().contains('\r') || value.bytes_as_string_view().contains('\n')) {
|
return strip_newlines();
|
||||||
StringBuilder builder;
|
|
||||||
for (auto c : value.bytes_as_string_view()) {
|
|
||||||
if (c != '\r' && c != '\n')
|
|
||||||
builder.append(c);
|
|
||||||
}
|
}
|
||||||
return MUST(builder.to_string());
|
|
||||||
}
|
// https://html.spec.whatwg.org/multipage/input.html#url-state-(type=url):value-sanitization-algorithm
|
||||||
} else if (type_state() == HTMLInputElement::TypeAttributeState::URL) {
|
if (type_state() == HTMLInputElement::TypeAttributeState::URL) {
|
||||||
// Strip newlines from the value, then strip leading and trailing ASCII whitespace from the value.
|
// Strip newlines from the value, then strip leading and trailing ASCII whitespace from the value.
|
||||||
if (value.bytes_as_string_view().contains('\r') || value.bytes_as_string_view().contains('\n')) {
|
return strip_newlines_and_trim();
|
||||||
StringBuilder builder;
|
|
||||||
for (auto c : value.bytes_as_string_view()) {
|
|
||||||
if (c != '\r' && c != '\n')
|
|
||||||
builder.append(c);
|
|
||||||
}
|
}
|
||||||
return MUST(String::from_utf8(builder.string_view().trim(Infra::ASCII_WHITESPACE)));
|
|
||||||
}
|
|
||||||
return MUST(value.trim(Infra::ASCII_WHITESPACE));
|
|
||||||
} else if (type_state() == HTMLInputElement::TypeAttributeState::Email) {
|
|
||||||
if (!has_attribute(AttributeNames::multiple)) {
|
|
||||||
// https://html.spec.whatwg.org/multipage/input.html#email-state-(type=email):value-sanitization-algorithm
|
// https://html.spec.whatwg.org/multipage/input.html#email-state-(type=email):value-sanitization-algorithm
|
||||||
// Strip newlines from the value, then strip leading and trailing ASCII whitespace from the value.
|
|
||||||
if (value.bytes_as_string_view().contains('\r') || value.bytes_as_string_view().contains('\n')) {
|
|
||||||
StringBuilder builder;
|
|
||||||
for (auto c : value.bytes_as_string_view()) {
|
|
||||||
if (c != '\r' && c != '\n')
|
|
||||||
builder.append(c);
|
|
||||||
}
|
|
||||||
return MUST(String::from_utf8(builder.string_view().trim_whitespace()));
|
|
||||||
}
|
|
||||||
return MUST(value.trim_ascii_whitespace());
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/input.html#email-state-(type=email):value-sanitization-algorithm-2
|
// https://html.spec.whatwg.org/multipage/input.html#email-state-(type=email):value-sanitization-algorithm-2
|
||||||
// 1. Split on commas the element's value, strip leading and trailing ASCII whitespace from each resulting token, if any,
|
if (type_state() == HTMLInputElement::TypeAttributeState::Email) {
|
||||||
// and let the element's values be the (possibly empty) resulting list of (possibly empty) tokens, maintaining the original order.
|
if (!has_attribute(AttributeNames::multiple)) {
|
||||||
Vector<String> values {};
|
// Strip newlines from the value, then strip leading and trailing ASCII whitespace from the value.
|
||||||
for (auto const& token : MUST(value.split(',', SplitBehavior::KeepEmpty))) {
|
return strip_newlines_and_trim();
|
||||||
values.append(MUST(token.trim_ascii_whitespace()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. Set the element's value to the result of concatenating the element's values, separating each value
|
// 1. Split on commas the element's value, strip leading and trailing ASCII whitespace from each resulting token,
|
||||||
// from the next by a single U+002C COMMA character (,), maintaining the list's order.
|
// if any, and let the element's values be the (possibly empty) resulting list of (possibly empty) tokens,
|
||||||
StringBuilder builder;
|
// maintaining the original order.
|
||||||
builder.join(',', values);
|
auto values = value.split_view(',', SplitBehavior::KeepEmpty);
|
||||||
return MUST(builder.to_string());
|
|
||||||
|
for (auto& value : values)
|
||||||
|
value = value.trim(Infra::ASCII_WHITESPACE);
|
||||||
|
|
||||||
|
// 2. Set the element's value to the result of concatenating the element's values, separating each value from
|
||||||
|
// the next by a single U+002C COMMA character (,), maintaining the list's order.
|
||||||
|
return Utf16String::join(',', values);
|
||||||
|
}
|
||||||
|
|
||||||
} else if (type_state() == HTMLInputElement::TypeAttributeState::Number) {
|
|
||||||
// https://html.spec.whatwg.org/multipage/input.html#number-state-(type=number):value-sanitization-algorithm
|
// https://html.spec.whatwg.org/multipage/input.html#number-state-(type=number):value-sanitization-algorithm
|
||||||
// If the value of the element is not a valid floating-point number, then set it
|
if (type_state() == HTMLInputElement::TypeAttributeState::Number) {
|
||||||
// to the empty string instead.
|
// If the value of the element is not a valid floating-point number, then set it to the empty string instead.
|
||||||
if (!is_valid_floating_point_number(value))
|
if (!is_valid_floating_point_number(value))
|
||||||
return String {};
|
return {};
|
||||||
auto maybe_value = parse_floating_point_number(value);
|
|
||||||
// AD-HOC: The spec doesn’t require these checks — but other engines do them, and
|
// AD-HOC: The spec doesn't require these checks - but other engines do them, and there's a WPT case which tests
|
||||||
// there’s a WPT case which tests that the value is less than Number.MAX_VALUE.
|
// that the value is less than Number.MAX_VALUE.
|
||||||
if (!maybe_value.has_value() || !isfinite(maybe_value.value()))
|
if (auto maybe_value = parse_floating_point_number(value); !maybe_value.has_value() || !isfinite(maybe_value.value()))
|
||||||
return String {};
|
return {};
|
||||||
} else if (type_state() == HTMLInputElement::TypeAttributeState::Date) {
|
}
|
||||||
// https://html.spec.whatwg.org/multipage/input.html#date-state-(type=date):value-sanitization-algorithm
|
// https://html.spec.whatwg.org/multipage/input.html#date-state-(type=date):value-sanitization-algorithm
|
||||||
|
else if (type_state() == HTMLInputElement::TypeAttributeState::Date) {
|
||||||
|
// If the value of the element is not a valid date string, then set it to the empty string instead.
|
||||||
if (!is_valid_date_string(value))
|
if (!is_valid_date_string(value))
|
||||||
return String {};
|
return {};
|
||||||
} else if (type_state() == HTMLInputElement::TypeAttributeState::Month) {
|
}
|
||||||
// https://html.spec.whatwg.org/multipage/input.html#month-state-(type=month):value-sanitization-algorithm
|
// https://html.spec.whatwg.org/multipage/input.html#month-state-(type=month):value-sanitization-algorithm
|
||||||
|
else if (type_state() == HTMLInputElement::TypeAttributeState::Month) {
|
||||||
|
// If the value of the element is not a valid month string, then set it to the empty string instead.
|
||||||
if (!is_valid_month_string(value))
|
if (!is_valid_month_string(value))
|
||||||
return String {};
|
return {};
|
||||||
} else if (type_state() == HTMLInputElement::TypeAttributeState::Week) {
|
}
|
||||||
// https://html.spec.whatwg.org/multipage/input.html#week-state-(type=week):value-sanitization-algorithm
|
// https://html.spec.whatwg.org/multipage/input.html#week-state-(type=week):value-sanitization-algorithm
|
||||||
|
else if (type_state() == HTMLInputElement::TypeAttributeState::Week) {
|
||||||
if (!is_valid_week_string(value))
|
if (!is_valid_week_string(value))
|
||||||
return String {};
|
return {};
|
||||||
} else if (type_state() == HTMLInputElement::TypeAttributeState::Time) {
|
}
|
||||||
// https://html.spec.whatwg.org/multipage/input.html#time-state-(type=time):value-sanitization-algorithm
|
// https://html.spec.whatwg.org/multipage/input.html#time-state-(type=time):value-sanitization-algorithm
|
||||||
|
else if (type_state() == HTMLInputElement::TypeAttributeState::Time) {
|
||||||
|
// If the value of the element is not a valid week string, then set it to the empty string instead.
|
||||||
if (!is_valid_time_string(value))
|
if (!is_valid_time_string(value))
|
||||||
return String {};
|
return {};
|
||||||
} else if (type_state() == HTMLInputElement::TypeAttributeState::LocalDateAndTime) {
|
}
|
||||||
// https://html.spec.whatwg.org/multipage/input.html#local-date-and-time-state-(type=datetime-local):value-sanitization-algorithm
|
// https://html.spec.whatwg.org/multipage/input.html#local-date-and-time-state-(type=datetime-local):value-sanitization-algorithm
|
||||||
|
else if (type_state() == HTMLInputElement::TypeAttributeState::LocalDateAndTime) {
|
||||||
|
// If the value of the element is a valid local date and time string, then set it to a valid normalized local
|
||||||
|
// date and time string representing the same date and time; otherwise, set it to the empty string instead.
|
||||||
if (is_valid_local_date_and_time_string(value))
|
if (is_valid_local_date_and_time_string(value))
|
||||||
return normalize_local_date_and_time_string(value);
|
return normalize_local_date_and_time_string(value);
|
||||||
return String {};
|
return {};
|
||||||
} else if (type_state() == HTMLInputElement::TypeAttributeState::Range) {
|
}
|
||||||
// https://html.spec.whatwg.org/multipage/input.html#range-state-(type=range):value-sanitization-algorithm
|
// https://html.spec.whatwg.org/multipage/input.html#range-state-(type=range):value-sanitization-algorithm
|
||||||
// If the value of the element is not a valid floating-point number, then set it to the best representation, as a floating-point number, of the default value.
|
else if (type_state() == HTMLInputElement::TypeAttributeState::Range) {
|
||||||
auto maybe_value = parse_floating_point_number(value);
|
// If the value of the element is not a valid floating-point number, then set it to the best representation, as
|
||||||
if (!is_valid_floating_point_number(value) ||
|
// a floating-point number, of the default value.
|
||||||
// AD-HOC: The spec doesn’t require these checks — but other engines do them.
|
if (auto maybe_value = parse_floating_point_number(value); !is_valid_floating_point_number(value) ||
|
||||||
|
// AD-HOC: The spec doesn't require these checks - but other engines do them.
|
||||||
!maybe_value.has_value() || !isfinite(maybe_value.value())) {
|
!maybe_value.has_value() || !isfinite(maybe_value.value())) {
|
||||||
// The default value is the minimum plus half the difference between the minimum and the maximum, unless the maximum is less than the minimum, in which case the default value is the minimum.
|
// The default value is the minimum plus half the difference between the minimum and the maximum, unless the
|
||||||
|
// maximum is less than the minimum, in which case the default value is the minimum.
|
||||||
auto minimum = *min();
|
auto minimum = *min();
|
||||||
auto maximum = *max();
|
auto maximum = *max();
|
||||||
if (maximum < minimum)
|
if (maximum < minimum)
|
||||||
return JS::number_to_string(minimum);
|
return JS::number_to_utf16_string(minimum);
|
||||||
return JS::number_to_string(minimum + (maximum - minimum) / 2);
|
return JS::number_to_utf16_string(minimum + ((maximum - minimum) / 2.0));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (type_state() == HTMLInputElement::TypeAttributeState::Color) {
|
|
||||||
// https://html.spec.whatwg.org/multipage/input.html#color-state-(type=color):value-sanitization-algorithm
|
// https://html.spec.whatwg.org/multipage/input.html#color-state-(type=color):value-sanitization-algorithm
|
||||||
// If the value of the element is a valid simple color, then set it to the value of the element converted to ASCII lowercase;
|
else if (type_state() == HTMLInputElement::TypeAttributeState::Color) {
|
||||||
|
// If the value of the element is a valid simple color, then set it to the value of the element converted to
|
||||||
|
// ASCII lowercase; otherwise, set it to the string "#000000".
|
||||||
if (is_valid_simple_color(value))
|
if (is_valid_simple_color(value))
|
||||||
return value.to_ascii_lowercase();
|
return value.to_ascii_lowercase();
|
||||||
// otherwise, set it to the string "#000000".
|
return "#000000"_utf16;
|
||||||
return "#000000"_string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1754,7 +1762,7 @@ void HTMLInputElement::reset_algorithm()
|
||||||
|
|
||||||
// set the value of the element to the value of the value content attribute, if there is one, or the empty string otherwise,
|
// set the value of the element to the value of the value content attribute, if there is one, or the empty string otherwise,
|
||||||
auto old_value = move(m_value);
|
auto old_value = move(m_value);
|
||||||
m_value = get_attribute_value(AttributeNames::value);
|
m_value = Utf16String::from_utf8(get_attribute_value(AttributeNames::value));
|
||||||
|
|
||||||
// set the checkedness of the element to true if the element has a checked content attribute and false if it does not,
|
// set the checkedness of the element to true if the element has a checked content attribute and false if it does not,
|
||||||
m_checked = has_attribute(AttributeNames::checked);
|
m_checked = has_attribute(AttributeNames::checked);
|
||||||
|
@ -1770,7 +1778,7 @@ void HTMLInputElement::reset_algorithm()
|
||||||
relevant_value_was_changed();
|
relevant_value_was_changed();
|
||||||
|
|
||||||
if (m_text_node) {
|
if (m_text_node) {
|
||||||
m_text_node->set_data(Utf16String::from_utf8(m_value));
|
m_text_node->set_data(m_value);
|
||||||
update_placeholder_visibility();
|
update_placeholder_visibility();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1786,7 +1794,7 @@ void HTMLInputElement::clear_algorithm()
|
||||||
|
|
||||||
// set the value of the element to an empty string,
|
// set the value of the element to an empty string,
|
||||||
auto old_value = move(m_value);
|
auto old_value = move(m_value);
|
||||||
m_value = String {};
|
m_value = {};
|
||||||
|
|
||||||
// set the checkedness of the element to true if the element has a checked content attribute and false if it does not,
|
// set the checkedness of the element to true if the element has a checked content attribute and false if it does not,
|
||||||
m_checked = has_attribute(AttributeNames::checked);
|
m_checked = has_attribute(AttributeNames::checked);
|
||||||
|
@ -1806,7 +1814,7 @@ void HTMLInputElement::clear_algorithm()
|
||||||
relevant_value_was_changed();
|
relevant_value_was_changed();
|
||||||
|
|
||||||
if (m_text_node) {
|
if (m_text_node) {
|
||||||
m_text_node->set_data(Utf16String::from_utf8(m_value));
|
m_text_node->set_data(m_value);
|
||||||
update_placeholder_visibility();
|
update_placeholder_visibility();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2310,19 +2318,28 @@ Optional<double> HTMLInputElement::convert_string_to_number(StringView input) co
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://html.spec.whatwg.org/multipage/input.html#concept-input-value-string-number
|
||||||
|
Optional<double> HTMLInputElement::convert_string_to_number(Utf16String const& input) const
|
||||||
|
{
|
||||||
|
// FIXME: Implement a UTF-16 GenericLexer.
|
||||||
|
if (!input.has_ascii_storage())
|
||||||
|
return {};
|
||||||
|
return convert_string_to_number(input.ascii_view());
|
||||||
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/input.html#month-state-(type=month):concept-input-value-number-string
|
// https://html.spec.whatwg.org/multipage/input.html#month-state-(type=month):concept-input-value-number-string
|
||||||
static String convert_number_to_month_string(double input)
|
static Utf16String convert_number_to_month_string(double input)
|
||||||
{
|
{
|
||||||
// The algorithm to convert a number to a string, given a number input, is as follows: Return a valid month
|
// The algorithm to convert a number to a string, given a number input, is as follows: Return a valid month
|
||||||
// string that represents the month that has input months between it and January 1970.
|
// string that represents the month that has input months between it and January 1970.
|
||||||
auto months = JS::modulo(input, 12);
|
auto months = JS::modulo(input, 12);
|
||||||
auto year = 1970 + (input - months) / 12;
|
auto year = 1970 + (input - months) / 12;
|
||||||
|
|
||||||
return MUST(String::formatted("{:04d}-{:02d}", static_cast<int>(year), static_cast<int>(months) + 1));
|
return Utf16String::formatted("{:04d}-{:02d}", static_cast<int>(year), static_cast<int>(months) + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/input.html#week-state-(type=week):concept-input-value-string-number
|
// https://html.spec.whatwg.org/multipage/input.html#week-state-(type=week):concept-input-value-string-number
|
||||||
static String convert_number_to_week_string(double input)
|
static Utf16String convert_number_to_week_string(double input)
|
||||||
{
|
{
|
||||||
// The algorithm to convert a number to a string, given a number input, is as follows: Return a valid week string that
|
// The algorithm to convert a number to a string, given a number input, is as follows: Return a valid week string that
|
||||||
// that represents the week that, in UTC, is current input milliseconds after midnight UTC on the morning of 1970-01-01
|
// that represents the week that, in UTC, is current input milliseconds after midnight UTC on the morning of 1970-01-01
|
||||||
|
@ -2348,21 +2365,21 @@ static String convert_number_to_week_string(double input)
|
||||||
week = weeks_in_year(year) + week;
|
week = weeks_in_year(year) + week;
|
||||||
}
|
}
|
||||||
|
|
||||||
return MUST(String::formatted("{:04d}-W{:02d}", year, week));
|
return Utf16String::formatted("{:04d}-W{:02d}", year, week);
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/input.html#date-state-(type=date):concept-input-value-number-string
|
// https://html.spec.whatwg.org/multipage/input.html#date-state-(type=date):concept-input-value-number-string
|
||||||
static String convert_number_to_date_string(double input)
|
static Utf16String convert_number_to_date_string(double input)
|
||||||
{
|
{
|
||||||
// The algorithm to convert a number to a string, given a number input, is as follows: Return a valid
|
// The algorithm to convert a number to a string, given a number input, is as follows: Return a valid
|
||||||
// date string that represents the date that, in UTC, is current input milliseconds after midnight UTC
|
// date string that represents the date that, in UTC, is current input milliseconds after midnight UTC
|
||||||
// on the morning of 1970-01-01 (the time represented by the value "1970-01-01T00:00:00.0Z").
|
// on the morning of 1970-01-01 (the time represented by the value "1970-01-01T00:00:00.0Z").
|
||||||
auto date = AK::UnixDateTime::from_seconds_since_epoch(input / 1000.);
|
auto date = AK::UnixDateTime::from_seconds_since_epoch(input / 1000.);
|
||||||
return MUST(date.to_string("%Y-%m-%d"sv, AK::UnixDateTime::LocalTime::No));
|
return date.to_utf16_string("%Y-%m-%d"sv, AK::UnixDateTime::LocalTime::No);
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/input.html#time-state-(type=time):concept-input-value-number-string
|
// https://html.spec.whatwg.org/multipage/input.html#time-state-(type=time):concept-input-value-number-string
|
||||||
static String convert_number_to_time_string(double input)
|
static Utf16String convert_number_to_time_string(double input)
|
||||||
{
|
{
|
||||||
// The algorithm to convert a number to a string, given a number input, is as follows: Return a valid time
|
// The algorithm to convert a number to a string, given a number input, is as follows: Return a valid time
|
||||||
// string that represents the time that is input milliseconds after midnight on a day with no time changes.
|
// string that represents the time that is input milliseconds after midnight on a day with no time changes.
|
||||||
|
@ -2370,14 +2387,14 @@ static String convert_number_to_time_string(double input)
|
||||||
auto milliseconds = JS::ms_from_time(input);
|
auto milliseconds = JS::ms_from_time(input);
|
||||||
if (seconds > 0) {
|
if (seconds > 0) {
|
||||||
if (milliseconds > 0)
|
if (milliseconds > 0)
|
||||||
return MUST(String::formatted("{:02d}:{:02d}:{:02d}.{:3d}", JS::hour_from_time(input), JS::min_from_time(input), seconds, milliseconds));
|
return Utf16String::formatted("{:02d}:{:02d}:{:02d}.{:3d}", JS::hour_from_time(input), JS::min_from_time(input), seconds, milliseconds);
|
||||||
return MUST(String::formatted("{:02d}:{:02d}:{:02d}", JS::hour_from_time(input), JS::min_from_time(input), seconds));
|
return Utf16String::formatted("{:02d}:{:02d}:{:02d}", JS::hour_from_time(input), JS::min_from_time(input), seconds);
|
||||||
}
|
}
|
||||||
return MUST(String::formatted("{:02d}:{:02d}", JS::hour_from_time(input), JS::min_from_time(input)));
|
return Utf16String::formatted("{:02d}:{:02d}", JS::hour_from_time(input), JS::min_from_time(input));
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/input.html#local-date-and-time-state-(type=datetime-local):concept-input-value-number-string
|
// https://html.spec.whatwg.org/multipage/input.html#local-date-and-time-state-(type=datetime-local):concept-input-value-number-string
|
||||||
static String convert_number_to_local_date_and_time_string(double input)
|
static Utf16String convert_number_to_local_date_and_time_string(double input)
|
||||||
{
|
{
|
||||||
// The algorithm to convert a number to a string, given a number input, is as follows: Return a valid
|
// The algorithm to convert a number to a string, given a number input, is as follows: Return a valid
|
||||||
// normalized local date and time string that represents the date and time that is input milliseconds
|
// normalized local date and time string that represents the date and time that is input milliseconds
|
||||||
|
@ -2392,23 +2409,23 @@ static String convert_number_to_local_date_and_time_string(double input)
|
||||||
|
|
||||||
if (seconds > 0) {
|
if (seconds > 0) {
|
||||||
if (milliseconds > 0)
|
if (milliseconds > 0)
|
||||||
return MUST(String::formatted("{:04d}-{:02d}-{:02d}T{:02d}:{:02d}:{:02d}.{:03d}", year, month, day, hour, minutes, seconds, milliseconds));
|
return Utf16String::formatted("{:04d}-{:02d}-{:02d}T{:02d}:{:02d}:{:02d}.{:03d}", year, month, day, hour, minutes, seconds, milliseconds);
|
||||||
return MUST(String::formatted("{:04d}-{:02d}-{:02d}T{:02d}:{:02d}:{:02d}", year, month, day, hour, minutes, seconds));
|
return Utf16String::formatted("{:04d}-{:02d}-{:02d}T{:02d}:{:02d}:{:02d}", year, month, day, hour, minutes, seconds);
|
||||||
}
|
}
|
||||||
|
|
||||||
return MUST(String::formatted("{:04d}-{:02d}-{:02d}T{:02d}:{:02d}", year, month, day, hour, minutes));
|
return Utf16String::formatted("{:04d}-{:02d}-{:02d}T{:02d}:{:02d}", year, month, day, hour, minutes);
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/input.html#concept-input-value-string-number
|
// https://html.spec.whatwg.org/multipage/input.html#concept-input-value-string-number
|
||||||
String HTMLInputElement::convert_number_to_string(double input) const
|
Utf16String HTMLInputElement::convert_number_to_string(double input) const
|
||||||
{
|
{
|
||||||
// https://html.spec.whatwg.org/multipage/input.html#number-state-(type=number):concept-input-value-number-string
|
// https://html.spec.whatwg.org/multipage/input.html#number-state-(type=number):concept-input-value-number-string
|
||||||
if (type_state() == TypeAttributeState::Number)
|
if (type_state() == TypeAttributeState::Number)
|
||||||
return String::number(input);
|
return Utf16String::number(input);
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/input.html#range-state-(type=range):concept-input-value-number-string
|
// https://html.spec.whatwg.org/multipage/input.html#range-state-(type=range):concept-input-value-number-string
|
||||||
if (type_state() == TypeAttributeState::Range)
|
if (type_state() == TypeAttributeState::Range)
|
||||||
return String::number(input);
|
return Utf16String::number(input);
|
||||||
|
|
||||||
if (type_state() == TypeAttributeState::Month)
|
if (type_state() == TypeAttributeState::Month)
|
||||||
return convert_number_to_month_string(input);
|
return convert_number_to_month_string(input);
|
||||||
|
@ -2459,8 +2476,17 @@ WebIDL::ExceptionOr<GC::Ptr<JS::Date>> HTMLInputElement::convert_string_to_date(
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://html.spec.whatwg.org/multipage/input.html#concept-input-value-string-date
|
||||||
|
WebIDL::ExceptionOr<GC::Ptr<JS::Date>> HTMLInputElement::convert_string_to_date(Utf16String const& input) const
|
||||||
|
{
|
||||||
|
// FIXME: Implement a UTF-16 GenericLexer.
|
||||||
|
if (!input.has_ascii_storage())
|
||||||
|
return nullptr;
|
||||||
|
return convert_string_to_date(input.ascii_view());
|
||||||
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/input.html#concept-input-value-date-string
|
// https://html.spec.whatwg.org/multipage/input.html#concept-input-value-date-string
|
||||||
String HTMLInputElement::convert_date_to_string(GC::Ref<JS::Date> input) const
|
Utf16String HTMLInputElement::convert_date_to_string(GC::Ref<JS::Date> input) const
|
||||||
{
|
{
|
||||||
// https://html.spec.whatwg.org/multipage/input.html#date-state-(type=date):concept-input-value-date-string
|
// https://html.spec.whatwg.org/multipage/input.html#date-state-(type=date):concept-input-value-date-string
|
||||||
if (type_state() == TypeAttributeState::Date) {
|
if (type_state() == TypeAttributeState::Date) {
|
||||||
|
@ -2665,12 +2691,12 @@ WebIDL::ExceptionOr<void> HTMLInputElement::set_value_as_date(Optional<GC::Root<
|
||||||
|
|
||||||
// otherwise if the new value is null or a Date object representing the NaN time value, then set the value of the element to the empty string;
|
// otherwise if the new value is null or a Date object representing the NaN time value, then set the value of the element to the empty string;
|
||||||
if (!value.has_value()) {
|
if (!value.has_value()) {
|
||||||
TRY(set_value(String {}));
|
TRY(set_value({}));
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
auto& date = static_cast<JS::Date&>(**value);
|
auto& date = static_cast<JS::Date&>(**value);
|
||||||
if (!isfinite(date.date_value())) {
|
if (!isfinite(date.date_value())) {
|
||||||
TRY(set_value(String {}));
|
TRY(set_value({}));
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2704,7 +2730,7 @@ WebIDL::ExceptionOr<void> HTMLInputElement::set_value_as_number(double value)
|
||||||
|
|
||||||
// Otherwise, if the new value is a Not-a-Number (NaN) value, then set the value of the element to the empty string.
|
// Otherwise, if the new value is a Not-a-Number (NaN) value, then set the value of the element to the empty string.
|
||||||
if (value == NAN) {
|
if (value == NAN) {
|
||||||
TRY(set_value(String {}));
|
TRY(set_value({}));
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3301,46 +3327,58 @@ bool HTMLInputElement::suffering_from_a_type_mismatch() const
|
||||||
{
|
{
|
||||||
auto input = value();
|
auto input = value();
|
||||||
switch (type_state()) {
|
switch (type_state()) {
|
||||||
case TypeAttributeState::URL:
|
|
||||||
// https://html.spec.whatwg.org/multipage/input.html#url-state-(type%3Durl)%3Asuffering-from-a-type-mismatch
|
// https://html.spec.whatwg.org/multipage/input.html#url-state-(type%3Durl)%3Asuffering-from-a-type-mismatch
|
||||||
|
case TypeAttributeState::URL:
|
||||||
// While the value of the element is neither the empty string nor a valid absolute URL, the element is suffering from a type mismatch.
|
// While the value of the element is neither the empty string nor a valid absolute URL, the element is suffering from a type mismatch.
|
||||||
// AD-HOC: https://github.com/whatwg/html/issues/11083 and https://github.com/web-platform-tests/wpt/pull/51011
|
// AD-HOC: https://github.com/whatwg/html/issues/11083 and https://github.com/web-platform-tests/wpt/pull/51011
|
||||||
// We intentionally don't check if the value is a "valid absolute URL", because that's not what other
|
// We intentionally don't check if the value is a "valid absolute URL", because that's not what other
|
||||||
// engines actually do. So we instead just implement what matches the behavior in existing engines.
|
// engines actually do. So we instead just implement what matches the behavior in existing engines.
|
||||||
return !input.is_empty() && !URL::Parser::basic_parse(input).has_value();
|
return !input.is_empty() && !URL::Parser::basic_parse(input.to_utf8_but_should_be_ported_to_utf16()).has_value();
|
||||||
case TypeAttributeState::Email:
|
|
||||||
// https://html.spec.whatwg.org/multipage/input.html#email-state-(type%3Demail)%3Asuffering-from-a-type-mismatch
|
// https://html.spec.whatwg.org/multipage/input.html#email-state-(type%3Demail)%3Asuffering-from-a-type-mismatch
|
||||||
|
case TypeAttributeState::Email: {
|
||||||
// When the multiple attribute is not specified on the element: While the value of the element is neither the
|
// When the multiple attribute is not specified on the element: While the value of the element is neither the
|
||||||
// empty string nor a single valid email address, the element is suffering from a type mismatch.
|
// empty string nor a single valid email address, the element is suffering from a type mismatch.
|
||||||
if (!has_attribute(HTML::AttributeNames::multiple))
|
if (!has_attribute(HTML::AttributeNames::multiple))
|
||||||
return !input.is_empty() && !valid_email_address_regex.match(input).success;
|
return !input.is_empty() && !valid_email_address_regex.match(input.utf16_view()).success;
|
||||||
|
|
||||||
// When the multiple attribute is specified on the element: While the value of the element is not a valid email
|
// When the multiple attribute is specified on the element: While the value of the element is not a valid email
|
||||||
// address list, the element is suffering from a type mismatch.
|
// address list, the element is suffering from a type mismatch.
|
||||||
// https://html.spec.whatwg.org/multipage/input.html#valid-e-mail-address-list
|
// https://html.spec.whatwg.org/multipage/input.html#valid-e-mail-address-list
|
||||||
// A valid email address list is a set of comma-separated tokens, where each token is itself a valid email
|
// A valid email address list is a set of comma-separated tokens, where each token is itself a valid email
|
||||||
// address. To obtain the list of tokens from a valid email address list, an implementation must split the
|
// address. To obtain the list of tokens from a valid email address list, an implementation must split the
|
||||||
// string on commas.
|
// string on commas.
|
||||||
for (auto& address : MUST(input.split(','))) {
|
bool valid = true;
|
||||||
if (!valid_email_address_regex.match(address).success)
|
|
||||||
return true;
|
input.for_each_split_view(',', SplitBehavior::Nothing, [&](auto const& address) {
|
||||||
|
if (valid_email_address_regex.match(address).success)
|
||||||
|
return IterationDecision::Continue;
|
||||||
|
|
||||||
|
valid = false;
|
||||||
|
return IterationDecision::Break;
|
||||||
|
});
|
||||||
|
|
||||||
|
return !valid;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/input.html#the-pattern-attribute%3Asuffering-from-a-pattern-mismatch
|
// https://html.spec.whatwg.org/multipage/input.html#the-pattern-attribute%3Asuffering-from-a-pattern-mismatch
|
||||||
bool HTMLInputElement::suffering_from_a_pattern_mismatch() const
|
bool HTMLInputElement::suffering_from_a_pattern_mismatch() const
|
||||||
{
|
{
|
||||||
// If the element's value is not the empty string, and either the element's multiple attribute is not specified or it does not apply to the input element given its
|
// If the element's value is not the empty string, and either the element's multiple attribute is not specified or
|
||||||
// type attribute's current state, and the element has a compiled pattern regular expression but that regular expression does not match the element's value, then the element is
|
// it does not apply to the input element given its type attribute's current state, and the element has a compiled
|
||||||
|
// pattern regular expression but that regular expression does not match the element's value, then the element is
|
||||||
// suffering from a pattern mismatch.
|
// suffering from a pattern mismatch.
|
||||||
|
|
||||||
// If the element's value is not the empty string, and the element's multiple attribute is specified and applies to the input element,
|
// If the element's value is not the empty string, and the element's multiple attribute is specified and applies to
|
||||||
// and the element has a compiled pattern regular expression but that regular expression does not match each of the element's values,
|
// the input element, and the element has a compiled pattern regular expression but that regular expression does not
|
||||||
// then the element is suffering from a pattern mismatch.
|
// match each of the element's values, then the element is suffering from a pattern mismatch.
|
||||||
|
|
||||||
if (!pattern_applies())
|
if (!pattern_applies())
|
||||||
return false;
|
return false;
|
||||||
|
@ -3355,13 +3393,20 @@ bool HTMLInputElement::suffering_from_a_pattern_mismatch() const
|
||||||
|
|
||||||
if (has_attribute(HTML::AttributeNames::multiple) && multiple_applies()) {
|
if (has_attribute(HTML::AttributeNames::multiple) && multiple_applies()) {
|
||||||
VERIFY(type_state() == HTMLInputElement::TypeAttributeState::Email);
|
VERIFY(type_state() == HTMLInputElement::TypeAttributeState::Email);
|
||||||
|
bool valid = true;
|
||||||
|
|
||||||
return AK::any_of(MUST(value.split(',')), [®exp_object](auto const& value) {
|
value.for_each_split_view(',', SplitBehavior::Nothing, [&](auto const& value) {
|
||||||
return !regexp_object->match(value).success;
|
if (regexp_object->match(value).success)
|
||||||
|
return IterationDecision::Continue;
|
||||||
|
|
||||||
|
valid = false;
|
||||||
|
return IterationDecision::Break;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return !valid;
|
||||||
}
|
}
|
||||||
|
|
||||||
return !regexp_object->match(value).success;
|
return !regexp_object->match(value.utf16_view()).success;
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#suffering-from-an-underflow
|
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#suffering-from-an-underflow
|
||||||
|
|
|
@ -79,13 +79,13 @@ public:
|
||||||
|
|
||||||
String default_value() const { return get_attribute_value(HTML::AttributeNames::value); }
|
String default_value() const { return get_attribute_value(HTML::AttributeNames::value); }
|
||||||
|
|
||||||
virtual String value() const override;
|
virtual Utf16String value() const override;
|
||||||
virtual Optional<String> optional_value() const override;
|
virtual Optional<String> optional_value() const override;
|
||||||
WebIDL::ExceptionOr<void> set_value(String const&);
|
WebIDL::ExceptionOr<void> set_value(Utf16String const&);
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#concept-textarea/input-relevant-value
|
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#concept-textarea/input-relevant-value
|
||||||
virtual Utf16String relevant_value() override { return Utf16String::from_utf8(value()); }
|
virtual Utf16String relevant_value() override { return value(); }
|
||||||
WebIDL::ExceptionOr<void> set_relevant_value(Utf16String const& value) override { return set_value(value.to_utf8_but_should_be_ported_to_utf16()); }
|
WebIDL::ExceptionOr<void> set_relevant_value(Utf16String const& value) override { return set_value(value); }
|
||||||
|
|
||||||
virtual void set_dirty_value_flag(bool flag) override { m_dirty_value = flag; }
|
virtual void set_dirty_value_flag(bool flag) override { m_dirty_value = flag; }
|
||||||
|
|
||||||
|
@ -290,10 +290,12 @@ private:
|
||||||
|
|
||||||
Optional<double> convert_time_string_to_number(StringView input) const;
|
Optional<double> convert_time_string_to_number(StringView input) const;
|
||||||
Optional<double> convert_string_to_number(StringView input) const;
|
Optional<double> convert_string_to_number(StringView input) const;
|
||||||
String convert_number_to_string(double input) const;
|
Optional<double> convert_string_to_number(Utf16String const& input) const;
|
||||||
|
Utf16String convert_number_to_string(double input) const;
|
||||||
|
|
||||||
WebIDL::ExceptionOr<GC::Ptr<JS::Date>> convert_string_to_date(StringView input) const;
|
WebIDL::ExceptionOr<GC::Ptr<JS::Date>> convert_string_to_date(StringView input) const;
|
||||||
String convert_date_to_string(GC::Ref<JS::Date> input) const;
|
WebIDL::ExceptionOr<GC::Ptr<JS::Date>> convert_string_to_date(Utf16String const& input) const;
|
||||||
|
Utf16String convert_date_to_string(GC::Ref<JS::Date> input) const;
|
||||||
|
|
||||||
Optional<double> min() const;
|
Optional<double> min() const;
|
||||||
Optional<double> max() const;
|
Optional<double> max() const;
|
||||||
|
@ -304,6 +306,9 @@ private:
|
||||||
WebIDL::ExceptionOr<void> step_up_or_down(bool is_down, WebIDL::Long n);
|
WebIDL::ExceptionOr<void> step_up_or_down(bool is_down, WebIDL::Long n);
|
||||||
|
|
||||||
static TypeAttributeState parse_type_attribute(StringView);
|
static TypeAttributeState parse_type_attribute(StringView);
|
||||||
|
|
||||||
|
Utf16String button_label() const;
|
||||||
|
|
||||||
void create_shadow_tree_if_needed();
|
void create_shadow_tree_if_needed();
|
||||||
void update_shadow_tree();
|
void update_shadow_tree();
|
||||||
void create_button_input_shadow_tree();
|
void create_button_input_shadow_tree();
|
||||||
|
@ -321,7 +326,7 @@ private:
|
||||||
void user_interaction_did_change_input_value();
|
void user_interaction_did_change_input_value();
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/input.html#value-sanitization-algorithm
|
// https://html.spec.whatwg.org/multipage/input.html#value-sanitization-algorithm
|
||||||
String value_sanitization_algorithm(String const&) const;
|
Utf16String value_sanitization_algorithm(Utf16String const&) const;
|
||||||
|
|
||||||
enum class ValueAttributeMode {
|
enum class ValueAttributeMode {
|
||||||
Value,
|
Value,
|
||||||
|
@ -386,7 +391,7 @@ private:
|
||||||
GC::Ptr<FileAPI::FileList> m_selected_files;
|
GC::Ptr<FileAPI::FileList> m_selected_files;
|
||||||
|
|
||||||
TypeAttributeState m_type { TypeAttributeState::Text };
|
TypeAttributeState m_type { TypeAttributeState::Text };
|
||||||
String m_value;
|
Utf16String m_value;
|
||||||
|
|
||||||
String m_last_src_value;
|
String m_last_src_value;
|
||||||
|
|
||||||
|
|
|
@ -44,7 +44,7 @@ interface HTMLInputElement : HTMLElement {
|
||||||
[CEReactions, Reflect] attribute boolean switch;
|
[CEReactions, Reflect] attribute boolean switch;
|
||||||
[CEReactions] attribute DOMString type;
|
[CEReactions] attribute DOMString type;
|
||||||
[CEReactions, Reflect=value] attribute DOMString defaultValue;
|
[CEReactions, Reflect=value] attribute DOMString defaultValue;
|
||||||
[CEReactions, LegacyNullToEmptyString] attribute DOMString value;
|
[CEReactions, LegacyNullToEmptyString] attribute Utf16DOMString value;
|
||||||
attribute object? valueAsDate;
|
attribute object? valueAsDate;
|
||||||
attribute unrestricted double valueAsNumber;
|
attribute unrestricted double valueAsNumber;
|
||||||
[CEReactions] attribute unsigned long width;
|
[CEReactions] attribute unsigned long width;
|
||||||
|
|
|
@ -89,15 +89,15 @@ void HTMLOptionElement::set_selected_internal(bool selected)
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/form-elements.html#dom-option-value
|
// https://html.spec.whatwg.org/multipage/form-elements.html#dom-option-value
|
||||||
String HTMLOptionElement::value() const
|
Utf16String HTMLOptionElement::value() const
|
||||||
{
|
{
|
||||||
// The value of an option element is the value of the value content attribute, if there is one.
|
// The value of an option element is the value of the value content attribute, if there is one.
|
||||||
// ...or, if there is not, the value of the element's text IDL attribute.
|
// ...or, if there is not, the value of the element's text IDL attribute.
|
||||||
return attribute(HTML::AttributeNames::value).value_or(text());
|
return Utf16String::from_utf8(attribute(HTML::AttributeNames::value).value_or(text()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/form-elements.html#dom-option-value
|
// https://html.spec.whatwg.org/multipage/form-elements.html#dom-option-value
|
||||||
WebIDL::ExceptionOr<void> HTMLOptionElement::set_value(String const& value)
|
WebIDL::ExceptionOr<void> HTMLOptionElement::set_value(Utf16String const& value)
|
||||||
{
|
{
|
||||||
return set_attribute(HTML::AttributeNames::value, value);
|
return set_attribute(HTML::AttributeNames::value, value);
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,8 +23,8 @@ public:
|
||||||
void set_selected_internal(bool);
|
void set_selected_internal(bool);
|
||||||
[[nodiscard]] u64 selectedness_update_index() const { return m_selectedness_update_index; }
|
[[nodiscard]] u64 selectedness_update_index() const { return m_selectedness_update_index; }
|
||||||
|
|
||||||
String value() const;
|
Utf16String value() const;
|
||||||
WebIDL::ExceptionOr<void> set_value(String const&);
|
WebIDL::ExceptionOr<void> set_value(Utf16String const&);
|
||||||
|
|
||||||
String text() const;
|
String text() const;
|
||||||
void set_text(String const&);
|
void set_text(String const&);
|
||||||
|
|
|
@ -10,7 +10,7 @@ interface HTMLOptionElement : HTMLElement {
|
||||||
[CEReactions] attribute DOMString label;
|
[CEReactions] attribute DOMString label;
|
||||||
[CEReactions, Reflect=selected] attribute boolean defaultSelected;
|
[CEReactions, Reflect=selected] attribute boolean defaultSelected;
|
||||||
attribute boolean selected;
|
attribute boolean selected;
|
||||||
[CEReactions] attribute DOMString value;
|
[CEReactions] attribute Utf16DOMString value;
|
||||||
|
|
||||||
[CEReactions] attribute DOMString text;
|
[CEReactions] attribute DOMString text;
|
||||||
readonly attribute long index;
|
readonly attribute long index;
|
||||||
|
|
|
@ -74,20 +74,20 @@ void HTMLOutputElement::set_default_value(String const& default_value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/form-elements.html#dom-output-value
|
// https://html.spec.whatwg.org/multipage/form-elements.html#dom-output-value
|
||||||
String HTMLOutputElement::value() const
|
Utf16String HTMLOutputElement::value() const
|
||||||
{
|
{
|
||||||
// The value getter steps are to return this's descendant text content.
|
// The value getter steps are to return this's descendant text content.
|
||||||
return descendant_text_content();
|
return Utf16String::from_utf8(descendant_text_content());
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/form-elements.html#dom-output-value
|
// https://html.spec.whatwg.org/multipage/form-elements.html#dom-output-value
|
||||||
void HTMLOutputElement::set_value(String const& value)
|
void HTMLOutputElement::set_value(Utf16String const& value)
|
||||||
{
|
{
|
||||||
// 1. Set this's default value override to its default value.
|
// 1. Set this's default value override to its default value.
|
||||||
m_default_value_override = default_value();
|
m_default_value_override = default_value();
|
||||||
|
|
||||||
// 2. String replace all with the given value within this.
|
// 2. String replace all with the given value within this.
|
||||||
string_replace_all(value);
|
string_replace_all(value.to_utf8_but_should_be_ported_to_utf16());
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/form-elements.html#the-output-element:concept-form-reset-control
|
// https://html.spec.whatwg.org/multipage/form-elements.html#the-output-element:concept-form-reset-control
|
||||||
|
|
|
@ -34,8 +34,8 @@ public:
|
||||||
String default_value() const;
|
String default_value() const;
|
||||||
void set_default_value(String const&);
|
void set_default_value(String const&);
|
||||||
|
|
||||||
String value() const override;
|
Utf16String value() const override;
|
||||||
void set_value(String const&);
|
void set_value(Utf16String const&);
|
||||||
|
|
||||||
// ^FormAssociatedElement
|
// ^FormAssociatedElement
|
||||||
// https://html.spec.whatwg.org/multipage/forms.html#category-listed
|
// https://html.spec.whatwg.org/multipage/forms.html#category-listed
|
||||||
|
|
|
@ -13,7 +13,7 @@ interface HTMLOutputElement : HTMLElement {
|
||||||
|
|
||||||
readonly attribute DOMString type;
|
readonly attribute DOMString type;
|
||||||
[CEReactions] attribute DOMString defaultValue;
|
[CEReactions] attribute DOMString defaultValue;
|
||||||
[CEReactions] attribute DOMString value;
|
[CEReactions] attribute Utf16DOMString value;
|
||||||
|
|
||||||
readonly attribute boolean willValidate;
|
readonly attribute boolean willValidate;
|
||||||
readonly attribute ValidityState validity;
|
readonly attribute ValidityState validity;
|
||||||
|
|
|
@ -365,16 +365,16 @@ Optional<ARIA::Role> HTMLSelectElement::default_role() const
|
||||||
return ARIA::Role::combobox;
|
return ARIA::Role::combobox;
|
||||||
}
|
}
|
||||||
|
|
||||||
String HTMLSelectElement::value() const
|
Utf16String HTMLSelectElement::value() const
|
||||||
{
|
{
|
||||||
update_cached_list_of_options();
|
update_cached_list_of_options();
|
||||||
for (auto const& option_element : m_cached_list_of_options)
|
for (auto const& option_element : m_cached_list_of_options)
|
||||||
if (option_element->selected())
|
if (option_element->selected())
|
||||||
return option_element->value();
|
return option_element->value();
|
||||||
return ""_string;
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
WebIDL::ExceptionOr<void> HTMLSelectElement::set_value(String const& value)
|
WebIDL::ExceptionOr<void> HTMLSelectElement::set_value(Utf16String const& value)
|
||||||
{
|
{
|
||||||
update_cached_list_of_options();
|
update_cached_list_of_options();
|
||||||
for (auto const& option_element : list_of_options())
|
for (auto const& option_element : list_of_options())
|
||||||
|
@ -478,7 +478,7 @@ void HTMLSelectElement::show_the_picker_if_applicable()
|
||||||
for (auto const& child : opt_group_element->children_as_vector()) {
|
for (auto const& child : opt_group_element->children_as_vector()) {
|
||||||
if (auto const& option_element = as_if<HTMLOptionElement>(*child)) {
|
if (auto const& option_element = as_if<HTMLOptionElement>(*child)) {
|
||||||
if (!option_element->has_attribute(Web::HTML::AttributeNames::hidden))
|
if (!option_element->has_attribute(Web::HTML::AttributeNames::hidden))
|
||||||
option_group_items.append(SelectItemOption { id_counter++, option_element->selected(), option_element->disabled(), option_element, strip_newlines(option_element->label()), option_element->value() });
|
option_group_items.append(SelectItemOption { id_counter++, option_element->selected(), option_element->disabled(), option_element, strip_newlines(option_element->label()), option_element->value().to_utf8_but_should_be_ported_to_utf16() });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_select_items.append(SelectItemOptionGroup { opt_group_element->get_attribute(AttributeNames::label).value_or(String {}), option_group_items });
|
m_select_items.append(SelectItemOptionGroup { opt_group_element->get_attribute(AttributeNames::label).value_or(String {}), option_group_items });
|
||||||
|
@ -487,7 +487,7 @@ void HTMLSelectElement::show_the_picker_if_applicable()
|
||||||
|
|
||||||
if (auto const& option_element = as_if<HTMLOptionElement>(*child)) {
|
if (auto const& option_element = as_if<HTMLOptionElement>(*child)) {
|
||||||
if (!option_element->has_attribute(Web::HTML::AttributeNames::hidden))
|
if (!option_element->has_attribute(Web::HTML::AttributeNames::hidden))
|
||||||
m_select_items.append(SelectItemOption { id_counter++, option_element->selected(), option_element->disabled(), option_element, strip_newlines(option_element->label()), option_element->value() });
|
m_select_items.append(SelectItemOption { id_counter++, option_element->selected(), option_element->disabled(), option_element, strip_newlines(option_element->label()), option_element->value().to_utf8_but_should_be_ported_to_utf16() });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (auto const* hr_element = as_if<HTMLHRElement>(*child)) {
|
if (auto const* hr_element = as_if<HTMLHRElement>(*child)) {
|
||||||
|
|
|
@ -51,8 +51,8 @@ public:
|
||||||
WebIDL::Long selected_index() const;
|
WebIDL::Long selected_index() const;
|
||||||
void set_selected_index(WebIDL::Long);
|
void set_selected_index(WebIDL::Long);
|
||||||
|
|
||||||
virtual String value() const override;
|
virtual Utf16String value() const override;
|
||||||
WebIDL::ExceptionOr<void> set_value(String const&);
|
WebIDL::ExceptionOr<void> set_value(Utf16String const&);
|
||||||
|
|
||||||
bool is_open() const { return m_is_open; }
|
bool is_open() const { return m_is_open; }
|
||||||
void set_is_open(bool);
|
void set_is_open(bool);
|
||||||
|
|
|
@ -29,7 +29,7 @@ interface HTMLSelectElement : HTMLElement {
|
||||||
|
|
||||||
[SameObject] readonly attribute HTMLCollection selectedOptions;
|
[SameObject] readonly attribute HTMLCollection selectedOptions;
|
||||||
attribute long selectedIndex;
|
attribute long selectedIndex;
|
||||||
attribute DOMString value;
|
attribute Utf16DOMString value;
|
||||||
|
|
||||||
readonly attribute boolean willValidate;
|
readonly attribute boolean willValidate;
|
||||||
readonly attribute ValidityState validity;
|
readonly attribute ValidityState validity;
|
||||||
|
|
|
@ -114,10 +114,10 @@ void HTMLTextAreaElement::reset_algorithm()
|
||||||
m_user_validity = false;
|
m_user_validity = false;
|
||||||
m_dirty_value = false;
|
m_dirty_value = false;
|
||||||
// and the raw value to its child text content.
|
// and the raw value to its child text content.
|
||||||
set_raw_value(child_text_content());
|
set_raw_value(Utf16String::from_utf8(child_text_content()));
|
||||||
|
|
||||||
if (m_text_node) {
|
if (m_text_node) {
|
||||||
m_text_node->set_text_content(m_raw_value);
|
m_text_node->set_text_content(m_raw_value.to_utf8_but_should_be_ported_to_utf16());
|
||||||
update_placeholder_visibility();
|
update_placeholder_visibility();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -129,7 +129,7 @@ void HTMLTextAreaElement::clear_algorithm()
|
||||||
m_dirty_value = false;
|
m_dirty_value = false;
|
||||||
|
|
||||||
// and set the raw value of element to an empty string.
|
// and set the raw value of element to an empty string.
|
||||||
set_raw_value(child_text_content());
|
set_raw_value(Utf16String::from_utf8(child_text_content()));
|
||||||
|
|
||||||
// Unlike their associated reset algorithms, changes made to form controls as part of these algorithms do count as
|
// Unlike their associated reset algorithms, changes made to form controls as part of these algorithms do count as
|
||||||
// changes caused by the user (and thus, e.g. do cause input events to fire).
|
// changes caused by the user (and thus, e.g. do cause input events to fire).
|
||||||
|
@ -169,14 +169,14 @@ void HTMLTextAreaElement::set_default_value(String const& default_value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/form-elements.html#dom-textarea-value
|
// https://html.spec.whatwg.org/multipage/form-elements.html#dom-textarea-value
|
||||||
String HTMLTextAreaElement::value() const
|
Utf16String HTMLTextAreaElement::value() const
|
||||||
{
|
{
|
||||||
// The value IDL attribute must, on getting, return the element's API value.
|
// The value IDL attribute must, on getting, return the element's API value.
|
||||||
return api_value();
|
return api_value();
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/form-elements.html#dom-textarea-value
|
// https://html.spec.whatwg.org/multipage/form-elements.html#dom-textarea-value
|
||||||
void HTMLTextAreaElement::set_value(String const& value)
|
void HTMLTextAreaElement::set_value(Utf16String const& value)
|
||||||
{
|
{
|
||||||
// 1. Let oldAPIValue be this element's API value.
|
// 1. Let oldAPIValue be this element's API value.
|
||||||
auto old_api_value = api_value();
|
auto old_api_value = api_value();
|
||||||
|
@ -191,7 +191,7 @@ void HTMLTextAreaElement::set_value(String const& value)
|
||||||
// the text control, unselecting any selected text and resetting the selection direction to "none".
|
// the text control, unselecting any selected text and resetting the selection direction to "none".
|
||||||
if (api_value() != old_api_value) {
|
if (api_value() != old_api_value) {
|
||||||
if (m_text_node) {
|
if (m_text_node) {
|
||||||
m_text_node->set_data(Utf16String::from_utf8(m_raw_value));
|
m_text_node->set_data(m_raw_value);
|
||||||
update_placeholder_visibility();
|
update_placeholder_visibility();
|
||||||
|
|
||||||
set_the_selection_range(m_text_node->length(), m_text_node->length());
|
set_the_selection_range(m_text_node->length(), m_text_node->length());
|
||||||
|
@ -199,7 +199,7 @@ void HTMLTextAreaElement::set_value(String const& value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void HTMLTextAreaElement::set_raw_value(String value)
|
void HTMLTextAreaElement::set_raw_value(Utf16String value)
|
||||||
{
|
{
|
||||||
auto old_raw_value = move(m_raw_value);
|
auto old_raw_value = move(m_raw_value);
|
||||||
m_raw_value = move(value);
|
m_raw_value = move(value);
|
||||||
|
@ -210,7 +210,7 @@ void HTMLTextAreaElement::set_raw_value(String value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/form-elements.html#the-textarea-element:concept-fe-api-value-3
|
// https://html.spec.whatwg.org/multipage/form-elements.html#the-textarea-element:concept-fe-api-value-3
|
||||||
String HTMLTextAreaElement::api_value() const
|
Utf16String HTMLTextAreaElement::api_value() const
|
||||||
{
|
{
|
||||||
// The algorithm for obtaining the element's API value is to return the element's raw value, with newlines normalized.
|
// The algorithm for obtaining the element's API value is to return the element's raw value, with newlines normalized.
|
||||||
if (!m_api_value.has_value())
|
if (!m_api_value.has_value())
|
||||||
|
@ -221,7 +221,7 @@ String HTMLTextAreaElement::api_value() const
|
||||||
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#concept-textarea/input-relevant-value
|
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#concept-textarea/input-relevant-value
|
||||||
WebIDL::ExceptionOr<void> HTMLTextAreaElement::set_relevant_value(Utf16String const& value)
|
WebIDL::ExceptionOr<void> HTMLTextAreaElement::set_relevant_value(Utf16String const& value)
|
||||||
{
|
{
|
||||||
set_value(value.to_utf8_but_should_be_ported_to_utf16());
|
set_value(value);
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -229,7 +229,7 @@ WebIDL::ExceptionOr<void> HTMLTextAreaElement::set_relevant_value(Utf16String co
|
||||||
u32 HTMLTextAreaElement::text_length() const
|
u32 HTMLTextAreaElement::text_length() const
|
||||||
{
|
{
|
||||||
// The textLength IDL attribute must return the length of the element's API value.
|
// The textLength IDL attribute must return the length of the element's API value.
|
||||||
return AK::utf16_code_unit_length_from_utf8(api_value());
|
return api_value().length_in_code_units();
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#dom-cva-willvalidate
|
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#dom-cva-willvalidate
|
||||||
|
@ -379,7 +379,7 @@ void HTMLTextAreaElement::create_shadow_tree_if_needed()
|
||||||
handle_readonly_attribute(attribute(HTML::AttributeNames::readonly));
|
handle_readonly_attribute(attribute(HTML::AttributeNames::readonly));
|
||||||
// NOTE: If `children_changed()` was called before now, `m_raw_value` will hold the text content.
|
// NOTE: If `children_changed()` was called before now, `m_raw_value` will hold the text content.
|
||||||
// Otherwise, it will get filled in whenever that does get called.
|
// Otherwise, it will get filled in whenever that does get called.
|
||||||
m_text_node->set_text_content(m_raw_value);
|
m_text_node->set_text_content(m_raw_value.to_utf8_but_should_be_ported_to_utf16());
|
||||||
handle_maxlength_attribute();
|
handle_maxlength_attribute();
|
||||||
MUST(m_inner_text_element->append_child(*m_text_node));
|
MUST(m_inner_text_element->append_child(*m_text_node));
|
||||||
|
|
||||||
|
@ -430,9 +430,9 @@ void HTMLTextAreaElement::children_changed(ChildrenChangedMetadata const* metada
|
||||||
// The children changed steps for textarea elements must, if the element's dirty value flag is false,
|
// The children changed steps for textarea elements must, if the element's dirty value flag is false,
|
||||||
// set the element's raw value to its child text content.
|
// set the element's raw value to its child text content.
|
||||||
if (!m_dirty_value) {
|
if (!m_dirty_value) {
|
||||||
set_raw_value(child_text_content());
|
set_raw_value(Utf16String::from_utf8(child_text_content()));
|
||||||
if (m_text_node)
|
if (m_text_node)
|
||||||
m_text_node->set_text_content(m_raw_value);
|
m_text_node->set_text_content(m_raw_value.to_utf8_but_should_be_ported_to_utf16());
|
||||||
update_placeholder_visibility();
|
update_placeholder_visibility();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -452,7 +452,7 @@ void HTMLTextAreaElement::form_associated_element_attribute_changed(FlyString co
|
||||||
void HTMLTextAreaElement::did_edit_text_node()
|
void HTMLTextAreaElement::did_edit_text_node()
|
||||||
{
|
{
|
||||||
VERIFY(m_text_node);
|
VERIFY(m_text_node);
|
||||||
set_raw_value(m_text_node->data().to_utf8_but_should_be_ported_to_utf16());
|
set_raw_value(m_text_node->data());
|
||||||
|
|
||||||
// Any time the user causes the element's raw value to change, the user agent must queue an element task on the user
|
// Any time the user causes the element's raw value to change, the user agent must queue an element task on the user
|
||||||
// interaction task source given the textarea element to fire an event named input at the textarea element, with the
|
// interaction task source given the textarea element to fire an event named input at the textarea element, with the
|
||||||
|
|
|
@ -80,14 +80,14 @@ public:
|
||||||
String default_value() const;
|
String default_value() const;
|
||||||
void set_default_value(String const&);
|
void set_default_value(String const&);
|
||||||
|
|
||||||
String value() const override;
|
Utf16String value() const override;
|
||||||
void set_value(String const&);
|
void set_value(Utf16String const&);
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/form-elements.html#the-textarea-element:concept-fe-api-value-3
|
// https://html.spec.whatwg.org/multipage/form-elements.html#the-textarea-element:concept-fe-api-value-3
|
||||||
String api_value() const;
|
Utf16String api_value() const;
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#concept-textarea/input-relevant-value
|
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#concept-textarea/input-relevant-value
|
||||||
virtual Utf16String relevant_value() override { return Utf16String::from_utf8(api_value()); }
|
virtual Utf16String relevant_value() override { return api_value(); }
|
||||||
virtual WebIDL::ExceptionOr<void> set_relevant_value(Utf16String const& value) override;
|
virtual WebIDL::ExceptionOr<void> set_relevant_value(Utf16String const& value) override;
|
||||||
|
|
||||||
virtual void set_dirty_value_flag(bool flag) override { m_dirty_value = flag; }
|
virtual void set_dirty_value_flag(bool flag) override { m_dirty_value = flag; }
|
||||||
|
@ -140,7 +140,7 @@ private:
|
||||||
virtual void initialize(JS::Realm&) override;
|
virtual void initialize(JS::Realm&) override;
|
||||||
virtual void visit_edges(Cell::Visitor&) override;
|
virtual void visit_edges(Cell::Visitor&) override;
|
||||||
|
|
||||||
void set_raw_value(String);
|
void set_raw_value(Utf16String);
|
||||||
|
|
||||||
// ^DOM::Element
|
// ^DOM::Element
|
||||||
virtual i32 default_tab_index_value() const override;
|
virtual i32 default_tab_index_value() const override;
|
||||||
|
@ -169,10 +169,10 @@ private:
|
||||||
bool m_user_validity { false };
|
bool m_user_validity { false };
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/form-elements.html#concept-textarea-raw-value
|
// https://html.spec.whatwg.org/multipage/form-elements.html#concept-textarea-raw-value
|
||||||
String m_raw_value;
|
Utf16String m_raw_value;
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#concept-fe-api-value
|
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#concept-fe-api-value
|
||||||
mutable Optional<String> m_api_value;
|
mutable Optional<Utf16String> m_api_value;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@ interface HTMLTextAreaElement : HTMLElement {
|
||||||
|
|
||||||
readonly attribute DOMString type;
|
readonly attribute DOMString type;
|
||||||
[CEReactions] attribute DOMString defaultValue;
|
[CEReactions] attribute DOMString defaultValue;
|
||||||
[LegacyNullToEmptyString] attribute DOMString value;
|
[LegacyNullToEmptyString] attribute Utf16DOMString value;
|
||||||
readonly attribute unsigned long textLength;
|
readonly attribute unsigned long textLength;
|
||||||
|
|
||||||
readonly attribute boolean willValidate;
|
readonly attribute boolean willValidate;
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
#include <AK/GenericLexer.h>
|
#include <AK/GenericLexer.h>
|
||||||
#include <AK/StringConversions.h>
|
#include <AK/StringConversions.h>
|
||||||
|
#include <AK/Utf16String.h>
|
||||||
#include <LibWeb/HTML/Numbers.h>
|
#include <LibWeb/HTML/Numbers.h>
|
||||||
#include <LibWeb/Infra/CharacterTypes.h>
|
#include <LibWeb/Infra/CharacterTypes.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
@ -283,7 +284,7 @@ fraction_exit:
|
||||||
value *= pow(10, exponent);
|
value *= pow(10, exponent);
|
||||||
}
|
}
|
||||||
|
|
||||||
conversion: {
|
conversion:
|
||||||
// 15. Conversion: Let S be the set of finite IEEE 754 double-precision floating-point values except −0,
|
// 15. Conversion: Let S be the set of finite IEEE 754 double-precision floating-point values except −0,
|
||||||
// but with two special values added: 2^1024 and −2^1024.
|
// but with two special values added: 2^1024 and −2^1024.
|
||||||
if (!isfinite(value)) {
|
if (!isfinite(value)) {
|
||||||
|
@ -305,6 +306,14 @@ conversion: {
|
||||||
// 18. Return rounded-value.
|
// 18. Return rounded-value.
|
||||||
return rounded_value;
|
return rounded_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#rules-for-parsing-floating-point-number-values
|
||||||
|
Optional<double> parse_floating_point_number(Utf16String const& string)
|
||||||
|
{
|
||||||
|
// FIXME: Implement a UTF-16 GenericLexer.
|
||||||
|
if (!string.has_ascii_storage())
|
||||||
|
return {};
|
||||||
|
return parse_floating_point_number(string.ascii_view());
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#valid-floating-point-number
|
// https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#valid-floating-point-number
|
||||||
|
@ -340,6 +349,15 @@ bool is_valid_floating_point_number(StringView string)
|
||||||
return lexer.tell_remaining() == 0;
|
return lexer.tell_remaining() == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#valid-floating-point-number
|
||||||
|
bool is_valid_floating_point_number(Utf16String const& string)
|
||||||
|
{
|
||||||
|
// FIXME: Implement a UTF-16 GenericLexer.
|
||||||
|
if (!string.has_ascii_storage())
|
||||||
|
return false;
|
||||||
|
return is_valid_floating_point_number(string.ascii_view());
|
||||||
|
}
|
||||||
|
|
||||||
WebIDL::ExceptionOr<String> convert_non_negative_integer_to_string(JS::Realm& realm, WebIDL::Long value)
|
WebIDL::ExceptionOr<String> convert_non_negative_integer_to_string(JS::Realm& realm, WebIDL::Long value)
|
||||||
{
|
{
|
||||||
if (value < 0)
|
if (value < 0)
|
||||||
|
|
|
@ -20,8 +20,10 @@ Optional<u32> parse_non_negative_integer(StringView string);
|
||||||
Optional<StringView> parse_non_negative_integer_digits(StringView string);
|
Optional<StringView> parse_non_negative_integer_digits(StringView string);
|
||||||
|
|
||||||
Optional<double> parse_floating_point_number(StringView string);
|
Optional<double> parse_floating_point_number(StringView string);
|
||||||
|
Optional<double> parse_floating_point_number(Utf16String const& string);
|
||||||
|
|
||||||
bool is_valid_floating_point_number(StringView string);
|
bool is_valid_floating_point_number(StringView string);
|
||||||
|
bool is_valid_floating_point_number(Utf16String const& string);
|
||||||
|
|
||||||
WebIDL::ExceptionOr<String> convert_non_negative_integer_to_string(JS::Realm&, WebIDL::Long);
|
WebIDL::ExceptionOr<String> convert_non_negative_integer_to_string(JS::Realm&, WebIDL::Long);
|
||||||
|
|
||||||
|
|
|
@ -43,6 +43,30 @@ String normalize_newlines(String const& string)
|
||||||
return MUST(builder.to_string());
|
return MUST(builder.to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://infra.spec.whatwg.org/#normalize-newlines
|
||||||
|
Utf16String normalize_newlines(Utf16String const& string)
|
||||||
|
{
|
||||||
|
// To normalize newlines in a string, replace every U+000D CR U+000A LF code point pair with a single U+000A LF
|
||||||
|
// code point, and then replace every remaining U+000D CR code point with a U+000A LF code point.
|
||||||
|
if (!string.contains('\r'))
|
||||||
|
return string;
|
||||||
|
|
||||||
|
// FIXME: Implement a UTF-16 GenericLexer.
|
||||||
|
StringBuilder builder(StringBuilder::Mode::UTF16, string.length_in_code_units());
|
||||||
|
|
||||||
|
for (size_t i = 0; i < string.length_in_code_units(); ++i) {
|
||||||
|
if (auto code_unit = string.code_unit_at(i); code_unit == '\r') {
|
||||||
|
if (i + 1 < string.length_in_code_units() && string.code_unit_at(i + 1) == '\n')
|
||||||
|
++i;
|
||||||
|
builder.append('\n');
|
||||||
|
} else {
|
||||||
|
builder.append_code_unit(code_unit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return builder.to_utf16_string();
|
||||||
|
}
|
||||||
|
|
||||||
// https://infra.spec.whatwg.org/#strip-and-collapse-ascii-whitespace
|
// https://infra.spec.whatwg.org/#strip-and-collapse-ascii-whitespace
|
||||||
ErrorOr<String> strip_and_collapse_whitespace(StringView string)
|
ErrorOr<String> strip_and_collapse_whitespace(StringView string)
|
||||||
{
|
{
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
namespace Web::Infra {
|
namespace Web::Infra {
|
||||||
|
|
||||||
String normalize_newlines(String const&);
|
String normalize_newlines(String const&);
|
||||||
|
Utf16String normalize_newlines(Utf16String const&);
|
||||||
ErrorOr<String> strip_and_collapse_whitespace(StringView string);
|
ErrorOr<String> strip_and_collapse_whitespace(StringView string);
|
||||||
bool is_code_unit_prefix(StringView potential_prefix, StringView input);
|
bool is_code_unit_prefix(StringView potential_prefix, StringView input);
|
||||||
ErrorOr<String> convert_to_scalar_value_string(StringView string);
|
ErrorOr<String> convert_to_scalar_value_string(StringView string);
|
||||||
|
|
|
@ -1951,7 +1951,7 @@ Web::WebDriver::Response WebDriverConnection::element_send_keys_impl(StringView
|
||||||
return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::ElementNotInteractable, "Element is immutable"sv);
|
return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::ElementNotInteractable, "Element is immutable"sv);
|
||||||
|
|
||||||
// 3. Set a property value to text on element.
|
// 3. Set a property value to text on element.
|
||||||
MUST(input_element.set_value(text));
|
MUST(input_element.set_value(Utf16String::from_utf8(text)));
|
||||||
|
|
||||||
// FIXME: 4. If element is suffering from bad input return an error with error code invalid argument.
|
// FIXME: 4. If element is suffering from bad input return an error with error code invalid argument.
|
||||||
|
|
||||||
|
|
|
@ -2,8 +2,8 @@ Harness status: OK
|
||||||
|
|
||||||
Found 85 tests
|
Found 85 tests
|
||||||
|
|
||||||
71 Pass
|
78 Pass
|
||||||
14 Fail
|
7 Fail
|
||||||
Pass [INPUT in TEXT status] The pattern attribute is not set
|
Pass [INPUT in TEXT status] The pattern attribute is not set
|
||||||
Pass [INPUT in TEXT status] The value attibute is empty string
|
Pass [INPUT in TEXT status] The value attibute is empty string
|
||||||
Pass [INPUT in TEXT status] The value attribute matches the pattern attribute
|
Pass [INPUT in TEXT status] The value attribute matches the pattern attribute
|
||||||
|
@ -13,7 +13,7 @@ Pass [INPUT in TEXT status] The value attribute mismatches the pattern attribute
|
||||||
Pass [INPUT in TEXT status] Invalid regular expression gets ignored
|
Pass [INPUT in TEXT status] Invalid regular expression gets ignored
|
||||||
Pass [INPUT in TEXT status] Invalid `v` regular expression gets ignored
|
Pass [INPUT in TEXT status] Invalid `v` regular expression gets ignored
|
||||||
Pass [INPUT in TEXT status] The pattern attribute tries to escape a group
|
Pass [INPUT in TEXT status] The pattern attribute tries to escape a group
|
||||||
Fail [INPUT in TEXT status] The pattern attribute uses Unicode features
|
Pass [INPUT in TEXT status] The pattern attribute uses Unicode features
|
||||||
Pass [INPUT in TEXT status] The value attribute matches JavaScript-specific regular expression
|
Pass [INPUT in TEXT status] The value attribute matches JavaScript-specific regular expression
|
||||||
Fail [INPUT in TEXT status] The value attribute mismatches JavaScript-specific regular expression
|
Fail [INPUT in TEXT status] The value attribute mismatches JavaScript-specific regular expression
|
||||||
Pass [INPUT in SEARCH status] The pattern attribute is not set
|
Pass [INPUT in SEARCH status] The pattern attribute is not set
|
||||||
|
@ -25,7 +25,7 @@ Pass [INPUT in SEARCH status] The value attribute mismatches the pattern attribu
|
||||||
Pass [INPUT in SEARCH status] Invalid regular expression gets ignored
|
Pass [INPUT in SEARCH status] Invalid regular expression gets ignored
|
||||||
Pass [INPUT in SEARCH status] Invalid `v` regular expression gets ignored
|
Pass [INPUT in SEARCH status] Invalid `v` regular expression gets ignored
|
||||||
Pass [INPUT in SEARCH status] The pattern attribute tries to escape a group
|
Pass [INPUT in SEARCH status] The pattern attribute tries to escape a group
|
||||||
Fail [INPUT in SEARCH status] The pattern attribute uses Unicode features
|
Pass [INPUT in SEARCH status] The pattern attribute uses Unicode features
|
||||||
Pass [INPUT in SEARCH status] The value attribute matches JavaScript-specific regular expression
|
Pass [INPUT in SEARCH status] The value attribute matches JavaScript-specific regular expression
|
||||||
Fail [INPUT in SEARCH status] The value attribute mismatches JavaScript-specific regular expression
|
Fail [INPUT in SEARCH status] The value attribute mismatches JavaScript-specific regular expression
|
||||||
Pass [INPUT in TEL status] The pattern attribute is not set
|
Pass [INPUT in TEL status] The pattern attribute is not set
|
||||||
|
@ -37,7 +37,7 @@ Pass [INPUT in TEL status] The value attribute mismatches the pattern attribute
|
||||||
Pass [INPUT in TEL status] Invalid regular expression gets ignored
|
Pass [INPUT in TEL status] Invalid regular expression gets ignored
|
||||||
Pass [INPUT in TEL status] Invalid `v` regular expression gets ignored
|
Pass [INPUT in TEL status] Invalid `v` regular expression gets ignored
|
||||||
Pass [INPUT in TEL status] The pattern attribute tries to escape a group
|
Pass [INPUT in TEL status] The pattern attribute tries to escape a group
|
||||||
Fail [INPUT in TEL status] The pattern attribute uses Unicode features
|
Pass [INPUT in TEL status] The pattern attribute uses Unicode features
|
||||||
Pass [INPUT in TEL status] The value attribute matches JavaScript-specific regular expression
|
Pass [INPUT in TEL status] The value attribute matches JavaScript-specific regular expression
|
||||||
Fail [INPUT in TEL status] The value attribute mismatches JavaScript-specific regular expression
|
Fail [INPUT in TEL status] The value attribute mismatches JavaScript-specific regular expression
|
||||||
Pass [INPUT in URL status] The pattern attribute is not set
|
Pass [INPUT in URL status] The pattern attribute is not set
|
||||||
|
@ -49,7 +49,7 @@ Pass [INPUT in URL status] The value attribute mismatches the pattern attribute
|
||||||
Pass [INPUT in URL status] Invalid regular expression gets ignored
|
Pass [INPUT in URL status] Invalid regular expression gets ignored
|
||||||
Pass [INPUT in URL status] Invalid `v` regular expression gets ignored
|
Pass [INPUT in URL status] Invalid `v` regular expression gets ignored
|
||||||
Pass [INPUT in URL status] The pattern attribute tries to escape a group
|
Pass [INPUT in URL status] The pattern attribute tries to escape a group
|
||||||
Fail [INPUT in URL status] The pattern attribute uses Unicode features
|
Pass [INPUT in URL status] The pattern attribute uses Unicode features
|
||||||
Pass [INPUT in URL status] The value attribute matches JavaScript-specific regular expression
|
Pass [INPUT in URL status] The value attribute matches JavaScript-specific regular expression
|
||||||
Fail [INPUT in URL status] The value attribute mismatches JavaScript-specific regular expression
|
Fail [INPUT in URL status] The value attribute mismatches JavaScript-specific regular expression
|
||||||
Pass [INPUT in EMAIL status] The pattern attribute is not set
|
Pass [INPUT in EMAIL status] The pattern attribute is not set
|
||||||
|
@ -61,7 +61,7 @@ Pass [INPUT in EMAIL status] The value attribute mismatches the pattern attribut
|
||||||
Pass [INPUT in EMAIL status] Invalid regular expression gets ignored
|
Pass [INPUT in EMAIL status] Invalid regular expression gets ignored
|
||||||
Pass [INPUT in EMAIL status] Invalid `v` regular expression gets ignored
|
Pass [INPUT in EMAIL status] Invalid `v` regular expression gets ignored
|
||||||
Pass [INPUT in EMAIL status] The pattern attribute tries to escape a group
|
Pass [INPUT in EMAIL status] The pattern attribute tries to escape a group
|
||||||
Fail [INPUT in EMAIL status] The pattern attribute uses Unicode features
|
Pass [INPUT in EMAIL status] The pattern attribute uses Unicode features
|
||||||
Pass [INPUT in EMAIL status] The value attribute matches JavaScript-specific regular expression
|
Pass [INPUT in EMAIL status] The value attribute matches JavaScript-specific regular expression
|
||||||
Fail [INPUT in EMAIL status] The value attribute mismatches JavaScript-specific regular expression
|
Fail [INPUT in EMAIL status] The value attribute mismatches JavaScript-specific regular expression
|
||||||
Pass [INPUT in PASSWORD status] The pattern attribute is not set
|
Pass [INPUT in PASSWORD status] The pattern attribute is not set
|
||||||
|
@ -73,7 +73,7 @@ Pass [INPUT in PASSWORD status] The value attribute mismatches the pattern attri
|
||||||
Pass [INPUT in PASSWORD status] Invalid regular expression gets ignored
|
Pass [INPUT in PASSWORD status] Invalid regular expression gets ignored
|
||||||
Pass [INPUT in PASSWORD status] Invalid `v` regular expression gets ignored
|
Pass [INPUT in PASSWORD status] Invalid `v` regular expression gets ignored
|
||||||
Pass [INPUT in PASSWORD status] The pattern attribute tries to escape a group
|
Pass [INPUT in PASSWORD status] The pattern attribute tries to escape a group
|
||||||
Fail [INPUT in PASSWORD status] The pattern attribute uses Unicode features
|
Pass [INPUT in PASSWORD status] The pattern attribute uses Unicode features
|
||||||
Pass [INPUT in PASSWORD status] The value attribute matches JavaScript-specific regular expression
|
Pass [INPUT in PASSWORD status] The value attribute matches JavaScript-specific regular expression
|
||||||
Fail [INPUT in PASSWORD status] The value attribute mismatches JavaScript-specific regular expression
|
Fail [INPUT in PASSWORD status] The value attribute mismatches JavaScript-specific regular expression
|
||||||
Pass [INPUT in EMAIL status] The pattern attribute is not set, if multiple is present
|
Pass [INPUT in EMAIL status] The pattern attribute is not set, if multiple is present
|
||||||
|
@ -85,7 +85,7 @@ Pass [INPUT in EMAIL status] The value attribute mismatches the pattern attribut
|
||||||
Pass [INPUT in EMAIL status] Invalid regular expression gets ignored, if multiple is present
|
Pass [INPUT in EMAIL status] Invalid regular expression gets ignored, if multiple is present
|
||||||
Pass [INPUT in EMAIL status] Invalid `v` regular expression gets ignored, if multiple is present
|
Pass [INPUT in EMAIL status] Invalid `v` regular expression gets ignored, if multiple is present
|
||||||
Pass [INPUT in EMAIL status] The pattern attribute tries to escape a group, if multiple is present
|
Pass [INPUT in EMAIL status] The pattern attribute tries to escape a group, if multiple is present
|
||||||
Fail [INPUT in EMAIL status] The pattern attribute uses Unicode features, if multiple is present
|
Pass [INPUT in EMAIL status] The pattern attribute uses Unicode features, if multiple is present
|
||||||
Pass [INPUT in EMAIL status] The value attribute matches JavaScript-specific regular expression, if multiple is present
|
Pass [INPUT in EMAIL status] The value attribute matches JavaScript-specific regular expression, if multiple is present
|
||||||
Fail [INPUT in EMAIL status] The value attribute mismatches JavaScript-specific regular expression, if multiple is present
|
Fail [INPUT in EMAIL status] The value attribute mismatches JavaScript-specific regular expression, if multiple is present
|
||||||
Pass [INPUT in EMAIL status] Commas should be stripped from regex input, if multiple is present
|
Pass [INPUT in EMAIL status] Commas should be stripped from regex input, if multiple is present
|
|
@ -2,9 +2,8 @@ Harness status: OK
|
||||||
|
|
||||||
Found 4 tests
|
Found 4 tests
|
||||||
|
|
||||||
3 Pass
|
4 Pass
|
||||||
1 Fail
|
|
||||||
Pass basic <input pattern> support
|
Pass basic <input pattern> support
|
||||||
Fail <input pattern> is Unicode code point-aware
|
Pass <input pattern> is Unicode code point-aware
|
||||||
Pass <input pattern> supports Unicode property escape syntax
|
Pass <input pattern> supports Unicode property escape syntax
|
||||||
Pass <input pattern> supports Unicode property escape syntax for properties of strings
|
Pass <input pattern> supports Unicode property escape syntax for properties of strings
|
Loading…
Add table
Add a link
Reference in a new issue