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;
});
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));
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());
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);
if (!name_value.is_string())
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())
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);
if (!name_value.is_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())
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");
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);
return JS::js_null();
}
@ -255,7 +255,7 @@ JS_DEFINE_NATIVE_FUNCTION(SheetGlobalObject::parse_cell_name)
auto name_value = vm.argument(0);
if (!name_value.is_string())
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())
return JS::js_undefined();
@ -301,7 +301,7 @@ JS_DEFINE_NATIVE_FUNCTION(SheetGlobalObject::column_index)
if (!column_name.is_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));
@ -326,7 +326,7 @@ JS_DEFINE_NATIVE_FUNCTION(SheetGlobalObject::column_arithmetic)
if (!column_name.is_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_number = static_cast<i32>(offset.as_double());
@ -354,7 +354,7 @@ JS_DEFINE_NATIVE_FUNCTION(SheetGlobalObject::get_column_bound)
if (!column_name.is_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));
if (!is<SheetGlobalObject>(this_object))
@ -405,7 +405,7 @@ JS_DEFINE_NATIVE_FUNCTION(WorkbookObject::sheet)
auto& workbook = static_cast<WorkbookObject*>(this_object)->m_workbook;
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()) {
if (sheet.name() == name)
return JS::Value(&sheet.global_object());

View file

@ -3446,7 +3446,7 @@ Completion ImportCall::execute(Interpreter& interpreter) const
// 4. If supportedAssertions contains key, then
if (supported_assertions.contains_slow(property_key.to_string())) {
// 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:
else {
// 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.
data[0] = concat;
}

View file

@ -20,7 +20,7 @@ ThrowCompletionOr<Value> IsHTMLDDA::call()
auto& vm = this->vm();
if (vm.argument_count() == 0)
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();
// Not sure if this really matters, INTERPRETING.md simply says:
// * 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)
{
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"));
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: ");
TRY(print_value(print_context, &segments.segments_segmenter(), seen_objects));
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,
};
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);
// 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()) {
// 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).
time_value = parse_date_string(primitive.as_string().deprecated_string());
time_value = parse_date_string(TRY(primitive.as_string().deprecated_string()));
}
// iii. Else,
else {

View file

@ -1257,7 +1257,7 @@ JS_DEFINE_NATIVE_FUNCTION(DatePrototype::symbol_to_primitive)
auto hint_value = vm.argument(0);
if (!hint_value.is_string())
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;
if (hint == "string" || hint == "default")
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
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.
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
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]].
auto const& matcher = options.locale_matcher;
MatcherResult matcher_result;
// 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).
matcher_result = lookup_matcher(requested_locales);
}
@ -578,7 +578,7 @@ ThrowCompletionOr<Array*> supported_locales(VM& vm, Vector<DeprecatedString> con
Vector<DeprecatedString> supported_locales;
// 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).
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);
Optional<DeprecatedString> best_available_locale(StringView locale);
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> best_fit_supported_locales(Vector<DeprecatedString> const& requested_locales);
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));
// 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
// 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
if (!collation.is_undefined()) {
// 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);
// 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).
@ -69,13 +69,13 @@ static ThrowCompletionOr<Collator*> initialize_collator(VM& vm, Collator& collat
// 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 {}));
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]].
auto relevant_extension_keys = Collator::relevant_extension_keys();
// 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]].
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.
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).
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.
// 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) {
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)
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
if (!calendar.is_undefined()) {
// 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);
// 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).
@ -119,11 +119,11 @@ ThrowCompletionOr<DateTimeFormat*> initialize_date_time_format(VM& vm, DateTimeF
// 10. If numberingSystem is not undefined, then
if (!numbering_system.is_undefined()) {
// 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);
// 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).
@ -140,11 +140,11 @@ ThrowCompletionOr<DateTimeFormat*> initialize_date_time_format(VM& vm, DateTimeF
// 15. Set opt.[[hc]] to hourCycle.
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]].
// 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]].
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.
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
// i. Set hasExplicitFormatComponents to true.
@ -296,14 +296,14 @@ ThrowCompletionOr<DateTimeFormat*> initialize_date_time_format(VM& vm, DateTimeF
// 39. Set dateTimeFormat.[[DateStyle]] to dateStyle.
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).
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.
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 {};
@ -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());
// 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).
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;
// 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").
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.
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).
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);
// 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").
auto fallback = TRY(get_option(vm, *options, vm.names.fallback, OptionType::String, { "code"sv, "none"sv }, "code"sv));
// 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]].
display_names->set_locale(move(result.locale));
@ -119,7 +119,7 @@ ThrowCompletionOr<NonnullGCPtr<Object>> DisplayNamesConstructor::construct(Funct
// 26. If type is "language", then
if (display_names->type() == DisplayNames::Type::Language) {
// 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>]].
// 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));
// 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]].
// 6. If fields has a field [[<code>]], return fields.[[<code>]].
@ -57,48 +57,48 @@ JS_DEFINE_NATIVE_FUNCTION(DisplayNamesPrototype::of)
switch (display_names->type()) {
case DisplayNames::Type::Language:
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())
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());
break;
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;
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;
case DisplayNames::Type::Currency:
switch (display_names->style()) {
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;
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;
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;
default:
VERIFY_NOT_REACHED();
}
break;
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;
case DisplayNames::Type::DateTimeField:
switch (display_names->style()) {
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;
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;
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;
default:
VERIFY_NOT_REACHED();

View file

@ -308,7 +308,7 @@ ThrowCompletionOr<DurationUnitOptions> get_duration_unit_options(VM& vm, Depreca
}
}
} 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".
@ -332,7 +332,7 @@ ThrowCompletionOr<DurationUnitOptions> get_duration_unit_options(VM& vm, Depreca
}
// 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

View file

@ -67,17 +67,17 @@ ThrowCompletionOr<NonnullGCPtr<Object>> DurationFormatConstructor::construct(Fun
// 7. If numberingSystem is not undefined, then
if (!numbering_system.is_undefined()) {
// 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);
}
// 8. Let opt be the Record { [[localeMatcher]]: matcher, [[nu]]: numberingSystem }.
LocaleOptions opt {};
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]]).
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]].
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));
// 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]].
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;
// 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]].
(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.
list.append(next_value.as_string().deprecated_string());
list.append(TRY(next_value.as_string().deprecated_string()));
}
} while (next != nullptr);

View file

@ -71,7 +71,7 @@ ThrowCompletionOr<NonnullGCPtr<Object>> ListFormatConstructor::construct(Functio
// 8. Let localeData be %ListFormat%.[[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]].
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));
// 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").
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.
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.

View file

@ -33,10 +33,10 @@ static ThrowCompletionOr<Optional<DeprecatedString>> get_string_option(VM& vm, O
if (option.is_undefined())
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 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

View file

@ -1604,7 +1604,7 @@ ThrowCompletionOr<MathematicalValue> to_intl_mathematical_value(VM& vm, Value va
// 3. If Type(primValue) is String,
// 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.

View file

@ -103,16 +103,16 @@ ThrowCompletionOr<NumberFormat*> initialize_number_format(VM& vm, NumberFormat&
// 7. If numberingSystem is not undefined, then
if (!numbering_system.is_undefined()) {
// 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);
// 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]].
// 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]].
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));
// 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).
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));
// 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").
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
if (number_format.notation() == NumberFormat::Notation::Compact) {
// 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".
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));
// 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").
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.
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.
return &number_format;
@ -282,7 +282,7 @@ ThrowCompletionOr<void> set_number_format_digit_options(VM& vm, NumberFormatBase
bool need_fraction_digits = true;
// 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.
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
if (need_significant_digits || need_fraction_digits) {
// 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.
intl_object.set_rounding_type(NumberFormatBase::RoundingType::MorePrecision);
}
// 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.
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));
// 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).
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,
// 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);
// 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,
// 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);
// 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
if (intl_object.style() == NumberFormat::Style::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.
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.
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
if (intl_object.style() == NumberFormat::Style::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.
intl_object.set_unit_display(unit_display.as_string().deprecated_string());
intl_object.set_unit_display(TRY(unit_display.as_string().deprecated_string()));
}
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));
// 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").
TRY(set_number_format_digit_options(vm, plural_rules, *options, 0, 3, NumberFormat::Notation::Standard));
// 9. Let localeData be %PluralRules%.[[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]].
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
if (!numbering_system.is_undefined()) {
// 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);
// 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]].
// 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]].
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));
// 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").
auto numeric = TRY(get_option(vm, *options, vm.names.numeric, OptionType::String, { "always"sv, "auto"sv }, "always"sv));
// 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 »).
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);
// 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).
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
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();
@ -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);
// 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)).
MUST(result->create_data_property_or_throw(vm.names.index, Value(start_index)));
// 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]].
auto granularity = segmenter.segmenter_granularity();

View file

@ -37,7 +37,7 @@ private:
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 {
Before,
After,

View file

@ -71,7 +71,7 @@ ThrowCompletionOr<NonnullGCPtr<Object>> SegmenterConstructor::construct(Function
// 9. Let localeData be %Segmenter%.[[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]].
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));
// 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.
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());
// 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

View file

@ -63,7 +63,7 @@ ThrowCompletionOr<DeprecatedString> JSONObject::stringify_impl(VM& vm, Value val
auto replacer_value = TRY(replacer_object.get(i));
DeprecatedString item;
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()) {
item = MUST(replacer_value.to_string(vm));
} 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);
state.gap = space_mv < 1 ? DeprecatedString::empty() : DeprecatedString::repeated(' ', space_mv);
} else if (space.is_string()) {
auto string = space.as_string().deprecated_string();
auto string = TRY(space.as_string().deprecated_string());
if (string.length() <= 10)
state.gap = string;
else
@ -185,7 +185,7 @@ ThrowCompletionOr<DeprecatedString> JSONObject::serialize_json_property(VM& vm,
// 8. If Type(value) is String, return QuoteJSONString(value).
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
if (value.is_number()) {
@ -250,7 +250,7 @@ ThrowCompletionOr<DeprecatedString> JSONObject::serialize_json_object(VM& vm, St
} else {
auto property_list = TRY(object.enumerable_own_property_names(PropertyKind::Key));
for (auto& property : property_list)
TRY(process_property(property.as_string().deprecated_string()));
TRY(process_property(TRY(property.as_string().deprecated_string())));
}
StringBuilder builder;
if (property_strings.is_empty()) {
@ -473,7 +473,7 @@ ThrowCompletionOr<Value> JSONObject::internalize_json_property(VM& vm, Object* h
} else {
auto property_list = TRY(value_object.enumerable_own_property_names(Object::PropertyKind::Key));
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) {
if (!key.is_string())
continue;
FlyString property_key = key.as_string().deprecated_string();
FlyString property_key = TRY(key.as_string().deprecated_string());
if (visited.contains(property_key))
continue;
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())
tag = move(builtin_tag);
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 "]".
return PrimitiveString::create(vm, DeprecatedString::formatted("[object {}]", tag));

View file

@ -25,20 +25,19 @@ PrimitiveString::PrimitiveString(PrimitiveString& lhs, PrimitiveString& rhs)
}
PrimitiveString::PrimitiveString(DeprecatedString string)
: m_has_utf8_string(true)
, m_utf8_string(move(string))
: m_utf8_string(move(string))
{
}
PrimitiveString::PrimitiveString(Utf16String string)
: m_has_utf16_string(true)
, m_utf16_string(move(string))
: m_utf16_string(move(string))
{
}
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)
@ -57,62 +56,60 @@ bool PrimitiveString::is_empty() const
return false;
}
if (m_has_utf16_string)
return m_utf16_string.is_empty();
if (m_has_utf8_string)
return m_utf8_string.is_empty();
if (has_utf16_string())
return m_utf16_string->is_empty();
if (has_utf8_string())
return m_utf8_string->is_empty();
VERIFY_NOT_REACHED();
}
DeprecatedString const& PrimitiveString::deprecated_string() const
ThrowCompletionOr<DeprecatedString const&> PrimitiveString::deprecated_string() const
{
resolve_rope_if_needed();
if (!m_has_utf8_string) {
// FIXME: Propagate this error.
m_utf8_string = MUST(m_utf16_string.to_utf8(vm()));
m_has_utf8_string = true;
TRY(resolve_rope_if_needed());
if (!has_utf8_string()) {
VERIFY(has_utf16_string());
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();
if (!m_has_utf16_string) {
m_utf16_string = Utf16String(m_utf8_string);
m_has_utf16_string = true;
TRY(resolve_rope_if_needed());
if (!has_utf16_string()) {
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())
return {};
return Optional<Value> {};
if (property_key.is_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));
}
}
auto index = canonical_numeric_index_string(property_key, CanonicalIndexMode::IgnoreNumericRoundtrip);
if (!index.is_index())
return {};
auto str = utf16_string_view();
return Optional<Value> {};
auto str = TRY(utf16_string_view());
auto length = str.length_in_code_units();
if (length <= index.as_index())
return {};
return create(vm, str.substring_view(index.as_index(), 1));
}
NonnullGCPtr<PrimitiveString> PrimitiveString::create(VM& vm, Utf16View const& view)
{
return create(vm, Utf16String(view));
return Optional<Value> {};
return create(vm, TRY(Utf16String::create(vm, str.substring_view(index.as_index(), 1))));
}
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);
}
void PrimitiveString::resolve_rope_if_needed() const
ThrowCompletionOr<void> PrimitiveString::resolve_rope_if_needed() const
{
if (!m_is_rope)
return;
return {};
auto& vm = this->vm();
// NOTE: Special case for two concatenated UTF-16 strings.
// 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()) {
auto const& lhs_string = m_lhs->utf16_string();
auto const& rhs_string = m_rhs->utf16_string();
auto const& lhs_string = TRY(m_lhs->utf16_string());
auto const& rhs_string = TRY(m_rhs->utf16_string());
Utf16Data combined;
combined.ensure_capacity(lhs_string.length_in_code_units() + rhs_string.length_in_code_units());
combined.extend(lhs_string.string());
combined.extend(rhs_string.string());
m_utf16_string = Utf16String(move(combined));
m_has_utf16_string = true;
m_utf16_string = TRY(Utf16String::create(vm, move(combined)));
m_is_rope = false;
m_lhs = nullptr;
m_rhs = nullptr;
return;
return {};
}
// 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) {
if (!previous) {
// This is the very first piece, just append it and continue.
builder.append(current->deprecated_string());
builder.append(TRY(current->deprecated_string()));
previous = current;
continue;
}
// Get the UTF-8 representations for both strings.
auto const& previous_string_as_utf8 = previous->deprecated_string();
auto const& current_string_as_utf8 = current->deprecated_string();
auto const& previous_string_as_utf8 = TRY(previous->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
// of the current string, to see if they should be combined into a surrogate.
// Surrogates encoded as UTF-8 are 3 bytes.
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;
continue;
}
@ -243,7 +241,7 @@ void PrimitiveString::resolve_rope_if_needed() const
// 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 not, just append the current string and continue.
builder.append(current->deprecated_string());
builder.append(TRY(current->deprecated_string()));
previous = current;
continue;
}
@ -251,7 +249,7 @@ void PrimitiveString::resolve_rope_if_needed() const
// Might the current string begin with a UTF-8 encoded surrogate?
if ((static_cast<u8>(current_string_as_utf8[0]) & 0xf0) != 0xe0) {
// If not, just append the current string and continue.
builder.append(current->deprecated_string());
builder.append(TRY(current->deprecated_string()));
previous = current;
continue;
}
@ -260,7 +258,7 @@ void PrimitiveString::resolve_rope_if_needed() const
auto low_surrogate = *Utf8View(current_string_as_utf8).begin();
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;
continue;
}
@ -275,10 +273,10 @@ void PrimitiveString::resolve_rope_if_needed() const
}
m_utf8_string = builder.to_deprecated_string();
m_has_utf8_string = true;
m_is_rope = false;
m_lhs = nullptr;
m_rhs = nullptr;
return {};
}
}

View file

@ -8,9 +8,11 @@
#pragma once
#include <AK/DeprecatedString.h>
#include <AK/Optional.h>
#include <AK/StringView.h>
#include <LibJS/Forward.h>
#include <LibJS/Heap/Cell.h>
#include <LibJS/Runtime/Completion.h>
#include <LibJS/Runtime/Utf16String.h>
#include <LibJS/Runtime/Value.h>
@ -20,7 +22,6 @@ class PrimitiveString final : public Cell {
JS_CELL(PrimitiveString, Cell);
public:
[[nodiscard]] static NonnullGCPtr<PrimitiveString> create(VM&, Utf16View const&);
[[nodiscard]] static NonnullGCPtr<PrimitiveString> create(VM&, Utf16String);
[[nodiscard]] static NonnullGCPtr<PrimitiveString> create(VM&, DeprecatedString);
[[nodiscard]] static NonnullGCPtr<PrimitiveString> create(VM&, PrimitiveString&, PrimitiveString&);
@ -31,15 +32,16 @@ public:
PrimitiveString& operator=(PrimitiveString const&) = delete;
bool is_empty() const;
u32 hash() const;
DeprecatedString const& deprecated_string() const;
bool has_utf8_string() const { return m_has_utf8_string; }
ThrowCompletionOr<DeprecatedString const&> deprecated_string() const;
bool has_utf8_string() const { return m_utf8_string.has_value(); }
Utf16String const& utf16_string() const;
Utf16View utf16_string_view() const;
bool has_utf16_string() const { return m_has_utf16_string; }
ThrowCompletionOr<Utf16String const&> utf16_string() const;
ThrowCompletionOr<Utf16View> utf16_string_view() const;
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:
explicit PrimitiveString(PrimitiveString&, PrimitiveString&);
@ -48,18 +50,15 @@ private:
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_has_utf8_string { false };
mutable bool m_has_utf16_string { false };
mutable PrimitiveString* m_lhs { nullptr };
mutable PrimitiveString* m_rhs { nullptr };
mutable DeprecatedString m_utf8_string;
mutable Utf16String m_utf16_string;
mutable Optional<DeprecatedString> m_utf8_string;
mutable Optional<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.
Object* base_obj = nullptr;
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())
return *string_value;
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-
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();
@ -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.
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.
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.
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.
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.
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
for (size_t i = 1; i <= 9; i++) {
auto value = Utf16String(""sv);
// If i ≤ n, set the value of Cs [[RegExpPareni]] internal slot to the ith element of capturedValues.
if (i <= group_count) {
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
}
// i. 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.
auto value = (i <= group_count) ? captured_values[i - 1] : TRY(Utf16String::create(vm));
if (i == 1) {
legacy_static_properties.set_$1(Utf16String(value));
legacy_static_properties.set_$1(move(value));
} else if (i == 2) {
legacy_static_properties.set_$2(Utf16String(value));
legacy_static_properties.set_$2(move(value));
} else if (i == 3) {
legacy_static_properties.set_$3(Utf16String(value));
legacy_static_properties.set_$3(move(value));
} else if (i == 4) {
legacy_static_properties.set_$4(Utf16String(value));
legacy_static_properties.set_$4(move(value));
} else if (i == 5) {
legacy_static_properties.set_$5(Utf16String(value));
legacy_static_properties.set_$5(move(value));
} else if (i == 6) {
legacy_static_properties.set_$6(Utf16String(value));
legacy_static_properties.set_$6(move(value));
} else if (i == 7) {
legacy_static_properties.set_$7(Utf16String(value));
legacy_static_properties.set_$7(move(value));
} else if (i == 8) {
legacy_static_properties.set_$8(Utf16String(value));
legacy_static_properties.set_$8(move(value));
} 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

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<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);
}

View file

@ -275,7 +275,7 @@ static ThrowCompletionOr<Value> regexp_builtin_exec(VM& vm, RegExpObject& regexp
// 27. Let matchedValue be ! GetMatchString(S, match).
// 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
// 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.
indices.append({});
// iii. Append capture to indices.
captured_values.append(Utf16String(""sv));
captured_values.append(TRY(Utf16String::create(vm)));
}
// c. Else,
else {
@ -311,7 +311,7 @@ static ThrowCompletionOr<Value> regexp_builtin_exec(VM& vm, RegExpObject& regexp
// 2. Set captureEnd to ! GetStringIndex(S, Input, captureEnd).
// iv. Let capture be the Match { [[StartIndex]]: captureStart, [[EndIndex]: captureEnd }.
// 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);
// vi. Append capture to indices.
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()) {
// a. Perform UpdateLegacyRegExpStaticProperties(%RegExp%, S, lastIndex, e, capturedValues).
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,
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);
// 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.
++array_length;
@ -1045,7 +1045,7 @@ JS_DEFINE_NATIVE_FUNCTION(RegExpPrototype::symbol_split)
auto substring = string.substring_view(last_match_end);
// 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.
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());
// 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 {};
}
@ -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.
// 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> {
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).

View file

@ -49,7 +49,7 @@ JS_DEFINE_NATIVE_FUNCTION(ShadowRealmPrototype::evaluate)
auto& eval_realm = object->shadow_realm();
// 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
@ -79,7 +79,7 @@ JS_DEFINE_NATIVE_FUNCTION(ShadowRealmPrototype::import_value)
auto& eval_context = object->execution_context();
// 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)
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
@ -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)));
}
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();
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)
@ -40,7 +42,7 @@ void StringObject::visit_edges(Cell::Visitor& visitor)
}
// 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());
@ -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 -
// this is not the case for PropertyKey, so '!property_key.is_string()' would be wrong.
if (property_key.is_symbol())
return {};
return Optional<PropertyDescriptor> {};
// 2. Let index be CanonicalNumericIndexString(P).
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.
// 5. If index is -0𝔽, return undefined.
if (!index.is_index())
return {};
return Optional<PropertyDescriptor> {};
// 6. Let str be S.[[StringData]].
// 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.
auto length = str.length_in_code_units();
// 9. If (index) < 0 or len ≤ (index), return undefined.
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).
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 }.
return PropertyDescriptor {
@ -104,7 +106,7 @@ ThrowCompletionOr<bool> StringObject::internal_define_own_property(PropertyKey c
VERIFY(property_key.is_valid());
// 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
if (string_descriptor.has_value()) {
@ -128,7 +130,7 @@ ThrowCompletionOr<MarkedVector<Value>> StringObject::internal_own_property_keys(
auto keys = MarkedVector<Value> { heap() };
// 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.

View file

@ -237,7 +237,7 @@ JS_DEFINE_NATIVE_FUNCTION(StringPrototype::at)
return js_undefined();
// 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
@ -248,7 +248,7 @@ JS_DEFINE_NATIVE_FUNCTION(StringPrototype::char_at)
if (position < 0 || position >= string.length_in_code_units())
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
@ -518,7 +518,7 @@ static ThrowCompletionOr<Value> pad_string(VM& vm, Utf16String string, PadPlacem
if (max_length <= string_length)
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()) {
fill_string = TRY(vm.argument(1).to_utf16_string(vm));
if (fill_string.is_empty())
@ -736,7 +736,7 @@ JS_DEFINE_NATIVE_FUNCTION(StringPrototype::slice)
if (int_start >= int_end)
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
@ -793,7 +793,7 @@ JS_DEFINE_NATIVE_FUNCTION(StringPrototype::split)
}
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;
if (array_length == limit)
return array;
@ -802,7 +802,7 @@ JS_DEFINE_NATIVE_FUNCTION(StringPrototype::split)
}
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;
}
@ -867,7 +867,7 @@ JS_DEFINE_NATIVE_FUNCTION(StringPrototype::substring)
size_t to = max(final_start, final_end);
// 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 {
@ -1111,7 +1111,7 @@ JS_DEFINE_NATIVE_FUNCTION(StringPrototype::substr)
return PrimitiveString::create(vm, DeprecatedString::empty());
// 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

View file

@ -146,8 +146,8 @@ ThrowCompletionOr<Value> get_option(VM& vm, Object const& options, PropertyKey c
if (!values.is_empty()) {
// NOTE: Every location in the spec that invokes GetOption with type=boolean also has values=undefined.
VERIFY(value.is_string());
if (!values.contains_slow(value.as_string().deprecated_string()))
return vm.throw_completion<RangeError>(ErrorType::OptionIsNotValidValue, value.as_string().deprecated_string(), property.as_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_string, property.as_string());
}
// 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));
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
@ -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));
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
@ -202,7 +202,7 @@ ThrowCompletionOr<DeprecatedString> to_temporal_rounding_mode(VM& vm, Object con
fallback.view()));
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
@ -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()));
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
@ -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));
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
@ -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));
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
@ -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));
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
@ -530,7 +530,7 @@ ThrowCompletionOr<Optional<DeprecatedString>> get_temporal_unit(VM& vm, Object c
Optional<DeprecatedString> value = option_value.is_undefined()
? 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
for (auto const& row : temporal_units) {

View file

@ -126,7 +126,7 @@ ThrowCompletionOr<Vector<DeprecatedString>> calendar_fields(VM& vm, Object& cale
Vector<DeprecatedString> result;
for (auto& value : list)
result.append(value.as_string().deprecated_string());
result.append(TRY(value.as_string().deprecated_string()));
return result;
}
@ -781,7 +781,7 @@ ThrowCompletionOr<double> resolve_iso_month(VM& vm, Object const& fields)
// 6. Assert: Type(monthCode) 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.
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
for (auto& key : fields_keys) {
// 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));
// 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.
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

View file

@ -559,19 +559,21 @@ JS_DEFINE_NATIVE_FUNCTION(CalendarPrototype::fields)
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
if (field_names.contains_slow(next_value)) {
// 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).
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
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).
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).
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.
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).
auto date_time_result = TRY(interpret_temporal_date_time_fields(vm, calendar, *fields, *options));

View file

@ -11,9 +11,9 @@
namespace JS {
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;
}
@ -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;
string.ensure_capacity(view.length_in_code_units());
string.append(view.data(), view.length_in_code_units());
return create(move(string));
TRY_OR_THROW_OOM(vm, string.try_ensure_capacity(view.length_in_code_units()));
string.unchecked_append(view.data(), view.length_in_code_units());
return create(vm, move(string));
}
Utf16Data const& Utf16StringImpl::string() const
@ -57,23 +57,28 @@ Utf16View Utf16StringImpl::view() const
}
Utf16String::Utf16String()
: m_string(Detail::the_empty_utf16_string())
ThrowCompletionOr<Utf16String> Utf16String::create(VM& vm)
{
return Utf16String { TRY(Detail::the_empty_utf16_string(vm)) };
}
Utf16String::Utf16String(Utf16Data string)
: m_string(Detail::Utf16StringImpl::create(move(string)))
ThrowCompletionOr<Utf16String> Utf16String::create(VM& vm, Utf16Data string)
{
return Utf16String { TRY(Detail::Utf16StringImpl::create(vm, move(string))) };
}
Utf16String::Utf16String(StringView string)
: m_string(Detail::Utf16StringImpl::create(move(string)))
ThrowCompletionOr<Utf16String> Utf16String::create(VM& vm, StringView string)
{
return Utf16String { TRY(Detail::Utf16StringImpl::create(vm, string)) };
}
Utf16String::Utf16String(Utf16View const& string)
: m_string(Detail::Utf16StringImpl::create(move(string)))
ThrowCompletionOr<Utf16String> Utf16String::create(VM& vm, Utf16View const& 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:
~Utf16StringImpl() = default;
static NonnullRefPtr<Utf16StringImpl> create();
static NonnullRefPtr<Utf16StringImpl> create(Utf16Data);
static NonnullRefPtr<Utf16StringImpl> create(StringView);
static NonnullRefPtr<Utf16StringImpl> create(Utf16View const&);
static ThrowCompletionOr<NonnullRefPtr<Utf16StringImpl>> create(VM&);
static ThrowCompletionOr<NonnullRefPtr<Utf16StringImpl>> create(VM&, Utf16Data);
static ThrowCompletionOr<NonnullRefPtr<Utf16StringImpl>> create(VM&, StringView);
static ThrowCompletionOr<NonnullRefPtr<Utf16StringImpl>> create(VM&, Utf16View const&);
Utf16Data const& string() const;
Utf16View view() const;
@ -40,10 +40,10 @@ private:
class Utf16String {
public:
Utf16String();
explicit Utf16String(Utf16Data);
explicit Utf16String(StringView);
explicit Utf16String(Utf16View const&);
static ThrowCompletionOr<Utf16String> create(VM&);
static ThrowCompletionOr<Utf16String> create(VM&, Utf16Data);
static ThrowCompletionOr<Utf16String> create(VM&, StringView);
static ThrowCompletionOr<Utf16String> create(VM&, Utf16View const&);
Utf16Data const& string() const;
Utf16View view() const;
@ -57,6 +57,8 @@ public:
bool is_empty() const;
private:
explicit Utf16String(NonnullRefPtr<Detail::Utf16StringImpl>);
NonnullRefPtr<Detail::Utf16StringImpl> m_string;
};

View file

@ -351,7 +351,7 @@ DeprecatedString Value::to_string_without_side_effects() const
case INT32_TAG:
return DeprecatedString::number(as_i32());
case STRING_TAG:
return as_string().deprecated_string();
return MUST(as_string().deprecated_string());
case SYMBOL_TAG:
return as_symbol().to_deprecated_string();
case BIGINT_TAG:
@ -382,7 +382,7 @@ ThrowCompletionOr<DeprecatedString> Value::to_string(VM& vm) const
switch (m_value.tag) {
// 1. If argument is a String, return argument.
case STRING_TAG:
return as_string().deprecated_string();
return TRY(as_string().deprecated_string());
// 2. If argument is a Symbol, throw a TypeError exception.
case SYMBOL_TAG:
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
{
if (is_string())
return as_string().utf16_string();
return TRY(as_string().utf16_string());
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
@ -684,7 +684,7 @@ ThrowCompletionOr<Value> Value::to_number(VM& vm) const
return Value(as_bool() ? 1 : 0);
// 6. If argument is a String, return StringToNumber(argument).
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.
case OBJECT_TAG: {
// 8. Let primValue be ? ToPrimitive(argument, number).
@ -738,7 +738,7 @@ ThrowCompletionOr<BigInt*> Value::to_bigint(VM& vm) const
return &primitive.as_bigint();
case STRING_TAG: {
// 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.
if (!bigint.has_value())
@ -2150,7 +2150,8 @@ bool same_value_non_number(Value lhs, Value rhs)
// 5. If x is a String, then
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.
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.
@ -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
if (lhs.is_bigint() && rhs.is_string()) {
// 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.
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
if (x_primitive.is_string() && y_primitive.is_string()) {
auto x_string = x_primitive.as_string().deprecated_string();
auto y_string = y_primitive.as_string().deprecated_string();
auto x_string = TRY(x_primitive.as_string().deprecated_string());
auto y_string = TRY(y_primitive.as_string().deprecated_string());
Utf8View x_code_points { x_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
if (x_primitive.is_bigint() && y_primitive.is_string()) {
// 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.
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
if (x_primitive.is_string() && y_primitive.is_bigint()) {
// 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.
if (!x_bigint.has_value())

View file

@ -16,8 +16,10 @@ struct ValueTraits : public Traits<Value> {
static unsigned hash(Value value)
{
VERIFY(!value.is_empty());
if (value.is_string())
return value.as_string().deprecated_string().hash();
if (value.is_string()) {
// FIXME: Propagate this error.
return value.as_string().deprecated_string().release_value().hash();
}
if (value.is_bigint())
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.
auto steps = [&vm, &realm, &object, type](JS::Value value) -> WebIDL::ExceptionOr<JS::Value> {
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());
};

View file

@ -49,7 +49,7 @@ WebIDL::ExceptionOr<DeprecatedString> serialize_javascript_value_to_json_string(
VERIFY(result.is_string());
// 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

View file

@ -35,7 +35,7 @@ JS::ThrowCompletionOr<JS::NonnullGCPtr<JS::Object>> WebAssemblyTableConstructor:
auto element_value = TRY(descriptor->get("element"));
if (!element_value.is_string())
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;
if (element == "anyfunc"sv)

View file

@ -95,7 +95,7 @@ static ErrorOr<JsonValue, ExecuteScriptResultType> internal_json_clone_algorithm
if (value.is_number())
return JsonValue { value.as_double() };
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.
// 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() }));
if (!to_json_result.is_string())
return ExecuteScriptResultType::JavaScriptError;
return to_json_result.as_string().deprecated_string();
return TRY_OR_JS_ERROR(to_json_result.as_string().deprecated_string());
}
// -> Otherwise