1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 13:18:13 +00:00

LibJS+Everywhere: Make PrimitiveString and Utf16String fallible

This makes construction of Utf16String fallible in OOM conditions. The
immediate impact is that PrimitiveString must then be fallible as well,
as it may either transcode UTF-8 to UTF-16, or create a UTF-16 string
from ropes.

There are a couple of places where it is very non-trivial to propagate
the error further. A FIXME has been added to those locations.
This commit is contained in:
Timothy Flynn 2023-01-07 12:24:05 -05:00 committed by Linus Groh
parent d793262beb
commit 115baa7e32
57 changed files with 306 additions and 295 deletions

View file

@ -62,14 +62,14 @@ TESTJS_GLOBAL_FUNCTION(mark_as_garbage, markAsGarbage)
return execution_context->lexical_environment != nullptr; return execution_context->lexical_environment != nullptr;
}); });
if (!outer_environment.has_value()) if (!outer_environment.has_value())
return vm.throw_completion<JS::ReferenceError>(JS::ErrorType::UnknownIdentifier, variable_name.deprecated_string()); return vm.throw_completion<JS::ReferenceError>(JS::ErrorType::UnknownIdentifier, TRY(variable_name.deprecated_string()));
auto reference = TRY(vm.resolve_binding(variable_name.deprecated_string(), outer_environment.value()->lexical_environment)); auto reference = TRY(vm.resolve_binding(TRY(variable_name.deprecated_string()), outer_environment.value()->lexical_environment));
auto value = TRY(reference.get_value(vm)); auto value = TRY(reference.get_value(vm));
if (!can_be_held_weakly(value)) if (!can_be_held_weakly(value))
return vm.throw_completion<JS::TypeError>(JS::ErrorType::CannotBeHeldWeakly, DeprecatedString::formatted("Variable with name {}", variable_name.deprecated_string())); return vm.throw_completion<JS::TypeError>(JS::ErrorType::CannotBeHeldWeakly, DeprecatedString::formatted("Variable with name {}", TRY(variable_name.deprecated_string())));
vm.heap().uproot_cell(&value.as_cell()); vm.heap().uproot_cell(&value.as_cell());
TRY(reference.delete_(vm)); TRY(reference.delete_(vm));

View file

@ -196,7 +196,7 @@ JS_DEFINE_NATIVE_FUNCTION(SheetGlobalObject::get_real_cell_contents)
auto name_value = vm.argument(0); auto name_value = vm.argument(0);
if (!name_value.is_string()) if (!name_value.is_string())
return vm.throw_completion<JS::TypeError>("Expected a String argument to get_real_cell_contents()"); return vm.throw_completion<JS::TypeError>("Expected a String argument to get_real_cell_contents()");
auto position = sheet_object->m_sheet.parse_cell_name(name_value.as_string().deprecated_string()); auto position = sheet_object->m_sheet.parse_cell_name(TRY(name_value.as_string().deprecated_string()));
if (!position.has_value()) if (!position.has_value())
return vm.throw_completion<JS::TypeError>("Invalid cell name"); return vm.throw_completion<JS::TypeError>("Invalid cell name");
@ -225,7 +225,7 @@ JS_DEFINE_NATIVE_FUNCTION(SheetGlobalObject::set_real_cell_contents)
auto name_value = vm.argument(0); auto name_value = vm.argument(0);
if (!name_value.is_string()) if (!name_value.is_string())
return vm.throw_completion<JS::TypeError>("Expected the first argument of set_real_cell_contents() to be a String"); return vm.throw_completion<JS::TypeError>("Expected the first argument of set_real_cell_contents() to be a String");
auto position = sheet_object->m_sheet.parse_cell_name(name_value.as_string().deprecated_string()); auto position = sheet_object->m_sheet.parse_cell_name(TRY(name_value.as_string().deprecated_string()));
if (!position.has_value()) if (!position.has_value())
return vm.throw_completion<JS::TypeError>("Invalid cell name"); return vm.throw_completion<JS::TypeError>("Invalid cell name");
@ -234,7 +234,7 @@ JS_DEFINE_NATIVE_FUNCTION(SheetGlobalObject::set_real_cell_contents)
return vm.throw_completion<JS::TypeError>("Expected the second argument of set_real_cell_contents() to be a String"); return vm.throw_completion<JS::TypeError>("Expected the second argument of set_real_cell_contents() to be a String");
auto& cell = sheet_object->m_sheet.ensure(position.value()); auto& cell = sheet_object->m_sheet.ensure(position.value());
auto& new_contents = new_contents_value.as_string().deprecated_string(); auto const& new_contents = TRY(new_contents_value.as_string().deprecated_string());
cell.set_data(new_contents); cell.set_data(new_contents);
return JS::js_null(); return JS::js_null();
} }
@ -255,7 +255,7 @@ JS_DEFINE_NATIVE_FUNCTION(SheetGlobalObject::parse_cell_name)
auto name_value = vm.argument(0); auto name_value = vm.argument(0);
if (!name_value.is_string()) if (!name_value.is_string())
return vm.throw_completion<JS::TypeError>("Expected a String argument to parse_cell_name()"); return vm.throw_completion<JS::TypeError>("Expected a String argument to parse_cell_name()");
auto position = sheet_object->m_sheet.parse_cell_name(name_value.as_string().deprecated_string()); auto position = sheet_object->m_sheet.parse_cell_name(TRY(name_value.as_string().deprecated_string()));
if (!position.has_value()) if (!position.has_value())
return JS::js_undefined(); return JS::js_undefined();
@ -301,7 +301,7 @@ JS_DEFINE_NATIVE_FUNCTION(SheetGlobalObject::column_index)
if (!column_name.is_string()) if (!column_name.is_string())
return vm.throw_completion<JS::TypeError>(JS::ErrorType::NotAnObjectOfType, "String"); return vm.throw_completion<JS::TypeError>(JS::ErrorType::NotAnObjectOfType, "String");
auto& column_name_str = column_name.as_string().deprecated_string(); auto const& column_name_str = TRY(column_name.as_string().deprecated_string());
auto* this_object = TRY(vm.this_value().to_object(vm)); auto* this_object = TRY(vm.this_value().to_object(vm));
@ -326,7 +326,7 @@ JS_DEFINE_NATIVE_FUNCTION(SheetGlobalObject::column_arithmetic)
if (!column_name.is_string()) if (!column_name.is_string())
return vm.throw_completion<JS::TypeError>(JS::ErrorType::NotAnObjectOfType, "String"); return vm.throw_completion<JS::TypeError>(JS::ErrorType::NotAnObjectOfType, "String");
auto& column_name_str = column_name.as_string().deprecated_string(); auto const& column_name_str = TRY(column_name.as_string().deprecated_string());
auto offset = TRY(vm.argument(1).to_number(vm)); auto offset = TRY(vm.argument(1).to_number(vm));
auto offset_number = static_cast<i32>(offset.as_double()); auto offset_number = static_cast<i32>(offset.as_double());
@ -354,7 +354,7 @@ JS_DEFINE_NATIVE_FUNCTION(SheetGlobalObject::get_column_bound)
if (!column_name.is_string()) if (!column_name.is_string())
return vm.throw_completion<JS::TypeError>(JS::ErrorType::NotAnObjectOfType, "String"); return vm.throw_completion<JS::TypeError>(JS::ErrorType::NotAnObjectOfType, "String");
auto& column_name_str = column_name.as_string().deprecated_string(); auto const& column_name_str = TRY(column_name.as_string().deprecated_string());
auto* this_object = TRY(vm.this_value().to_object(vm)); auto* this_object = TRY(vm.this_value().to_object(vm));
if (!is<SheetGlobalObject>(this_object)) if (!is<SheetGlobalObject>(this_object))
@ -405,7 +405,7 @@ JS_DEFINE_NATIVE_FUNCTION(WorkbookObject::sheet)
auto& workbook = static_cast<WorkbookObject*>(this_object)->m_workbook; auto& workbook = static_cast<WorkbookObject*>(this_object)->m_workbook;
if (name_value.is_string()) { if (name_value.is_string()) {
auto& name = name_value.as_string().deprecated_string(); auto const& name = TRY(name_value.as_string().deprecated_string());
for (auto& sheet : workbook.sheets()) { for (auto& sheet : workbook.sheets()) {
if (sheet.name() == name) if (sheet.name() == name)
return JS::Value(&sheet.global_object()); return JS::Value(&sheet.global_object());

View file

@ -3446,7 +3446,7 @@ Completion ImportCall::execute(Interpreter& interpreter) const
// 4. If supportedAssertions contains key, then // 4. If supportedAssertions contains key, then
if (supported_assertions.contains_slow(property_key.to_string())) { if (supported_assertions.contains_slow(property_key.to_string())) {
// a. Append { [[Key]]: key, [[Value]]: value } to assertions. // a. Append { [[Key]]: key, [[Value]]: value } to assertions.
assertions.empend(property_key.to_string(), value.as_string().deprecated_string()); assertions.empend(property_key.to_string(), TRY(value.as_string().deprecated_string()));
} }
} }
} }

View file

@ -212,7 +212,7 @@ ThrowCompletionOr<Value> Console::assert_()
// 3. Otherwise: // 3. Otherwise:
else { else {
// 1. Let concat be the concatenation of message, U+003A (:), U+0020 SPACE, and first. // 1. Let concat be the concatenation of message, U+003A (:), U+0020 SPACE, and first.
auto concat = PrimitiveString::create(vm, DeprecatedString::formatted("{}: {}", message->deprecated_string(), first.to_string(vm).value())); auto concat = PrimitiveString::create(vm, DeprecatedString::formatted("{}: {}", TRY(message->deprecated_string()), first.to_string(vm).value()));
// 2. Set data[0] to concat. // 2. Set data[0] to concat.
data[0] = concat; data[0] = concat;
} }

View file

@ -20,7 +20,7 @@ ThrowCompletionOr<Value> IsHTMLDDA::call()
auto& vm = this->vm(); auto& vm = this->vm();
if (vm.argument_count() == 0) if (vm.argument_count() == 0)
return js_null(); return js_null();
if (vm.argument(0).is_string() && vm.argument(0).as_string().deprecated_string().is_empty()) if (vm.argument(0).is_string() && TRY(vm.argument(0).as_string().deprecated_string()).is_empty())
return js_null(); return js_null();
// Not sure if this really matters, INTERPRETING.md simply says: // Not sure if this really matters, INTERPRETING.md simply says:
// * IsHTMLDDA - (present only in implementations that can provide it) an object that: // * IsHTMLDDA - (present only in implementations that can provide it) an object that:

View file

@ -777,9 +777,13 @@ ErrorOr<void> print_intl_segmenter(JS::PrintContext& print_context, JS::Intl::Se
ErrorOr<void> print_intl_segments(JS::PrintContext& print_context, JS::Intl::Segments const& segments, HashTable<JS::Object*>& seen_objects) ErrorOr<void> print_intl_segments(JS::PrintContext& print_context, JS::Intl::Segments const& segments, HashTable<JS::Object*>& seen_objects)
{ {
auto segments_string = JS::Utf16String::create(segments.vm(), segments.segments_string());
if (segments_string.is_error())
return Error::from_errno(ENOMEM);
TRY(print_type(print_context, "Segments")); TRY(print_type(print_context, "Segments"));
out("\n string: "); out("\n string: ");
TRY(print_value(print_context, JS::PrimitiveString::create(segments.vm(), segments.segments_string()), seen_objects)); TRY(print_value(print_context, JS::PrimitiveString::create(segments.vm(), segments_string.release_value()), seen_objects));
out("\n segmenter: "); out("\n segmenter: ");
TRY(print_value(print_context, &segments.segments_segmenter(), seen_objects)); TRY(print_value(print_context, &segments.segments_segmenter(), seen_objects));
return {}; return {};

View file

@ -594,7 +594,7 @@ ThrowCompletionOr<Value> perform_eval(VM& vm, Value x, CallerMode strict_caller,
.in_class_field_initializer = in_class_field_initializer, .in_class_field_initializer = in_class_field_initializer,
}; };
Parser parser { Lexer { code_string.deprecated_string() }, Program::Type::Script, move(initial_state) }; Parser parser { Lexer { TRY(code_string.deprecated_string()) }, Program::Type::Script, move(initial_state) };
auto program = parser.parse_program(strict_caller == CallerMode::Strict); auto program = parser.parse_program(strict_caller == CallerMode::Strict);
// b. If script is a List of errors, throw a SyntaxError exception. // b. If script is a List of errors, throw a SyntaxError exception.

View file

@ -241,7 +241,7 @@ ThrowCompletionOr<NonnullGCPtr<Object>> DateConstructor::construct(FunctionObjec
if (primitive.is_string()) { if (primitive.is_string()) {
// 1. Assert: The next step never returns an abrupt completion because Type(v) is String. // 1. Assert: The next step never returns an abrupt completion because Type(v) is String.
// 2. Let tv be the result of parsing v as a date, in exactly the same manner as for the parse method (21.4.3.2). // 2. Let tv be the result of parsing v as a date, in exactly the same manner as for the parse method (21.4.3.2).
time_value = parse_date_string(primitive.as_string().deprecated_string()); time_value = parse_date_string(TRY(primitive.as_string().deprecated_string()));
} }
// iii. Else, // iii. Else,
else { else {

View file

@ -1257,7 +1257,7 @@ JS_DEFINE_NATIVE_FUNCTION(DatePrototype::symbol_to_primitive)
auto hint_value = vm.argument(0); auto hint_value = vm.argument(0);
if (!hint_value.is_string()) if (!hint_value.is_string())
return vm.throw_completion<TypeError>(ErrorType::InvalidHint, hint_value.to_string_without_side_effects()); return vm.throw_completion<TypeError>(ErrorType::InvalidHint, hint_value.to_string_without_side_effects());
auto& hint = hint_value.as_string().deprecated_string(); auto const& hint = TRY(hint_value.as_string().deprecated_string());
Value::PreferredType try_first; Value::PreferredType try_first;
if (hint == "string" || hint == "default") if (hint == "string" || hint == "default")
try_first = Value::PreferredType::String; try_first = Value::PreferredType::String;

View file

@ -343,7 +343,7 @@ JS_DEFINE_NATIVE_FUNCTION(GlobalObject::eval)
// 19.2.6.1.1 Encode ( string, unescapedSet ), https://tc39.es/ecma262/#sec-encode // 19.2.6.1.1 Encode ( string, unescapedSet ), https://tc39.es/ecma262/#sec-encode
static ThrowCompletionOr<DeprecatedString> encode(VM& vm, DeprecatedString const& string, StringView unescaped_set) static ThrowCompletionOr<DeprecatedString> encode(VM& vm, DeprecatedString const& string, StringView unescaped_set)
{ {
auto utf16_string = Utf16String(string); auto utf16_string = TRY(Utf16String::create(vm, string));
// 1. Let strLen be the length of string. // 1. Let strLen be the length of string.
auto string_length = utf16_string.length_in_code_units(); auto string_length = utf16_string.length_in_code_units();

View file

@ -376,14 +376,14 @@ static auto& find_key_in_value(T& value, StringView key)
} }
// 9.2.7 ResolveLocale ( availableLocales, requestedLocales, options, relevantExtensionKeys, localeData ), https://tc39.es/ecma402/#sec-resolvelocale // 9.2.7 ResolveLocale ( availableLocales, requestedLocales, options, relevantExtensionKeys, localeData ), https://tc39.es/ecma402/#sec-resolvelocale
LocaleResult resolve_locale(Vector<DeprecatedString> const& requested_locales, LocaleOptions const& options, Span<StringView const> relevant_extension_keys) ThrowCompletionOr<LocaleResult> resolve_locale(Vector<DeprecatedString> const& requested_locales, LocaleOptions const& options, Span<StringView const> relevant_extension_keys)
{ {
// 1. Let matcher be options.[[localeMatcher]]. // 1. Let matcher be options.[[localeMatcher]].
auto const& matcher = options.locale_matcher; auto const& matcher = options.locale_matcher;
MatcherResult matcher_result; MatcherResult matcher_result;
// 2. If matcher is "lookup", then // 2. If matcher is "lookup", then
if (matcher.is_string() && (matcher.as_string().deprecated_string() == "lookup"sv)) { if (matcher.is_string() && (TRY(matcher.as_string().deprecated_string()) == "lookup"sv)) {
// a. Let r be ! LookupMatcher(availableLocales, requestedLocales). // a. Let r be ! LookupMatcher(availableLocales, requestedLocales).
matcher_result = lookup_matcher(requested_locales); matcher_result = lookup_matcher(requested_locales);
} }
@ -578,7 +578,7 @@ ThrowCompletionOr<Array*> supported_locales(VM& vm, Vector<DeprecatedString> con
Vector<DeprecatedString> supported_locales; Vector<DeprecatedString> supported_locales;
// 3. If matcher is "best fit", then // 3. If matcher is "best fit", then
if (matcher.as_string().deprecated_string() == "best fit"sv) { if (TRY(matcher.as_string().deprecated_string()) == "best fit"sv) {
// a. Let supportedLocales be BestFitSupportedLocales(availableLocales, requestedLocales). // a. Let supportedLocales be BestFitSupportedLocales(availableLocales, requestedLocales).
supported_locales = best_fit_supported_locales(requested_locales); supported_locales = best_fit_supported_locales(requested_locales);
} }

View file

@ -86,7 +86,7 @@ bool is_well_formed_unit_identifier(StringView unit_identifier);
ThrowCompletionOr<Vector<DeprecatedString>> canonicalize_locale_list(VM&, Value locales); ThrowCompletionOr<Vector<DeprecatedString>> canonicalize_locale_list(VM&, Value locales);
Optional<DeprecatedString> best_available_locale(StringView locale); Optional<DeprecatedString> best_available_locale(StringView locale);
DeprecatedString insert_unicode_extension_and_canonicalize(::Locale::LocaleID locale_id, ::Locale::LocaleExtension extension); DeprecatedString insert_unicode_extension_and_canonicalize(::Locale::LocaleID locale_id, ::Locale::LocaleExtension extension);
LocaleResult resolve_locale(Vector<DeprecatedString> const& requested_locales, LocaleOptions const& options, Span<StringView const> relevant_extension_keys); ThrowCompletionOr<LocaleResult> resolve_locale(Vector<DeprecatedString> const& requested_locales, LocaleOptions const& options, Span<StringView const> relevant_extension_keys);
Vector<DeprecatedString> lookup_supported_locales(Vector<DeprecatedString> const& requested_locales); Vector<DeprecatedString> lookup_supported_locales(Vector<DeprecatedString> const& requested_locales);
Vector<DeprecatedString> best_fit_supported_locales(Vector<DeprecatedString> const& requested_locales); Vector<DeprecatedString> best_fit_supported_locales(Vector<DeprecatedString> const& requested_locales);
ThrowCompletionOr<Array*> supported_locales(VM&, Vector<DeprecatedString> const& requested_locales, Value options); ThrowCompletionOr<Array*> supported_locales(VM&, Vector<DeprecatedString> const& requested_locales, Value options);

View file

@ -27,7 +27,7 @@ static ThrowCompletionOr<Collator*> initialize_collator(VM& vm, Collator& collat
auto usage = TRY(get_option(vm, *options, vm.names.usage, OptionType::String, { "sort"sv, "search"sv }, "sort"sv)); auto usage = TRY(get_option(vm, *options, vm.names.usage, OptionType::String, { "sort"sv, "search"sv }, "sort"sv));
// 4. Set collator.[[Usage]] to usage. // 4. Set collator.[[Usage]] to usage.
collator.set_usage(usage.as_string().deprecated_string()); collator.set_usage(TRY(usage.as_string().deprecated_string()));
// 5. If usage is "sort", then // 5. If usage is "sort", then
// a. Let localeData be %Collator%.[[SortLocaleData]]. // a. Let localeData be %Collator%.[[SortLocaleData]].
@ -49,11 +49,11 @@ static ThrowCompletionOr<Collator*> initialize_collator(VM& vm, Collator& collat
// 11. If collation is not undefined, then // 11. If collation is not undefined, then
if (!collation.is_undefined()) { if (!collation.is_undefined()) {
// a. If collation does not match the Unicode Locale Identifier type nonterminal, throw a RangeError exception. // a. If collation does not match the Unicode Locale Identifier type nonterminal, throw a RangeError exception.
if (!::Locale::is_type_identifier(collation.as_string().deprecated_string())) if (!::Locale::is_type_identifier(TRY(collation.as_string().deprecated_string())))
return vm.throw_completion<RangeError>(ErrorType::OptionIsNotValidValue, collation, "collation"sv); return vm.throw_completion<RangeError>(ErrorType::OptionIsNotValidValue, collation, "collation"sv);
// 12. Set opt.[[co]] to collation. // 12. Set opt.[[co]] to collation.
opt.co = collation.as_string().deprecated_string(); opt.co = TRY(collation.as_string().deprecated_string());
} }
// 13. Let numeric be ? GetOption(options, "numeric", "boolean", undefined, undefined). // 13. Let numeric be ? GetOption(options, "numeric", "boolean", undefined, undefined).
@ -69,13 +69,13 @@ static ThrowCompletionOr<Collator*> initialize_collator(VM& vm, Collator& collat
// 17. Set opt.[[kf]] to caseFirst. // 17. Set opt.[[kf]] to caseFirst.
auto case_first = TRY(get_option(vm, *options, vm.names.caseFirst, OptionType::String, { "upper"sv, "lower"sv, "false"sv }, Empty {})); auto case_first = TRY(get_option(vm, *options, vm.names.caseFirst, OptionType::String, { "upper"sv, "lower"sv, "false"sv }, Empty {}));
if (!case_first.is_undefined()) if (!case_first.is_undefined())
opt.kf = case_first.as_string().deprecated_string(); opt.kf = TRY(case_first.as_string().deprecated_string());
// 18. Let relevantExtensionKeys be %Collator%.[[RelevantExtensionKeys]]. // 18. Let relevantExtensionKeys be %Collator%.[[RelevantExtensionKeys]].
auto relevant_extension_keys = Collator::relevant_extension_keys(); auto relevant_extension_keys = Collator::relevant_extension_keys();
// 19. Let r be ResolveLocale(%Collator%.[[AvailableLocales]], requestedLocales, opt, relevantExtensionKeys, localeData). // 19. Let r be ResolveLocale(%Collator%.[[AvailableLocales]], requestedLocales, opt, relevantExtensionKeys, localeData).
auto result = resolve_locale(requested_locales, opt, relevant_extension_keys); auto result = TRY(resolve_locale(requested_locales, opt, relevant_extension_keys));
// 20. Set collator.[[Locale]] to r.[[locale]]. // 20. Set collator.[[Locale]] to r.[[locale]].
collator.set_locale(move(result.locale)); collator.set_locale(move(result.locale));
@ -117,7 +117,7 @@ static ThrowCompletionOr<Collator*> initialize_collator(VM& vm, Collator& collat
} }
// 28. Set collator.[[Sensitivity]] to sensitivity. // 28. Set collator.[[Sensitivity]] to sensitivity.
collator.set_sensitivity(sensitivity.as_string().deprecated_string()); collator.set_sensitivity(TRY(sensitivity.as_string().deprecated_string()));
// 29. Let ignorePunctuation be ? GetOption(options, "ignorePunctuation", "boolean", undefined, false). // 29. Let ignorePunctuation be ? GetOption(options, "ignorePunctuation", "boolean", undefined, false).
auto ignore_punctuation = TRY(get_option(vm, *options, vm.names.ignorePunctuation, OptionType::Boolean, {}, false)); auto ignore_punctuation = TRY(get_option(vm, *options, vm.names.ignorePunctuation, OptionType::Boolean, {}, false));

View file

@ -716,7 +716,7 @@ ThrowCompletionOr<Vector<PatternPartition>> format_date_time_pattern(VM& vm, Dat
// 2. If the "length" property of fv is greater than 2, let fv be the substring of fv containing the last two characters. // 2. If the "length" property of fv is greater than 2, let fv be the substring of fv containing the last two characters.
// NOTE: The first length check here isn't enough, but lets us avoid UTF-16 transcoding when the formatted value is ASCII. // NOTE: The first length check here isn't enough, but lets us avoid UTF-16 transcoding when the formatted value is ASCII.
if (formatted_value.length() > 2) { if (formatted_value.length() > 2) {
Utf16String utf16_formatted_value { formatted_value }; auto utf16_formatted_value = TRY(Utf16String::create(vm, formatted_value));
if (utf16_formatted_value.length_in_code_units() > 2) if (utf16_formatted_value.length_in_code_units() > 2)
formatted_value = TRY_OR_THROW_OOM(vm, utf16_formatted_value.substring_view(utf16_formatted_value.length_in_code_units() - 2).to_utf8()); formatted_value = TRY_OR_THROW_OOM(vm, utf16_formatted_value.substring_view(utf16_formatted_value.length_in_code_units() - 2).to_utf8());
} }

View file

@ -106,11 +106,11 @@ ThrowCompletionOr<DateTimeFormat*> initialize_date_time_format(VM& vm, DateTimeF
// 7. If calendar is not undefined, then // 7. If calendar is not undefined, then
if (!calendar.is_undefined()) { if (!calendar.is_undefined()) {
// a. If calendar does not match the Unicode Locale Identifier type nonterminal, throw a RangeError exception. // a. If calendar does not match the Unicode Locale Identifier type nonterminal, throw a RangeError exception.
if (!::Locale::is_type_identifier(calendar.as_string().deprecated_string())) if (!::Locale::is_type_identifier(TRY(calendar.as_string().deprecated_string())))
return vm.throw_completion<RangeError>(ErrorType::OptionIsNotValidValue, calendar, "calendar"sv); return vm.throw_completion<RangeError>(ErrorType::OptionIsNotValidValue, calendar, "calendar"sv);
// 8. Set opt.[[ca]] to calendar. // 8. Set opt.[[ca]] to calendar.
opt.ca = calendar.as_string().deprecated_string(); opt.ca = TRY(calendar.as_string().deprecated_string());
} }
// 9. Let numberingSystem be ? GetOption(options, "numberingSystem", "string", undefined, undefined). // 9. Let numberingSystem be ? GetOption(options, "numberingSystem", "string", undefined, undefined).
@ -119,11 +119,11 @@ ThrowCompletionOr<DateTimeFormat*> initialize_date_time_format(VM& vm, DateTimeF
// 10. If numberingSystem is not undefined, then // 10. If numberingSystem is not undefined, then
if (!numbering_system.is_undefined()) { if (!numbering_system.is_undefined()) {
// a. If numberingSystem does not match the Unicode Locale Identifier type nonterminal, throw a RangeError exception. // a. If numberingSystem does not match the Unicode Locale Identifier type nonterminal, throw a RangeError exception.
if (!::Locale::is_type_identifier(numbering_system.as_string().deprecated_string())) if (!::Locale::is_type_identifier(TRY(numbering_system.as_string().deprecated_string())))
return vm.throw_completion<RangeError>(ErrorType::OptionIsNotValidValue, numbering_system, "numberingSystem"sv); return vm.throw_completion<RangeError>(ErrorType::OptionIsNotValidValue, numbering_system, "numberingSystem"sv);
// 11. Set opt.[[nu]] to numberingSystem. // 11. Set opt.[[nu]] to numberingSystem.
opt.nu = numbering_system.as_string().deprecated_string(); opt.nu = TRY(numbering_system.as_string().deprecated_string());
} }
// 12. Let hour12 be ? GetOption(options, "hour12", "boolean", undefined, undefined). // 12. Let hour12 be ? GetOption(options, "hour12", "boolean", undefined, undefined).
@ -140,11 +140,11 @@ ThrowCompletionOr<DateTimeFormat*> initialize_date_time_format(VM& vm, DateTimeF
// 15. Set opt.[[hc]] to hourCycle. // 15. Set opt.[[hc]] to hourCycle.
if (!hour_cycle.is_nullish()) if (!hour_cycle.is_nullish())
opt.hc = hour_cycle.as_string().deprecated_string(); opt.hc = TRY(hour_cycle.as_string().deprecated_string());
// 16. Let localeData be %DateTimeFormat%.[[LocaleData]]. // 16. Let localeData be %DateTimeFormat%.[[LocaleData]].
// 17. Let r be ResolveLocale(%DateTimeFormat%.[[AvailableLocales]], requestedLocales, opt, %DateTimeFormat%.[[RelevantExtensionKeys]], localeData). // 17. Let r be ResolveLocale(%DateTimeFormat%.[[AvailableLocales]], requestedLocales, opt, %DateTimeFormat%.[[RelevantExtensionKeys]], localeData).
auto result = resolve_locale(requested_locales, opt, DateTimeFormat::relevant_extension_keys()); auto result = TRY(resolve_locale(requested_locales, opt, DateTimeFormat::relevant_extension_keys()));
// 18. Set dateTimeFormat.[[Locale]] to r.[[locale]]. // 18. Set dateTimeFormat.[[Locale]] to r.[[locale]].
date_time_format.set_locale(move(result.locale)); date_time_format.set_locale(move(result.locale));
@ -277,7 +277,7 @@ ThrowCompletionOr<DateTimeFormat*> initialize_date_time_format(VM& vm, DateTimeF
// d. Set formatOptions.[[<prop>]] to value. // d. Set formatOptions.[[<prop>]] to value.
if (!value.is_undefined()) { if (!value.is_undefined()) {
option = ::Locale::calendar_pattern_style_from_string(value.as_string().deprecated_string()); option = ::Locale::calendar_pattern_style_from_string(TRY(value.as_string().deprecated_string()));
// e. If value is not undefined, then // e. If value is not undefined, then
// i. Set hasExplicitFormatComponents to true. // i. Set hasExplicitFormatComponents to true.
@ -296,14 +296,14 @@ ThrowCompletionOr<DateTimeFormat*> initialize_date_time_format(VM& vm, DateTimeF
// 39. Set dateTimeFormat.[[DateStyle]] to dateStyle. // 39. Set dateTimeFormat.[[DateStyle]] to dateStyle.
if (!date_style.is_undefined()) if (!date_style.is_undefined())
date_time_format.set_date_style(date_style.as_string().deprecated_string()); date_time_format.set_date_style(TRY(date_style.as_string().deprecated_string()));
// 40. Let timeStyle be ? GetOption(options, "timeStyle", "string", « "full", "long", "medium", "short" », undefined). // 40. Let timeStyle be ? GetOption(options, "timeStyle", "string", « "full", "long", "medium", "short" », undefined).
auto time_style = TRY(get_option(vm, *options, vm.names.timeStyle, OptionType::String, AK::Array { "full"sv, "long"sv, "medium"sv, "short"sv }, Empty {})); auto time_style = TRY(get_option(vm, *options, vm.names.timeStyle, OptionType::String, AK::Array { "full"sv, "long"sv, "medium"sv, "short"sv }, Empty {}));
// 41. Set dateTimeFormat.[[TimeStyle]] to timeStyle. // 41. Set dateTimeFormat.[[TimeStyle]] to timeStyle.
if (!time_style.is_undefined()) if (!time_style.is_undefined())
date_time_format.set_time_style(time_style.as_string().deprecated_string()); date_time_format.set_time_style(TRY(time_style.as_string().deprecated_string()));
Optional<::Locale::CalendarPattern> best_format {}; Optional<::Locale::CalendarPattern> best_format {};
@ -325,7 +325,7 @@ ThrowCompletionOr<DateTimeFormat*> initialize_date_time_format(VM& vm, DateTimeF
auto formats = ::Locale::get_calendar_available_formats(data_locale, date_time_format.calendar()); auto formats = ::Locale::get_calendar_available_formats(data_locale, date_time_format.calendar());
// b. If matcher is "basic", then // b. If matcher is "basic", then
if (matcher.as_string().deprecated_string() == "basic"sv) { if (TRY(matcher.as_string().deprecated_string()) == "basic"sv) {
// i. Let bestFormat be BasicFormatMatcher(formatOptions, formats). // i. Let bestFormat be BasicFormatMatcher(formatOptions, formats).
best_format = basic_format_matcher(format_options, move(formats)); best_format = basic_format_matcher(format_options, move(formats));
} }

View file

@ -76,13 +76,13 @@ ThrowCompletionOr<NonnullGCPtr<Object>> DisplayNamesConstructor::construct(Funct
opt.locale_matcher = matcher; opt.locale_matcher = matcher;
// 10. Let r be ResolveLocale(%DisplayNames%.[[AvailableLocales]], requestedLocales, opt, %DisplayNames%.[[RelevantExtensionKeys]]). // 10. Let r be ResolveLocale(%DisplayNames%.[[AvailableLocales]], requestedLocales, opt, %DisplayNames%.[[RelevantExtensionKeys]]).
auto result = resolve_locale(requested_locales, opt, {}); auto result = TRY(resolve_locale(requested_locales, opt, {}));
// 11. Let style be ? GetOption(options, "style", "string", « "narrow", "short", "long" », "long"). // 11. Let style be ? GetOption(options, "style", "string", « "narrow", "short", "long" », "long").
auto style = TRY(get_option(vm, *options, vm.names.style, OptionType::String, { "narrow"sv, "short"sv, "long"sv }, "long"sv)); auto style = TRY(get_option(vm, *options, vm.names.style, OptionType::String, { "narrow"sv, "short"sv, "long"sv }, "long"sv));
// 12. Set displayNames.[[Style]] to style. // 12. Set displayNames.[[Style]] to style.
display_names->set_style(style.as_string().deprecated_string()); display_names->set_style(TRY(style.as_string().deprecated_string()));
// 13. Let type be ? GetOption(options, "type", "string", « "language", "region", "script", "currency", "calendar", "dateTimeField" », undefined). // 13. Let type be ? GetOption(options, "type", "string", « "language", "region", "script", "currency", "calendar", "dateTimeField" », undefined).
auto type = TRY(get_option(vm, *options, vm.names.type, OptionType::String, { "language"sv, "region"sv, "script"sv, "currency"sv, "calendar"sv, "dateTimeField"sv }, Empty {})); auto type = TRY(get_option(vm, *options, vm.names.type, OptionType::String, { "language"sv, "region"sv, "script"sv, "currency"sv, "calendar"sv, "dateTimeField"sv }, Empty {}));
@ -92,13 +92,13 @@ ThrowCompletionOr<NonnullGCPtr<Object>> DisplayNamesConstructor::construct(Funct
return vm.throw_completion<TypeError>(ErrorType::IsUndefined, "options.type"sv); return vm.throw_completion<TypeError>(ErrorType::IsUndefined, "options.type"sv);
// 15. Set displayNames.[[Type]] to type. // 15. Set displayNames.[[Type]] to type.
display_names->set_type(type.as_string().deprecated_string()); display_names->set_type(TRY(type.as_string().deprecated_string()));
// 16. Let fallback be ? GetOption(options, "fallback", "string", « "code", "none" », "code"). // 16. Let fallback be ? GetOption(options, "fallback", "string", « "code", "none" », "code").
auto fallback = TRY(get_option(vm, *options, vm.names.fallback, OptionType::String, { "code"sv, "none"sv }, "code"sv)); auto fallback = TRY(get_option(vm, *options, vm.names.fallback, OptionType::String, { "code"sv, "none"sv }, "code"sv));
// 17. Set displayNames.[[Fallback]] to fallback. // 17. Set displayNames.[[Fallback]] to fallback.
display_names->set_fallback(fallback.as_string().deprecated_string()); display_names->set_fallback(TRY(fallback.as_string().deprecated_string()));
// 18. Set displayNames.[[Locale]] to r.[[locale]]. // 18. Set displayNames.[[Locale]] to r.[[locale]].
display_names->set_locale(move(result.locale)); display_names->set_locale(move(result.locale));
@ -119,7 +119,7 @@ ThrowCompletionOr<NonnullGCPtr<Object>> DisplayNamesConstructor::construct(Funct
// 26. If type is "language", then // 26. If type is "language", then
if (display_names->type() == DisplayNames::Type::Language) { if (display_names->type() == DisplayNames::Type::Language) {
// a. Set displayNames.[[LanguageDisplay]] to languageDisplay. // a. Set displayNames.[[LanguageDisplay]] to languageDisplay.
display_names->set_language_display(language_display.as_string().deprecated_string()); display_names->set_language_display(TRY(language_display.as_string().deprecated_string()));
// b. Let typeFields be typeFields.[[<languageDisplay>]]. // b. Let typeFields be typeFields.[[<languageDisplay>]].
// c. Assert: typeFields is a Record (see 12.4.3). // c. Assert: typeFields is a Record (see 12.4.3).

View file

@ -47,7 +47,7 @@ JS_DEFINE_NATIVE_FUNCTION(DisplayNamesPrototype::of)
code = PrimitiveString::create(vm, move(code_string)); code = PrimitiveString::create(vm, move(code_string));
// 4. Let code be ? CanonicalCodeForDisplayNames(displayNames.[[Type]], code). // 4. Let code be ? CanonicalCodeForDisplayNames(displayNames.[[Type]], code).
code = TRY(canonical_code_for_display_names(vm, display_names->type(), code.as_string().deprecated_string())); code = TRY(canonical_code_for_display_names(vm, display_names->type(), TRY(code.as_string().deprecated_string())));
// 5. Let fields be displayNames.[[Fields]]. // 5. Let fields be displayNames.[[Fields]].
// 6. If fields has a field [[<code>]], return fields.[[<code>]]. // 6. If fields has a field [[<code>]], return fields.[[<code>]].
@ -57,48 +57,48 @@ JS_DEFINE_NATIVE_FUNCTION(DisplayNamesPrototype::of)
switch (display_names->type()) { switch (display_names->type()) {
case DisplayNames::Type::Language: case DisplayNames::Type::Language:
if (display_names->language_display() == DisplayNames::LanguageDisplay::Dialect) { if (display_names->language_display() == DisplayNames::LanguageDisplay::Dialect) {
result = ::Locale::get_locale_language_mapping(display_names->locale(), code.as_string().deprecated_string()); result = ::Locale::get_locale_language_mapping(display_names->locale(), TRY(code.as_string().deprecated_string()));
if (result.has_value()) if (result.has_value())
break; break;
} }
if (auto locale = is_structurally_valid_language_tag(code.as_string().deprecated_string()); locale.has_value()) if (auto locale = is_structurally_valid_language_tag(TRY(code.as_string().deprecated_string())); locale.has_value())
formatted_result = ::Locale::format_locale_for_display(display_names->locale(), locale.release_value()); formatted_result = ::Locale::format_locale_for_display(display_names->locale(), locale.release_value());
break; break;
case DisplayNames::Type::Region: case DisplayNames::Type::Region:
result = ::Locale::get_locale_territory_mapping(display_names->locale(), code.as_string().deprecated_string()); result = ::Locale::get_locale_territory_mapping(display_names->locale(), TRY(code.as_string().deprecated_string()));
break; break;
case DisplayNames::Type::Script: case DisplayNames::Type::Script:
result = ::Locale::get_locale_script_mapping(display_names->locale(), code.as_string().deprecated_string()); result = ::Locale::get_locale_script_mapping(display_names->locale(), TRY(code.as_string().deprecated_string()));
break; break;
case DisplayNames::Type::Currency: case DisplayNames::Type::Currency:
switch (display_names->style()) { switch (display_names->style()) {
case ::Locale::Style::Long: case ::Locale::Style::Long:
result = ::Locale::get_locale_long_currency_mapping(display_names->locale(), code.as_string().deprecated_string()); result = ::Locale::get_locale_long_currency_mapping(display_names->locale(), TRY(code.as_string().deprecated_string()));
break; break;
case ::Locale::Style::Short: case ::Locale::Style::Short:
result = ::Locale::get_locale_short_currency_mapping(display_names->locale(), code.as_string().deprecated_string()); result = ::Locale::get_locale_short_currency_mapping(display_names->locale(), TRY(code.as_string().deprecated_string()));
break; break;
case ::Locale::Style::Narrow: case ::Locale::Style::Narrow:
result = ::Locale::get_locale_narrow_currency_mapping(display_names->locale(), code.as_string().deprecated_string()); result = ::Locale::get_locale_narrow_currency_mapping(display_names->locale(), TRY(code.as_string().deprecated_string()));
break; break;
default: default:
VERIFY_NOT_REACHED(); VERIFY_NOT_REACHED();
} }
break; break;
case DisplayNames::Type::Calendar: case DisplayNames::Type::Calendar:
result = ::Locale::get_locale_calendar_mapping(display_names->locale(), code.as_string().deprecated_string()); result = ::Locale::get_locale_calendar_mapping(display_names->locale(), TRY(code.as_string().deprecated_string()));
break; break;
case DisplayNames::Type::DateTimeField: case DisplayNames::Type::DateTimeField:
switch (display_names->style()) { switch (display_names->style()) {
case ::Locale::Style::Long: case ::Locale::Style::Long:
result = ::Locale::get_locale_long_date_field_mapping(display_names->locale(), code.as_string().deprecated_string()); result = ::Locale::get_locale_long_date_field_mapping(display_names->locale(), TRY(code.as_string().deprecated_string()));
break; break;
case ::Locale::Style::Short: case ::Locale::Style::Short:
result = ::Locale::get_locale_short_date_field_mapping(display_names->locale(), code.as_string().deprecated_string()); result = ::Locale::get_locale_short_date_field_mapping(display_names->locale(), TRY(code.as_string().deprecated_string()));
break; break;
case ::Locale::Style::Narrow: case ::Locale::Style::Narrow:
result = ::Locale::get_locale_narrow_date_field_mapping(display_names->locale(), code.as_string().deprecated_string()); result = ::Locale::get_locale_narrow_date_field_mapping(display_names->locale(), TRY(code.as_string().deprecated_string()));
break; break;
default: default:
VERIFY_NOT_REACHED(); VERIFY_NOT_REACHED();

View file

@ -308,7 +308,7 @@ ThrowCompletionOr<DurationUnitOptions> get_duration_unit_options(VM& vm, Depreca
} }
} }
} else { } else {
style = style_value.as_string().deprecated_string(); style = TRY(style_value.as_string().deprecated_string());
} }
// 4. Let displayField be the string-concatenation of unit and "Display". // 4. Let displayField be the string-concatenation of unit and "Display".
@ -332,7 +332,7 @@ ThrowCompletionOr<DurationUnitOptions> get_duration_unit_options(VM& vm, Depreca
} }
// 7. Return the Record { [[Style]]: style, [[Display]]: display }. // 7. Return the Record { [[Style]]: style, [[Display]]: display }.
return DurationUnitOptions { .style = move(style), .display = display.as_string().deprecated_string() }; return DurationUnitOptions { .style = move(style), .display = TRY(display.as_string().deprecated_string()) };
} }
// 1.1.7 PartitionDurationFormatPattern ( durationFormat, duration ), https://tc39.es/proposal-intl-duration-format/#sec-partitiondurationformatpattern // 1.1.7 PartitionDurationFormatPattern ( durationFormat, duration ), https://tc39.es/proposal-intl-duration-format/#sec-partitiondurationformatpattern

View file

@ -67,17 +67,17 @@ ThrowCompletionOr<NonnullGCPtr<Object>> DurationFormatConstructor::construct(Fun
// 7. If numberingSystem is not undefined, then // 7. If numberingSystem is not undefined, then
if (!numbering_system.is_undefined()) { if (!numbering_system.is_undefined()) {
// a. If numberingSystem does not match the Unicode Locale Identifier type nonterminal, throw a RangeError exception. // a. If numberingSystem does not match the Unicode Locale Identifier type nonterminal, throw a RangeError exception.
if (!::Locale::is_type_identifier(numbering_system.as_string().deprecated_string())) if (!::Locale::is_type_identifier(TRY(numbering_system.as_string().deprecated_string())))
return vm.throw_completion<RangeError>(ErrorType::OptionIsNotValidValue, numbering_system, "numberingSystem"sv); return vm.throw_completion<RangeError>(ErrorType::OptionIsNotValidValue, numbering_system, "numberingSystem"sv);
} }
// 8. Let opt be the Record { [[localeMatcher]]: matcher, [[nu]]: numberingSystem }. // 8. Let opt be the Record { [[localeMatcher]]: matcher, [[nu]]: numberingSystem }.
LocaleOptions opt {}; LocaleOptions opt {};
opt.locale_matcher = matcher; opt.locale_matcher = matcher;
opt.nu = numbering_system.is_undefined() ? Optional<DeprecatedString>() : numbering_system.as_string().deprecated_string(); opt.nu = numbering_system.is_undefined() ? Optional<DeprecatedString>() : TRY(numbering_system.as_string().deprecated_string());
// 9. Let r be ResolveLocale(%DurationFormat%.[[AvailableLocales]], requestedLocales, opt, %DurationFormat%.[[RelevantExtensionKeys]], %DurationFormat%.[[LocaleData]]). // 9. Let r be ResolveLocale(%DurationFormat%.[[AvailableLocales]], requestedLocales, opt, %DurationFormat%.[[RelevantExtensionKeys]], %DurationFormat%.[[LocaleData]]).
auto result = resolve_locale(requested_locales, opt, DurationFormat::relevant_extension_keys()); auto result = TRY(resolve_locale(requested_locales, opt, DurationFormat::relevant_extension_keys()));
// 10. Let locale be r.[[locale]]. // 10. Let locale be r.[[locale]].
auto locale = move(result.locale); auto locale = move(result.locale);
@ -93,7 +93,7 @@ ThrowCompletionOr<NonnullGCPtr<Object>> DurationFormatConstructor::construct(Fun
auto style = TRY(get_option(vm, *options, vm.names.style, OptionType::String, { "long"sv, "short"sv, "narrow"sv, "digital"sv }, "short"sv)); auto style = TRY(get_option(vm, *options, vm.names.style, OptionType::String, { "long"sv, "short"sv, "narrow"sv, "digital"sv }, "short"sv));
// 14. Set durationFormat.[[Style]] to style. // 14. Set durationFormat.[[Style]] to style.
duration_format->set_style(style.as_string().deprecated_string()); duration_format->set_style(TRY(style.as_string().deprecated_string()));
// 15. Set durationFormat.[[DataLocale]] to r.[[dataLocale]]. // 15. Set durationFormat.[[DataLocale]] to r.[[dataLocale]].
duration_format->set_data_locale(move(result.data_locale)); duration_format->set_data_locale(move(result.data_locale));
@ -119,7 +119,7 @@ ThrowCompletionOr<NonnullGCPtr<Object>> DurationFormatConstructor::construct(Fun
auto digital_base = duration_instances_component.digital_default; auto digital_base = duration_instances_component.digital_default;
// f. Let unitOptions be ? GetDurationUnitOptions(unit, options, style, valueList, digitalBase, prevStyle). // f. Let unitOptions be ? GetDurationUnitOptions(unit, options, style, valueList, digitalBase, prevStyle).
auto unit_options = TRY(get_duration_unit_options(vm, unit, *options, style.as_string().deprecated_string(), value_list, digital_base, previous_style)); auto unit_options = TRY(get_duration_unit_options(vm, unit, *options, TRY(style.as_string().deprecated_string()), value_list, digital_base, previous_style));
// g. Set the value of the styleSlot slot of durationFormat to unitOptions.[[Style]]. // g. Set the value of the styleSlot slot of durationFormat to unitOptions.[[Style]].
(duration_format->*style_slot)(unit_options.style); (duration_format->*style_slot)(unit_options.style);

View file

@ -274,7 +274,7 @@ ThrowCompletionOr<Vector<DeprecatedString>> string_list_from_iterable(VM& vm, Va
} }
// iii. Append nextValue to the end of the List list. // iii. Append nextValue to the end of the List list.
list.append(next_value.as_string().deprecated_string()); list.append(TRY(next_value.as_string().deprecated_string()));
} }
} while (next != nullptr); } while (next != nullptr);

View file

@ -71,7 +71,7 @@ ThrowCompletionOr<NonnullGCPtr<Object>> ListFormatConstructor::construct(Functio
// 8. Let localeData be %ListFormat%.[[LocaleData]]. // 8. Let localeData be %ListFormat%.[[LocaleData]].
// 9. Let r be ResolveLocale(%ListFormat%.[[AvailableLocales]], requestedLocales, opt, %ListFormat%.[[RelevantExtensionKeys]], localeData). // 9. Let r be ResolveLocale(%ListFormat%.[[AvailableLocales]], requestedLocales, opt, %ListFormat%.[[RelevantExtensionKeys]], localeData).
auto result = resolve_locale(requested_locales, opt, {}); auto result = TRY(resolve_locale(requested_locales, opt, {}));
// 10. Set listFormat.[[Locale]] to r.[[locale]]. // 10. Set listFormat.[[Locale]] to r.[[locale]].
list_format->set_locale(move(result.locale)); list_format->set_locale(move(result.locale));
@ -80,13 +80,13 @@ ThrowCompletionOr<NonnullGCPtr<Object>> ListFormatConstructor::construct(Functio
auto type = TRY(get_option(vm, *options, vm.names.type, OptionType::String, { "conjunction"sv, "disjunction"sv, "unit"sv }, "conjunction"sv)); auto type = TRY(get_option(vm, *options, vm.names.type, OptionType::String, { "conjunction"sv, "disjunction"sv, "unit"sv }, "conjunction"sv));
// 12. Set listFormat.[[Type]] to type. // 12. Set listFormat.[[Type]] to type.
list_format->set_type(type.as_string().deprecated_string()); list_format->set_type(TRY(type.as_string().deprecated_string()));
// 13. Let style be ? GetOption(options, "style", "string", « "long", "short", "narrow" », "long"). // 13. Let style be ? GetOption(options, "style", "string", « "long", "short", "narrow" », "long").
auto style = TRY(get_option(vm, *options, vm.names.style, OptionType::String, { "long"sv, "short"sv, "narrow"sv }, "long"sv)); auto style = TRY(get_option(vm, *options, vm.names.style, OptionType::String, { "long"sv, "short"sv, "narrow"sv }, "long"sv));
// 14. Set listFormat.[[Style]] to style. // 14. Set listFormat.[[Style]] to style.
list_format->set_style(style.as_string().deprecated_string()); list_format->set_style(TRY(style.as_string().deprecated_string()));
// Note: The remaining steps are skipped in favor of deferring to LibUnicode. // Note: The remaining steps are skipped in favor of deferring to LibUnicode.

View file

@ -33,10 +33,10 @@ static ThrowCompletionOr<Optional<DeprecatedString>> get_string_option(VM& vm, O
if (option.is_undefined()) if (option.is_undefined())
return Optional<DeprecatedString> {}; return Optional<DeprecatedString> {};
if (validator && !validator(option.as_string().deprecated_string())) if (validator && !validator(TRY(option.as_string().deprecated_string())))
return vm.throw_completion<RangeError>(ErrorType::OptionIsNotValidValue, option, property); return vm.throw_completion<RangeError>(ErrorType::OptionIsNotValidValue, option, property);
return option.as_string().deprecated_string(); return TRY(option.as_string().deprecated_string());
} }
// 14.1.2 ApplyOptionsToTag ( tag, options ), https://tc39.es/ecma402/#sec-apply-options-to-tag // 14.1.2 ApplyOptionsToTag ( tag, options ), https://tc39.es/ecma402/#sec-apply-options-to-tag

View file

@ -1604,7 +1604,7 @@ ThrowCompletionOr<MathematicalValue> to_intl_mathematical_value(VM& vm, Value va
// 3. If Type(primValue) is String, // 3. If Type(primValue) is String,
// a. Let str be primValue. // a. Let str be primValue.
auto const& string = primitive_value.as_string().deprecated_string(); auto const& string = TRY(primitive_value.as_string().deprecated_string());
// Step 4 handled separately by the FIXME above. // Step 4 handled separately by the FIXME above.

View file

@ -103,16 +103,16 @@ ThrowCompletionOr<NumberFormat*> initialize_number_format(VM& vm, NumberFormat&
// 7. If numberingSystem is not undefined, then // 7. If numberingSystem is not undefined, then
if (!numbering_system.is_undefined()) { if (!numbering_system.is_undefined()) {
// a. If numberingSystem does not match the Unicode Locale Identifier type nonterminal, throw a RangeError exception. // a. If numberingSystem does not match the Unicode Locale Identifier type nonterminal, throw a RangeError exception.
if (!::Locale::is_type_identifier(numbering_system.as_string().deprecated_string())) if (!::Locale::is_type_identifier(TRY(numbering_system.as_string().deprecated_string())))
return vm.throw_completion<RangeError>(ErrorType::OptionIsNotValidValue, numbering_system, "numberingSystem"sv); return vm.throw_completion<RangeError>(ErrorType::OptionIsNotValidValue, numbering_system, "numberingSystem"sv);
// 8. Set opt.[[nu]] to numberingSystem. // 8. Set opt.[[nu]] to numberingSystem.
opt.nu = numbering_system.as_string().deprecated_string(); opt.nu = TRY(numbering_system.as_string().deprecated_string());
} }
// 9. Let localeData be %NumberFormat%.[[LocaleData]]. // 9. Let localeData be %NumberFormat%.[[LocaleData]].
// 10. Let r be ResolveLocale(%NumberFormat%.[[AvailableLocales]], requestedLocales, opt, %NumberFormat%.[[RelevantExtensionKeys]], localeData). // 10. Let r be ResolveLocale(%NumberFormat%.[[AvailableLocales]], requestedLocales, opt, %NumberFormat%.[[RelevantExtensionKeys]], localeData).
auto result = resolve_locale(requested_locales, opt, NumberFormat::relevant_extension_keys()); auto result = TRY(resolve_locale(requested_locales, opt, NumberFormat::relevant_extension_keys()));
// 11. Set numberFormat.[[Locale]] to r.[[locale]]. // 11. Set numberFormat.[[Locale]] to r.[[locale]].
number_format.set_locale(move(result.locale)); number_format.set_locale(move(result.locale));
@ -176,7 +176,7 @@ ThrowCompletionOr<NumberFormat*> initialize_number_format(VM& vm, NumberFormat&
auto notation = TRY(get_option(vm, *options, vm.names.notation, OptionType::String, { "standard"sv, "scientific"sv, "engineering"sv, "compact"sv }, "standard"sv)); auto notation = TRY(get_option(vm, *options, vm.names.notation, OptionType::String, { "standard"sv, "scientific"sv, "engineering"sv, "compact"sv }, "standard"sv));
// 22. Set numberFormat.[[Notation]] to notation. // 22. Set numberFormat.[[Notation]] to notation.
number_format.set_notation(notation.as_string().deprecated_string()); number_format.set_notation(TRY(notation.as_string().deprecated_string()));
// 23. Perform ? SetNumberFormatDigitOptions(numberFormat, options, mnfdDefault, mxfdDefault, notation). // 23. Perform ? SetNumberFormatDigitOptions(numberFormat, options, mnfdDefault, mxfdDefault, notation).
TRY(set_number_format_digit_options(vm, number_format, *options, default_min_fraction_digits, default_max_fraction_digits, number_format.notation())); TRY(set_number_format_digit_options(vm, number_format, *options, default_min_fraction_digits, default_max_fraction_digits, number_format.notation()));
@ -199,7 +199,7 @@ ThrowCompletionOr<NumberFormat*> initialize_number_format(VM& vm, NumberFormat&
auto trailing_zero_display = TRY(get_option(vm, *options, vm.names.trailingZeroDisplay, OptionType::String, { "auto"sv, "stripIfInteger"sv }, "auto"sv)); auto trailing_zero_display = TRY(get_option(vm, *options, vm.names.trailingZeroDisplay, OptionType::String, { "auto"sv, "stripIfInteger"sv }, "auto"sv));
// 27. Set numberFormat.[[TrailingZeroDisplay]] to trailingZeroDisplay. // 27. Set numberFormat.[[TrailingZeroDisplay]] to trailingZeroDisplay.
number_format.set_trailing_zero_display(trailing_zero_display.as_string().deprecated_string()); number_format.set_trailing_zero_display(TRY(trailing_zero_display.as_string().deprecated_string()));
// 28. Let compactDisplay be ? GetOption(options, "compactDisplay", "string", « "short", "long" », "short"). // 28. Let compactDisplay be ? GetOption(options, "compactDisplay", "string", « "short", "long" », "short").
auto compact_display = TRY(get_option(vm, *options, vm.names.compactDisplay, OptionType::String, { "short"sv, "long"sv }, "short"sv)); auto compact_display = TRY(get_option(vm, *options, vm.names.compactDisplay, OptionType::String, { "short"sv, "long"sv }, "short"sv));
@ -210,7 +210,7 @@ ThrowCompletionOr<NumberFormat*> initialize_number_format(VM& vm, NumberFormat&
// 30. If notation is "compact", then // 30. If notation is "compact", then
if (number_format.notation() == NumberFormat::Notation::Compact) { if (number_format.notation() == NumberFormat::Notation::Compact) {
// a. Set numberFormat.[[CompactDisplay]] to compactDisplay. // a. Set numberFormat.[[CompactDisplay]] to compactDisplay.
number_format.set_compact_display(compact_display.as_string().deprecated_string()); number_format.set_compact_display(TRY(compact_display.as_string().deprecated_string()));
// b. Set defaultUseGrouping to "min2". // b. Set defaultUseGrouping to "min2".
default_use_grouping = "min2"sv; default_use_grouping = "min2"sv;
@ -226,13 +226,13 @@ ThrowCompletionOr<NumberFormat*> initialize_number_format(VM& vm, NumberFormat&
auto sign_display = TRY(get_option(vm, *options, vm.names.signDisplay, OptionType::String, { "auto"sv, "never"sv, "always"sv, "exceptZero"sv, "negative"sv }, "auto"sv)); auto sign_display = TRY(get_option(vm, *options, vm.names.signDisplay, OptionType::String, { "auto"sv, "never"sv, "always"sv, "exceptZero"sv, "negative"sv }, "auto"sv));
// 34. Set numberFormat.[[SignDisplay]] to signDisplay. // 34. Set numberFormat.[[SignDisplay]] to signDisplay.
number_format.set_sign_display(sign_display.as_string().deprecated_string()); number_format.set_sign_display(TRY(sign_display.as_string().deprecated_string()));
// 35. Let roundingMode be ? GetOption(options, "roundingMode", "string", « "ceil", "floor", "expand", "trunc", "halfCeil", "halfFloor", "halfExpand", "halfTrunc", "halfEven" », "halfExpand"). // 35. Let roundingMode be ? GetOption(options, "roundingMode", "string", « "ceil", "floor", "expand", "trunc", "halfCeil", "halfFloor", "halfExpand", "halfTrunc", "halfEven" », "halfExpand").
auto rounding_mode = TRY(get_option(vm, *options, vm.names.roundingMode, OptionType::String, { "ceil"sv, "floor"sv, "expand"sv, "trunc"sv, "halfCeil"sv, "halfFloor"sv, "halfExpand"sv, "halfTrunc"sv, "halfEven"sv }, "halfExpand"sv)); auto rounding_mode = TRY(get_option(vm, *options, vm.names.roundingMode, OptionType::String, { "ceil"sv, "floor"sv, "expand"sv, "trunc"sv, "halfCeil"sv, "halfFloor"sv, "halfExpand"sv, "halfTrunc"sv, "halfEven"sv }, "halfExpand"sv));
// 36. Set numberFormat.[[RoundingMode]] to roundingMode. // 36. Set numberFormat.[[RoundingMode]] to roundingMode.
number_format.set_rounding_mode(rounding_mode.as_string().deprecated_string()); number_format.set_rounding_mode(TRY(rounding_mode.as_string().deprecated_string()));
// 37. Return numberFormat. // 37. Return numberFormat.
return &number_format; return &number_format;
@ -282,7 +282,7 @@ ThrowCompletionOr<void> set_number_format_digit_options(VM& vm, NumberFormatBase
bool need_fraction_digits = true; bool need_fraction_digits = true;
// 14. If roundingPriority is "auto", then // 14. If roundingPriority is "auto", then
if (rounding_priority.as_string().deprecated_string() == "auto"sv) { if (TRY(rounding_priority.as_string().deprecated_string()) == "auto"sv) {
// a. Set needSd to hasSd. // a. Set needSd to hasSd.
need_significant_digits = has_significant_digits; need_significant_digits = has_significant_digits;
@ -358,12 +358,12 @@ ThrowCompletionOr<void> set_number_format_digit_options(VM& vm, NumberFormatBase
// 17. If needSd is true or needFd is true, then // 17. If needSd is true or needFd is true, then
if (need_significant_digits || need_fraction_digits) { if (need_significant_digits || need_fraction_digits) {
// a. If roundingPriority is "morePrecision", then // a. If roundingPriority is "morePrecision", then
if (rounding_priority.as_string().deprecated_string() == "morePrecision"sv) { if (TRY(rounding_priority.as_string().deprecated_string()) == "morePrecision"sv) {
// i. Set intlObj.[[RoundingType]] to morePrecision. // i. Set intlObj.[[RoundingType]] to morePrecision.
intl_object.set_rounding_type(NumberFormatBase::RoundingType::MorePrecision); intl_object.set_rounding_type(NumberFormatBase::RoundingType::MorePrecision);
} }
// b. Else if roundingPriority is "lessPrecision", then // b. Else if roundingPriority is "lessPrecision", then
else if (rounding_priority.as_string().deprecated_string() == "lessPrecision"sv) { else if (TRY(rounding_priority.as_string().deprecated_string()) == "lessPrecision"sv) {
// i. Set intlObj.[[RoundingType]] to lessPrecision. // i. Set intlObj.[[RoundingType]] to lessPrecision.
intl_object.set_rounding_type(NumberFormatBase::RoundingType::LessPrecision); intl_object.set_rounding_type(NumberFormatBase::RoundingType::LessPrecision);
} }
@ -410,7 +410,7 @@ ThrowCompletionOr<void> set_number_format_unit_options(VM& vm, NumberFormat& int
auto style = TRY(get_option(vm, options, vm.names.style, OptionType::String, { "decimal"sv, "percent"sv, "currency"sv, "unit"sv }, "decimal"sv)); auto style = TRY(get_option(vm, options, vm.names.style, OptionType::String, { "decimal"sv, "percent"sv, "currency"sv, "unit"sv }, "decimal"sv));
// 4. Set intlObj.[[Style]] to style. // 4. Set intlObj.[[Style]] to style.
intl_object.set_style(style.as_string().deprecated_string()); intl_object.set_style(TRY(style.as_string().deprecated_string()));
// 5. Let currency be ? GetOption(options, "currency", "string", undefined, undefined). // 5. Let currency be ? GetOption(options, "currency", "string", undefined, undefined).
auto currency = TRY(get_option(vm, options, vm.names.currency, OptionType::String, {}, Empty {})); auto currency = TRY(get_option(vm, options, vm.names.currency, OptionType::String, {}, Empty {}));
@ -423,7 +423,7 @@ ThrowCompletionOr<void> set_number_format_unit_options(VM& vm, NumberFormat& int
} }
// 7. Else, // 7. Else,
// a. If ! IsWellFormedCurrencyCode(currency) is false, throw a RangeError exception. // a. If ! IsWellFormedCurrencyCode(currency) is false, throw a RangeError exception.
else if (!is_well_formed_currency_code(currency.as_string().deprecated_string())) else if (!is_well_formed_currency_code(TRY(currency.as_string().deprecated_string())))
return vm.throw_completion<RangeError>(ErrorType::OptionIsNotValidValue, currency, "currency"sv); return vm.throw_completion<RangeError>(ErrorType::OptionIsNotValidValue, currency, "currency"sv);
// 8. Let currencyDisplay be ? GetOption(options, "currencyDisplay", "string", « "code", "symbol", "narrowSymbol", "name" », "symbol"). // 8. Let currencyDisplay be ? GetOption(options, "currencyDisplay", "string", « "code", "symbol", "narrowSymbol", "name" », "symbol").
@ -443,7 +443,7 @@ ThrowCompletionOr<void> set_number_format_unit_options(VM& vm, NumberFormat& int
} }
// 12. Else, // 12. Else,
// a. If ! IsWellFormedUnitIdentifier(unit) is false, throw a RangeError exception. // a. If ! IsWellFormedUnitIdentifier(unit) is false, throw a RangeError exception.
else if (!is_well_formed_unit_identifier(unit.as_string().deprecated_string())) else if (!is_well_formed_unit_identifier(TRY(unit.as_string().deprecated_string())))
return vm.throw_completion<RangeError>(ErrorType::OptionIsNotValidValue, unit, "unit"sv); return vm.throw_completion<RangeError>(ErrorType::OptionIsNotValidValue, unit, "unit"sv);
// 13. Let unitDisplay be ? GetOption(options, "unitDisplay", "string", « "short", "narrow", "long" », "short"). // 13. Let unitDisplay be ? GetOption(options, "unitDisplay", "string", « "short", "narrow", "long" », "short").
@ -452,22 +452,22 @@ ThrowCompletionOr<void> set_number_format_unit_options(VM& vm, NumberFormat& int
// 14. If style is "currency", then // 14. If style is "currency", then
if (intl_object.style() == NumberFormat::Style::Currency) { if (intl_object.style() == NumberFormat::Style::Currency) {
// a. Set intlObj.[[Currency]] to the ASCII-uppercase of currency. // a. Set intlObj.[[Currency]] to the ASCII-uppercase of currency.
intl_object.set_currency(currency.as_string().deprecated_string().to_uppercase()); intl_object.set_currency(TRY(currency.as_string().deprecated_string()).to_uppercase());
// c. Set intlObj.[[CurrencyDisplay]] to currencyDisplay. // c. Set intlObj.[[CurrencyDisplay]] to currencyDisplay.
intl_object.set_currency_display(currency_display.as_string().deprecated_string()); intl_object.set_currency_display(TRY(currency_display.as_string().deprecated_string()));
// d. Set intlObj.[[CurrencySign]] to currencySign. // d. Set intlObj.[[CurrencySign]] to currencySign.
intl_object.set_currency_sign(currency_sign.as_string().deprecated_string()); intl_object.set_currency_sign(TRY(currency_sign.as_string().deprecated_string()));
} }
// 15. If style is "unit", then // 15. If style is "unit", then
if (intl_object.style() == NumberFormat::Style::Unit) { if (intl_object.style() == NumberFormat::Style::Unit) {
// a. Set intlObj.[[Unit]] to unit. // a. Set intlObj.[[Unit]] to unit.
intl_object.set_unit(unit.as_string().deprecated_string()); intl_object.set_unit(TRY(unit.as_string().deprecated_string()));
// b. Set intlObj.[[UnitDisplay]] to unitDisplay. // b. Set intlObj.[[UnitDisplay]] to unitDisplay.
intl_object.set_unit_display(unit_display.as_string().deprecated_string()); intl_object.set_unit_display(TRY(unit_display.as_string().deprecated_string()));
} }
return {}; return {};

View file

@ -94,14 +94,14 @@ ThrowCompletionOr<PluralRules*> initialize_plural_rules(VM& vm, PluralRules& plu
auto type = TRY(get_option(vm, *options, vm.names.type, OptionType::String, AK::Array { "cardinal"sv, "ordinal"sv }, "cardinal"sv)); auto type = TRY(get_option(vm, *options, vm.names.type, OptionType::String, AK::Array { "cardinal"sv, "ordinal"sv }, "cardinal"sv));
// 7. Set pluralRules.[[Type]] to t. // 7. Set pluralRules.[[Type]] to t.
plural_rules.set_type(type.as_string().deprecated_string()); plural_rules.set_type(TRY(type.as_string().deprecated_string()));
// 8. Perform ? SetNumberFormatDigitOptions(pluralRules, options, +0𝔽, 3𝔽, "standard"). // 8. Perform ? SetNumberFormatDigitOptions(pluralRules, options, +0𝔽, 3𝔽, "standard").
TRY(set_number_format_digit_options(vm, plural_rules, *options, 0, 3, NumberFormat::Notation::Standard)); TRY(set_number_format_digit_options(vm, plural_rules, *options, 0, 3, NumberFormat::Notation::Standard));
// 9. Let localeData be %PluralRules%.[[LocaleData]]. // 9. Let localeData be %PluralRules%.[[LocaleData]].
// 10. Let r be ResolveLocale(%PluralRules%.[[AvailableLocales]], requestedLocales, opt, %PluralRules%.[[RelevantExtensionKeys]], localeData). // 10. Let r be ResolveLocale(%PluralRules%.[[AvailableLocales]], requestedLocales, opt, %PluralRules%.[[RelevantExtensionKeys]], localeData).
auto result = resolve_locale(requested_locales, opt, {}); auto result = TRY(resolve_locale(requested_locales, opt, {}));
// 11. Set pluralRules.[[Locale]] to r.[[locale]]. // 11. Set pluralRules.[[Locale]] to r.[[locale]].
plural_rules.set_locale(move(result.locale)); plural_rules.set_locale(move(result.locale));

View file

@ -101,16 +101,16 @@ ThrowCompletionOr<RelativeTimeFormat*> initialize_relative_time_format(VM& vm, R
// 7. If numberingSystem is not undefined, then // 7. If numberingSystem is not undefined, then
if (!numbering_system.is_undefined()) { if (!numbering_system.is_undefined()) {
// a. If numberingSystem does not match the Unicode Locale Identifier type nonterminal, throw a RangeError exception. // a. If numberingSystem does not match the Unicode Locale Identifier type nonterminal, throw a RangeError exception.
if (!::Locale::is_type_identifier(numbering_system.as_string().deprecated_string())) if (!::Locale::is_type_identifier(TRY(numbering_system.as_string().deprecated_string())))
return vm.throw_completion<RangeError>(ErrorType::OptionIsNotValidValue, numbering_system, "numberingSystem"sv); return vm.throw_completion<RangeError>(ErrorType::OptionIsNotValidValue, numbering_system, "numberingSystem"sv);
// 8. Set opt.[[nu]] to numberingSystem. // 8. Set opt.[[nu]] to numberingSystem.
opt.nu = numbering_system.as_string().deprecated_string(); opt.nu = TRY(numbering_system.as_string().deprecated_string());
} }
// 9. Let localeData be %RelativeTimeFormat%.[[LocaleData]]. // 9. Let localeData be %RelativeTimeFormat%.[[LocaleData]].
// 10. Let r be ResolveLocale(%RelativeTimeFormat%.[[AvailableLocales]], requestedLocales, opt, %RelativeTimeFormat%.[[RelevantExtensionKeys]], localeData). // 10. Let r be ResolveLocale(%RelativeTimeFormat%.[[AvailableLocales]], requestedLocales, opt, %RelativeTimeFormat%.[[RelevantExtensionKeys]], localeData).
auto result = resolve_locale(requested_locales, opt, RelativeTimeFormat::relevant_extension_keys()); auto result = TRY(resolve_locale(requested_locales, opt, RelativeTimeFormat::relevant_extension_keys()));
// 11. Let locale be r.[[locale]]. // 11. Let locale be r.[[locale]].
auto locale = move(result.locale); auto locale = move(result.locale);
@ -129,13 +129,13 @@ ThrowCompletionOr<RelativeTimeFormat*> initialize_relative_time_format(VM& vm, R
auto style = TRY(get_option(vm, *options, vm.names.style, OptionType::String, { "long"sv, "short"sv, "narrow"sv }, "long"sv)); auto style = TRY(get_option(vm, *options, vm.names.style, OptionType::String, { "long"sv, "short"sv, "narrow"sv }, "long"sv));
// 16. Set relativeTimeFormat.[[Style]] to style. // 16. Set relativeTimeFormat.[[Style]] to style.
relative_time_format.set_style(style.as_string().deprecated_string()); relative_time_format.set_style(TRY(style.as_string().deprecated_string()));
// 17. Let numeric be ? GetOption(options, "numeric", "string", « "always", "auto" », "always"). // 17. Let numeric be ? GetOption(options, "numeric", "string", « "always", "auto" », "always").
auto numeric = TRY(get_option(vm, *options, vm.names.numeric, OptionType::String, { "always"sv, "auto"sv }, "always"sv)); auto numeric = TRY(get_option(vm, *options, vm.names.numeric, OptionType::String, { "always"sv, "auto"sv }, "always"sv));
// 18. Set relativeTimeFormat.[[Numeric]] to numeric. // 18. Set relativeTimeFormat.[[Numeric]] to numeric.
relative_time_format.set_numeric(numeric.as_string().deprecated_string()); relative_time_format.set_numeric(TRY(numeric.as_string().deprecated_string()));
// 19. Let relativeTimeFormat.[[NumberFormat]] be ! Construct(%NumberFormat%, « locale »). // 19. Let relativeTimeFormat.[[NumberFormat]] be ! Construct(%NumberFormat%, « locale »).
auto number_format = MUST(construct(vm, *realm.intrinsics().intl_number_format_constructor(), PrimitiveString::create(vm, locale))); auto number_format = MUST(construct(vm, *realm.intrinsics().intl_number_format_constructor(), PrimitiveString::create(vm, locale)));

View file

@ -60,7 +60,7 @@ JS_DEFINE_NATIVE_FUNCTION(SegmentIteratorPrototype::next)
iterator->set_iterated_string_next_segment_code_unit_index(end_index); iterator->set_iterated_string_next_segment_code_unit_index(end_index);
// 9. Let segmentData be ! CreateSegmentDataObject(segmenter, string, startIndex, endIndex). // 9. Let segmentData be ! CreateSegmentDataObject(segmenter, string, startIndex, endIndex).
auto* segment_data = create_segment_data_object(vm, segmenter, string, start_index, end_index); auto segment_data = TRY(create_segment_data_object(vm, segmenter, string, start_index, end_index));
// 10. Return CreateIterResultObject(segmentData, false). // 10. Return CreateIterResultObject(segmentData, false).
return create_iterator_result_object(vm, segment_data, false); return create_iterator_result_object(vm, segment_data, false);

View file

@ -45,7 +45,7 @@ StringView Segmenter::segmenter_granularity_string() const
} }
// 18.7.1 CreateSegmentDataObject ( segmenter, string, startIndex, endIndex ), https://tc39.es/ecma402/#sec-createsegmentdataobject // 18.7.1 CreateSegmentDataObject ( segmenter, string, startIndex, endIndex ), https://tc39.es/ecma402/#sec-createsegmentdataobject
Object* create_segment_data_object(VM& vm, Segmenter const& segmenter, Utf16View const& string, double start_index, double end_index) ThrowCompletionOr<NonnullGCPtr<Object>> create_segment_data_object(VM& vm, Segmenter const& segmenter, Utf16View const& string, double start_index, double end_index)
{ {
auto& realm = *vm.current_realm(); auto& realm = *vm.current_realm();
@ -68,13 +68,13 @@ Object* create_segment_data_object(VM& vm, Segmenter const& segmenter, Utf16View
auto segment = string.substring_view(start_index, end_index - start_index); auto segment = string.substring_view(start_index, end_index - start_index);
// 7. Perform ! CreateDataPropertyOrThrow(result, "segment", segment). // 7. Perform ! CreateDataPropertyOrThrow(result, "segment", segment).
MUST(result->create_data_property_or_throw(vm.names.segment, PrimitiveString::create(vm, segment))); MUST(result->create_data_property_or_throw(vm.names.segment, PrimitiveString::create(vm, TRY(Utf16String::create(vm, segment)))));
// 8. Perform ! CreateDataPropertyOrThrow(result, "index", 𝔽(startIndex)). // 8. Perform ! CreateDataPropertyOrThrow(result, "index", 𝔽(startIndex)).
MUST(result->create_data_property_or_throw(vm.names.index, Value(start_index))); MUST(result->create_data_property_or_throw(vm.names.index, Value(start_index)));
// 9. Perform ! CreateDataPropertyOrThrow(result, "input", string). // 9. Perform ! CreateDataPropertyOrThrow(result, "input", string).
MUST(result->create_data_property_or_throw(vm.names.input, PrimitiveString::create(vm, string))); MUST(result->create_data_property_or_throw(vm.names.input, PrimitiveString::create(vm, TRY(Utf16String::create(vm, string)))));
// 10. Let granularity be segmenter.[[SegmenterGranularity]]. // 10. Let granularity be segmenter.[[SegmenterGranularity]].
auto granularity = segmenter.segmenter_granularity(); auto granularity = segmenter.segmenter_granularity();

View file

@ -37,7 +37,7 @@ private:
SegmenterGranularity m_segmenter_granularity { SegmenterGranularity::Grapheme }; // [[SegmenterGranularity]] SegmenterGranularity m_segmenter_granularity { SegmenterGranularity::Grapheme }; // [[SegmenterGranularity]]
}; };
Object* create_segment_data_object(VM&, Segmenter const&, Utf16View const&, double start_index, double end_index); ThrowCompletionOr<NonnullGCPtr<Object>> create_segment_data_object(VM&, Segmenter const&, Utf16View const&, double start_index, double end_index);
enum class Direction { enum class Direction {
Before, Before,
After, After,

View file

@ -71,7 +71,7 @@ ThrowCompletionOr<NonnullGCPtr<Object>> SegmenterConstructor::construct(Function
// 9. Let localeData be %Segmenter%.[[LocaleData]]. // 9. Let localeData be %Segmenter%.[[LocaleData]].
// 10. Let r be ResolveLocale(%Segmenter%.[[AvailableLocales]], requestedLocales, opt, %Segmenter%.[[RelevantExtensionKeys]], localeData). // 10. Let r be ResolveLocale(%Segmenter%.[[AvailableLocales]], requestedLocales, opt, %Segmenter%.[[RelevantExtensionKeys]], localeData).
auto result = resolve_locale(requested_locales, opt, {}); auto result = TRY(resolve_locale(requested_locales, opt, {}));
// 11. Set segmenter.[[Locale]] to r.[[locale]]. // 11. Set segmenter.[[Locale]] to r.[[locale]].
segmenter->set_locale(move(result.locale)); segmenter->set_locale(move(result.locale));
@ -80,7 +80,7 @@ ThrowCompletionOr<NonnullGCPtr<Object>> SegmenterConstructor::construct(Function
auto granularity = TRY(get_option(vm, *options, vm.names.granularity, OptionType::String, { "grapheme"sv, "word"sv, "sentence"sv }, "grapheme"sv)); auto granularity = TRY(get_option(vm, *options, vm.names.granularity, OptionType::String, { "grapheme"sv, "word"sv, "sentence"sv }, "grapheme"sv));
// 13. Set segmenter.[[SegmenterGranularity]] to granularity. // 13. Set segmenter.[[SegmenterGranularity]] to granularity.
segmenter->set_segmenter_granularity(granularity.as_string().deprecated_string()); segmenter->set_segmenter_granularity(TRY(granularity.as_string().deprecated_string()));
// 14. Return segmenter. // 14. Return segmenter.
return segmenter; return segmenter;

View file

@ -58,7 +58,7 @@ JS_DEFINE_NATIVE_FUNCTION(SegmentsPrototype::containing)
auto end_index = find_boundary(segmenter, string, n, Direction::After, segments->boundaries_cache()); auto end_index = find_boundary(segmenter, string, n, Direction::After, segments->boundaries_cache());
// 10. Return ! CreateSegmentDataObject(segmenter, string, startIndex, endIndex). // 10. Return ! CreateSegmentDataObject(segmenter, string, startIndex, endIndex).
return create_segment_data_object(vm, segmenter, string, start_index, end_index); return TRY(create_segment_data_object(vm, segmenter, string, start_index, end_index));
} }
// 18.5.2.2 %SegmentsPrototype% [ @@iterator ] ( ), https://tc39.es/ecma402/#sec-%segmentsprototype%-@@iterator // 18.5.2.2 %SegmentsPrototype% [ @@iterator ] ( ), https://tc39.es/ecma402/#sec-%segmentsprototype%-@@iterator

View file

@ -63,7 +63,7 @@ ThrowCompletionOr<DeprecatedString> JSONObject::stringify_impl(VM& vm, Value val
auto replacer_value = TRY(replacer_object.get(i)); auto replacer_value = TRY(replacer_object.get(i));
DeprecatedString item; DeprecatedString item;
if (replacer_value.is_string()) { if (replacer_value.is_string()) {
item = replacer_value.as_string().deprecated_string(); item = TRY(replacer_value.as_string().deprecated_string());
} else if (replacer_value.is_number()) { } else if (replacer_value.is_number()) {
item = MUST(replacer_value.to_string(vm)); item = MUST(replacer_value.to_string(vm));
} else if (replacer_value.is_object()) { } else if (replacer_value.is_object()) {
@ -93,7 +93,7 @@ ThrowCompletionOr<DeprecatedString> JSONObject::stringify_impl(VM& vm, Value val
space_mv = min(10, space_mv); space_mv = min(10, space_mv);
state.gap = space_mv < 1 ? DeprecatedString::empty() : DeprecatedString::repeated(' ', space_mv); state.gap = space_mv < 1 ? DeprecatedString::empty() : DeprecatedString::repeated(' ', space_mv);
} else if (space.is_string()) { } else if (space.is_string()) {
auto string = space.as_string().deprecated_string(); auto string = TRY(space.as_string().deprecated_string());
if (string.length() <= 10) if (string.length() <= 10)
state.gap = string; state.gap = string;
else else
@ -185,7 +185,7 @@ ThrowCompletionOr<DeprecatedString> JSONObject::serialize_json_property(VM& vm,
// 8. If Type(value) is String, return QuoteJSONString(value). // 8. If Type(value) is String, return QuoteJSONString(value).
if (value.is_string()) if (value.is_string())
return quote_json_string(value.as_string().deprecated_string()); return quote_json_string(TRY(value.as_string().deprecated_string()));
// 9. If Type(value) is Number, then // 9. If Type(value) is Number, then
if (value.is_number()) { if (value.is_number()) {
@ -250,7 +250,7 @@ ThrowCompletionOr<DeprecatedString> JSONObject::serialize_json_object(VM& vm, St
} else { } else {
auto property_list = TRY(object.enumerable_own_property_names(PropertyKind::Key)); auto property_list = TRY(object.enumerable_own_property_names(PropertyKind::Key));
for (auto& property : property_list) for (auto& property : property_list)
TRY(process_property(property.as_string().deprecated_string())); TRY(process_property(TRY(property.as_string().deprecated_string())));
} }
StringBuilder builder; StringBuilder builder;
if (property_strings.is_empty()) { if (property_strings.is_empty()) {
@ -473,7 +473,7 @@ ThrowCompletionOr<Value> JSONObject::internalize_json_property(VM& vm, Object* h
} else { } else {
auto property_list = TRY(value_object.enumerable_own_property_names(Object::PropertyKind::Key)); auto property_list = TRY(value_object.enumerable_own_property_names(Object::PropertyKind::Key));
for (auto& property_key : property_list) for (auto& property_key : property_list)
TRY(process_property(property_key.as_string().deprecated_string())); TRY(process_property(TRY(property_key.as_string().deprecated_string())));
} }
} }

View file

@ -1267,7 +1267,7 @@ Optional<Completion> Object::enumerate_object_properties(Function<Optional<Compl
for (auto& key : own_keys) { for (auto& key : own_keys) {
if (!key.is_string()) if (!key.is_string())
continue; continue;
FlyString property_key = key.as_string().deprecated_string(); FlyString property_key = TRY(key.as_string().deprecated_string());
if (visited.contains(property_key)) if (visited.contains(property_key))
continue; continue;
auto descriptor = TRY(target->internal_get_own_property(property_key)); auto descriptor = TRY(target->internal_get_own_property(property_key));

View file

@ -125,7 +125,7 @@ JS_DEFINE_NATIVE_FUNCTION(ObjectPrototype::to_string)
if (!to_string_tag.is_string()) if (!to_string_tag.is_string())
tag = move(builtin_tag); tag = move(builtin_tag);
else else
tag = to_string_tag.as_string().deprecated_string(); tag = TRY(to_string_tag.as_string().deprecated_string());
// 17. Return the string-concatenation of "[object ", tag, and "]". // 17. Return the string-concatenation of "[object ", tag, and "]".
return PrimitiveString::create(vm, DeprecatedString::formatted("[object {}]", tag)); return PrimitiveString::create(vm, DeprecatedString::formatted("[object {}]", tag));

View file

@ -25,20 +25,19 @@ PrimitiveString::PrimitiveString(PrimitiveString& lhs, PrimitiveString& rhs)
} }
PrimitiveString::PrimitiveString(DeprecatedString string) PrimitiveString::PrimitiveString(DeprecatedString string)
: m_has_utf8_string(true) : m_utf8_string(move(string))
, m_utf8_string(move(string))
{ {
} }
PrimitiveString::PrimitiveString(Utf16String string) PrimitiveString::PrimitiveString(Utf16String string)
: m_has_utf16_string(true) : m_utf16_string(move(string))
, m_utf16_string(move(string))
{ {
} }
PrimitiveString::~PrimitiveString() PrimitiveString::~PrimitiveString()
{ {
vm().string_cache().remove(m_utf8_string); if (has_utf8_string())
vm().string_cache().remove(*m_utf8_string);
} }
void PrimitiveString::visit_edges(Cell::Visitor& visitor) void PrimitiveString::visit_edges(Cell::Visitor& visitor)
@ -57,62 +56,60 @@ bool PrimitiveString::is_empty() const
return false; return false;
} }
if (m_has_utf16_string) if (has_utf16_string())
return m_utf16_string.is_empty(); return m_utf16_string->is_empty();
if (m_has_utf8_string) if (has_utf8_string())
return m_utf8_string.is_empty(); return m_utf8_string->is_empty();
VERIFY_NOT_REACHED(); VERIFY_NOT_REACHED();
} }
DeprecatedString const& PrimitiveString::deprecated_string() const ThrowCompletionOr<DeprecatedString const&> PrimitiveString::deprecated_string() const
{ {
resolve_rope_if_needed(); TRY(resolve_rope_if_needed());
if (!m_has_utf8_string) {
// FIXME: Propagate this error. if (!has_utf8_string()) {
m_utf8_string = MUST(m_utf16_string.to_utf8(vm())); VERIFY(has_utf16_string());
m_has_utf8_string = true; m_utf8_string = TRY(m_utf16_string->to_utf8(vm()));
} }
return m_utf8_string;
return *m_utf8_string;
} }
Utf16String const& PrimitiveString::utf16_string() const ThrowCompletionOr<Utf16String const&> PrimitiveString::utf16_string() const
{ {
resolve_rope_if_needed(); TRY(resolve_rope_if_needed());
if (!m_has_utf16_string) {
m_utf16_string = Utf16String(m_utf8_string); if (!has_utf16_string()) {
m_has_utf16_string = true; VERIFY(has_utf8_string());
m_utf16_string = TRY(Utf16String::create(vm(), *m_utf8_string));
} }
return m_utf16_string;
return *m_utf16_string;
} }
Utf16View PrimitiveString::utf16_string_view() const ThrowCompletionOr<Utf16View> PrimitiveString::utf16_string_view() const
{ {
return utf16_string().view(); return TRY(utf16_string()).view();
} }
Optional<Value> PrimitiveString::get(VM& vm, PropertyKey const& property_key) const ThrowCompletionOr<Optional<Value>> PrimitiveString::get(VM& vm, PropertyKey const& property_key) const
{ {
if (property_key.is_symbol()) if (property_key.is_symbol())
return {}; return Optional<Value> {};
if (property_key.is_string()) { if (property_key.is_string()) {
if (property_key.as_string() == vm.names.length.as_string()) { if (property_key.as_string() == vm.names.length.as_string()) {
auto length = utf16_string().length_in_code_units(); auto length = TRY(utf16_string()).length_in_code_units();
return Value(static_cast<double>(length)); return Value(static_cast<double>(length));
} }
} }
auto index = canonical_numeric_index_string(property_key, CanonicalIndexMode::IgnoreNumericRoundtrip); auto index = canonical_numeric_index_string(property_key, CanonicalIndexMode::IgnoreNumericRoundtrip);
if (!index.is_index()) if (!index.is_index())
return {}; return Optional<Value> {};
auto str = utf16_string_view(); auto str = TRY(utf16_string_view());
auto length = str.length_in_code_units(); auto length = str.length_in_code_units();
if (length <= index.as_index()) if (length <= index.as_index())
return {}; return Optional<Value> {};
return create(vm, str.substring_view(index.as_index(), 1)); return create(vm, TRY(Utf16String::create(vm, str.substring_view(index.as_index(), 1))));
}
NonnullGCPtr<PrimitiveString> PrimitiveString::create(VM& vm, Utf16View const& view)
{
return create(vm, Utf16String(view));
} }
NonnullGCPtr<PrimitiveString> PrimitiveString::create(VM& vm, Utf16String string) NonnullGCPtr<PrimitiveString> PrimitiveString::create(VM& vm, Utf16String string)
@ -170,28 +167,29 @@ NonnullGCPtr<PrimitiveString> PrimitiveString::create(VM& vm, PrimitiveString& l
return vm.heap().allocate_without_realm<PrimitiveString>(lhs, rhs); return vm.heap().allocate_without_realm<PrimitiveString>(lhs, rhs);
} }
void PrimitiveString::resolve_rope_if_needed() const ThrowCompletionOr<void> PrimitiveString::resolve_rope_if_needed() const
{ {
if (!m_is_rope) if (!m_is_rope)
return; return {};
auto& vm = this->vm();
// NOTE: Special case for two concatenated UTF-16 strings. // NOTE: Special case for two concatenated UTF-16 strings.
// This is here as an optimization, although I'm unsure how valuable it is. // This is here as an optimization, although I'm unsure how valuable it is.
if (m_lhs->has_utf16_string() && m_rhs->has_utf16_string()) { if (m_lhs->has_utf16_string() && m_rhs->has_utf16_string()) {
auto const& lhs_string = m_lhs->utf16_string(); auto const& lhs_string = TRY(m_lhs->utf16_string());
auto const& rhs_string = m_rhs->utf16_string(); auto const& rhs_string = TRY(m_rhs->utf16_string());
Utf16Data combined; Utf16Data combined;
combined.ensure_capacity(lhs_string.length_in_code_units() + rhs_string.length_in_code_units()); combined.ensure_capacity(lhs_string.length_in_code_units() + rhs_string.length_in_code_units());
combined.extend(lhs_string.string()); combined.extend(lhs_string.string());
combined.extend(rhs_string.string()); combined.extend(rhs_string.string());
m_utf16_string = Utf16String(move(combined)); m_utf16_string = TRY(Utf16String::create(vm, move(combined)));
m_has_utf16_string = true;
m_is_rope = false; m_is_rope = false;
m_lhs = nullptr; m_lhs = nullptr;
m_rhs = nullptr; m_rhs = nullptr;
return; return {};
} }
// This vector will hold all the pieces of the rope that need to be assembled // This vector will hold all the pieces of the rope that need to be assembled
@ -221,21 +219,21 @@ void PrimitiveString::resolve_rope_if_needed() const
for (auto const* current : pieces) { for (auto const* current : pieces) {
if (!previous) { if (!previous) {
// This is the very first piece, just append it and continue. // This is the very first piece, just append it and continue.
builder.append(current->deprecated_string()); builder.append(TRY(current->deprecated_string()));
previous = current; previous = current;
continue; continue;
} }
// Get the UTF-8 representations for both strings. // Get the UTF-8 representations for both strings.
auto const& previous_string_as_utf8 = previous->deprecated_string(); auto const& previous_string_as_utf8 = TRY(previous->deprecated_string());
auto const& current_string_as_utf8 = current->deprecated_string(); auto const& current_string_as_utf8 = TRY(current->deprecated_string());
// NOTE: Now we need to look at the end of the previous string and the start // NOTE: Now we need to look at the end of the previous string and the start
// of the current string, to see if they should be combined into a surrogate. // of the current string, to see if they should be combined into a surrogate.
// Surrogates encoded as UTF-8 are 3 bytes. // Surrogates encoded as UTF-8 are 3 bytes.
if ((previous_string_as_utf8.length() < 3) || (current_string_as_utf8.length() < 3)) { if ((previous_string_as_utf8.length() < 3) || (current_string_as_utf8.length() < 3)) {
builder.append(current->deprecated_string()); builder.append(TRY(current->deprecated_string()));
previous = current; previous = current;
continue; continue;
} }
@ -243,7 +241,7 @@ void PrimitiveString::resolve_rope_if_needed() const
// Might the previous string end with a UTF-8 encoded surrogate? // Might the previous string end with a UTF-8 encoded surrogate?
if ((static_cast<u8>(previous_string_as_utf8[previous_string_as_utf8.length() - 3]) & 0xf0) != 0xe0) { if ((static_cast<u8>(previous_string_as_utf8[previous_string_as_utf8.length() - 3]) & 0xf0) != 0xe0) {
// If not, just append the current string and continue. // If not, just append the current string and continue.
builder.append(current->deprecated_string()); builder.append(TRY(current->deprecated_string()));
previous = current; previous = current;
continue; continue;
} }
@ -251,7 +249,7 @@ void PrimitiveString::resolve_rope_if_needed() const
// Might the current string begin with a UTF-8 encoded surrogate? // Might the current string begin with a UTF-8 encoded surrogate?
if ((static_cast<u8>(current_string_as_utf8[0]) & 0xf0) != 0xe0) { if ((static_cast<u8>(current_string_as_utf8[0]) & 0xf0) != 0xe0) {
// If not, just append the current string and continue. // If not, just append the current string and continue.
builder.append(current->deprecated_string()); builder.append(TRY(current->deprecated_string()));
previous = current; previous = current;
continue; continue;
} }
@ -260,7 +258,7 @@ void PrimitiveString::resolve_rope_if_needed() const
auto low_surrogate = *Utf8View(current_string_as_utf8).begin(); auto low_surrogate = *Utf8View(current_string_as_utf8).begin();
if (!Utf16View::is_high_surrogate(high_surrogate) || !Utf16View::is_low_surrogate(low_surrogate)) { if (!Utf16View::is_high_surrogate(high_surrogate) || !Utf16View::is_low_surrogate(low_surrogate)) {
builder.append(current->deprecated_string()); builder.append(TRY(current->deprecated_string()));
previous = current; previous = current;
continue; continue;
} }
@ -275,10 +273,10 @@ void PrimitiveString::resolve_rope_if_needed() const
} }
m_utf8_string = builder.to_deprecated_string(); m_utf8_string = builder.to_deprecated_string();
m_has_utf8_string = true;
m_is_rope = false; m_is_rope = false;
m_lhs = nullptr; m_lhs = nullptr;
m_rhs = nullptr; m_rhs = nullptr;
return {};
} }
} }

View file

@ -8,9 +8,11 @@
#pragma once #pragma once
#include <AK/DeprecatedString.h> #include <AK/DeprecatedString.h>
#include <AK/Optional.h>
#include <AK/StringView.h> #include <AK/StringView.h>
#include <LibJS/Forward.h> #include <LibJS/Forward.h>
#include <LibJS/Heap/Cell.h> #include <LibJS/Heap/Cell.h>
#include <LibJS/Runtime/Completion.h>
#include <LibJS/Runtime/Utf16String.h> #include <LibJS/Runtime/Utf16String.h>
#include <LibJS/Runtime/Value.h> #include <LibJS/Runtime/Value.h>
@ -20,7 +22,6 @@ class PrimitiveString final : public Cell {
JS_CELL(PrimitiveString, Cell); JS_CELL(PrimitiveString, Cell);
public: public:
[[nodiscard]] static NonnullGCPtr<PrimitiveString> create(VM&, Utf16View const&);
[[nodiscard]] static NonnullGCPtr<PrimitiveString> create(VM&, Utf16String); [[nodiscard]] static NonnullGCPtr<PrimitiveString> create(VM&, Utf16String);
[[nodiscard]] static NonnullGCPtr<PrimitiveString> create(VM&, DeprecatedString); [[nodiscard]] static NonnullGCPtr<PrimitiveString> create(VM&, DeprecatedString);
[[nodiscard]] static NonnullGCPtr<PrimitiveString> create(VM&, PrimitiveString&, PrimitiveString&); [[nodiscard]] static NonnullGCPtr<PrimitiveString> create(VM&, PrimitiveString&, PrimitiveString&);
@ -31,15 +32,16 @@ public:
PrimitiveString& operator=(PrimitiveString const&) = delete; PrimitiveString& operator=(PrimitiveString const&) = delete;
bool is_empty() const; bool is_empty() const;
u32 hash() const;
DeprecatedString const& deprecated_string() const; ThrowCompletionOr<DeprecatedString const&> deprecated_string() const;
bool has_utf8_string() const { return m_has_utf8_string; } bool has_utf8_string() const { return m_utf8_string.has_value(); }
Utf16String const& utf16_string() const; ThrowCompletionOr<Utf16String const&> utf16_string() const;
Utf16View utf16_string_view() const; ThrowCompletionOr<Utf16View> utf16_string_view() const;
bool has_utf16_string() const { return m_has_utf16_string; } bool has_utf16_string() const { return m_utf16_string.has_value(); }
Optional<Value> get(VM&, PropertyKey const&) const; ThrowCompletionOr<Optional<Value>> get(VM&, PropertyKey const&) const;
private: private:
explicit PrimitiveString(PrimitiveString&, PrimitiveString&); explicit PrimitiveString(PrimitiveString&, PrimitiveString&);
@ -48,18 +50,15 @@ private:
virtual void visit_edges(Cell::Visitor&) override; virtual void visit_edges(Cell::Visitor&) override;
void resolve_rope_if_needed() const; ThrowCompletionOr<void> resolve_rope_if_needed() const;
mutable bool m_is_rope { false }; mutable bool m_is_rope { false };
mutable bool m_has_utf8_string { false };
mutable bool m_has_utf16_string { false };
mutable PrimitiveString* m_lhs { nullptr }; mutable PrimitiveString* m_lhs { nullptr };
mutable PrimitiveString* m_rhs { nullptr }; mutable PrimitiveString* m_rhs { nullptr };
mutable DeprecatedString m_utf8_string; mutable Optional<DeprecatedString> m_utf8_string;
mutable Optional<Utf16String> m_utf16_string;
mutable Utf16String m_utf16_string;
}; };
} }

View file

@ -114,7 +114,7 @@ ThrowCompletionOr<Value> Reference::get_value(VM& vm) const
// OPTIMIZATION: For various primitives we can avoid actually creating a new object for them. // OPTIMIZATION: For various primitives we can avoid actually creating a new object for them.
Object* base_obj = nullptr; Object* base_obj = nullptr;
if (m_base_value.is_string()) { if (m_base_value.is_string()) {
auto string_value = m_base_value.as_string().get(vm, m_name); auto string_value = TRY(m_base_value.as_string().get(vm, m_name));
if (string_value.has_value()) if (string_value.has_value())
return *string_value; return *string_value;
base_obj = realm.intrinsics().string_prototype(); base_obj = realm.intrinsics().string_prototype();

View file

@ -68,7 +68,7 @@ ThrowCompletionOr<void> set_legacy_regexp_static_property(VM& vm, RegExpConstruc
} }
// UpdateLegacyRegExpStaticProperties ( C, S, startIndex, endIndex, capturedValues ), https://github.com/tc39/proposal-regexp-legacy-features#updatelegacyregexpstaticproperties--c-s-startindex-endindex-capturedvalues- // UpdateLegacyRegExpStaticProperties ( C, S, startIndex, endIndex, capturedValues ), https://github.com/tc39/proposal-regexp-legacy-features#updatelegacyregexpstaticproperties--c-s-startindex-endindex-capturedvalues-
void update_legacy_regexp_static_properties(RegExpConstructor& constructor, Utf16String const& string, size_t start_index, size_t end_index, Vector<Utf16String> const& captured_values) ThrowCompletionOr<void> update_legacy_regexp_static_properties(VM& vm, RegExpConstructor& constructor, Utf16String const& string, size_t start_index, size_t end_index, Vector<Utf16String> const& captured_values)
{ {
auto& legacy_static_properties = constructor.legacy_static_properties(); auto& legacy_static_properties = constructor.legacy_static_properties();
@ -92,7 +92,7 @@ void update_legacy_regexp_static_properties(RegExpConstructor& constructor, Utf1
// 8. Set the value of Cs [[RegExpLastMatch]] internal slot to a String whose length is endIndex - startIndex and containing the code units from S with indices startIndex through endIndex - 1, in ascending order. // 8. Set the value of Cs [[RegExpLastMatch]] internal slot to a String whose length is endIndex - startIndex and containing the code units from S with indices startIndex through endIndex - 1, in ascending order.
auto last_match = string.view().substring_view(start_index, end_index - start_index); auto last_match = string.view().substring_view(start_index, end_index - start_index);
legacy_static_properties.set_last_match(Utf16String(last_match)); legacy_static_properties.set_last_match(TRY(Utf16String::create(vm, last_match)));
// 9. If n > 0, set the value of Cs [[RegExpLastParen]] internal slot to the last element of capturedValues. // 9. If n > 0, set the value of Cs [[RegExpLastParen]] internal slot to the last element of capturedValues.
if (group_count > 0) { if (group_count > 0) {
@ -101,49 +101,45 @@ void update_legacy_regexp_static_properties(RegExpConstructor& constructor, Utf1
} }
// 10. Else, set the value of Cs [[RegExpLastParen]] internal slot to the empty String. // 10. Else, set the value of Cs [[RegExpLastParen]] internal slot to the empty String.
else { else {
legacy_static_properties.set_last_paren(Utf16String(""sv)); legacy_static_properties.set_last_paren(TRY(Utf16String::create(vm)));
} }
// 11. Set the value of Cs [[RegExpLeftContext]] internal slot to a String whose length is startIndex and containing the code units from S with indices 0 through startIndex - 1, in ascending order. // 11. Set the value of Cs [[RegExpLeftContext]] internal slot to a String whose length is startIndex and containing the code units from S with indices 0 through startIndex - 1, in ascending order.
auto left_context = string.view().substring_view(0, start_index); auto left_context = string.view().substring_view(0, start_index);
legacy_static_properties.set_left_context(Utf16String(left_context)); legacy_static_properties.set_left_context(TRY(Utf16String::create(vm, left_context)));
// 12. Set the value of Cs [[RegExpRightContext]] internal slot to a String whose length is len - endIndex and containing the code units from S with indices endIndex through len - 1, in ascending order. // 12. Set the value of Cs [[RegExpRightContext]] internal slot to a String whose length is len - endIndex and containing the code units from S with indices endIndex through len - 1, in ascending order.
auto right_context = string.view().substring_view(end_index, len - end_index); auto right_context = string.view().substring_view(end_index, len - end_index);
legacy_static_properties.set_right_context(Utf16String(right_context)); legacy_static_properties.set_right_context(TRY(Utf16String::create(vm, right_context)));
// 13. For each integer i such that 1 ≤ i ≤ 9 // 13. For each integer i such that 1 ≤ i ≤ 9
for (size_t i = 1; i <= 9; i++) { for (size_t i = 1; i <= 9; i++) {
auto value = Utf16String(""sv); // i. If i ≤ n, set the value of Cs [[RegExpPareni]] internal slot to the ith element of capturedValues.
// If i ≤ n, set the value of Cs [[RegExpPareni]] internal slot to the ith element of capturedValues. // ii. Else, set the value of Cs [[RegExpPareni]] internal slot to the empty String.
if (i <= group_count) { auto value = (i <= group_count) ? captured_values[i - 1] : TRY(Utf16String::create(vm));
value = captured_values[i - 1];
}
// Else, set the value of Cs [[RegExpPareni]] internal slot to the empty String.
else {
// It's already an empty string
}
if (i == 1) { if (i == 1) {
legacy_static_properties.set_$1(Utf16String(value)); legacy_static_properties.set_$1(move(value));
} else if (i == 2) { } else if (i == 2) {
legacy_static_properties.set_$2(Utf16String(value)); legacy_static_properties.set_$2(move(value));
} else if (i == 3) { } else if (i == 3) {
legacy_static_properties.set_$3(Utf16String(value)); legacy_static_properties.set_$3(move(value));
} else if (i == 4) { } else if (i == 4) {
legacy_static_properties.set_$4(Utf16String(value)); legacy_static_properties.set_$4(move(value));
} else if (i == 5) { } else if (i == 5) {
legacy_static_properties.set_$5(Utf16String(value)); legacy_static_properties.set_$5(move(value));
} else if (i == 6) { } else if (i == 6) {
legacy_static_properties.set_$6(Utf16String(value)); legacy_static_properties.set_$6(move(value));
} else if (i == 7) { } else if (i == 7) {
legacy_static_properties.set_$7(Utf16String(value)); legacy_static_properties.set_$7(move(value));
} else if (i == 8) { } else if (i == 8) {
legacy_static_properties.set_$8(Utf16String(value)); legacy_static_properties.set_$8(move(value));
} else if (i == 9) { } else if (i == 9) {
legacy_static_properties.set_$9(Utf16String(value)); legacy_static_properties.set_$9(move(value));
} }
} }
return {};
} }
// InvalidateLegacyRegExpStaticProperties ( C ), https://github.com/tc39/proposal-regexp-legacy-features#invalidatelegacyregexpstaticproperties--c // InvalidateLegacyRegExpStaticProperties ( C ), https://github.com/tc39/proposal-regexp-legacy-features#invalidatelegacyregexpstaticproperties--c

View file

@ -73,7 +73,7 @@ private:
ThrowCompletionOr<void> set_legacy_regexp_static_property(VM& vm, RegExpConstructor& constructor, Value this_value, void (RegExpLegacyStaticProperties::*property_setter)(Utf16String), Value value); ThrowCompletionOr<void> set_legacy_regexp_static_property(VM& vm, RegExpConstructor& constructor, Value this_value, void (RegExpLegacyStaticProperties::*property_setter)(Utf16String), Value value);
ThrowCompletionOr<Value> get_legacy_regexp_static_property(VM& vm, RegExpConstructor& constructor, Value this_value, Optional<Utf16String> const& (RegExpLegacyStaticProperties::*property_getter)() const); ThrowCompletionOr<Value> get_legacy_regexp_static_property(VM& vm, RegExpConstructor& constructor, Value this_value, Optional<Utf16String> const& (RegExpLegacyStaticProperties::*property_getter)() const);
void update_legacy_regexp_static_properties(RegExpConstructor& constructor, Utf16String const& string, size_t start_index, size_t end_index, Vector<Utf16String> const& captured_values); ThrowCompletionOr<void> update_legacy_regexp_static_properties(VM& vm, RegExpConstructor& constructor, Utf16String const& string, size_t start_index, size_t end_index, Vector<Utf16String> const& captured_values);
void invalidate_legacy_regexp_static_properties(RegExpConstructor& constructor); void invalidate_legacy_regexp_static_properties(RegExpConstructor& constructor);
} }

View file

@ -275,7 +275,7 @@ static ThrowCompletionOr<Value> regexp_builtin_exec(VM& vm, RegExpObject& regexp
// 27. Let matchedValue be ! GetMatchString(S, match). // 27. Let matchedValue be ! GetMatchString(S, match).
// 28. Perform ! CreateDataPropertyOrThrow(A, "0", matchedValue). // 28. Perform ! CreateDataPropertyOrThrow(A, "0", matchedValue).
MUST(array->create_data_property_or_throw(0, PrimitiveString::create(vm, match.view.u16_view()))); MUST(array->create_data_property_or_throw(0, PrimitiveString::create(vm, TRY(Utf16String::create(vm, match.view.u16_view())))));
// 29. If R contains any GroupName, then // 29. If R contains any GroupName, then
// a. Let groups be OrdinaryObjectCreate(null). // a. Let groups be OrdinaryObjectCreate(null).
@ -300,7 +300,7 @@ static ThrowCompletionOr<Value> regexp_builtin_exec(VM& vm, RegExpObject& regexp
// ii. Append undefined to indices. // ii. Append undefined to indices.
indices.append({}); indices.append({});
// iii. Append capture to indices. // iii. Append capture to indices.
captured_values.append(Utf16String(""sv)); captured_values.append(TRY(Utf16String::create(vm)));
} }
// c. Else, // c. Else,
else { else {
@ -311,7 +311,7 @@ static ThrowCompletionOr<Value> regexp_builtin_exec(VM& vm, RegExpObject& regexp
// 2. Set captureEnd to ! GetStringIndex(S, Input, captureEnd). // 2. Set captureEnd to ! GetStringIndex(S, Input, captureEnd).
// iv. Let capture be the Match { [[StartIndex]]: captureStart, [[EndIndex]: captureEnd }. // iv. Let capture be the Match { [[StartIndex]]: captureStart, [[EndIndex]: captureEnd }.
// v. Let capturedValue be ! GetMatchString(S, capture). // v. Let capturedValue be ! GetMatchString(S, capture).
auto capture_as_utf16_string = Utf16String(capture.view.u16_view()); auto capture_as_utf16_string = TRY(Utf16String::create(vm, capture.view.u16_view()));
captured_value = PrimitiveString::create(vm, capture_as_utf16_string); captured_value = PrimitiveString::create(vm, capture_as_utf16_string);
// vi. Append capture to indices. // vi. Append capture to indices.
indices.append(Match::create(capture)); indices.append(Match::create(capture));
@ -351,7 +351,7 @@ static ThrowCompletionOr<Value> regexp_builtin_exec(VM& vm, RegExpObject& regexp
if (regexp_object.legacy_features_enabled()) { if (regexp_object.legacy_features_enabled()) {
// a. Perform UpdateLegacyRegExpStaticProperties(%RegExp%, S, lastIndex, e, capturedValues). // a. Perform UpdateLegacyRegExpStaticProperties(%RegExp%, S, lastIndex, e, capturedValues).
auto* regexp_constructor = realm.intrinsics().regexp_constructor(); auto* regexp_constructor = realm.intrinsics().regexp_constructor();
update_legacy_regexp_static_properties(*regexp_constructor, string, match_indices.start_index, match_indices.end_index, captured_values); TRY(update_legacy_regexp_static_properties(vm, *regexp_constructor, string, match_indices.start_index, match_indices.end_index, captured_values));
} }
// ii. Else, // ii. Else,
else { else {
@ -998,7 +998,7 @@ JS_DEFINE_NATIVE_FUNCTION(RegExpPrototype::symbol_split)
auto substring = string.substring_view(last_match_end, next_search_from - last_match_end); auto substring = string.substring_view(last_match_end, next_search_from - last_match_end);
// 2. Perform ! CreateDataPropertyOrThrow(A, ! ToString(𝔽(lengthA)), T). // 2. Perform ! CreateDataPropertyOrThrow(A, ! ToString(𝔽(lengthA)), T).
MUST(array->create_data_property_or_throw(array_length, PrimitiveString::create(vm, substring))); MUST(array->create_data_property_or_throw(array_length, PrimitiveString::create(vm, TRY(Utf16String::create(vm, substring)))));
// 3. Set lengthA to lengthA + 1. // 3. Set lengthA to lengthA + 1.
++array_length; ++array_length;
@ -1045,7 +1045,7 @@ JS_DEFINE_NATIVE_FUNCTION(RegExpPrototype::symbol_split)
auto substring = string.substring_view(last_match_end); auto substring = string.substring_view(last_match_end);
// 21. Perform ! CreateDataPropertyOrThrow(A, ! ToString(𝔽(lengthA)), T). // 21. Perform ! CreateDataPropertyOrThrow(A, ! ToString(𝔽(lengthA)), T).
MUST(array->create_data_property_or_throw(array_length, PrimitiveString::create(vm, substring))); MUST(array->create_data_property_or_throw(array_length, PrimitiveString::create(vm, TRY(Utf16String::create(vm, substring)))));
// 22. Return A. // 22. Return A.
return array; return array;

View file

@ -86,7 +86,7 @@ ThrowCompletionOr<void> copy_name_and_length(VM& vm, FunctionObject& function, F
target_name = PrimitiveString::create(vm, DeprecatedString::empty()); target_name = PrimitiveString::create(vm, DeprecatedString::empty());
// 8. Perform SetFunctionName(F, targetName, prefix). // 8. Perform SetFunctionName(F, targetName, prefix).
function.set_function_name({ target_name.as_string().deprecated_string() }, move(prefix)); function.set_function_name({ TRY(target_name.as_string().deprecated_string()) }, move(prefix));
return {}; return {};
} }
@ -272,7 +272,7 @@ ThrowCompletionOr<Value> shadow_realm_import_value(VM& vm, DeprecatedString spec
// NOTE: Even though the spec tells us to use %ThrowTypeError%, it's not observable if we actually do. // NOTE: Even though the spec tells us to use %ThrowTypeError%, it's not observable if we actually do.
// Throw a nicer TypeError forwarding the import error message instead (we know the argument is an Error object). // Throw a nicer TypeError forwarding the import error message instead (we know the argument is an Error object).
auto throw_type_error = NativeFunction::create(realm, {}, [](auto& vm) -> ThrowCompletionOr<Value> { auto throw_type_error = NativeFunction::create(realm, {}, [](auto& vm) -> ThrowCompletionOr<Value> {
return vm.template throw_completion<TypeError>(vm.argument(0).as_object().get_without_side_effects(vm.names.message).as_string().deprecated_string()); return vm.template throw_completion<TypeError>(TRY(vm.argument(0).as_object().get_without_side_effects(vm.names.message).as_string().deprecated_string()));
}); });
// 13. Return PerformPromiseThen(innerCapability.[[Promise]], onFulfilled, callerRealm.[[Intrinsics]].[[%ThrowTypeError%]], promiseCapability). // 13. Return PerformPromiseThen(innerCapability.[[Promise]], onFulfilled, callerRealm.[[Intrinsics]].[[%ThrowTypeError%]], promiseCapability).

View file

@ -49,7 +49,7 @@ JS_DEFINE_NATIVE_FUNCTION(ShadowRealmPrototype::evaluate)
auto& eval_realm = object->shadow_realm(); auto& eval_realm = object->shadow_realm();
// 6. Return ? PerformShadowRealmEval(sourceText, callerRealm, evalRealm). // 6. Return ? PerformShadowRealmEval(sourceText, callerRealm, evalRealm).
return perform_shadow_realm_eval(vm, source_text.as_string().deprecated_string(), *caller_realm, eval_realm); return perform_shadow_realm_eval(vm, TRY(source_text.as_string().deprecated_string()), *caller_realm, eval_realm);
} }
// 3.4.2 ShadowRealm.prototype.importValue ( specifier, exportName ), https://tc39.es/proposal-shadowrealm/#sec-shadowrealm.prototype.importvalue // 3.4.2 ShadowRealm.prototype.importValue ( specifier, exportName ), https://tc39.es/proposal-shadowrealm/#sec-shadowrealm.prototype.importvalue
@ -79,7 +79,7 @@ JS_DEFINE_NATIVE_FUNCTION(ShadowRealmPrototype::import_value)
auto& eval_context = object->execution_context(); auto& eval_context = object->execution_context();
// 8. Return ? ShadowRealmImportValue(specifierString, exportNameString, callerRealm, evalRealm, evalContext). // 8. Return ? ShadowRealmImportValue(specifierString, exportNameString, callerRealm, evalRealm, evalContext).
return shadow_realm_import_value(vm, move(specifier_string), export_name.as_string().deprecated_string(), *caller_realm, eval_realm, eval_context); return shadow_realm_import_value(vm, move(specifier_string), TRY(export_name.as_string().deprecated_string()), *caller_realm, eval_realm, eval_context);
} }
} }

View file

@ -106,7 +106,7 @@ JS_DEFINE_NATIVE_FUNCTION(StringConstructor::from_char_code)
for (size_t i = 0; i < vm.argument_count(); ++i) for (size_t i = 0; i < vm.argument_count(); ++i)
string.append(TRY(vm.argument(i).to_u16(vm))); string.append(TRY(vm.argument(i).to_u16(vm)));
return PrimitiveString::create(vm, Utf16String(move(string))); return PrimitiveString::create(vm, TRY(Utf16String::create(vm, move(string))));
} }
// 22.1.2.2 String.fromCodePoint ( ...codePoints ), https://tc39.es/ecma262/#sec-string.fromcodepoint // 22.1.2.2 String.fromCodePoint ( ...codePoints ), https://tc39.es/ecma262/#sec-string.fromcodepoint
@ -126,7 +126,7 @@ JS_DEFINE_NATIVE_FUNCTION(StringConstructor::from_code_point)
TRY_OR_THROW_OOM(vm, code_point_to_utf16(string, static_cast<u32>(code_point))); TRY_OR_THROW_OOM(vm, code_point_to_utf16(string, static_cast<u32>(code_point)));
} }
return PrimitiveString::create(vm, Utf16String(move(string))); return PrimitiveString::create(vm, TRY(Utf16String::create(vm, move(string))));
} }
} }

View file

@ -30,7 +30,9 @@ void StringObject::initialize(Realm& realm)
{ {
auto& vm = this->vm(); auto& vm = this->vm();
Object::initialize(realm); Object::initialize(realm);
define_direct_property(vm.names.length, Value(m_string.utf16_string_view().length_in_code_units()), 0);
// FIXME: Propagate this error.
define_direct_property(vm.names.length, Value(MUST(m_string.utf16_string_view()).length_in_code_units()), 0);
} }
void StringObject::visit_edges(Cell::Visitor& visitor) void StringObject::visit_edges(Cell::Visitor& visitor)
@ -40,7 +42,7 @@ void StringObject::visit_edges(Cell::Visitor& visitor)
} }
// 10.4.3.5 StringGetOwnProperty ( S, P ), https://tc39.es/ecma262/#sec-stringgetownproperty // 10.4.3.5 StringGetOwnProperty ( S, P ), https://tc39.es/ecma262/#sec-stringgetownproperty
static Optional<PropertyDescriptor> string_get_own_property(StringObject const& string, PropertyKey const& property_key) static ThrowCompletionOr<Optional<PropertyDescriptor>> string_get_own_property(StringObject const& string, PropertyKey const& property_key)
{ {
VERIFY(property_key.is_valid()); VERIFY(property_key.is_valid());
@ -48,7 +50,7 @@ static Optional<PropertyDescriptor> string_get_own_property(StringObject const&
// NOTE: The spec only uses string and symbol keys, and later coerces to numbers - // NOTE: The spec only uses string and symbol keys, and later coerces to numbers -
// this is not the case for PropertyKey, so '!property_key.is_string()' would be wrong. // this is not the case for PropertyKey, so '!property_key.is_string()' would be wrong.
if (property_key.is_symbol()) if (property_key.is_symbol())
return {}; return Optional<PropertyDescriptor> {};
// 2. Let index be CanonicalNumericIndexString(P). // 2. Let index be CanonicalNumericIndexString(P).
auto index = canonical_numeric_index_string(property_key, CanonicalIndexMode::IgnoreNumericRoundtrip); auto index = canonical_numeric_index_string(property_key, CanonicalIndexMode::IgnoreNumericRoundtrip);
@ -57,21 +59,21 @@ static Optional<PropertyDescriptor> string_get_own_property(StringObject const&
// 4. If IsIntegralNumber(index) is false, return undefined. // 4. If IsIntegralNumber(index) is false, return undefined.
// 5. If index is -0𝔽, return undefined. // 5. If index is -0𝔽, return undefined.
if (!index.is_index()) if (!index.is_index())
return {}; return Optional<PropertyDescriptor> {};
// 6. Let str be S.[[StringData]]. // 6. Let str be S.[[StringData]].
// 7. Assert: Type(str) is String. // 7. Assert: Type(str) is String.
auto str = string.primitive_string().utf16_string_view(); auto str = TRY(string.primitive_string().utf16_string_view());
// 8. Let len be the length of str. // 8. Let len be the length of str.
auto length = str.length_in_code_units(); auto length = str.length_in_code_units();
// 9. If (index) < 0 or len ≤ (index), return undefined. // 9. If (index) < 0 or len ≤ (index), return undefined.
if (length <= index.as_index()) if (length <= index.as_index())
return {}; return Optional<PropertyDescriptor> {};
// 10. Let resultStr be the String value of length 1, containing one code unit from str, specifically the code unit at index (index). // 10. Let resultStr be the String value of length 1, containing one code unit from str, specifically the code unit at index (index).
auto result_str = PrimitiveString::create(string.vm(), str.substring_view(index.as_index(), 1)); auto result_str = PrimitiveString::create(string.vm(), TRY(Utf16String::create(string.vm(), str.substring_view(index.as_index(), 1))));
// 11. Return the PropertyDescriptor { [[Value]]: resultStr, [[Writable]]: false, [[Enumerable]]: true, [[Configurable]]: false }. // 11. Return the PropertyDescriptor { [[Value]]: resultStr, [[Writable]]: false, [[Enumerable]]: true, [[Configurable]]: false }.
return PropertyDescriptor { return PropertyDescriptor {
@ -104,7 +106,7 @@ ThrowCompletionOr<bool> StringObject::internal_define_own_property(PropertyKey c
VERIFY(property_key.is_valid()); VERIFY(property_key.is_valid());
// 1. Let stringDesc be StringGetOwnProperty(S, P). // 1. Let stringDesc be StringGetOwnProperty(S, P).
auto string_descriptor = string_get_own_property(*this, property_key); auto string_descriptor = TRY(string_get_own_property(*this, property_key));
// 2. If stringDesc is not undefined, then // 2. If stringDesc is not undefined, then
if (string_descriptor.has_value()) { if (string_descriptor.has_value()) {
@ -128,7 +130,7 @@ ThrowCompletionOr<MarkedVector<Value>> StringObject::internal_own_property_keys(
auto keys = MarkedVector<Value> { heap() }; auto keys = MarkedVector<Value> { heap() };
// 2. Let str be O.[[StringData]]. // 2. Let str be O.[[StringData]].
auto str = m_string.utf16_string_view(); auto str = TRY(m_string.utf16_string_view());
// 3. Assert: Type(str) is String. // 3. Assert: Type(str) is String.

View file

@ -237,7 +237,7 @@ JS_DEFINE_NATIVE_FUNCTION(StringPrototype::at)
return js_undefined(); return js_undefined();
// 7. Return ? Get(O, ! ToString(𝔽(k))). // 7. Return ? Get(O, ! ToString(𝔽(k))).
return PrimitiveString::create(vm, string.substring_view(index.value(), 1)); return PrimitiveString::create(vm, TRY(Utf16String::create(vm, string.substring_view(index.value(), 1))));
} }
// 22.1.3.2 String.prototype.charAt ( pos ), https://tc39.es/ecma262/#sec-string.prototype.charat // 22.1.3.2 String.prototype.charAt ( pos ), https://tc39.es/ecma262/#sec-string.prototype.charat
@ -248,7 +248,7 @@ JS_DEFINE_NATIVE_FUNCTION(StringPrototype::char_at)
if (position < 0 || position >= string.length_in_code_units()) if (position < 0 || position >= string.length_in_code_units())
return PrimitiveString::create(vm, DeprecatedString::empty()); return PrimitiveString::create(vm, DeprecatedString::empty());
return PrimitiveString::create(vm, string.substring_view(position, 1)); return PrimitiveString::create(vm, TRY(Utf16String::create(vm, string.substring_view(position, 1))));
} }
// 22.1.3.3 String.prototype.charCodeAt ( pos ), https://tc39.es/ecma262/#sec-string.prototype.charcodeat // 22.1.3.3 String.prototype.charCodeAt ( pos ), https://tc39.es/ecma262/#sec-string.prototype.charcodeat
@ -518,7 +518,7 @@ static ThrowCompletionOr<Value> pad_string(VM& vm, Utf16String string, PadPlacem
if (max_length <= string_length) if (max_length <= string_length)
return PrimitiveString::create(vm, move(string)); return PrimitiveString::create(vm, move(string));
Utf16String fill_string(Utf16Data { 0x20 }); auto fill_string = TRY(Utf16String::create(vm, Utf16Data { 0x20 }));
if (!vm.argument(1).is_undefined()) { if (!vm.argument(1).is_undefined()) {
fill_string = TRY(vm.argument(1).to_utf16_string(vm)); fill_string = TRY(vm.argument(1).to_utf16_string(vm));
if (fill_string.is_empty()) if (fill_string.is_empty())
@ -736,7 +736,7 @@ JS_DEFINE_NATIVE_FUNCTION(StringPrototype::slice)
if (int_start >= int_end) if (int_start >= int_end)
return PrimitiveString::create(vm, DeprecatedString::empty()); return PrimitiveString::create(vm, DeprecatedString::empty());
return PrimitiveString::create(vm, string.substring_view(int_start, int_end - int_start)); return PrimitiveString::create(vm, TRY(Utf16String::create(vm, string.substring_view(int_start, int_end - int_start))));
} }
// 22.1.3.22 String.prototype.split ( separator, limit ), https://tc39.es/ecma262/#sec-string.prototype.split // 22.1.3.22 String.prototype.split ( separator, limit ), https://tc39.es/ecma262/#sec-string.prototype.split
@ -793,7 +793,7 @@ JS_DEFINE_NATIVE_FUNCTION(StringPrototype::split)
} }
auto segment = string.substring_view(start, position - start); auto segment = string.substring_view(start, position - start);
MUST(array->create_data_property_or_throw(array_length, PrimitiveString::create(vm, segment))); MUST(array->create_data_property_or_throw(array_length, PrimitiveString::create(vm, TRY(Utf16String::create(vm, segment)))));
++array_length; ++array_length;
if (array_length == limit) if (array_length == limit)
return array; return array;
@ -802,7 +802,7 @@ JS_DEFINE_NATIVE_FUNCTION(StringPrototype::split)
} }
auto rest = string.substring_view(start); auto rest = string.substring_view(start);
MUST(array->create_data_property_or_throw(array_length, PrimitiveString::create(vm, rest))); MUST(array->create_data_property_or_throw(array_length, PrimitiveString::create(vm, TRY(Utf16String::create(vm, rest)))));
return array; return array;
} }
@ -867,7 +867,7 @@ JS_DEFINE_NATIVE_FUNCTION(StringPrototype::substring)
size_t to = max(final_start, final_end); size_t to = max(final_start, final_end);
// 10. Return the substring of S from from to to. // 10. Return the substring of S from from to to.
return PrimitiveString::create(vm, string.substring_view(from, to - from)); return PrimitiveString::create(vm, TRY(Utf16String::create(vm, string.substring_view(from, to - from))));
} }
enum class TargetCase { enum class TargetCase {
@ -1111,7 +1111,7 @@ JS_DEFINE_NATIVE_FUNCTION(StringPrototype::substr)
return PrimitiveString::create(vm, DeprecatedString::empty()); return PrimitiveString::create(vm, DeprecatedString::empty());
// 11. Return the substring of S from intStart to intEnd. // 11. Return the substring of S from intStart to intEnd.
return PrimitiveString::create(vm, string.substring_view(int_start, int_end - int_start)); return PrimitiveString::create(vm, TRY(Utf16String::create(vm, string.substring_view(int_start, int_end - int_start))));
} }
// B.2.2.2.1 CreateHTML ( string, tag, attribute, value ), https://tc39.es/ecma262/#sec-createhtml // B.2.2.2.1 CreateHTML ( string, tag, attribute, value ), https://tc39.es/ecma262/#sec-createhtml

View file

@ -146,8 +146,8 @@ ThrowCompletionOr<Value> get_option(VM& vm, Object const& options, PropertyKey c
if (!values.is_empty()) { if (!values.is_empty()) {
// NOTE: Every location in the spec that invokes GetOption with type=boolean also has values=undefined. // NOTE: Every location in the spec that invokes GetOption with type=boolean also has values=undefined.
VERIFY(value.is_string()); VERIFY(value.is_string());
if (!values.contains_slow(value.as_string().deprecated_string())) if (auto const& value_string = TRY(value.as_string().deprecated_string()); !values.contains_slow(value_string))
return vm.throw_completion<RangeError>(ErrorType::OptionIsNotValidValue, value.as_string().deprecated_string(), property.as_string()); return vm.throw_completion<RangeError>(ErrorType::OptionIsNotValidValue, value_string, property.as_string());
} }
// 9. Return value. // 9. Return value.
@ -165,7 +165,7 @@ ThrowCompletionOr<DeprecatedString> to_temporal_overflow(VM& vm, Object const* o
auto option = TRY(get_option(vm, *options, vm.names.overflow, OptionType::String, { "constrain"sv, "reject"sv }, "constrain"sv)); auto option = TRY(get_option(vm, *options, vm.names.overflow, OptionType::String, { "constrain"sv, "reject"sv }, "constrain"sv));
VERIFY(option.is_string()); VERIFY(option.is_string());
return option.as_string().deprecated_string(); return TRY(option.as_string().deprecated_string());
} }
// 13.5 ToTemporalDisambiguation ( options ), https://tc39.es/proposal-temporal/#sec-temporal-totemporaldisambiguation // 13.5 ToTemporalDisambiguation ( options ), https://tc39.es/proposal-temporal/#sec-temporal-totemporaldisambiguation
@ -179,7 +179,7 @@ ThrowCompletionOr<DeprecatedString> to_temporal_disambiguation(VM& vm, Object co
auto option = TRY(get_option(vm, *options, vm.names.disambiguation, OptionType::String, { "compatible"sv, "earlier"sv, "later"sv, "reject"sv }, "compatible"sv)); auto option = TRY(get_option(vm, *options, vm.names.disambiguation, OptionType::String, { "compatible"sv, "earlier"sv, "later"sv, "reject"sv }, "compatible"sv));
VERIFY(option.is_string()); VERIFY(option.is_string());
return option.as_string().deprecated_string(); return TRY(option.as_string().deprecated_string());
} }
// 13.6 ToTemporalRoundingMode ( normalizedOptions, fallback ), https://tc39.es/proposal-temporal/#sec-temporal-totemporalroundingmode // 13.6 ToTemporalRoundingMode ( normalizedOptions, fallback ), https://tc39.es/proposal-temporal/#sec-temporal-totemporalroundingmode
@ -202,7 +202,7 @@ ThrowCompletionOr<DeprecatedString> to_temporal_rounding_mode(VM& vm, Object con
fallback.view())); fallback.view()));
VERIFY(option.is_string()); VERIFY(option.is_string());
return option.as_string().deprecated_string(); return TRY(option.as_string().deprecated_string());
} }
// 13.7 NegateTemporalRoundingMode ( roundingMode ), https://tc39.es/proposal-temporal/#sec-temporal-negatetemporalroundingmode // 13.7 NegateTemporalRoundingMode ( roundingMode ), https://tc39.es/proposal-temporal/#sec-temporal-negatetemporalroundingmode
@ -239,7 +239,7 @@ ThrowCompletionOr<DeprecatedString> to_temporal_offset(VM& vm, Object const* opt
auto option = TRY(get_option(vm, *options, vm.names.offset, OptionType::String, { "prefer"sv, "use"sv, "ignore"sv, "reject"sv }, fallback.view())); auto option = TRY(get_option(vm, *options, vm.names.offset, OptionType::String, { "prefer"sv, "use"sv, "ignore"sv, "reject"sv }, fallback.view()));
VERIFY(option.is_string()); VERIFY(option.is_string());
return option.as_string().deprecated_string(); return TRY(option.as_string().deprecated_string());
} }
// 13.9 ToCalendarNameOption ( normalizedOptions ), https://tc39.es/proposal-temporal/#sec-temporal-tocalendarnameoption // 13.9 ToCalendarNameOption ( normalizedOptions ), https://tc39.es/proposal-temporal/#sec-temporal-tocalendarnameoption
@ -249,7 +249,7 @@ ThrowCompletionOr<DeprecatedString> to_calendar_name_option(VM& vm, Object const
auto option = TRY(get_option(vm, normalized_options, vm.names.calendarName, OptionType::String, { "auto"sv, "always"sv, "never"sv, "critical"sv }, "auto"sv)); auto option = TRY(get_option(vm, normalized_options, vm.names.calendarName, OptionType::String, { "auto"sv, "always"sv, "never"sv, "critical"sv }, "auto"sv));
VERIFY(option.is_string()); VERIFY(option.is_string());
return option.as_string().deprecated_string(); return TRY(option.as_string().deprecated_string());
} }
// 13.10 ToTimeZoneNameOption ( normalizedOptions ), https://tc39.es/proposal-temporal/#sec-temporal-totimezonenameoption // 13.10 ToTimeZoneNameOption ( normalizedOptions ), https://tc39.es/proposal-temporal/#sec-temporal-totimezonenameoption
@ -259,7 +259,7 @@ ThrowCompletionOr<DeprecatedString> to_time_zone_name_option(VM& vm, Object cons
auto option = TRY(get_option(vm, normalized_options, vm.names.timeZoneName, OptionType::String, { "auto"sv, "never"sv, "critical"sv }, "auto"sv)); auto option = TRY(get_option(vm, normalized_options, vm.names.timeZoneName, OptionType::String, { "auto"sv, "never"sv, "critical"sv }, "auto"sv));
VERIFY(option.is_string()); VERIFY(option.is_string());
return option.as_string().deprecated_string(); return TRY(option.as_string().deprecated_string());
} }
// 13.11 ToShowOffsetOption ( normalizedOptions ), https://tc39.es/proposal-temporal/#sec-temporal-toshowoffsetoption // 13.11 ToShowOffsetOption ( normalizedOptions ), https://tc39.es/proposal-temporal/#sec-temporal-toshowoffsetoption
@ -269,7 +269,7 @@ ThrowCompletionOr<DeprecatedString> to_show_offset_option(VM& vm, Object const&
auto option = TRY(get_option(vm, normalized_options, vm.names.offset, OptionType::String, { "auto"sv, "never"sv }, "auto"sv)); auto option = TRY(get_option(vm, normalized_options, vm.names.offset, OptionType::String, { "auto"sv, "never"sv }, "auto"sv));
VERIFY(option.is_string()); VERIFY(option.is_string());
return option.as_string().deprecated_string(); return TRY(option.as_string().deprecated_string());
} }
// 13.12 ToTemporalRoundingIncrement ( normalizedOptions, dividend, inclusive ), https://tc39.es/proposal-temporal/#sec-temporal-totemporalroundingincrement // 13.12 ToTemporalRoundingIncrement ( normalizedOptions, dividend, inclusive ), https://tc39.es/proposal-temporal/#sec-temporal-totemporalroundingincrement
@ -530,7 +530,7 @@ ThrowCompletionOr<Optional<DeprecatedString>> get_temporal_unit(VM& vm, Object c
Optional<DeprecatedString> value = option_value.is_undefined() Optional<DeprecatedString> value = option_value.is_undefined()
? Optional<DeprecatedString> {} ? Optional<DeprecatedString> {}
: option_value.as_string().deprecated_string(); : TRY(option_value.as_string().deprecated_string());
// 11. If value is listed in the Plural column of Table 13, then // 11. If value is listed in the Plural column of Table 13, then
for (auto const& row : temporal_units) { for (auto const& row : temporal_units) {

View file

@ -126,7 +126,7 @@ ThrowCompletionOr<Vector<DeprecatedString>> calendar_fields(VM& vm, Object& cale
Vector<DeprecatedString> result; Vector<DeprecatedString> result;
for (auto& value : list) for (auto& value : list)
result.append(value.as_string().deprecated_string()); result.append(TRY(value.as_string().deprecated_string()));
return result; return result;
} }
@ -781,7 +781,7 @@ ThrowCompletionOr<double> resolve_iso_month(VM& vm, Object const& fields)
// 6. Assert: Type(monthCode) is String. // 6. Assert: Type(monthCode) is String.
VERIFY(month_code.is_string()); VERIFY(month_code.is_string());
auto& month_code_string = month_code.as_string().deprecated_string(); auto const& month_code_string = TRY(month_code.as_string().deprecated_string());
// 7. If the length of monthCode is not 3, throw a RangeError exception. // 7. If the length of monthCode is not 3, throw a RangeError exception.
auto month_length = month_code_string.length(); auto month_length = month_code_string.length();
@ -943,7 +943,7 @@ ThrowCompletionOr<Object*> default_merge_calendar_fields(VM& vm, Object const& f
// 3. For each element key of fieldsKeys, do // 3. For each element key of fieldsKeys, do
for (auto& key : fields_keys) { for (auto& key : fields_keys) {
// a. If key is not "month" or "monthCode", then // a. If key is not "month" or "monthCode", then
if (key.as_string().deprecated_string() != vm.names.month.as_string() && key.as_string().deprecated_string() != vm.names.monthCode.as_string()) { if (!TRY(key.as_string().deprecated_string()).is_one_of(vm.names.month.as_string(), vm.names.monthCode.as_string())) {
auto property_key = MUST(PropertyKey::from_value(vm, key)); auto property_key = MUST(PropertyKey::from_value(vm, key));
// i. Let propValue be ? Get(fields, key). // i. Let propValue be ? Get(fields, key).
@ -977,7 +977,7 @@ ThrowCompletionOr<Object*> default_merge_calendar_fields(VM& vm, Object const& f
} }
// See comment above. // See comment above.
additional_fields_keys_contains_month_or_month_code_property |= key.as_string().deprecated_string() == vm.names.month.as_string() || key.as_string().deprecated_string() == vm.names.monthCode.as_string(); additional_fields_keys_contains_month_or_month_code_property |= TRY(key.as_string().deprecated_string()) == vm.names.month.as_string() || TRY(key.as_string().deprecated_string()) == vm.names.monthCode.as_string();
} }
// 6. If additionalFieldsKeys does not contain either "month" or "monthCode", then // 6. If additionalFieldsKeys does not contain either "month" or "monthCode", then

View file

@ -559,19 +559,21 @@ JS_DEFINE_NATIVE_FUNCTION(CalendarPrototype::fields)
return TRY(iterator_close(vm, iterator_record, move(completion))); return TRY(iterator_close(vm, iterator_record, move(completion)));
} }
auto const& next_value_string = TRY(next_value.as_string().deprecated_string());
// iii. If fieldNames contains nextValue, then // iii. If fieldNames contains nextValue, then
if (field_names.contains_slow(next_value)) { if (field_names.contains_slow(next_value)) {
// 1. Let completion be ThrowCompletion(a newly created RangeError object). // 1. Let completion be ThrowCompletion(a newly created RangeError object).
auto completion = vm.throw_completion<RangeError>(ErrorType::TemporalDuplicateCalendarField, next_value.as_string().deprecated_string()); auto completion = vm.throw_completion<RangeError>(ErrorType::TemporalDuplicateCalendarField, next_value_string);
// 2. Return ? IteratorClose(iteratorRecord, completion). // 2. Return ? IteratorClose(iteratorRecord, completion).
return TRY(iterator_close(vm, iterator_record, move(completion))); return TRY(iterator_close(vm, iterator_record, move(completion)));
} }
// iv. If nextValue is not one of "year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond", then // iv. If nextValue is not one of "year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond", then
if (!next_value.as_string().deprecated_string().is_one_of("year"sv, "month"sv, "monthCode"sv, "day"sv, "hour"sv, "minute"sv, "second"sv, "millisecond"sv, "microsecond"sv, "nanosecond"sv)) { if (!next_value_string.is_one_of("year"sv, "month"sv, "monthCode"sv, "day"sv, "hour"sv, "minute"sv, "second"sv, "millisecond"sv, "microsecond"sv, "nanosecond"sv)) {
// 1. Let completion be ThrowCompletion(a newly created RangeError object). // 1. Let completion be ThrowCompletion(a newly created RangeError object).
auto completion = vm.throw_completion<RangeError>(ErrorType::TemporalInvalidCalendarFieldName, next_value.as_string().deprecated_string()); auto completion = vm.throw_completion<RangeError>(ErrorType::TemporalInvalidCalendarFieldName, next_value_string);
// 2. Return ? IteratorClose(iteratorRecord, completion). // 2. Return ? IteratorClose(iteratorRecord, completion).
return TRY(iterator_close(vm, iterator_record, move(completion))); return TRY(iterator_close(vm, iterator_record, move(completion)));

View file

@ -801,7 +801,7 @@ JS_DEFINE_NATIVE_FUNCTION(ZonedDateTimePrototype::with)
// 18. Assert: Type(offsetString) is String. // 18. Assert: Type(offsetString) is String.
VERIFY(offset_string_value.is_string()); VERIFY(offset_string_value.is_string());
auto const& offset_string = offset_string_value.as_string().deprecated_string(); auto const& offset_string = TRY(offset_string_value.as_string().deprecated_string());
// 19. Let dateTimeResult be ? InterpretTemporalDateTimeFields(calendar, fields, options). // 19. Let dateTimeResult be ? InterpretTemporalDateTimeFields(calendar, fields, options).
auto date_time_result = TRY(interpret_temporal_date_time_fields(vm, calendar, *fields, *options)); auto date_time_result = TRY(interpret_temporal_date_time_fields(vm, calendar, *fields, *options));

View file

@ -11,9 +11,9 @@
namespace JS { namespace JS {
namespace Detail { namespace Detail {
static NonnullRefPtr<Utf16StringImpl> the_empty_utf16_string() static ThrowCompletionOr<NonnullRefPtr<Utf16StringImpl>> the_empty_utf16_string(VM& vm)
{ {
static NonnullRefPtr<Utf16StringImpl> empty_string = Utf16StringImpl::create(); static NonnullRefPtr<Utf16StringImpl> empty_string = TRY(Utf16StringImpl::create(vm));
return empty_string; return empty_string;
} }
@ -22,27 +22,27 @@ Utf16StringImpl::Utf16StringImpl(Utf16Data string)
{ {
} }
NonnullRefPtr<Utf16StringImpl> Utf16StringImpl::create() ThrowCompletionOr<NonnullRefPtr<Utf16StringImpl>> Utf16StringImpl::create(VM& vm)
{ {
return adopt_ref(*new Utf16StringImpl()); return TRY_OR_THROW_OOM(vm, adopt_nonnull_ref_or_enomem(new (nothrow) Utf16StringImpl()));
} }
NonnullRefPtr<Utf16StringImpl> Utf16StringImpl::create(Utf16Data string) ThrowCompletionOr<NonnullRefPtr<Utf16StringImpl>> Utf16StringImpl::create(VM& vm, Utf16Data string)
{ {
return adopt_ref(*new Utf16StringImpl(move(string))); return TRY_OR_THROW_OOM(vm, adopt_nonnull_ref_or_enomem(new (nothrow) Utf16StringImpl(move(string))));
} }
NonnullRefPtr<Utf16StringImpl> Utf16StringImpl::create(StringView string) ThrowCompletionOr<NonnullRefPtr<Utf16StringImpl>> Utf16StringImpl::create(VM& vm, StringView string)
{ {
return create(AK::utf8_to_utf16(string).release_value_but_fixme_should_propagate_errors()); return create(vm, TRY_OR_THROW_OOM(vm, utf8_to_utf16(string)));
} }
NonnullRefPtr<Utf16StringImpl> Utf16StringImpl::create(Utf16View const& view) ThrowCompletionOr<NonnullRefPtr<Utf16StringImpl>> Utf16StringImpl::create(VM& vm, Utf16View const& view)
{ {
Utf16Data string; Utf16Data string;
string.ensure_capacity(view.length_in_code_units()); TRY_OR_THROW_OOM(vm, string.try_ensure_capacity(view.length_in_code_units()));
string.append(view.data(), view.length_in_code_units()); string.unchecked_append(view.data(), view.length_in_code_units());
return create(move(string)); return create(vm, move(string));
} }
Utf16Data const& Utf16StringImpl::string() const Utf16Data const& Utf16StringImpl::string() const
@ -57,23 +57,28 @@ Utf16View Utf16StringImpl::view() const
} }
Utf16String::Utf16String() ThrowCompletionOr<Utf16String> Utf16String::create(VM& vm)
: m_string(Detail::the_empty_utf16_string())
{ {
return Utf16String { TRY(Detail::the_empty_utf16_string(vm)) };
} }
Utf16String::Utf16String(Utf16Data string) ThrowCompletionOr<Utf16String> Utf16String::create(VM& vm, Utf16Data string)
: m_string(Detail::Utf16StringImpl::create(move(string)))
{ {
return Utf16String { TRY(Detail::Utf16StringImpl::create(vm, move(string))) };
} }
Utf16String::Utf16String(StringView string) ThrowCompletionOr<Utf16String> Utf16String::create(VM& vm, StringView string)
: m_string(Detail::Utf16StringImpl::create(move(string)))
{ {
return Utf16String { TRY(Detail::Utf16StringImpl::create(vm, string)) };
} }
Utf16String::Utf16String(Utf16View const& string) ThrowCompletionOr<Utf16String> Utf16String::create(VM& vm, Utf16View const& string)
: m_string(Detail::Utf16StringImpl::create(move(string))) {
return Utf16String { TRY(Detail::Utf16StringImpl::create(vm, string)) };
}
Utf16String::Utf16String(NonnullRefPtr<Detail::Utf16StringImpl> string)
: m_string(move(string))
{ {
} }

View file

@ -21,10 +21,10 @@ class Utf16StringImpl : public RefCounted<Utf16StringImpl> {
public: public:
~Utf16StringImpl() = default; ~Utf16StringImpl() = default;
static NonnullRefPtr<Utf16StringImpl> create(); static ThrowCompletionOr<NonnullRefPtr<Utf16StringImpl>> create(VM&);
static NonnullRefPtr<Utf16StringImpl> create(Utf16Data); static ThrowCompletionOr<NonnullRefPtr<Utf16StringImpl>> create(VM&, Utf16Data);
static NonnullRefPtr<Utf16StringImpl> create(StringView); static ThrowCompletionOr<NonnullRefPtr<Utf16StringImpl>> create(VM&, StringView);
static NonnullRefPtr<Utf16StringImpl> create(Utf16View const&); static ThrowCompletionOr<NonnullRefPtr<Utf16StringImpl>> create(VM&, Utf16View const&);
Utf16Data const& string() const; Utf16Data const& string() const;
Utf16View view() const; Utf16View view() const;
@ -40,10 +40,10 @@ private:
class Utf16String { class Utf16String {
public: public:
Utf16String(); static ThrowCompletionOr<Utf16String> create(VM&);
explicit Utf16String(Utf16Data); static ThrowCompletionOr<Utf16String> create(VM&, Utf16Data);
explicit Utf16String(StringView); static ThrowCompletionOr<Utf16String> create(VM&, StringView);
explicit Utf16String(Utf16View const&); static ThrowCompletionOr<Utf16String> create(VM&, Utf16View const&);
Utf16Data const& string() const; Utf16Data const& string() const;
Utf16View view() const; Utf16View view() const;
@ -57,6 +57,8 @@ public:
bool is_empty() const; bool is_empty() const;
private: private:
explicit Utf16String(NonnullRefPtr<Detail::Utf16StringImpl>);
NonnullRefPtr<Detail::Utf16StringImpl> m_string; NonnullRefPtr<Detail::Utf16StringImpl> m_string;
}; };

View file

@ -351,7 +351,7 @@ DeprecatedString Value::to_string_without_side_effects() const
case INT32_TAG: case INT32_TAG:
return DeprecatedString::number(as_i32()); return DeprecatedString::number(as_i32());
case STRING_TAG: case STRING_TAG:
return as_string().deprecated_string(); return MUST(as_string().deprecated_string());
case SYMBOL_TAG: case SYMBOL_TAG:
return as_symbol().to_deprecated_string(); return as_symbol().to_deprecated_string();
case BIGINT_TAG: case BIGINT_TAG:
@ -382,7 +382,7 @@ ThrowCompletionOr<DeprecatedString> Value::to_string(VM& vm) const
switch (m_value.tag) { switch (m_value.tag) {
// 1. If argument is a String, return argument. // 1. If argument is a String, return argument.
case STRING_TAG: case STRING_TAG:
return as_string().deprecated_string(); return TRY(as_string().deprecated_string());
// 2. If argument is a Symbol, throw a TypeError exception. // 2. If argument is a Symbol, throw a TypeError exception.
case SYMBOL_TAG: case SYMBOL_TAG:
return vm.throw_completion<TypeError>(ErrorType::Convert, "symbol", "string"); return vm.throw_completion<TypeError>(ErrorType::Convert, "symbol", "string");
@ -421,10 +421,10 @@ ThrowCompletionOr<DeprecatedString> Value::to_string(VM& vm) const
ThrowCompletionOr<Utf16String> Value::to_utf16_string(VM& vm) const ThrowCompletionOr<Utf16String> Value::to_utf16_string(VM& vm) const
{ {
if (is_string()) if (is_string())
return as_string().utf16_string(); return TRY(as_string().utf16_string());
auto utf8_string = TRY(to_string(vm)); auto utf8_string = TRY(to_string(vm));
return Utf16String(utf8_string); return Utf16String::create(vm, utf8_string);
} }
// 7.1.2 ToBoolean ( argument ), https://tc39.es/ecma262/#sec-toboolean // 7.1.2 ToBoolean ( argument ), https://tc39.es/ecma262/#sec-toboolean
@ -684,7 +684,7 @@ ThrowCompletionOr<Value> Value::to_number(VM& vm) const
return Value(as_bool() ? 1 : 0); return Value(as_bool() ? 1 : 0);
// 6. If argument is a String, return StringToNumber(argument). // 6. If argument is a String, return StringToNumber(argument).
case STRING_TAG: case STRING_TAG:
return string_to_number(as_string().deprecated_string().view()); return string_to_number(TRY(as_string().deprecated_string()));
// 7. Assert: argument is an Object. // 7. Assert: argument is an Object.
case OBJECT_TAG: { case OBJECT_TAG: {
// 8. Let primValue be ? ToPrimitive(argument, number). // 8. Let primValue be ? ToPrimitive(argument, number).
@ -738,7 +738,7 @@ ThrowCompletionOr<BigInt*> Value::to_bigint(VM& vm) const
return &primitive.as_bigint(); return &primitive.as_bigint();
case STRING_TAG: { case STRING_TAG: {
// 1. Let n be ! StringToBigInt(prim). // 1. Let n be ! StringToBigInt(prim).
auto bigint = string_to_bigint(vm, primitive.as_string().deprecated_string()); auto bigint = string_to_bigint(vm, TRY(primitive.as_string().deprecated_string()));
// 2. If n is undefined, throw a SyntaxError exception. // 2. If n is undefined, throw a SyntaxError exception.
if (!bigint.has_value()) if (!bigint.has_value())
@ -2150,7 +2150,8 @@ bool same_value_non_number(Value lhs, Value rhs)
// 5. If x is a String, then // 5. If x is a String, then
if (lhs.is_string()) { if (lhs.is_string()) {
// a. If x and y are exactly the same sequence of code units (same length and same code units at corresponding indices), return true; otherwise, return false. // a. If x and y are exactly the same sequence of code units (same length and same code units at corresponding indices), return true; otherwise, return false.
return lhs.as_string().deprecated_string() == rhs.as_string().deprecated_string(); // FIXME: Propagate this error.
return MUST(lhs.as_string().deprecated_string()) == MUST(rhs.as_string().deprecated_string());
} }
// 3. If x is undefined, return true. // 3. If x is undefined, return true.
@ -2231,7 +2232,7 @@ ThrowCompletionOr<bool> is_loosely_equal(VM& vm, Value lhs, Value rhs)
// 7. If Type(x) is BigInt and Type(y) is String, then // 7. If Type(x) is BigInt and Type(y) is String, then
if (lhs.is_bigint() && rhs.is_string()) { if (lhs.is_bigint() && rhs.is_string()) {
// a. Let n be StringToBigInt(y). // a. Let n be StringToBigInt(y).
auto bigint = string_to_bigint(vm, rhs.as_string().deprecated_string()); auto bigint = string_to_bigint(vm, TRY(rhs.as_string().deprecated_string()));
// b. If n is undefined, return false. // b. If n is undefined, return false.
if (!bigint.has_value()) if (!bigint.has_value())
@ -2312,8 +2313,8 @@ ThrowCompletionOr<TriState> is_less_than(VM& vm, Value lhs, Value rhs, bool left
// 3. If px is a String and py is a String, then // 3. If px is a String and py is a String, then
if (x_primitive.is_string() && y_primitive.is_string()) { if (x_primitive.is_string() && y_primitive.is_string()) {
auto x_string = x_primitive.as_string().deprecated_string(); auto x_string = TRY(x_primitive.as_string().deprecated_string());
auto y_string = y_primitive.as_string().deprecated_string(); auto y_string = TRY(y_primitive.as_string().deprecated_string());
Utf8View x_code_points { x_string }; Utf8View x_code_points { x_string };
Utf8View y_code_points { y_string }; Utf8View y_code_points { y_string };
@ -2348,7 +2349,7 @@ ThrowCompletionOr<TriState> is_less_than(VM& vm, Value lhs, Value rhs, bool left
// a. If px is a BigInt and py is a String, then // a. If px is a BigInt and py is a String, then
if (x_primitive.is_bigint() && y_primitive.is_string()) { if (x_primitive.is_bigint() && y_primitive.is_string()) {
// i. Let ny be StringToBigInt(py). // i. Let ny be StringToBigInt(py).
auto y_bigint = string_to_bigint(vm, y_primitive.as_string().deprecated_string()); auto y_bigint = string_to_bigint(vm, TRY(y_primitive.as_string().deprecated_string()));
// ii. If ny is undefined, return undefined. // ii. If ny is undefined, return undefined.
if (!y_bigint.has_value()) if (!y_bigint.has_value())
@ -2363,7 +2364,7 @@ ThrowCompletionOr<TriState> is_less_than(VM& vm, Value lhs, Value rhs, bool left
// b. If px is a String and py is a BigInt, then // b. If px is a String and py is a BigInt, then
if (x_primitive.is_string() && y_primitive.is_bigint()) { if (x_primitive.is_string() && y_primitive.is_bigint()) {
// i. Let nx be StringToBigInt(px). // i. Let nx be StringToBigInt(px).
auto x_bigint = string_to_bigint(vm, x_primitive.as_string().deprecated_string()); auto x_bigint = string_to_bigint(vm, TRY(x_primitive.as_string().deprecated_string()));
// ii. If nx is undefined, return undefined. // ii. If nx is undefined, return undefined.
if (!x_bigint.has_value()) if (!x_bigint.has_value())

View file

@ -16,8 +16,10 @@ struct ValueTraits : public Traits<Value> {
static unsigned hash(Value value) static unsigned hash(Value value)
{ {
VERIFY(!value.is_empty()); VERIFY(!value.is_empty());
if (value.is_string()) if (value.is_string()) {
return value.as_string().deprecated_string().hash(); // FIXME: Propagate this error.
return value.as_string().deprecated_string().release_value().hash();
}
if (value.is_bigint()) if (value.is_bigint())
return value.as_bigint().big_integer().hash(); return value.as_bigint().big_integer().hash();

View file

@ -163,7 +163,7 @@ JS::NonnullGCPtr<JS::Promise> consume_body(JS::Realm& realm, BodyMixin const& ob
// 4. Let steps be to return the result of package data with the first argument given, type, and objects MIME type. // 4. Let steps be to return the result of package data with the first argument given, type, and objects MIME type.
auto steps = [&vm, &realm, &object, type](JS::Value value) -> WebIDL::ExceptionOr<JS::Value> { auto steps = [&vm, &realm, &object, type](JS::Value value) -> WebIDL::ExceptionOr<JS::Value> {
VERIFY(value.is_string()); VERIFY(value.is_string());
auto bytes = TRY_OR_THROW_OOM(vm, ByteBuffer::copy(value.as_string().deprecated_string().bytes())); auto bytes = TRY_OR_THROW_OOM(vm, ByteBuffer::copy(TRY(value.as_string().deprecated_string()).bytes()));
return package_data(realm, move(bytes), type, object.mime_type_impl()); return package_data(realm, move(bytes), type, object.mime_type_impl());
}; };

View file

@ -49,7 +49,7 @@ WebIDL::ExceptionOr<DeprecatedString> serialize_javascript_value_to_json_string(
VERIFY(result.is_string()); VERIFY(result.is_string());
// 4. Return result. // 4. Return result.
return result.as_string().deprecated_string(); return TRY(result.as_string().deprecated_string());
} }
// https://infra.spec.whatwg.org/#serialize-a-javascript-value-to-json-bytes // https://infra.spec.whatwg.org/#serialize-a-javascript-value-to-json-bytes

View file

@ -35,7 +35,7 @@ JS::ThrowCompletionOr<JS::NonnullGCPtr<JS::Object>> WebAssemblyTableConstructor:
auto element_value = TRY(descriptor->get("element")); auto element_value = TRY(descriptor->get("element"));
if (!element_value.is_string()) if (!element_value.is_string())
return vm.throw_completion<JS::TypeError>(JS::ErrorType::InvalidHint, element_value.to_string_without_side_effects()); return vm.throw_completion<JS::TypeError>(JS::ErrorType::InvalidHint, element_value.to_string_without_side_effects());
auto& element = element_value.as_string().deprecated_string(); auto const& element = TRY(element_value.as_string().deprecated_string());
Optional<Wasm::ValueType> reference_type; Optional<Wasm::ValueType> reference_type;
if (element == "anyfunc"sv) if (element == "anyfunc"sv)

View file

@ -95,7 +95,7 @@ static ErrorOr<JsonValue, ExecuteScriptResultType> internal_json_clone_algorithm
if (value.is_number()) if (value.is_number())
return JsonValue { value.as_double() }; return JsonValue { value.as_double() };
if (value.is_string()) if (value.is_string())
return JsonValue { value.as_string().deprecated_string() }; return JsonValue { TRY_OR_JS_ERROR(value.as_string().deprecated_string()) };
// NOTE: BigInt and Symbol not mentioned anywhere in the WebDriver spec, as it references ES5. // NOTE: BigInt and Symbol not mentioned anywhere in the WebDriver spec, as it references ES5.
// It assumes that all primitives are handled above, and the value is an object for the remaining steps. // It assumes that all primitives are handled above, and the value is an object for the remaining steps.
@ -114,7 +114,7 @@ static ErrorOr<JsonValue, ExecuteScriptResultType> internal_json_clone_algorithm
auto to_json_result = TRY_OR_JS_ERROR(to_json.as_function().internal_call(value, JS::MarkedVector<JS::Value> { vm.heap() })); auto to_json_result = TRY_OR_JS_ERROR(to_json.as_function().internal_call(value, JS::MarkedVector<JS::Value> { vm.heap() }));
if (!to_json_result.is_string()) if (!to_json_result.is_string())
return ExecuteScriptResultType::JavaScriptError; return ExecuteScriptResultType::JavaScriptError;
return to_json_result.as_string().deprecated_string(); return TRY_OR_JS_ERROR(to_json_result.as_string().deprecated_string());
} }
// -> Otherwise // -> Otherwise