diff --git a/AK/Base64.cpp b/AK/Base64.cpp index cd85868926..7aa6852480 100644 --- a/AK/Base64.cpp +++ b/AK/Base64.cpp @@ -44,20 +44,25 @@ static Optional base64_error_from_result(simdutf::result result, output.resize((result.count / 4) * 3); - auto error = [&]() { + struct DecodeError { + Base64DecodeError decode_error; + Error error; + }; + + auto [decode_error, error] = [&]() -> DecodeError { switch (result.error) { case simdutf::BASE64_EXTRA_BITS: - return Error::from_string_literal("Extra bits found at end of chunk"); + return { Base64DecodeError::ExtraBits, Error::from_string_literal("Extra bits found at end of chunk") }; case simdutf::BASE64_INPUT_REMAINDER: - return Error::from_string_literal("Invalid trailing data"); + return { Base64DecodeError::InputRemainder, Error::from_string_literal("Invalid trailing data") }; case simdutf::INVALID_BASE64_CHARACTER: - return Error::from_string_literal("Invalid base64 character"); + return { Base64DecodeError::InvalidCharacter, Error::from_string_literal("Invalid base64 character") }; default: - return Error::from_string_literal("Invalid base64-encoded data"); + return { Base64DecodeError::InvalidData, Error::from_string_literal("Invalid base64-encoded data") }; } }(); - return InvalidBase64 { .error = move(error), .valid_input_bytes = result.count }; + return InvalidBase64 { .decode_error = decode_error, .error = move(error), .valid_input_bytes = result.count }; } static ErrorOr decode_base64_into_impl(StringView input, ByteBuffer& output, LastChunkHandling last_chunk_handling, simdutf::base64_options options) diff --git a/AK/Base64.h b/AK/Base64.h index 8aab8146ca..3ebaf57c30 100644 --- a/AK/Base64.h +++ b/AK/Base64.h @@ -24,10 +24,18 @@ enum class LastChunkHandling { StopBeforePartial, }; +enum class Base64DecodeError { + ExtraBits, + InputRemainder, + InvalidCharacter, + InvalidData, +}; + ErrorOr decode_base64(StringView, LastChunkHandling = LastChunkHandling::Loose); ErrorOr decode_base64url(StringView, LastChunkHandling = LastChunkHandling::Loose); struct InvalidBase64 { + Base64DecodeError decode_error { Base64DecodeError::InvalidData }; Error error; size_t valid_input_bytes { 0 }; }; diff --git a/AK/LexicalPath.cpp b/AK/LexicalPath.cpp index 04c8455d52..1184298c4a 100644 --- a/AK/LexicalPath.cpp +++ b/AK/LexicalPath.cpp @@ -144,11 +144,11 @@ ByteString LexicalPath::canonicalized_path(ByteString path) return builder.to_byte_string(); } -ByteString LexicalPath::absolute_path(ByteString dir_path, ByteString target) +ByteString LexicalPath::absolute_path(StringView dir_path, StringView target) { - if (LexicalPath(target).is_absolute()) { + if (is_absolute_path(target)) return LexicalPath::canonicalized_path(target); - } + return LexicalPath::canonicalized_path(join(dir_path, target).string()); } diff --git a/AK/LexicalPath.h b/AK/LexicalPath.h index be80595325..38554f585f 100644 --- a/AK/LexicalPath.h +++ b/AK/LexicalPath.h @@ -48,7 +48,7 @@ public: [[nodiscard]] LexicalPath parent() const; [[nodiscard]] static ByteString canonicalized_path(ByteString); - [[nodiscard]] static ByteString absolute_path(ByteString dir_path, ByteString target); + [[nodiscard]] static ByteString absolute_path(StringView dir_path, StringView target); [[nodiscard]] static Optional relative_path(StringView absolute_path, StringView absolute_prefix); template diff --git a/AK/LexicalPathWindows.cpp b/AK/LexicalPathWindows.cpp index d35804a768..d5bb0a5a47 100644 --- a/AK/LexicalPathWindows.cpp +++ b/AK/LexicalPathWindows.cpp @@ -106,7 +106,7 @@ ByteString LexicalPath::canonicalized_path(ByteString path) return path == "" ? "." : path; } -ByteString LexicalPath::absolute_path(ByteString dir_path, ByteString target) +ByteString LexicalPath::absolute_path(StringView dir_path, StringView target) { if (is_absolute_path(target)) return canonicalized_path(target); diff --git a/Libraries/LibJS/Bytecode/Executable.cpp b/Libraries/LibJS/Bytecode/Executable.cpp index 12a64e606d..26f833d7b1 100644 --- a/Libraries/LibJS/Bytecode/Executable.cpp +++ b/Libraries/LibJS/Bytecode/Executable.cpp @@ -358,12 +358,16 @@ static void dump_header(StringBuilder& output, Executable const& executable) // Show source location if available. if (first_source_map_entry) { - auto filename = executable.source_code->filename(); + auto filename = executable.source_code->filename().utf16_view(); if (!filename.is_empty()) { // Show just the basename to keep output portable across machines. - auto last_slash = filename.bytes_as_string_view().find_last('/'); + Optional last_slash; + for (size_t i = 0; i < filename.length_in_code_units(); ++i) { + if (filename.code_unit_at(i) == '/') + last_slash = i; + } if (last_slash.has_value()) - filename = MUST(filename.substring_from_byte_offset(last_slash.value() + 1)); + filename = filename.substring_view(last_slash.value() + 1); output.appendff(" {}:{}:{}", filename, first_source_map_entry->line, first_source_map_entry->column); } else { output.appendff(" line {}, column {}", first_source_map_entry->line, first_source_map_entry->column); diff --git a/Libraries/LibJS/Console.cpp b/Libraries/LibJS/Console.cpp index 790b63a065..ae06dac21c 100644 --- a/Libraries/LibJS/Console.cpp +++ b/Libraries/LibJS/Console.cpp @@ -367,7 +367,7 @@ ThrowCompletionOr Console::trace() if (element.source_range.has_value()) { auto const& source_range = *element.source_range; if (!source_range.filename().is_empty()) { - frame.source_file = MUST(String::from_byte_string(source_range.filename())); + frame.source_file = source_range.filename(); frame.line = source_range.start.line; frame.column = source_range.start.column; } diff --git a/Libraries/LibJS/Console.h b/Libraries/LibJS/Console.h index bfbacb0012..da03b3dd93 100644 --- a/Libraries/LibJS/Console.h +++ b/Libraries/LibJS/Console.h @@ -59,7 +59,7 @@ public: struct TraceFrame { Utf16String function_name; - Optional source_file; + Optional source_file; Optional line; Optional column; }; diff --git a/Libraries/LibJS/CyclicModule.cpp b/Libraries/LibJS/CyclicModule.cpp index c6d1b8d7e2..5b04980098 100644 --- a/Libraries/LibJS/CyclicModule.cpp +++ b/Libraries/LibJS/CyclicModule.cpp @@ -7,6 +7,7 @@ #include #include +#include #include #include #include @@ -265,7 +266,7 @@ ThrowCompletionOr CyclicModule::inner_module_linking(VM& vm, GC::RootVector // b. Return index. // Note: Step 1, 1.a and 1.b are handled in Module.cpp - dbgln_if(JS_MODULE_DEBUG, "[JS MODULE] inner_module_linking[{}](vm, {}, {})", this, ByteString::join(',', stack), index); + dbgln_if(JS_MODULE_DEBUG, "[JS MODULE] inner_module_linking[{}](vm, {}, {})", this, MUST(String::join(',', stack)), index); // 2. If module.[[Status]] is linking, linked, evaluating-async, or evaluated, then if (m_status == ModuleStatus::Linking || m_status == ModuleStatus::Linked || m_status == ModuleStatus::EvaluatingAsync || m_status == ModuleStatus::Evaluated) { @@ -470,7 +471,7 @@ ThrowCompletionOr> CyclicModule::evaluate(VM& vm) // 16.2.1.5.2.1 InnerModuleEvaluation ( module, stack, index ), https://tc39.es/ecma262/#sec-innermoduleevaluation ThrowCompletionOr CyclicModule::inner_module_evaluation(VM& vm, GC::RootVector>& stack, u32 index) { - dbgln_if(JS_MODULE_DEBUG, "[JS MODULE] inner_module_evaluation[{}](vm, {}, {})", this, ByteString::join(", "sv, stack), index); + dbgln_if(JS_MODULE_DEBUG, "[JS MODULE] inner_module_evaluation[{}](vm, {}, {})", this, MUST(String::join(", "sv, stack)), index); // Note: Step 1 is performed in Module.cpp // 2. If module.[[Status]] is evaluating-async or evaluated, then diff --git a/Libraries/LibJS/ParserError.cpp b/Libraries/LibJS/ParserError.cpp index d8ea8b9797..0fb99c5635 100644 --- a/Libraries/LibJS/ParserError.cpp +++ b/Libraries/LibJS/ParserError.cpp @@ -5,8 +5,8 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include #include +#include #include #include #include @@ -20,14 +20,7 @@ Utf16String ParserError::to_utf16_string() const return Utf16String::formatted("{} (line: {}, column: {})", message, position.value().line, position.value().column); } -ByteString ParserError::to_byte_string() const -{ - if (!position.has_value()) - return message.to_byte_string(); - return Utf16String::formatted("{} (line: {}, column: {})", message, position.value().line, position.value().column).to_byte_string(); -} - -ByteString ParserError::source_location_hint(Utf16View const& source, char spacer, char indicator) const +Utf16String ParserError::source_location_hint(Utf16View const& source, char spacer, char indicator) const { if (!position.has_value()) return {}; @@ -36,13 +29,13 @@ ByteString ParserError::source_location_hint(Utf16View const& source, char space // line terminators to \n is easier than splitting using all different LT characters. auto source_string = source.replace("\r\n"sv, "\n"sv, ReplaceMode::All).replace("\r"sv, "\n"sv, ReplaceMode::All).replace(LINE_SEPARATOR, "\n"sv, ReplaceMode::All).replace(PARAGRAPH_SEPARATOR, "\n"sv, ReplaceMode::All); - StringBuilder builder; + Utf16StringBuilder builder; builder.append(source_string.split_view('\n', SplitBehavior::KeepEmpty)[position.value().line - 1]); - builder.append('\n'); + builder.append_ascii('\n'); for (size_t i = 0; i < position.value().column - 1; ++i) - builder.append(spacer); - builder.append(indicator); - return builder.to_byte_string(); + builder.append_ascii(spacer); + builder.append_ascii(indicator); + return builder.to_string(); } } diff --git a/Libraries/LibJS/ParserError.h b/Libraries/LibJS/ParserError.h index 8b08933245..adf83238b7 100644 --- a/Libraries/LibJS/ParserError.h +++ b/Libraries/LibJS/ParserError.h @@ -7,7 +7,6 @@ #pragma once -#include #include #include #include @@ -21,8 +20,7 @@ struct JS_API ParserError { Optional position; Utf16String to_utf16_string() const; - ByteString to_byte_string() const; - ByteString source_location_hint(Utf16View const& source, char spacer = ' ', char indicator = '^') const; + Utf16String source_location_hint(Utf16View const& source, char spacer = ' ', char indicator = '^') const; }; } diff --git a/Libraries/LibJS/Print.cpp b/Libraries/LibJS/Print.cpp index 1b2e1df4f3..d0b948037b 100644 --- a/Libraries/LibJS/Print.cpp +++ b/Libraries/LibJS/Print.cpp @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -119,7 +120,7 @@ ErrorOr print_value(JS::PrintContext& print_context, JS::ThrowCompletionOr ErrorOr strip_ansi(StringView format_string) { if (format_string.is_empty()) - return String(); + return String {}; StringBuilder builder; size_t i; diff --git a/Libraries/LibJS/Runtime/AbstractOperations.cpp b/Libraries/LibJS/Runtime/AbstractOperations.cpp index 405b8c87ec..b40684400d 100644 --- a/Libraries/LibJS/Runtime/AbstractOperations.cpp +++ b/Libraries/LibJS/Runtime/AbstractOperations.cpp @@ -1285,7 +1285,7 @@ CanonicalIndex canonical_numeric_index_string(PropertyKey const& property_key, C } // 22.1.3.19.1 GetSubstitution ( matched, str, position, captures, namedCaptures, replacementTemplate ), https://tc39.es/ecma262/#sec-getsubstitution -ThrowCompletionOr get_substitution(VM& vm, Utf16View const& matched, Utf16View const& str, size_t position, Span captures, Value named_captures, Value replacement_template) +ThrowCompletionOr get_substitution(VM& vm, Utf16View const& matched, Utf16View const& str, size_t position, Span captures, Value named_captures, Utf16View const& replacement_template) { // 1. Let stringLength be the length of str. auto string_length = str.length_in_code_units(); @@ -1297,8 +1297,7 @@ ThrowCompletionOr get_substitution(VM& vm, Utf16View const& matched Utf16StringBuilder result; // 4. Let templateRemainder be replacementTemplate. - auto replace_template_string = TRY(replacement_template.to_utf16_string(vm)); - Utf16View template_remainder { replace_template_string }; + auto template_remainder = replacement_template; // 5. Repeat, while templateRemainder is not the empty String, while (!template_remainder.is_empty()) { @@ -1948,18 +1947,17 @@ ThrowCompletionOr get_option(VM& vm, Object const& options, PropertyKey c VERIFY(type == OptionType::String); // b. Set value to ? ToString(value). - value = TRY(value.to_primitive_string(vm)); - } + auto value_string = TRY(value.to_utf16_string(vm)); - // 5. If values is not EMPTY and values does not contain value, throw a RangeError exception. - if (!values.is_empty()) { - // NOTE: Every location in the spec that invokes GetOption with type=boolean also has values=undefined. - VERIFY(value.is_string()); + // 5. If values is not EMPTY and values does not contain value, throw a RangeError exception. + if (!values.is_empty()) { + auto value_string_view = value_string.utf16_view(); + auto it = find_if(values.begin(), values.end(), [&](auto allowed_value) { return value_string_view == allowed_value; }); + if (it == values.end()) + return vm.throw_completion(ErrorType::OptionIsNotValidValue, value_string_view, property.as_string()); + } - auto value_string = value.as_string().utf16_string_view(); - auto it = find_if(values.begin(), values.end(), [&](auto allowed_value) { return value_string == allowed_value; }); - if (it == values.end()) - return vm.throw_completion(ErrorType::OptionIsNotValidValue, value_string, property.as_string()); + value = PrimitiveString::create(vm, value_string); } // 6. Return value. diff --git a/Libraries/LibJS/Runtime/AbstractOperations.h b/Libraries/LibJS/Runtime/AbstractOperations.h index 3647f82cc7..cef6e4d9fc 100644 --- a/Libraries/LibJS/Runtime/AbstractOperations.h +++ b/Libraries/LibJS/Runtime/AbstractOperations.h @@ -88,7 +88,7 @@ enum class CanonicalIndexMode { IgnoreNumericRoundtrip, }; [[nodiscard]] CanonicalIndex canonical_numeric_index_string(PropertyKey const&, CanonicalIndexMode needs_numeric); -ThrowCompletionOr get_substitution(VM&, Utf16View const& matched, Utf16View const& str, size_t position, Span captures, Value named_captures, Value replacement); +ThrowCompletionOr get_substitution(VM&, Utf16View const& matched, Utf16View const& str, size_t position, Span captures, Value named_captures, Utf16View const& replacement); enum class CallerMode { Strict, diff --git a/Libraries/LibJS/Runtime/ConsoleObjectPrototype.cpp b/Libraries/LibJS/Runtime/ConsoleObjectPrototype.cpp index 9b8349bb9d..9ecc903e84 100644 --- a/Libraries/LibJS/Runtime/ConsoleObjectPrototype.cpp +++ b/Libraries/LibJS/Runtime/ConsoleObjectPrototype.cpp @@ -6,7 +6,6 @@ #include "ConsoleObjectPrototype.h" -#include #include #include #include diff --git a/Libraries/LibJS/Runtime/Date.cpp b/Libraries/LibJS/Runtime/Date.cpp index 51819aef15..edd634769c 100644 --- a/Libraries/LibJS/Runtime/Date.cpp +++ b/Libraries/LibJS/Runtime/Date.cpp @@ -399,7 +399,7 @@ i64 clip_double_to_sane_time(double value) // 21.4.1.20 GetNamedTimeZoneEpochNanoseconds ( timeZoneIdentifier, year, month, day, hour, minute, second, millisecond, microsecond, nanosecond ), https://tc39.es/ecma262/#sec-getnamedtimezoneepochnanoseconds // 14.6.3 GetNamedTimeZoneEpochNanoseconds ( timeZoneIdentifier, isoDateTime ), https://tc39.es/proposal-temporal/#sec-getnamedtimezoneepochnanoseconds -Vector get_named_time_zone_epoch_nanoseconds(StringView time_zone_identifier, Temporal::ISODateTime const& iso_date_time) +Vector get_named_time_zone_epoch_nanoseconds(Utf16View time_zone_identifier, Temporal::ISODateTime const& iso_date_time) { auto local_nanoseconds = get_utc_epoch_nanoseconds(iso_date_time); auto local_time = UnixDateTime::from_nanoseconds_since_epoch(clip_bigint_to_sane_time(local_nanoseconds)); @@ -416,7 +416,7 @@ Vector get_named_time_zone_epoch_nanoseconds(StringVie } // 21.4.1.21 GetNamedTimeZoneOffsetNanoseconds ( timeZoneIdentifier, epochNanoseconds ), https://tc39.es/ecma262/#sec-getnamedtimezoneoffsetnanoseconds -Unicode::TimeZoneOffset get_named_time_zone_offset_nanoseconds(StringView time_zone_identifier, Crypto::SignedBigInteger const& epoch_nanoseconds) +Unicode::TimeZoneOffset get_named_time_zone_offset_nanoseconds(Utf16View time_zone_identifier, Crypto::SignedBigInteger const& epoch_nanoseconds) { // Since UnixDateTime::from_seconds_since_epoch() and UnixDateTime::from_nanoseconds_since_epoch() both take an i64, converting to // seconds first gives us a greater range. The TZDB doesn't have sub-second offsets. @@ -431,7 +431,7 @@ Unicode::TimeZoneOffset get_named_time_zone_offset_nanoseconds(StringView time_z // 21.4.1.21 GetNamedTimeZoneOffsetNanoseconds ( timeZoneIdentifier, epochNanoseconds ), https://tc39.es/ecma262/#sec-getnamedtimezoneoffsetnanoseconds // OPTIMIZATION: This overload is provided to allow callers to avoid BigInt construction if they do not need infinitely precise nanosecond resolution. -Unicode::TimeZoneOffset get_named_time_zone_offset_milliseconds(StringView time_zone_identifier, double epoch_milliseconds) +Unicode::TimeZoneOffset get_named_time_zone_offset_milliseconds(Utf16View time_zone_identifier, double epoch_milliseconds) { auto seconds = epoch_milliseconds / 1000.0; auto time = UnixDateTime::from_seconds_since_epoch(clip_double_to_sane_time(seconds)); @@ -499,7 +499,7 @@ double local_time(double time) // 4. Else, else { // a. Let offsetNs be GetNamedTimeZoneOffsetNanoseconds(systemTimeZoneIdentifier, ℤ(ℝ(t) × 10^6)). - auto offset = get_named_time_zone_offset_milliseconds(system_time_zone_identifier.utf16_view().bytes(), time); + auto offset = get_named_time_zone_offset_milliseconds(system_time_zone_identifier.utf16_view(), time); offset_nanoseconds = static_cast(offset.offset.to_nanoseconds()); } @@ -533,7 +533,7 @@ double utc_time(double time) auto iso_date_time = Temporal::time_value_to_iso_date_time_record(time); // b. Let possibleInstants be GetNamedTimeZoneEpochNanoseconds(systemTimeZoneIdentifier, isoDateTime). - auto possible_instants = get_named_time_zone_epoch_nanoseconds(system_time_zone_identifier.utf16_view().bytes(), iso_date_time); + auto possible_instants = get_named_time_zone_epoch_nanoseconds(system_time_zone_identifier.utf16_view(), iso_date_time); // c. NOTE: The following steps ensure that when t represents local time repeating multiple times at a negative // time zone transition (e.g. when the daylight saving time ends or the time zone offset is decreased due to @@ -568,7 +568,7 @@ double utc_time(double time) } // f. Let offsetNs be GetNamedTimeZoneOffsetNanoseconds(systemTimeZoneIdentifier, disambiguatedInstant). - auto offset = get_named_time_zone_offset_nanoseconds(system_time_zone_identifier.utf16_view().bytes(), disambiguated_instant); + auto offset = get_named_time_zone_offset_nanoseconds(system_time_zone_identifier.utf16_view(), disambiguated_instant); offset_nanoseconds = static_cast(offset.offset.to_nanoseconds()); } diff --git a/Libraries/LibJS/Runtime/Date.h b/Libraries/LibJS/Runtime/Date.h index 3c02743a1c..8908daf153 100644 --- a/Libraries/LibJS/Runtime/Date.h +++ b/Libraries/LibJS/Runtime/Date.h @@ -88,9 +88,9 @@ JS_API u16 ms_from_time(double); Crypto::SignedBigInteger get_utc_epoch_nanoseconds(Temporal::ISODateTime const&); i64 clip_bigint_to_sane_time(Crypto::SignedBigInteger const& value); i64 clip_double_to_sane_time(double value); -Vector get_named_time_zone_epoch_nanoseconds(StringView time_zone_identifier, Temporal::ISODateTime const&); -Unicode::TimeZoneOffset get_named_time_zone_offset_nanoseconds(StringView time_zone_identifier, Crypto::SignedBigInteger const& epoch_nanoseconds); -Unicode::TimeZoneOffset get_named_time_zone_offset_milliseconds(StringView time_zone_identifier, double epoch_milliseconds); +Vector get_named_time_zone_epoch_nanoseconds(Utf16View time_zone_identifier, Temporal::ISODateTime const&); +Unicode::TimeZoneOffset get_named_time_zone_offset_nanoseconds(Utf16View time_zone_identifier, Crypto::SignedBigInteger const& epoch_nanoseconds); +Unicode::TimeZoneOffset get_named_time_zone_offset_milliseconds(Utf16View time_zone_identifier, double epoch_milliseconds); Utf16String system_time_zone_identifier(); JS_API void clear_system_time_zone_cache(); double local_time(double time); diff --git a/Libraries/LibJS/Runtime/DatePrototype.cpp b/Libraries/LibJS/Runtime/DatePrototype.cpp index 365e7712a6..a77f0bfcaf 100644 --- a/Libraries/LibJS/Runtime/DatePrototype.cpp +++ b/Libraries/LibJS/Runtime/DatePrototype.cpp @@ -1117,7 +1117,7 @@ Utf16String time_zone_string(double time) // 2. If offsetMinutes is EMPTY, then if (!offset_minutes.has_value()) { // a. Let offsetNs be GetNamedTimeZoneOffsetNanoseconds(systemTimeZoneIdentifier, ℤ(ℝ(tv) × 10^6)). - auto offset = get_named_time_zone_offset_milliseconds(system_time_zone_identifier.utf16_view().bytes(), time); + auto offset = get_named_time_zone_offset_milliseconds(system_time_zone_identifier.utf16_view(), time); in_dst = offset.in_dst; // b. Set offsetMinutes to truncate(offsetNs / (60 × 10**9)). @@ -1133,7 +1133,9 @@ Utf16String time_zone_string(double time) auto tz_name = Unicode::current_time_zone(); // Most implementations seem to prefer the long-form display name of the time zone. Not super important, but we may as well match that behavior. - if (auto name = Unicode::time_zone_display_name(Unicode::default_locale().bytes(), tz_name.utf16_view().bytes(), in_dst, time); name.has_value()) + auto locale = MUST(Unicode::default_locale().to_byte_string()); + auto time_zone_identifier = MUST(tz_name.utf16_view().to_byte_string()); + if (auto name = Unicode::time_zone_display_name(locale.view(), time_zone_identifier.view(), in_dst, time); name.has_value()) tz_name = name.release_value(); // 10. Return the string-concatenation of offsetString and tzName. diff --git a/Libraries/LibJS/Runtime/Error.cpp b/Libraries/LibJS/Runtime/Error.cpp index 42d1a0616a..32ed94d350 100644 --- a/Libraries/LibJS/Runtime/Error.cpp +++ b/Libraries/LibJS/Runtime/Error.cpp @@ -32,11 +32,6 @@ GC::Ref Error::create(Realm& realm, Utf16View message) return error; } -GC::Ref Error::create(Realm& realm, StringView message) -{ - return create(realm, Utf16String::from_utf8(message)); -} - Utf16String Error::stack_string(CompactTraceback compact) const { return ErrorData::stack_string(compact); @@ -114,11 +109,6 @@ void Error::set_message(Utf16View message) return error; \ } \ \ - GC::Ref ClassName::create(Realm& realm, StringView message) \ - { \ - return create(realm, Utf16String::from_utf8(message)); \ - } \ - \ ClassName::ClassName(Object& prototype) \ : Error(prototype) \ { \ diff --git a/Libraries/LibJS/Runtime/Error.h b/Libraries/LibJS/Runtime/Error.h index 464518a93e..d9c3cc579f 100644 --- a/Libraries/LibJS/Runtime/Error.h +++ b/Libraries/LibJS/Runtime/Error.h @@ -27,7 +27,6 @@ public: static GC::Ref create(Realm&); static GC::Ref create(Realm&, Utf16String message); static GC::Ref create(Realm&, Utf16View message); - static GC::Ref create(Realm&, StringView message); virtual ~Error() override = default; @@ -65,7 +64,6 @@ inline bool Object::fast_is() const { return is_error_object(); } static GC::Ref create(Realm&); \ static GC::Ref create(Realm&, Utf16String message); \ static GC::Ref create(Realm&, Utf16View message); \ - static GC::Ref create(Realm&, StringView message); \ \ explicit ClassName(Object& prototype); \ virtual ~ClassName() override = default; \ diff --git a/Libraries/LibJS/Runtime/FunctionObject.cpp b/Libraries/LibJS/Runtime/FunctionObject.cpp index 2fb9f90abd..cf8d0eb55e 100644 --- a/Libraries/LibJS/Runtime/FunctionObject.cpp +++ b/Libraries/LibJS/Runtime/FunctionObject.cpp @@ -51,7 +51,7 @@ GC::Ref FunctionObject::make_function_name(Variant().to_string(); + name = name_arg.get().to_utf16_string(); } // 4. If F has an [[InitialName]] internal slot, then diff --git a/Libraries/LibJS/Runtime/GlobalObject.cpp b/Libraries/LibJS/Runtime/GlobalObject.cpp index ca4daad9da..4eb2ebe9c3 100644 --- a/Libraries/LibJS/Runtime/GlobalObject.cpp +++ b/Libraries/LibJS/Runtime/GlobalObject.cpp @@ -373,7 +373,7 @@ static ThrowCompletionOr encode(VM& vm, Utf16View const& string, St auto string_length = string.length_in_code_units(); // 2. Let R be the empty String. - StringBuilder encoded_builder(StringBuilder::Mode::UTF16); + Utf16StringBuilder encoded_builder; // 3. Let alwaysUnescaped be the string-concatenation of the ASCII word characters and "-.!~*'()". // 4. Let unescapedSet be the string-concatenation of alwaysUnescaped and extraUnescaped. @@ -396,7 +396,7 @@ static ThrowCompletionOr encode(VM& vm, Utf16View const& string, St k++; // ii. Set R to the string-concatenation of R and C. - encoded_builder.append(code_unit); + encoded_builder.append_code_unit(code_unit); } // d. Else, else { @@ -419,7 +419,7 @@ static ThrowCompletionOr encode(VM& vm, Utf16View const& string, St VERIFY(nwritten > 0); } } - return encoded_builder.to_utf16_string(); + return encoded_builder.to_string(); } static ThrowCompletionOr decode_percent_encoded_byte(VM& vm, Utf16View const& string, size_t percent_index) @@ -543,7 +543,7 @@ JS_DEFINE_NATIVE_FUNCTION(GlobalObject::escape) auto string = TRY(vm.argument(0).to_utf16_string(vm)); // 3. Let R be the empty String. - StringBuilder escaped(StringBuilder::Mode::UTF16); + Utf16StringBuilder escaped; // 4. Let unescapedSet be the string-concatenation of the ASCII word characters and "@*+-./". auto unescaped_set = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789@*_+-./"sv; @@ -559,7 +559,7 @@ JS_DEFINE_NATIVE_FUNCTION(GlobalObject::escape) // NOTE: We know unescapedSet is ASCII-only, so ensure we have an ASCII codepoint before casting to char. if (is_ascii(code_unit) && unescaped_set.contains(static_cast(code_unit))) { // i. Let S be the String value containing the single code unit char. - escaped.append(static_cast(code_unit)); + escaped.append_ascii(static_cast(code_unit)); } // c. Else, // i. Let n be the numeric value of char. @@ -581,7 +581,7 @@ JS_DEFINE_NATIVE_FUNCTION(GlobalObject::escape) } // 7. Return R. - return PrimitiveString::create(vm, escaped.to_utf16_string()); + return PrimitiveString::create(vm, escaped.to_string()); } // B.2.1.2 unescape ( string ), https://tc39.es/ecma262/#sec-unescape-string diff --git a/Libraries/LibJS/Runtime/Intl/AbstractOperations.cpp b/Libraries/LibJS/Runtime/Intl/AbstractOperations.cpp index ddf706c906..8425bc0464 100644 --- a/Libraries/LibJS/Runtime/Intl/AbstractOperations.cpp +++ b/Libraries/LibJS/Runtime/Intl/AbstractOperations.cpp @@ -4,7 +4,6 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include #include #include #include @@ -110,43 +109,18 @@ static bool is_well_formed_language_tag_impl(ViewType locale) } // 6.2.1 IsWellFormedLanguageTag ( locale ), https://tc39.es/ecma402/#sec-iswellformedlanguagetag -bool is_well_formed_language_tag(StringView locale) -{ - return is_well_formed_language_tag_impl(locale); -} - bool is_well_formed_language_tag(Utf16View locale) { return is_well_formed_language_tag_impl(locale); } // 6.2.2 CanonicalizeUnicodeLocaleId ( locale ), https://tc39.es/ecma402/#sec-canonicalizeunicodelocaleid -Utf16String canonicalize_unicode_locale_id(StringView locale) -{ - return Unicode::canonicalize_unicode_locale_id(locale); -} - Utf16String canonicalize_unicode_locale_id(Utf16View locale) { return Unicode::canonicalize_unicode_locale_id(locale); } // 6.3.1 IsWellFormedCurrencyCode ( currency ), https://tc39.es/ecma402/#sec-iswellformedcurrencycode -bool is_well_formed_currency_code(StringView currency) -{ - // 1. If the length of currency is not 3, return false. - if (currency.length() != 3) - return false; - - // 2. Let normalized be the ASCII-uppercase of currency. - // 3. If normalized contains any code unit outside of 0x0041 through 0x005A (corresponding to Unicode characters LATIN CAPITAL LETTER A through LATIN CAPITAL LETTER Z), return false. - if (!all_of(currency, is_ascii_alpha)) - return false; - - // 4. Return true. - return true; -} - bool is_well_formed_currency_code(Utf16View currency) { // 1. If the length of currency is not 3, return false. @@ -190,7 +164,7 @@ Vector const& available_named_time_zone_identifiers() // b. If identifier is a Link name and identifier is not "UTC", then if (identifier.utf16_view() != "UTC"sv) { - if (auto resolved = Unicode::resolve_primary_time_zone(identifier.utf16_view().bytes()); resolved.has_value() && identifier != *resolved) { + if (auto resolved = Unicode::resolve_primary_time_zone(identifier.utf16_view()); resolved.has_value() && identifier != *resolved) { // i. Set primary to the Zone name that identifier resolves to, according to the rules for resolving Link // names in the IANA Time Zone Database. primary = resolved.release_value(); @@ -443,7 +417,8 @@ Utf16String insert_unicode_extension_and_canonicalize(Unicode::LocaleID locale, locale.extensions.append(Unicode::LocaleExtension { move(attributes), move(keywords) }); // 10. Return CanonicalizeUnicodeLocaleId(newLocale). - return JS::Intl::canonicalize_unicode_locale_id(locale.to_utf16_string()); + auto locale_string = locale.to_utf16_string(); + return JS::Intl::canonicalize_unicode_locale_id(locale_string.utf16_view()); } template diff --git a/Libraries/LibJS/Runtime/Intl/AbstractOperations.h b/Libraries/LibJS/Runtime/Intl/AbstractOperations.h index f11678183e..1e4880f8f7 100644 --- a/Libraries/LibJS/Runtime/Intl/AbstractOperations.h +++ b/Libraries/LibJS/Runtime/Intl/AbstractOperations.h @@ -66,11 +66,8 @@ AK_ENUM_BITWISE_OPERATORS(SpecialBehaviors); using StringOrBoolean = Variant; -bool is_well_formed_language_tag(StringView locale); bool is_well_formed_language_tag(Utf16View locale); -Utf16String canonicalize_unicode_locale_id(StringView locale); Utf16String canonicalize_unicode_locale_id(Utf16View locale); -bool is_well_formed_currency_code(StringView currency); bool is_well_formed_currency_code(Utf16View currency); Vector const& available_named_time_zone_identifiers(); Optional get_available_named_time_zone_identifier(Utf16View time_zone_identifier); diff --git a/Libraries/LibJS/Runtime/Intl/CollatorConstructor.cpp b/Libraries/LibJS/Runtime/Intl/CollatorConstructor.cpp index 71ac2425bc..ff0e166e49 100644 --- a/Libraries/LibJS/Runtime/Intl/CollatorConstructor.cpp +++ b/Libraries/LibJS/Runtime/Intl/CollatorConstructor.cpp @@ -128,9 +128,9 @@ ThrowCompletionOr> CollatorConstructor::construct(FunctionObject // Non-standard, create an ICU collator for this Intl object. auto icu_collator = Unicode::Collator::create( - result.icu_locale.utf16_view().bytes(), + result.icu_locale.utf16_view(), collator->usage(), - collator->collation().utf16_view().bytes(), + collator->collation().utf16_view(), sensitivity, collator->case_first(), collator->numeric(), diff --git a/Libraries/LibJS/Runtime/Intl/DateTimeFormat.cpp b/Libraries/LibJS/Runtime/Intl/DateTimeFormat.cpp index cad7ac93b4..056d1dd8e5 100644 --- a/Libraries/LibJS/Runtime/Intl/DateTimeFormat.cpp +++ b/Libraries/LibJS/Runtime/Intl/DateTimeFormat.cpp @@ -62,7 +62,7 @@ ReadonlySpan DateTimeFormat::resolution_option_descr return *descriptors; } -static Optional get_or_create_formatter(StringView locale, StringView time_zone, OwnPtr& formatter, Optional const& format) +static Optional get_or_create_formatter(Utf16View locale, Utf16View time_zone, OwnPtr& formatter, Optional const& format) { if (formatter) return *formatter; @@ -75,32 +75,32 @@ static Optional get_or_create_formatter(StringVi Optional DateTimeFormat::temporal_plain_date_formatter() { - return get_or_create_formatter(m_icu_locale.utf16_view().bytes(), "GMT+00:00"sv, m_temporal_plain_date_formatter, m_temporal_plain_date_format); + return get_or_create_formatter(m_icu_locale.utf16_view(), "GMT+00:00"sv, m_temporal_plain_date_formatter, m_temporal_plain_date_format); } Optional DateTimeFormat::temporal_plain_year_month_formatter() { - return get_or_create_formatter(m_icu_locale.utf16_view().bytes(), "GMT+00:00"sv, m_temporal_plain_year_month_formatter, m_temporal_plain_year_month_format); + return get_or_create_formatter(m_icu_locale.utf16_view(), "GMT+00:00"sv, m_temporal_plain_year_month_formatter, m_temporal_plain_year_month_format); } Optional DateTimeFormat::temporal_plain_month_day_formatter() { - return get_or_create_formatter(m_icu_locale.utf16_view().bytes(), "GMT+00:00"sv, m_temporal_plain_month_day_formatter, m_temporal_plain_month_day_format); + return get_or_create_formatter(m_icu_locale.utf16_view(), "GMT+00:00"sv, m_temporal_plain_month_day_formatter, m_temporal_plain_month_day_format); } Optional DateTimeFormat::temporal_plain_time_formatter() { - return get_or_create_formatter(m_icu_locale.utf16_view().bytes(), "GMT+00:00"sv, m_temporal_plain_time_formatter, m_temporal_plain_time_format); + return get_or_create_formatter(m_icu_locale.utf16_view(), "GMT+00:00"sv, m_temporal_plain_time_formatter, m_temporal_plain_time_format); } Optional DateTimeFormat::temporal_plain_date_time_formatter() { - return get_or_create_formatter(m_icu_locale.utf16_view().bytes(), "GMT+00:00"sv, m_temporal_plain_date_time_formatter, m_temporal_plain_date_time_format); + return get_or_create_formatter(m_icu_locale.utf16_view(), "GMT+00:00"sv, m_temporal_plain_date_time_formatter, m_temporal_plain_date_time_format); } Optional DateTimeFormat::temporal_instant_formatter() { - return get_or_create_formatter(m_icu_locale.utf16_view().bytes(), m_temporal_time_zone.utf16_view().bytes(), m_temporal_instant_formatter, m_temporal_instant_format); + return get_or_create_formatter(m_icu_locale.utf16_view(), m_temporal_time_zone.utf16_view(), m_temporal_instant_formatter, m_temporal_instant_format); } // 11.5.5 FormatDateTimePattern ( dateTimeFormat, patternParts, x, rangeFormatOptions ), https://tc39.es/ecma402/#sec-formatdatetimepattern @@ -535,7 +535,7 @@ static double to_epoch_milliseconds(Crypto::SignedBigInteger const& epoch_nanose ThrowCompletionOr handle_date_time_temporal_date(VM& vm, DateTimeFormat& date_time_format, Temporal::PlainDate const& temporal_date) { // 1. If temporalDate.[[Calendar]] is not either dateTimeFormat.[[Calendar]] or "iso8601", throw a RangeError exception. - auto date_time_format_calendar = date_time_format.calendar().utf16_view().bytes(); + auto date_time_format_calendar = date_time_format.calendar().utf16_view(); if (!temporal_date.calendar().is_one_of(date_time_format_calendar, "iso8601"sv)) return vm.throw_completion(ErrorType::IntlTemporalInvalidCalendar, "Temporal.PlainDate"sv, temporal_date.calendar(), date_time_format.calendar()); @@ -560,7 +560,7 @@ ThrowCompletionOr handle_date_time_temporal_date(VM& vm, DateTimeFo ThrowCompletionOr handle_date_time_temporal_year_month(VM& vm, DateTimeFormat& date_time_format, Temporal::PlainYearMonth const& temporal_year_month) { // 1. If temporalYearMonth.[[Calendar]] is not equal to dateTimeFormat.[[Calendar]], throw a RangeError exception. - if (temporal_year_month.calendar() != date_time_format.calendar().utf16_view().bytes()) + if (temporal_year_month.calendar() != date_time_format.calendar().utf16_view()) return vm.throw_completion(ErrorType::IntlTemporalInvalidCalendar, "Temporal.PlainYearMonth"sv, temporal_year_month.calendar(), date_time_format.calendar()); // 2. Let isoDateTime be CombineISODateAndTimeRecord(temporalYearMonth.[[ISODate]], NoonTimeRecord()). @@ -584,7 +584,7 @@ ThrowCompletionOr handle_date_time_temporal_year_month(VM& vm, Date ThrowCompletionOr handle_date_time_temporal_month_day(VM& vm, DateTimeFormat& date_time_format, Temporal::PlainMonthDay const& temporal_month_day) { // 1. If temporalMonthDay.[[Calendar]] is not equal to dateTimeFormat.[[Calendar]], throw a RangeError exception. - if (temporal_month_day.calendar() != date_time_format.calendar().utf16_view().bytes()) + if (temporal_month_day.calendar() != date_time_format.calendar().utf16_view()) return vm.throw_completion(ErrorType::IntlTemporalInvalidCalendar, "Temporal.PlainMonthDay"sv, temporal_month_day.calendar(), date_time_format.calendar()); // 2. Let isoDateTime be CombineISODateAndTimeRecord(temporalMonthDay.[[ISODate]], NoonTimeRecord()). @@ -631,7 +631,7 @@ ThrowCompletionOr handle_date_time_temporal_time(VM& vm, DateTimeFo ThrowCompletionOr handle_date_time_temporal_date_time(VM& vm, DateTimeFormat& date_time_format, Temporal::PlainDateTime const& date_time) { // 1. If dateTime.[[Calendar]] is not "iso8601" and not equal to dateTimeFormat.[[Calendar]], throw a RangeError exception. - auto date_time_format_calendar = date_time_format.calendar().utf16_view().bytes(); + auto date_time_format_calendar = date_time_format.calendar().utf16_view(); if (!date_time.calendar().is_one_of(date_time_format_calendar, "iso8601"sv)) return vm.throw_completion(ErrorType::IntlTemporalInvalidCalendar, "Temporal.PlainDateTime"sv, date_time.calendar(), date_time_format.calendar()); diff --git a/Libraries/LibJS/Runtime/Intl/DateTimeFormatConstructor.cpp b/Libraries/LibJS/Runtime/Intl/DateTimeFormatConstructor.cpp index b0143ef781..bdf719377e 100644 --- a/Libraries/LibJS/Runtime/Intl/DateTimeFormatConstructor.cpp +++ b/Libraries/LibJS/Runtime/Intl/DateTimeFormatConstructor.cpp @@ -337,8 +337,8 @@ ThrowCompletionOr> create_date_time_format(VM& vm, Funct // d. Let styles be resolvedLocaleData.[[styles]].[[]]. // e. Let bestFormat be DateTimeStyleFormat(dateStyle, timeStyle, styles). formatter = Unicode::DateTimeFormat::create_for_date_and_time_style( - date_time_format->icu_locale().utf16_view().bytes(), - icu_time_zone.utf16_view().bytes(), + date_time_format->icu_locale().utf16_view(), + icu_time_zone.utf16_view(), format_options.hour_cycle, format_options.hour12, date_time_format->date_style(), @@ -425,8 +425,8 @@ ThrowCompletionOr> create_date_time_format(VM& vm, Funct } formatter = Unicode::DateTimeFormat::create_for_pattern_options( - date_time_format->icu_locale().utf16_view().bytes(), - icu_time_zone.utf16_view().bytes(), + date_time_format->icu_locale().utf16_view(), + icu_time_zone.utf16_view(), best_format); } diff --git a/Libraries/LibJS/Runtime/Intl/DisplayNamesPrototype.cpp b/Libraries/LibJS/Runtime/Intl/DisplayNamesPrototype.cpp index ac56f78bdb..fc1a68ea57 100644 --- a/Libraries/LibJS/Runtime/Intl/DisplayNamesPrototype.cpp +++ b/Libraries/LibJS/Runtime/Intl/DisplayNamesPrototype.cpp @@ -79,6 +79,12 @@ JS_DEFINE_NATIVE_FUNCTION(DisplayNamesPrototype::of) // 4. Let code be ? CanonicalCodeForDisplayNames(displayNames.[[Type]], code). code = TRY(canonical_code_for_display_names(vm, display_names->type(), code.as_string().utf16_string_view())); auto code_view = code.as_string().utf16_string_view(); + VERIFY(code_view.is_ascii()); + auto code_string = MUST(code_view.to_byte_string()); + + auto locale_view = display_names->icu_locale().utf16_view(); + VERIFY(locale_view.is_ascii()); + auto locale_string = MUST(locale_view.to_byte_string()); // 5. Let fields be displayNames.[[Fields]]. // 6. If fields has a field [[]], return fields.[[]]. @@ -86,22 +92,22 @@ JS_DEFINE_NATIVE_FUNCTION(DisplayNamesPrototype::of) switch (display_names->type()) { case DisplayNames::Type::Language: - result = Unicode::language_display_name(display_names->icu_locale().utf16_view().bytes(), code_view, display_names->language_display()); + result = Unicode::language_display_name(locale_string.view(), code_string.view(), display_names->language_display()); break; case DisplayNames::Type::Region: - result = Unicode::region_display_name(display_names->icu_locale().utf16_view().bytes(), code_view); + result = Unicode::region_display_name(locale_string.view(), code_string.view()); break; case DisplayNames::Type::Script: - result = Unicode::script_display_name(display_names->icu_locale().utf16_view().bytes(), code_view); + result = Unicode::script_display_name(locale_string.view(), code_string.view()); break; case DisplayNames::Type::Currency: - result = Unicode::currency_display_name(display_names->icu_locale().utf16_view().bytes(), code_view, display_names->style()); + result = Unicode::currency_display_name(locale_string.view(), code_string.view(), display_names->style()); break; case DisplayNames::Type::Calendar: - result = Unicode::calendar_display_name(display_names->icu_locale().utf16_view().bytes(), code_view); + result = Unicode::calendar_display_name(locale_string.view(), code_string.view()); break; case DisplayNames::Type::DateTimeField: - result = Unicode::date_time_field_display_name(display_names->icu_locale().utf16_view().bytes(), code_view, display_names->style()); + result = Unicode::date_time_field_display_name(locale_string.view(), code_string.view(), display_names->style()); break; default: VERIFY_NOT_REACHED(); diff --git a/Libraries/LibJS/Runtime/Intl/ListFormatConstructor.cpp b/Libraries/LibJS/Runtime/Intl/ListFormatConstructor.cpp index 6fec1a0df3..141f19c6a0 100644 --- a/Libraries/LibJS/Runtime/Intl/ListFormatConstructor.cpp +++ b/Libraries/LibJS/Runtime/Intl/ListFormatConstructor.cpp @@ -78,7 +78,7 @@ ThrowCompletionOr> ListFormatConstructor::construct(FunctionObje // 12. Let dataLocaleTypes be resolvedLocaleData.[[]]. // 13. Set listFormat.[[Templates]] to dataLocaleTypes.[[