1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-27 06:17:35 +00:00

LibJS: Convert StringPrototype functions to ThrowCompletionOr

This commit is contained in:
Idan Horowitz 2021-10-23 03:09:34 +03:00 committed by Andreas Kling
parent 38c4693c70
commit 18c2d537c7
2 changed files with 297 additions and 364 deletions

View file

@ -29,16 +29,16 @@
namespace JS { namespace JS {
static Optional<String> ak_string_from(VM& vm, GlobalObject& global_object) static ThrowCompletionOr<String> ak_string_from(VM& vm, GlobalObject& global_object)
{ {
auto this_value = TRY_OR_DISCARD(require_object_coercible(global_object, vm.this_value(global_object))); auto this_value = TRY(require_object_coercible(global_object, vm.this_value(global_object)));
return TRY_OR_DISCARD(this_value.to_string(global_object)); return TRY(this_value.to_string(global_object));
} }
static Utf16String utf16_string_from(VM& vm, GlobalObject& global_object) static ThrowCompletionOr<Utf16String> utf16_string_from(VM& vm, GlobalObject& global_object)
{ {
auto this_value = TRY_OR_DISCARD(require_object_coercible(global_object, vm.this_value(global_object))); auto this_value = TRY(require_object_coercible(global_object, vm.this_value(global_object)));
return TRY_OR_DISCARD(this_value.to_utf16_string(global_object)); return TRY(this_value.to_utf16_string(global_object));
} }
// 22.1.3.21.1 SplitMatch ( S, q, R ), https://tc39.es/ecma262/#sec-splitmatch // 22.1.3.21.1 SplitMatch ( S, q, R ), https://tc39.es/ecma262/#sec-splitmatch
@ -110,54 +110,54 @@ void StringPrototype::initialize(GlobalObject& global_object)
StringObject::initialize(global_object); StringObject::initialize(global_object);
u8 attr = Attribute::Writable | Attribute::Configurable; u8 attr = Attribute::Writable | Attribute::Configurable;
define_old_native_function(vm.names.charAt, char_at, 1, attr); define_native_function(vm.names.charAt, char_at, 1, attr);
define_old_native_function(vm.names.charCodeAt, char_code_at, 1, attr); define_native_function(vm.names.charCodeAt, char_code_at, 1, attr);
define_old_native_function(vm.names.codePointAt, code_point_at, 1, attr); define_native_function(vm.names.codePointAt, code_point_at, 1, attr);
define_old_native_function(vm.names.repeat, repeat, 1, attr); define_native_function(vm.names.repeat, repeat, 1, attr);
define_old_native_function(vm.names.startsWith, starts_with, 1, attr); define_native_function(vm.names.startsWith, starts_with, 1, attr);
define_old_native_function(vm.names.endsWith, ends_with, 1, attr); define_native_function(vm.names.endsWith, ends_with, 1, attr);
define_old_native_function(vm.names.indexOf, index_of, 1, attr); define_native_function(vm.names.indexOf, index_of, 1, attr);
define_old_native_function(vm.names.toLocaleLowerCase, to_locale_lowercase, 0, attr); define_native_function(vm.names.toLocaleLowerCase, to_locale_lowercase, 0, attr);
define_old_native_function(vm.names.toLocaleUpperCase, to_locale_uppercase, 0, attr); define_native_function(vm.names.toLocaleUpperCase, to_locale_uppercase, 0, attr);
define_old_native_function(vm.names.toLowerCase, to_lowercase, 0, attr); define_native_function(vm.names.toLowerCase, to_lowercase, 0, attr);
define_old_native_function(vm.names.toUpperCase, to_uppercase, 0, attr); define_native_function(vm.names.toUpperCase, to_uppercase, 0, attr);
define_old_native_function(vm.names.toString, to_string, 0, attr); define_native_function(vm.names.toString, to_string, 0, attr);
define_old_native_function(vm.names.valueOf, value_of, 0, attr); define_native_function(vm.names.valueOf, value_of, 0, attr);
define_old_native_function(vm.names.padStart, pad_start, 1, attr); define_native_function(vm.names.padStart, pad_start, 1, attr);
define_old_native_function(vm.names.padEnd, pad_end, 1, attr); define_native_function(vm.names.padEnd, pad_end, 1, attr);
define_old_native_function(vm.names.trim, trim, 0, attr); define_native_function(vm.names.trim, trim, 0, attr);
define_old_native_function(vm.names.trimStart, trim_start, 0, attr); define_native_function(vm.names.trimStart, trim_start, 0, attr);
define_direct_property(vm.names.trimLeft, get_without_side_effects(vm.names.trimStart), attr); define_direct_property(vm.names.trimLeft, get_without_side_effects(vm.names.trimStart), attr);
define_old_native_function(vm.names.trimEnd, trim_end, 0, attr); define_native_function(vm.names.trimEnd, trim_end, 0, attr);
define_direct_property(vm.names.trimRight, get_without_side_effects(vm.names.trimEnd), attr); define_direct_property(vm.names.trimRight, get_without_side_effects(vm.names.trimEnd), attr);
define_old_native_function(vm.names.concat, concat, 1, attr); define_native_function(vm.names.concat, concat, 1, attr);
define_old_native_function(vm.names.substr, substr, 2, attr); define_native_function(vm.names.substr, substr, 2, attr);
define_old_native_function(vm.names.substring, substring, 2, attr); define_native_function(vm.names.substring, substring, 2, attr);
define_old_native_function(vm.names.includes, includes, 1, attr); define_native_function(vm.names.includes, includes, 1, attr);
define_old_native_function(vm.names.slice, slice, 2, attr); define_native_function(vm.names.slice, slice, 2, attr);
define_old_native_function(vm.names.split, split, 2, attr); define_native_function(vm.names.split, split, 2, attr);
define_old_native_function(vm.names.lastIndexOf, last_index_of, 1, attr); define_native_function(vm.names.lastIndexOf, last_index_of, 1, attr);
define_old_native_function(vm.names.at, at, 1, attr); define_native_function(vm.names.at, at, 1, attr);
define_old_native_function(vm.names.match, match, 1, attr); define_native_function(vm.names.match, match, 1, attr);
define_old_native_function(vm.names.matchAll, match_all, 1, attr); define_native_function(vm.names.matchAll, match_all, 1, attr);
define_old_native_function(vm.names.replace, replace, 2, attr); define_native_function(vm.names.replace, replace, 2, attr);
define_old_native_function(vm.names.replaceAll, replace_all, 2, attr); define_native_function(vm.names.replaceAll, replace_all, 2, attr);
define_old_native_function(vm.names.search, search, 1, attr); define_native_function(vm.names.search, search, 1, attr);
define_old_native_function(vm.names.anchor, anchor, 1, attr); define_native_function(vm.names.anchor, anchor, 1, attr);
define_old_native_function(vm.names.big, big, 0, attr); define_native_function(vm.names.big, big, 0, attr);
define_old_native_function(vm.names.blink, blink, 0, attr); define_native_function(vm.names.blink, blink, 0, attr);
define_old_native_function(vm.names.bold, bold, 0, attr); define_native_function(vm.names.bold, bold, 0, attr);
define_old_native_function(vm.names.fixed, fixed, 0, attr); define_native_function(vm.names.fixed, fixed, 0, attr);
define_old_native_function(vm.names.fontcolor, fontcolor, 1, attr); define_native_function(vm.names.fontcolor, fontcolor, 1, attr);
define_old_native_function(vm.names.fontsize, fontsize, 1, attr); define_native_function(vm.names.fontsize, fontsize, 1, attr);
define_old_native_function(vm.names.italics, italics, 0, attr); define_native_function(vm.names.italics, italics, 0, attr);
define_old_native_function(vm.names.link, link, 1, attr); define_native_function(vm.names.link, link, 1, attr);
define_old_native_function(vm.names.small, small, 0, attr); define_native_function(vm.names.small, small, 0, attr);
define_old_native_function(vm.names.strike, strike, 0, attr); define_native_function(vm.names.strike, strike, 0, attr);
define_old_native_function(vm.names.sub, sub, 0, attr); define_native_function(vm.names.sub, sub, 0, attr);
define_old_native_function(vm.names.sup, sup, 0, attr); define_native_function(vm.names.sup, sup, 0, attr);
define_old_native_function(vm.names.localeCompare, locale_compare, 1, attr); define_native_function(vm.names.localeCompare, locale_compare, 1, attr);
define_old_native_function(*vm.well_known_symbol_iterator(), symbol_iterator, 0, attr); define_native_function(*vm.well_known_symbol_iterator(), symbol_iterator, 0, attr);
} }
StringPrototype::~StringPrototype() StringPrototype::~StringPrototype()
@ -176,12 +176,10 @@ static ThrowCompletionOr<PrimitiveString*> this_string_value(GlobalObject& globa
} }
// 22.1.3.2 String.prototype.charAt ( pos ), https://tc39.es/ecma262/#sec-string.prototype.charat // 22.1.3.2 String.prototype.charAt ( pos ), https://tc39.es/ecma262/#sec-string.prototype.charat
JS_DEFINE_OLD_NATIVE_FUNCTION(StringPrototype::char_at) JS_DEFINE_NATIVE_FUNCTION(StringPrototype::char_at)
{ {
auto string = utf16_string_from(vm, global_object); auto string = TRY(utf16_string_from(vm, global_object));
if (vm.exception()) auto position = TRY(vm.argument(0).to_integer_or_infinity(global_object));
return {};
auto position = TRY_OR_DISCARD(vm.argument(0).to_integer_or_infinity(global_object));
if (position < 0 || position >= string.length_in_code_units()) if (position < 0 || position >= string.length_in_code_units())
return js_string(vm, String::empty()); return js_string(vm, String::empty());
@ -189,12 +187,10 @@ JS_DEFINE_OLD_NATIVE_FUNCTION(StringPrototype::char_at)
} }
// 22.1.3.3 String.prototype.charCodeAt ( pos ), https://tc39.es/ecma262/#sec-string.prototype.charcodeat // 22.1.3.3 String.prototype.charCodeAt ( pos ), https://tc39.es/ecma262/#sec-string.prototype.charcodeat
JS_DEFINE_OLD_NATIVE_FUNCTION(StringPrototype::char_code_at) JS_DEFINE_NATIVE_FUNCTION(StringPrototype::char_code_at)
{ {
auto string = utf16_string_from(vm, global_object); auto string = TRY(utf16_string_from(vm, global_object));
if (vm.exception()) auto position = TRY(vm.argument(0).to_integer_or_infinity(global_object));
return {};
auto position = TRY_OR_DISCARD(vm.argument(0).to_integer_or_infinity(global_object));
if (position < 0 || position >= string.length_in_code_units()) if (position < 0 || position >= string.length_in_code_units())
return js_nan(); return js_nan();
@ -202,12 +198,10 @@ JS_DEFINE_OLD_NATIVE_FUNCTION(StringPrototype::char_code_at)
} }
// 22.1.3.4 String.prototype.codePointAt ( pos ), https://tc39.es/ecma262/#sec-string.prototype.codepointat // 22.1.3.4 String.prototype.codePointAt ( pos ), https://tc39.es/ecma262/#sec-string.prototype.codepointat
JS_DEFINE_OLD_NATIVE_FUNCTION(StringPrototype::code_point_at) JS_DEFINE_NATIVE_FUNCTION(StringPrototype::code_point_at)
{ {
auto string = utf16_string_from(vm, global_object); auto string = TRY(utf16_string_from(vm, global_object));
if (vm.exception()) auto position = TRY(vm.argument(0).to_integer_or_infinity(global_object));
return {};
auto position = TRY_OR_DISCARD(vm.argument(0).to_integer_or_infinity(global_object));
if (position < 0 || position >= string.length_in_code_units()) if (position < 0 || position >= string.length_in_code_units())
return js_undefined(); return js_undefined();
@ -216,59 +210,49 @@ JS_DEFINE_OLD_NATIVE_FUNCTION(StringPrototype::code_point_at)
} }
// 22.1.3.17 String.prototype.repeat ( count ), https://tc39.es/ecma262/#sec-string.prototype.repeat // 22.1.3.17 String.prototype.repeat ( count ), https://tc39.es/ecma262/#sec-string.prototype.repeat
JS_DEFINE_OLD_NATIVE_FUNCTION(StringPrototype::repeat) JS_DEFINE_NATIVE_FUNCTION(StringPrototype::repeat)
{ {
auto string = ak_string_from(vm, global_object); auto string = TRY(ak_string_from(vm, global_object));
if (!string.has_value())
return {};
auto n = TRY_OR_DISCARD(vm.argument(0).to_integer_or_infinity(global_object)); auto n = TRY(vm.argument(0).to_integer_or_infinity(global_object));
if (n < 0) { if (n < 0)
vm.throw_exception<RangeError>(global_object, ErrorType::StringRepeatCountMustBe, "positive"); return vm.throw_completion<RangeError>(global_object, ErrorType::StringRepeatCountMustBe, "positive");
return {};
}
if (Value(n).is_positive_infinity()) { if (Value(n).is_positive_infinity())
vm.throw_exception<RangeError>(global_object, ErrorType::StringRepeatCountMustBe, "finite"); return vm.throw_completion<RangeError>(global_object, ErrorType::StringRepeatCountMustBe, "finite");
return {};
}
if (n == 0) if (n == 0)
return js_string(vm, String::empty()); return js_string(vm, String::empty());
// NOTE: This is an optimization, it is not required by the specification but it produces equivalent behavior // NOTE: This is an optimization, it is not required by the specification but it produces equivalent behavior
if (string->is_empty()) if (string.is_empty())
return js_string(vm, String::empty()); return js_string(vm, String::empty());
StringBuilder builder; StringBuilder builder;
for (size_t i = 0; i < n; ++i) for (size_t i = 0; i < n; ++i)
builder.append(*string); builder.append(string);
return js_string(vm, builder.to_string()); return js_string(vm, builder.to_string());
} }
// 22.1.3.23 String.prototype.startsWith ( searchString [ , position ] ), https://tc39.es/ecma262/#sec-string.prototype.startswith // 22.1.3.23 String.prototype.startsWith ( searchString [ , position ] ), https://tc39.es/ecma262/#sec-string.prototype.startswith
JS_DEFINE_OLD_NATIVE_FUNCTION(StringPrototype::starts_with) JS_DEFINE_NATIVE_FUNCTION(StringPrototype::starts_with)
{ {
auto string = utf16_string_from(vm, global_object); auto string = TRY(utf16_string_from(vm, global_object));
if (vm.exception())
return {};
auto search_string_value = vm.argument(0); auto search_string_value = vm.argument(0);
bool search_is_regexp = TRY_OR_DISCARD(search_string_value.is_regexp(global_object)); bool search_is_regexp = TRY(search_string_value.is_regexp(global_object));
if (search_is_regexp) { if (search_is_regexp)
vm.throw_exception<TypeError>(global_object, ErrorType::IsNotA, "searchString", "string, but a regular expression"); return vm.throw_completion<TypeError>(global_object, ErrorType::IsNotA, "searchString", "string, but a regular expression");
return {};
}
auto search_string = TRY_OR_DISCARD(search_string_value.to_utf16_string(global_object)); auto search_string = TRY(search_string_value.to_utf16_string(global_object));
auto string_length = string.length_in_code_units(); auto string_length = string.length_in_code_units();
auto search_length = search_string.length_in_code_units(); auto search_length = search_string.length_in_code_units();
size_t start = 0; size_t start = 0;
if (!vm.argument(1).is_undefined()) { if (!vm.argument(1).is_undefined()) {
auto position = TRY_OR_DISCARD(vm.argument(1).to_integer_or_infinity(global_object)); auto position = TRY(vm.argument(1).to_integer_or_infinity(global_object));
start = clamp(position, static_cast<double>(0), static_cast<double>(string_length)); start = clamp(position, static_cast<double>(0), static_cast<double>(string_length));
} }
@ -284,27 +268,23 @@ JS_DEFINE_OLD_NATIVE_FUNCTION(StringPrototype::starts_with)
} }
// 22.1.3.7 String.prototype.endsWith ( searchString [ , endPosition ] ), https://tc39.es/ecma262/#sec-string.prototype.endswith // 22.1.3.7 String.prototype.endsWith ( searchString [ , endPosition ] ), https://tc39.es/ecma262/#sec-string.prototype.endswith
JS_DEFINE_OLD_NATIVE_FUNCTION(StringPrototype::ends_with) JS_DEFINE_NATIVE_FUNCTION(StringPrototype::ends_with)
{ {
auto string = utf16_string_from(vm, global_object); auto string = TRY(utf16_string_from(vm, global_object));
if (vm.exception())
return {};
auto search_string_value = vm.argument(0); auto search_string_value = vm.argument(0);
bool search_is_regexp = TRY_OR_DISCARD(search_string_value.is_regexp(global_object)); bool search_is_regexp = TRY(search_string_value.is_regexp(global_object));
if (search_is_regexp) { if (search_is_regexp)
vm.throw_exception<TypeError>(global_object, ErrorType::IsNotA, "searchString", "string, but a regular expression"); return vm.throw_completion<TypeError>(global_object, ErrorType::IsNotA, "searchString", "string, but a regular expression");
return {};
}
auto search_string = TRY_OR_DISCARD(search_string_value.to_utf16_string(global_object)); auto search_string = TRY(search_string_value.to_utf16_string(global_object));
auto string_length = string.length_in_code_units(); auto string_length = string.length_in_code_units();
auto search_length = search_string.length_in_code_units(); auto search_length = search_string.length_in_code_units();
size_t end = string_length; size_t end = string_length;
if (!vm.argument(1).is_undefined()) { if (!vm.argument(1).is_undefined()) {
auto position = TRY_OR_DISCARD(vm.argument(1).to_integer_or_infinity(global_object)); auto position = TRY(vm.argument(1).to_integer_or_infinity(global_object));
end = clamp(position, static_cast<double>(0), static_cast<double>(string_length)); end = clamp(position, static_cast<double>(0), static_cast<double>(string_length));
} }
@ -320,19 +300,17 @@ JS_DEFINE_OLD_NATIVE_FUNCTION(StringPrototype::ends_with)
} }
// 22.1.3.9 String.prototype.indexOf ( searchString [ , position ] ), https://tc39.es/ecma262/#sec-string.prototype.indexof // 22.1.3.9 String.prototype.indexOf ( searchString [ , position ] ), https://tc39.es/ecma262/#sec-string.prototype.indexof
JS_DEFINE_OLD_NATIVE_FUNCTION(StringPrototype::index_of) JS_DEFINE_NATIVE_FUNCTION(StringPrototype::index_of)
{ {
auto string = utf16_string_from(vm, global_object); auto string = TRY(utf16_string_from(vm, global_object));
if (vm.exception())
return {};
auto search_string = TRY_OR_DISCARD(vm.argument(0).to_utf16_string(global_object)); auto search_string = TRY(vm.argument(0).to_utf16_string(global_object));
auto utf16_string_view = string.view(); auto utf16_string_view = string.view();
auto utf16_search_view = search_string.view(); auto utf16_search_view = search_string.view();
size_t start = 0; size_t start = 0;
if (vm.argument_count() > 1) { if (vm.argument_count() > 1) {
auto position = TRY_OR_DISCARD(vm.argument(1).to_integer_or_infinity(global_object)); auto position = TRY(vm.argument(1).to_integer_or_infinity(global_object));
start = clamp(position, static_cast<double>(0), static_cast<double>(utf16_string_view.length_in_code_units())); start = clamp(position, static_cast<double>(0), static_cast<double>(utf16_string_view.length_in_code_units()));
} }
@ -377,63 +355,49 @@ static ThrowCompletionOr<String> resolve_best_locale(GlobalObject& global_object
} }
// 18.1.2 String.prototype.toLocaleLowerCase ( [ locales ] ), https://tc39.es/ecma402/#sup-string.prototype.tolocalelowercase // 18.1.2 String.prototype.toLocaleLowerCase ( [ locales ] ), https://tc39.es/ecma402/#sup-string.prototype.tolocalelowercase
JS_DEFINE_OLD_NATIVE_FUNCTION(StringPrototype::to_locale_lowercase) JS_DEFINE_NATIVE_FUNCTION(StringPrototype::to_locale_lowercase)
{ {
auto string = ak_string_from(vm, global_object); auto string = TRY(ak_string_from(vm, global_object));
if (!string.has_value()) auto locale = TRY(resolve_best_locale(global_object, vm.argument(0)));
return {}; auto lowercase = Unicode::to_unicode_lowercase_full(string, locale);
auto locale = TRY_OR_DISCARD(resolve_best_locale(global_object, vm.argument(0)));
auto lowercase = Unicode::to_unicode_lowercase_full(*string, locale);
return js_string(vm, move(lowercase)); return js_string(vm, move(lowercase));
} }
// 18.1.3 String.prototype.toLocaleUpperCase ( [ locales ] ), https://tc39.es/ecma402/#sup-string.prototype.tolocaleuppercase // 18.1.3 String.prototype.toLocaleUpperCase ( [ locales ] ), https://tc39.es/ecma402/#sup-string.prototype.tolocaleuppercase
JS_DEFINE_OLD_NATIVE_FUNCTION(StringPrototype::to_locale_uppercase) JS_DEFINE_NATIVE_FUNCTION(StringPrototype::to_locale_uppercase)
{ {
auto string = ak_string_from(vm, global_object); auto string = TRY(ak_string_from(vm, global_object));
if (!string.has_value()) auto locale = TRY(resolve_best_locale(global_object, vm.argument(0)));
return {}; auto uppercase = Unicode::to_unicode_uppercase_full(string, locale);
auto locale = TRY_OR_DISCARD(resolve_best_locale(global_object, vm.argument(0)));
auto uppercase = Unicode::to_unicode_uppercase_full(*string, locale);
return js_string(vm, move(uppercase)); return js_string(vm, move(uppercase));
} }
// 22.1.3.27 String.prototype.toLowerCase ( ), https://tc39.es/ecma262/#sec-string.prototype.tolowercase // 22.1.3.27 String.prototype.toLowerCase ( ), https://tc39.es/ecma262/#sec-string.prototype.tolowercase
JS_DEFINE_OLD_NATIVE_FUNCTION(StringPrototype::to_lowercase) JS_DEFINE_NATIVE_FUNCTION(StringPrototype::to_lowercase)
{ {
auto string = ak_string_from(vm, global_object); auto string = TRY(ak_string_from(vm, global_object));
if (!string.has_value()) auto lowercase = Unicode::to_unicode_lowercase_full(string);
return {};
auto lowercase = Unicode::to_unicode_lowercase_full(*string);
return js_string(vm, move(lowercase)); return js_string(vm, move(lowercase));
} }
// 22.1.3.29 String.prototype.toUpperCase ( ), https://tc39.es/ecma262/#sec-string.prototype.touppercase // 22.1.3.29 String.prototype.toUpperCase ( ), https://tc39.es/ecma262/#sec-string.prototype.touppercase
JS_DEFINE_OLD_NATIVE_FUNCTION(StringPrototype::to_uppercase) JS_DEFINE_NATIVE_FUNCTION(StringPrototype::to_uppercase)
{ {
auto string = ak_string_from(vm, global_object); auto string = TRY(ak_string_from(vm, global_object));
if (!string.has_value()) auto uppercase = Unicode::to_unicode_uppercase_full(string);
return {};
auto uppercase = Unicode::to_unicode_uppercase_full(*string);
return js_string(vm, move(uppercase)); return js_string(vm, move(uppercase));
} }
// 22.1.3.28 String.prototype.toString ( ), https://tc39.es/ecma262/#sec-string.prototype.tostring // 22.1.3.28 String.prototype.toString ( ), https://tc39.es/ecma262/#sec-string.prototype.tostring
JS_DEFINE_OLD_NATIVE_FUNCTION(StringPrototype::to_string) JS_DEFINE_NATIVE_FUNCTION(StringPrototype::to_string)
{ {
return TRY_OR_DISCARD(this_string_value(global_object, vm.this_value(global_object))); return TRY(this_string_value(global_object, vm.this_value(global_object)));
} }
// 22.1.3.33 String.prototype.valueOf ( ), https://tc39.es/ecma262/#sec-string.prototype.valueof // 22.1.3.33 String.prototype.valueOf ( ), https://tc39.es/ecma262/#sec-string.prototype.valueof
JS_DEFINE_OLD_NATIVE_FUNCTION(StringPrototype::value_of) JS_DEFINE_NATIVE_FUNCTION(StringPrototype::value_of)
{ {
return TRY_OR_DISCARD(this_string_value(global_object, vm.this_value(global_object))); return TRY(this_string_value(global_object, vm.this_value(global_object)));
} }
enum class PadPlacement { enum class PadPlacement {
@ -475,75 +439,65 @@ static ThrowCompletionOr<Value> pad_string(GlobalObject& global_object, Utf16Str
} }
// 22.1.3.16 String.prototype.padStart ( maxLength [ , fillString ] ), https://tc39.es/ecma262/#sec-string.prototype.padstart // 22.1.3.16 String.prototype.padStart ( maxLength [ , fillString ] ), https://tc39.es/ecma262/#sec-string.prototype.padstart
JS_DEFINE_OLD_NATIVE_FUNCTION(StringPrototype::pad_start) JS_DEFINE_NATIVE_FUNCTION(StringPrototype::pad_start)
{ {
auto string = utf16_string_from(vm, global_object); auto string = TRY(utf16_string_from(vm, global_object));
return TRY_OR_DISCARD(pad_string(global_object, move(string), PadPlacement::Start)); return pad_string(global_object, move(string), PadPlacement::Start);
} }
// 22.1.3.15 String.prototype.padEnd ( maxLength [ , fillString ] ), https://tc39.es/ecma262/#sec-string.prototype.padend // 22.1.3.15 String.prototype.padEnd ( maxLength [ , fillString ] ), https://tc39.es/ecma262/#sec-string.prototype.padend
JS_DEFINE_OLD_NATIVE_FUNCTION(StringPrototype::pad_end) JS_DEFINE_NATIVE_FUNCTION(StringPrototype::pad_end)
{ {
auto string = utf16_string_from(vm, global_object); auto string = TRY(utf16_string_from(vm, global_object));
return TRY_OR_DISCARD(pad_string(global_object, move(string), PadPlacement::End)); return pad_string(global_object, move(string), PadPlacement::End);
} }
static Utf8View const whitespace_characters = Utf8View("\x09\x0A\x0B\x0C\x0D\x20\xC2\xA0\xE1\x9A\x80\xE2\x80\x80\xE2\x80\x81\xE2\x80\x82\xE2\x80\x83\xE2\x80\x84\xE2\x80\x85\xE2\x80\x86\xE2\x80\x87\xE2\x80\x88\xE2\x80\x89\xE2\x80\x8A\xE2\x80\xAF\xE2\x81\x9F\xE3\x80\x80\xE2\x80\xA8\xE2\x80\xA9\xEF\xBB\xBF"sv); static Utf8View const whitespace_characters = Utf8View("\x09\x0A\x0B\x0C\x0D\x20\xC2\xA0\xE1\x9A\x80\xE2\x80\x80\xE2\x80\x81\xE2\x80\x82\xE2\x80\x83\xE2\x80\x84\xE2\x80\x85\xE2\x80\x86\xE2\x80\x87\xE2\x80\x88\xE2\x80\x89\xE2\x80\x8A\xE2\x80\xAF\xE2\x81\x9F\xE3\x80\x80\xE2\x80\xA8\xE2\x80\xA9\xEF\xBB\xBF"sv);
// 22.1.3.30 String.prototype.trim ( ), https://tc39.es/ecma262/#sec-string.prototype.trim // 22.1.3.30 String.prototype.trim ( ), https://tc39.es/ecma262/#sec-string.prototype.trim
JS_DEFINE_OLD_NATIVE_FUNCTION(StringPrototype::trim) JS_DEFINE_NATIVE_FUNCTION(StringPrototype::trim)
{ {
auto string = ak_string_from(vm, global_object); auto string = TRY(ak_string_from(vm, global_object));
if (!string.has_value()) return js_string(vm, Utf8View(string).trim(whitespace_characters, TrimMode::Both).as_string());
return {};
return js_string(vm, Utf8View(*string).trim(whitespace_characters, TrimMode::Both).as_string());
} }
// 22.1.3.32 String.prototype.trimStart ( ), https://tc39.es/ecma262/#sec-string.prototype.trimstart // 22.1.3.32 String.prototype.trimStart ( ), https://tc39.es/ecma262/#sec-string.prototype.trimstart
JS_DEFINE_OLD_NATIVE_FUNCTION(StringPrototype::trim_start) JS_DEFINE_NATIVE_FUNCTION(StringPrototype::trim_start)
{ {
auto string = ak_string_from(vm, global_object); auto string = TRY(ak_string_from(vm, global_object));
if (!string.has_value()) return js_string(vm, Utf8View(string).trim(whitespace_characters, TrimMode::Left).as_string());
return {};
return js_string(vm, Utf8View(*string).trim(whitespace_characters, TrimMode::Left).as_string());
} }
// 22.1.3.31 String.prototype.trimEnd ( ), https://tc39.es/ecma262/#sec-string.prototype.trimend // 22.1.3.31 String.prototype.trimEnd ( ), https://tc39.es/ecma262/#sec-string.prototype.trimend
JS_DEFINE_OLD_NATIVE_FUNCTION(StringPrototype::trim_end) JS_DEFINE_NATIVE_FUNCTION(StringPrototype::trim_end)
{ {
auto string = ak_string_from(vm, global_object); auto string = TRY(ak_string_from(vm, global_object));
if (!string.has_value()) return js_string(vm, Utf8View(string).trim(whitespace_characters, TrimMode::Right).as_string());
return {};
return js_string(vm, Utf8View(*string).trim(whitespace_characters, TrimMode::Right).as_string());
} }
// 22.1.3.5 String.prototype.concat ( ...args ), https://tc39.es/ecma262/#sec-string.prototype.concat // 22.1.3.5 String.prototype.concat ( ...args ), https://tc39.es/ecma262/#sec-string.prototype.concat
JS_DEFINE_OLD_NATIVE_FUNCTION(StringPrototype::concat) JS_DEFINE_NATIVE_FUNCTION(StringPrototype::concat)
{ {
auto string = ak_string_from(vm, global_object); auto string = TRY(ak_string_from(vm, global_object));
if (!string.has_value())
return {};
StringBuilder builder; StringBuilder builder;
builder.append(*string); builder.append(string);
for (size_t i = 0; i < vm.argument_count(); ++i) { for (size_t i = 0; i < vm.argument_count(); ++i) {
auto string_argument = TRY_OR_DISCARD(vm.argument(i).to_string(global_object)); auto string_argument = TRY(vm.argument(i).to_string(global_object));
builder.append(string_argument); builder.append(string_argument);
} }
return js_string(vm, builder.to_string()); return js_string(vm, builder.to_string());
} }
// 22.1.3.24 String.prototype.substring ( start, end ), https://tc39.es/ecma262/#sec-string.prototype.substring // 22.1.3.24 String.prototype.substring ( start, end ), https://tc39.es/ecma262/#sec-string.prototype.substring
JS_DEFINE_OLD_NATIVE_FUNCTION(StringPrototype::substring) JS_DEFINE_NATIVE_FUNCTION(StringPrototype::substring)
{ {
auto string = utf16_string_from(vm, global_object); auto string = TRY(utf16_string_from(vm, global_object));
if (vm.exception())
return {};
auto string_length = static_cast<double>(string.length_in_code_units()); auto string_length = static_cast<double>(string.length_in_code_units());
auto start = TRY_OR_DISCARD(vm.argument(0).to_integer_or_infinity(global_object)); auto start = TRY(vm.argument(0).to_integer_or_infinity(global_object));
auto end = string_length; auto end = string_length;
if (!vm.argument(1).is_undefined()) if (!vm.argument(1).is_undefined())
end = TRY_OR_DISCARD(vm.argument(1).to_integer_or_infinity(global_object)); end = TRY(vm.argument(1).to_integer_or_infinity(global_object));
size_t final_start = clamp(start, static_cast<double>(0), string_length); size_t final_start = clamp(start, static_cast<double>(0), string_length);
size_t final_end = clamp(end, static_cast<double>(0), string_length); size_t final_end = clamp(end, static_cast<double>(0), string_length);
@ -555,14 +509,12 @@ JS_DEFINE_OLD_NATIVE_FUNCTION(StringPrototype::substring)
} }
// B.2.2.1 String.prototype.substr ( start, length ), https://tc39.es/ecma262/#sec-string.prototype.substr // B.2.2.1 String.prototype.substr ( start, length ), https://tc39.es/ecma262/#sec-string.prototype.substr
JS_DEFINE_OLD_NATIVE_FUNCTION(StringPrototype::substr) JS_DEFINE_NATIVE_FUNCTION(StringPrototype::substr)
{ {
auto string = utf16_string_from(vm, global_object); auto string = TRY(utf16_string_from(vm, global_object));
if (vm.exception())
return {};
auto size = string.length_in_code_units(); auto size = string.length_in_code_units();
auto int_start = TRY_OR_DISCARD(vm.argument(0).to_integer_or_infinity(global_object)); auto int_start = TRY(vm.argument(0).to_integer_or_infinity(global_object));
if (Value(int_start).is_negative_infinity()) if (Value(int_start).is_negative_infinity())
int_start = 0; int_start = 0;
if (int_start < 0) if (int_start < 0)
@ -570,7 +522,7 @@ JS_DEFINE_OLD_NATIVE_FUNCTION(StringPrototype::substr)
auto length = vm.argument(1); auto length = vm.argument(1);
auto int_length = length.is_undefined() ? size : TRY_OR_DISCARD(length.to_integer_or_infinity(global_object)); auto int_length = length.is_undefined() ? size : TRY(length.to_integer_or_infinity(global_object));
if (Value(int_start).is_positive_infinity() || (int_length <= 0) || Value(int_length).is_positive_infinity()) if (Value(int_start).is_positive_infinity() || (int_length <= 0) || Value(int_length).is_positive_infinity())
return js_string(vm, String::empty()); return js_string(vm, String::empty());
@ -583,25 +535,21 @@ JS_DEFINE_OLD_NATIVE_FUNCTION(StringPrototype::substr)
} }
// 22.1.3.8 String.prototype.includes ( searchString [ , position ] ), https://tc39.es/ecma262/#sec-string.prototype.includes // 22.1.3.8 String.prototype.includes ( searchString [ , position ] ), https://tc39.es/ecma262/#sec-string.prototype.includes
JS_DEFINE_OLD_NATIVE_FUNCTION(StringPrototype::includes) JS_DEFINE_NATIVE_FUNCTION(StringPrototype::includes)
{ {
auto string = utf16_string_from(vm, global_object); auto string = TRY(utf16_string_from(vm, global_object));
if (vm.exception())
return {};
auto search_string_value = vm.argument(0); auto search_string_value = vm.argument(0);
bool search_is_regexp = TRY_OR_DISCARD(search_string_value.is_regexp(global_object)); bool search_is_regexp = TRY(search_string_value.is_regexp(global_object));
if (search_is_regexp) { if (search_is_regexp)
vm.throw_exception<TypeError>(global_object, ErrorType::IsNotA, "searchString", "string, but a regular expression"); return vm.throw_completion<TypeError>(global_object, ErrorType::IsNotA, "searchString", "string, but a regular expression");
return {};
}
auto search_string = TRY_OR_DISCARD(search_string_value.to_utf16_string(global_object)); auto search_string = TRY(search_string_value.to_utf16_string(global_object));
size_t start = 0; size_t start = 0;
if (!vm.argument(1).is_undefined()) { if (!vm.argument(1).is_undefined()) {
auto position = TRY_OR_DISCARD(vm.argument(1).to_integer_or_infinity(global_object)); auto position = TRY(vm.argument(1).to_integer_or_infinity(global_object));
start = clamp(position, static_cast<double>(0), static_cast<double>(string.length_in_code_units())); start = clamp(position, static_cast<double>(0), static_cast<double>(string.length_in_code_units()));
} }
@ -610,14 +558,12 @@ JS_DEFINE_OLD_NATIVE_FUNCTION(StringPrototype::includes)
} }
// 22.1.3.21 String.prototype.slice ( start, end ), https://tc39.es/ecma262/#sec-string.prototype.slice // 22.1.3.21 String.prototype.slice ( start, end ), https://tc39.es/ecma262/#sec-string.prototype.slice
JS_DEFINE_OLD_NATIVE_FUNCTION(StringPrototype::slice) JS_DEFINE_NATIVE_FUNCTION(StringPrototype::slice)
{ {
auto string = utf16_string_from(vm, global_object); auto string = TRY(utf16_string_from(vm, global_object));
if (vm.exception())
return {};
auto string_length = static_cast<double>(string.length_in_code_units()); auto string_length = static_cast<double>(string.length_in_code_units());
auto int_start = TRY_OR_DISCARD(vm.argument(0).to_integer_or_infinity(global_object)); auto int_start = TRY(vm.argument(0).to_integer_or_infinity(global_object));
if (Value(int_start).is_negative_infinity()) if (Value(int_start).is_negative_infinity())
int_start = 0; int_start = 0;
else if (int_start < 0) else if (int_start < 0)
@ -627,7 +573,7 @@ JS_DEFINE_OLD_NATIVE_FUNCTION(StringPrototype::slice)
auto int_end = string_length; auto int_end = string_length;
if (!vm.argument(1).is_undefined()) { if (!vm.argument(1).is_undefined()) {
int_end = TRY_OR_DISCARD(vm.argument(1).to_integer_or_infinity(global_object)); int_end = TRY(vm.argument(1).to_integer_or_infinity(global_object));
if (Value(int_end).is_negative_infinity()) if (Value(int_end).is_negative_infinity())
int_end = 0; int_end = 0;
else if (int_end < 0) else if (int_end < 0)
@ -643,29 +589,29 @@ JS_DEFINE_OLD_NATIVE_FUNCTION(StringPrototype::slice)
} }
// 22.1.3.22 String.prototype.split ( separator, limit ), https://tc39.es/ecma262/#sec-string.prototype.split // 22.1.3.22 String.prototype.split ( separator, limit ), https://tc39.es/ecma262/#sec-string.prototype.split
JS_DEFINE_OLD_NATIVE_FUNCTION(StringPrototype::split) JS_DEFINE_NATIVE_FUNCTION(StringPrototype::split)
{ {
auto object = TRY_OR_DISCARD(require_object_coercible(global_object, vm.this_value(global_object))); auto object = TRY(require_object_coercible(global_object, vm.this_value(global_object)));
auto separator_argument = vm.argument(0); auto separator_argument = vm.argument(0);
auto limit_argument = vm.argument(1); auto limit_argument = vm.argument(1);
if (!separator_argument.is_nullish()) { if (!separator_argument.is_nullish()) {
auto splitter = TRY_OR_DISCARD(separator_argument.get_method(global_object, *vm.well_known_symbol_split())); auto splitter = TRY(separator_argument.get_method(global_object, *vm.well_known_symbol_split()));
if (splitter) if (splitter)
return TRY_OR_DISCARD(vm.call(*splitter, separator_argument, object, limit_argument)); return TRY(vm.call(*splitter, separator_argument, object, limit_argument));
} }
auto string = TRY_OR_DISCARD(object.to_utf16_string(global_object)); auto string = TRY(object.to_utf16_string(global_object));
auto* array = MUST(Array::create(global_object, 0)); auto* array = MUST(Array::create(global_object, 0));
size_t array_length = 0; size_t array_length = 0;
auto limit = NumericLimits<u32>::max(); auto limit = NumericLimits<u32>::max();
if (!limit_argument.is_undefined()) if (!limit_argument.is_undefined())
limit = TRY_OR_DISCARD(limit_argument.to_u32(global_object)); limit = TRY(limit_argument.to_u32(global_object));
auto separator = TRY_OR_DISCARD(separator_argument.to_utf16_string(global_object)); auto separator = TRY(separator_argument.to_utf16_string(global_object));
if (limit == 0) if (limit == 0)
return array; return array;
@ -709,18 +655,16 @@ JS_DEFINE_OLD_NATIVE_FUNCTION(StringPrototype::split)
} }
// 22.1.3.10 String.prototype.lastIndexOf ( searchString [ , position ] ), https://tc39.es/ecma262/#sec-string.prototype.lastindexof // 22.1.3.10 String.prototype.lastIndexOf ( searchString [ , position ] ), https://tc39.es/ecma262/#sec-string.prototype.lastindexof
JS_DEFINE_OLD_NATIVE_FUNCTION(StringPrototype::last_index_of) JS_DEFINE_NATIVE_FUNCTION(StringPrototype::last_index_of)
{ {
auto string = utf16_string_from(vm, global_object); auto string = TRY(utf16_string_from(vm, global_object));
if (vm.exception())
return {};
auto search_string = TRY_OR_DISCARD(vm.argument(0).to_utf16_string(global_object)); auto search_string = TRY(vm.argument(0).to_utf16_string(global_object));
auto string_length = string.length_in_code_units(); auto string_length = string.length_in_code_units();
auto search_length = search_string.length_in_code_units(); auto search_length = search_string.length_in_code_units();
auto position = TRY_OR_DISCARD(vm.argument(1).to_number(global_object)); auto position = TRY(vm.argument(1).to_number(global_object));
double pos = position.is_nan() ? static_cast<double>(INFINITY) : TRY_OR_DISCARD(position.to_integer_or_infinity(global_object)); double pos = position.is_nan() ? static_cast<double>(INFINITY) : TRY(position.to_integer_or_infinity(global_object));
size_t start = clamp(pos, static_cast<double>(0), static_cast<double>(string_length)); size_t start = clamp(pos, static_cast<double>(0), static_cast<double>(string_length));
Optional<size_t> last_index; Optional<size_t> last_index;
@ -743,14 +687,12 @@ JS_DEFINE_OLD_NATIVE_FUNCTION(StringPrototype::last_index_of)
} }
// 22.1.3.1 String.prototype.at ( index ), https://tc39.es/ecma262/#sec-string.prototype.at // 22.1.3.1 String.prototype.at ( index ), https://tc39.es/ecma262/#sec-string.prototype.at
JS_DEFINE_OLD_NATIVE_FUNCTION(StringPrototype::at) JS_DEFINE_NATIVE_FUNCTION(StringPrototype::at)
{ {
auto string = utf16_string_from(vm, global_object); auto string = TRY(utf16_string_from(vm, global_object));
if (vm.exception())
return {};
auto length = string.length_in_code_units(); auto length = string.length_in_code_units();
auto relative_index = TRY_OR_DISCARD(vm.argument(0).to_integer_or_infinity(global_object)); auto relative_index = TRY(vm.argument(0).to_integer_or_infinity(global_object));
if (Value(relative_index).is_infinity()) if (Value(relative_index).is_infinity())
return js_undefined(); return js_undefined();
@ -768,76 +710,74 @@ JS_DEFINE_OLD_NATIVE_FUNCTION(StringPrototype::at)
} }
// 22.1.3.34 String.prototype [ @@iterator ] ( ), https://tc39.es/ecma262/#sec-string.prototype-@@iterator // 22.1.3.34 String.prototype [ @@iterator ] ( ), https://tc39.es/ecma262/#sec-string.prototype-@@iterator
JS_DEFINE_OLD_NATIVE_FUNCTION(StringPrototype::symbol_iterator) JS_DEFINE_NATIVE_FUNCTION(StringPrototype::symbol_iterator)
{ {
auto this_object = TRY_OR_DISCARD(require_object_coercible(global_object, vm.this_value(global_object))); auto this_object = TRY(require_object_coercible(global_object, vm.this_value(global_object)));
auto string = TRY_OR_DISCARD(this_object.to_string(global_object)); auto string = TRY(this_object.to_string(global_object));
return StringIterator::create(global_object, string); return StringIterator::create(global_object, string);
} }
// 22.1.3.12 String.prototype.match ( regexp ), https://tc39.es/ecma262/#sec-string.prototype.match // 22.1.3.12 String.prototype.match ( regexp ), https://tc39.es/ecma262/#sec-string.prototype.match
JS_DEFINE_OLD_NATIVE_FUNCTION(StringPrototype::match) JS_DEFINE_NATIVE_FUNCTION(StringPrototype::match)
{ {
auto this_object = TRY_OR_DISCARD(require_object_coercible(global_object, vm.this_value(global_object))); auto this_object = TRY(require_object_coercible(global_object, vm.this_value(global_object)));
auto regexp = vm.argument(0); auto regexp = vm.argument(0);
if (!regexp.is_nullish()) { if (!regexp.is_nullish()) {
if (auto* matcher = TRY_OR_DISCARD(regexp.get_method(global_object, *vm.well_known_symbol_match()))) if (auto* matcher = TRY(regexp.get_method(global_object, *vm.well_known_symbol_match())))
return TRY_OR_DISCARD(vm.call(*matcher, regexp, this_object)); return TRY(vm.call(*matcher, regexp, this_object));
} }
auto string = TRY_OR_DISCARD(this_object.to_utf16_string(global_object)); auto string = TRY(this_object.to_utf16_string(global_object));
auto rx = regexp_create(global_object, regexp, js_undefined()); auto* rx = regexp_create(global_object, regexp, js_undefined());
if (!rx) if (auto* exception = vm.exception())
return {}; return throw_completion(exception->value());
return TRY_OR_DISCARD(Value(rx).invoke(global_object, *vm.well_known_symbol_match(), js_string(vm, move(string)))); return TRY(Value(rx).invoke(global_object, *vm.well_known_symbol_match(), js_string(vm, move(string))));
} }
// 22.1.3.13 String.prototype.matchAll ( regexp ), https://tc39.es/ecma262/#sec-string.prototype.matchall // 22.1.3.13 String.prototype.matchAll ( regexp ), https://tc39.es/ecma262/#sec-string.prototype.matchall
JS_DEFINE_OLD_NATIVE_FUNCTION(StringPrototype::match_all) JS_DEFINE_NATIVE_FUNCTION(StringPrototype::match_all)
{ {
auto this_object = TRY_OR_DISCARD(require_object_coercible(global_object, vm.this_value(global_object))); auto this_object = TRY(require_object_coercible(global_object, vm.this_value(global_object)));
auto regexp = vm.argument(0); auto regexp = vm.argument(0);
if (!regexp.is_nullish()) { if (!regexp.is_nullish()) {
auto is_regexp = TRY_OR_DISCARD(regexp.is_regexp(global_object)); auto is_regexp = TRY(regexp.is_regexp(global_object));
if (is_regexp) { if (is_regexp) {
auto flags = TRY_OR_DISCARD(regexp.as_object().get("flags")); auto flags = TRY(regexp.as_object().get("flags"));
auto flags_object = TRY_OR_DISCARD(require_object_coercible(global_object, flags)); auto flags_object = TRY(require_object_coercible(global_object, flags));
auto flags_string = TRY_OR_DISCARD(flags_object.to_string(global_object)); auto flags_string = TRY(flags_object.to_string(global_object));
if (!flags_string.contains("g")) { if (!flags_string.contains("g"))
vm.throw_exception<TypeError>(global_object, ErrorType::StringNonGlobalRegExp); return vm.throw_completion<TypeError>(global_object, ErrorType::StringNonGlobalRegExp);
return {};
} }
} if (auto* matcher = TRY(regexp.get_method(global_object, *vm.well_known_symbol_match_all())))
if (auto* matcher = TRY_OR_DISCARD(regexp.get_method(global_object, *vm.well_known_symbol_match_all()))) return TRY(vm.call(*matcher, regexp, this_object));
return TRY_OR_DISCARD(vm.call(*matcher, regexp, this_object));
} }
auto string = TRY_OR_DISCARD(this_object.to_utf16_string(global_object)); auto string = TRY(this_object.to_utf16_string(global_object));
auto rx = regexp_create(global_object, regexp, js_string(vm, "g")); auto* rx = regexp_create(global_object, regexp, js_string(vm, "g"));
if (!rx) if (auto* exception = vm.exception())
return {}; return throw_completion(exception->value());
return TRY_OR_DISCARD(Value(rx).invoke(global_object, *vm.well_known_symbol_match_all(), js_string(vm, move(string)))); return TRY(Value(rx).invoke(global_object, *vm.well_known_symbol_match_all(), js_string(vm, move(string))));
} }
// 22.1.3.18 String.prototype.replace ( searchValue, replaceValue ), https://tc39.es/ecma262/#sec-string.prototype.replace // 22.1.3.18 String.prototype.replace ( searchValue, replaceValue ), https://tc39.es/ecma262/#sec-string.prototype.replace
JS_DEFINE_OLD_NATIVE_FUNCTION(StringPrototype::replace) JS_DEFINE_NATIVE_FUNCTION(StringPrototype::replace)
{ {
auto this_object = TRY_OR_DISCARD(require_object_coercible(global_object, vm.this_value(global_object))); auto this_object = TRY(require_object_coercible(global_object, vm.this_value(global_object)));
auto search_value = vm.argument(0); auto search_value = vm.argument(0);
auto replace_value = vm.argument(1); auto replace_value = vm.argument(1);
if (!search_value.is_nullish()) { if (!search_value.is_nullish()) {
if (auto* replacer = TRY_OR_DISCARD(search_value.get_method(global_object, *vm.well_known_symbol_replace()))) if (auto* replacer = TRY(search_value.get_method(global_object, *vm.well_known_symbol_replace())))
return TRY_OR_DISCARD(vm.call(*replacer, search_value, this_object, replace_value)); return TRY(vm.call(*replacer, search_value, this_object, replace_value));
} }
auto string = TRY_OR_DISCARD(this_object.to_utf16_string(global_object)); auto string = TRY(this_object.to_utf16_string(global_object));
auto search_string = TRY_OR_DISCARD(search_value.to_utf16_string(global_object)); auto search_string = TRY(search_value.to_utf16_string(global_object));
if (!replace_value.is_function()) { if (!replace_value.is_function()) {
auto replace_string = TRY_OR_DISCARD(replace_value.to_utf16_string(global_object)); auto replace_string = TRY(replace_value.to_utf16_string(global_object));
replace_value = js_string(vm, move(replace_string)); replace_value = js_string(vm, move(replace_string));
} }
@ -849,10 +789,10 @@ JS_DEFINE_OLD_NATIVE_FUNCTION(StringPrototype::replace)
String replacement; String replacement;
if (replace_value.is_function()) { if (replace_value.is_function()) {
auto result = TRY_OR_DISCARD(vm.call(replace_value.as_function(), js_undefined(), js_string(vm, search_string), Value(position.value()), js_string(vm, string))); auto result = TRY(vm.call(replace_value.as_function(), js_undefined(), js_string(vm, search_string), Value(position.value()), js_string(vm, string)));
replacement = TRY_OR_DISCARD(result.to_string(global_object)); replacement = TRY(result.to_string(global_object));
} else { } else {
replacement = TRY_OR_DISCARD(get_substitution(global_object, search_string.view(), string.view(), *position, {}, js_undefined(), replace_value)); replacement = TRY(get_substitution(global_object, search_string.view(), string.view(), *position, {}, js_undefined(), replace_value));
} }
StringBuilder builder; StringBuilder builder;
@ -864,38 +804,34 @@ JS_DEFINE_OLD_NATIVE_FUNCTION(StringPrototype::replace)
} }
// 22.1.3.19 String.prototype.replaceAll ( searchValue, replaceValue ), https://tc39.es/ecma262/#sec-string.prototype.replaceall // 22.1.3.19 String.prototype.replaceAll ( searchValue, replaceValue ), https://tc39.es/ecma262/#sec-string.prototype.replaceall
JS_DEFINE_OLD_NATIVE_FUNCTION(StringPrototype::replace_all) JS_DEFINE_NATIVE_FUNCTION(StringPrototype::replace_all)
{ {
auto this_object = TRY_OR_DISCARD(require_object_coercible(global_object, vm.this_value(global_object))); auto this_object = TRY(require_object_coercible(global_object, vm.this_value(global_object)));
auto search_value = vm.argument(0); auto search_value = vm.argument(0);
auto replace_value = vm.argument(1); auto replace_value = vm.argument(1);
if (!search_value.is_nullish()) { if (!search_value.is_nullish()) {
bool is_regexp = TRY_OR_DISCARD(search_value.is_regexp(global_object)); bool is_regexp = TRY(search_value.is_regexp(global_object));
if (is_regexp) { if (is_regexp) {
auto flags = TRY_OR_DISCARD(search_value.as_object().get(vm.names.flags)); auto flags = TRY(search_value.as_object().get(vm.names.flags));
auto flags_object = TRY_OR_DISCARD(require_object_coercible(global_object, flags)); auto flags_object = TRY(require_object_coercible(global_object, flags));
auto flags_string = TRY_OR_DISCARD(flags_object.to_string(global_object)); auto flags_string = TRY(flags_object.to_string(global_object));
if (!flags_string.contains("g")) { if (!flags_string.contains("g"))
vm.throw_exception<TypeError>(global_object, ErrorType::StringNonGlobalRegExp); return vm.throw_completion<TypeError>(global_object, ErrorType::StringNonGlobalRegExp);
return {};
}
} }
auto* replacer = TRY_OR_DISCARD(search_value.get_method(global_object, *vm.well_known_symbol_replace())); auto* replacer = TRY(search_value.get_method(global_object, *vm.well_known_symbol_replace()));
if (replacer) if (replacer)
return TRY_OR_DISCARD(vm.call(*replacer, search_value, this_object, replace_value)); return TRY(vm.call(*replacer, search_value, this_object, replace_value));
} }
auto string = TRY_OR_DISCARD(this_object.to_utf16_string(global_object)); auto string = TRY(this_object.to_utf16_string(global_object));
auto search_string = TRY_OR_DISCARD(search_value.to_utf16_string(global_object)); auto search_string = TRY(search_value.to_utf16_string(global_object));
if (!replace_value.is_function()) { if (!replace_value.is_function()) {
auto replace_string = TRY_OR_DISCARD(replace_value.to_utf16_string(global_object)); auto replace_string = TRY(replace_value.to_utf16_string(global_object));
replace_value = js_string(vm, move(replace_string)); replace_value = js_string(vm, move(replace_string));
if (vm.exception())
return {};
} }
auto string_length = string.length_in_code_units(); auto string_length = string.length_in_code_units();
@ -918,10 +854,10 @@ JS_DEFINE_OLD_NATIVE_FUNCTION(StringPrototype::replace_all)
String replacement; String replacement;
if (replace_value.is_function()) { if (replace_value.is_function()) {
auto result = TRY_OR_DISCARD(vm.call(replace_value.as_function(), js_undefined(), js_string(vm, search_string), Value(position), js_string(vm, string))); auto result = TRY(vm.call(replace_value.as_function(), js_undefined(), js_string(vm, search_string), Value(position), js_string(vm, string)));
replacement = TRY_OR_DISCARD(result.to_string(global_object)); replacement = TRY(result.to_string(global_object));
} else { } else {
replacement = TRY_OR_DISCARD(get_substitution(global_object, search_string.view(), string.view(), position, {}, js_undefined(), replace_value)); replacement = TRY(get_substitution(global_object, search_string.view(), string.view(), position, {}, js_undefined(), replace_value));
} }
result.append(preserved); result.append(preserved);
@ -937,21 +873,21 @@ JS_DEFINE_OLD_NATIVE_FUNCTION(StringPrototype::replace_all)
} }
// 22.1.3.20 String.prototype.search ( regexp ), https://tc39.es/ecma262/#sec-string.prototype.search // 22.1.3.20 String.prototype.search ( regexp ), https://tc39.es/ecma262/#sec-string.prototype.search
JS_DEFINE_OLD_NATIVE_FUNCTION(StringPrototype::search) JS_DEFINE_NATIVE_FUNCTION(StringPrototype::search)
{ {
auto this_object = TRY_OR_DISCARD(require_object_coercible(global_object, vm.this_value(global_object))); auto this_object = TRY(require_object_coercible(global_object, vm.this_value(global_object)));
auto regexp = vm.argument(0); auto regexp = vm.argument(0);
if (!regexp.is_nullish()) { if (!regexp.is_nullish()) {
if (auto* searcher = TRY_OR_DISCARD(regexp.get_method(global_object, *vm.well_known_symbol_search()))) if (auto* searcher = TRY(regexp.get_method(global_object, *vm.well_known_symbol_search())))
return TRY_OR_DISCARD(vm.call(*searcher, regexp, this_object)); return TRY(vm.call(*searcher, regexp, this_object));
} }
auto string = TRY_OR_DISCARD(this_object.to_utf16_string(global_object)); auto string = TRY(this_object.to_utf16_string(global_object));
auto rx = regexp_create(global_object, regexp, js_undefined()); auto* rx = regexp_create(global_object, regexp, js_undefined());
if (!rx) if (auto* exception = vm.exception())
return {}; return throw_completion(exception->value());
return TRY_OR_DISCARD(Value(rx).invoke(global_object, *vm.well_known_symbol_search(), js_string(vm, move(string)))); return TRY(Value(rx).invoke(global_object, *vm.well_known_symbol_search(), js_string(vm, move(string))));
} }
// B.2.2.2.1 CreateHTML ( string, tag, attribute, value ), https://tc39.es/ecma262/#sec-createhtml // B.2.2.2.1 CreateHTML ( string, tag, attribute, value ), https://tc39.es/ecma262/#sec-createhtml
@ -980,97 +916,94 @@ static ThrowCompletionOr<Value> create_html(GlobalObject& global_object, Value s
} }
// B.2.2.2 String.prototype.anchor ( name ), https://tc39.es/ecma262/#sec-string.prototype.anchor // B.2.2.2 String.prototype.anchor ( name ), https://tc39.es/ecma262/#sec-string.prototype.anchor
JS_DEFINE_OLD_NATIVE_FUNCTION(StringPrototype::anchor) JS_DEFINE_NATIVE_FUNCTION(StringPrototype::anchor)
{ {
return TRY_OR_DISCARD(create_html(global_object, vm.this_value(global_object), "a", "name", vm.argument(0))); return create_html(global_object, vm.this_value(global_object), "a", "name", vm.argument(0));
} }
// B.2.2.3 String.prototype.big ( ), https://tc39.es/ecma262/#sec-string.prototype.big // B.2.2.3 String.prototype.big ( ), https://tc39.es/ecma262/#sec-string.prototype.big
JS_DEFINE_OLD_NATIVE_FUNCTION(StringPrototype::big) JS_DEFINE_NATIVE_FUNCTION(StringPrototype::big)
{ {
return TRY_OR_DISCARD(create_html(global_object, vm.this_value(global_object), "big", String::empty(), Value())); return create_html(global_object, vm.this_value(global_object), "big", String::empty(), Value());
} }
// B.2.2.4 String.prototype.blink ( ), https://tc39.es/ecma262/#sec-string.prototype.blink // B.2.2.4 String.prototype.blink ( ), https://tc39.es/ecma262/#sec-string.prototype.blink
JS_DEFINE_OLD_NATIVE_FUNCTION(StringPrototype::blink) JS_DEFINE_NATIVE_FUNCTION(StringPrototype::blink)
{ {
return TRY_OR_DISCARD(create_html(global_object, vm.this_value(global_object), "blink", String::empty(), Value())); return create_html(global_object, vm.this_value(global_object), "blink", String::empty(), Value());
} }
// B.2.2.5 String.prototype.bold ( ), https://tc39.es/ecma262/#sec-string.prototype.bold // B.2.2.5 String.prototype.bold ( ), https://tc39.es/ecma262/#sec-string.prototype.bold
JS_DEFINE_OLD_NATIVE_FUNCTION(StringPrototype::bold) JS_DEFINE_NATIVE_FUNCTION(StringPrototype::bold)
{ {
return TRY_OR_DISCARD(create_html(global_object, vm.this_value(global_object), "b", String::empty(), Value())); return create_html(global_object, vm.this_value(global_object), "b", String::empty(), Value());
} }
// B.2.2.6 String.prototype.fixed ( ), https://tc39.es/ecma262/#sec-string.prototype.fixed // B.2.2.6 String.prototype.fixed ( ), https://tc39.es/ecma262/#sec-string.prototype.fixed
JS_DEFINE_OLD_NATIVE_FUNCTION(StringPrototype::fixed) JS_DEFINE_NATIVE_FUNCTION(StringPrototype::fixed)
{ {
return TRY_OR_DISCARD(create_html(global_object, vm.this_value(global_object), "tt", String::empty(), Value())); return create_html(global_object, vm.this_value(global_object), "tt", String::empty(), Value());
} }
// B.2.2.7 String.prototype.fontcolor ( color ), https://tc39.es/ecma262/#sec-string.prototype.fontcolor // B.2.2.7 String.prototype.fontcolor ( color ), https://tc39.es/ecma262/#sec-string.prototype.fontcolor
JS_DEFINE_OLD_NATIVE_FUNCTION(StringPrototype::fontcolor) JS_DEFINE_NATIVE_FUNCTION(StringPrototype::fontcolor)
{ {
return TRY_OR_DISCARD(create_html(global_object, vm.this_value(global_object), "font", "color", vm.argument(0))); return create_html(global_object, vm.this_value(global_object), "font", "color", vm.argument(0));
} }
// B.2.2.8 String.prototype.fontsize ( size ), https://tc39.es/ecma262/#sec-string.prototype.fontsize // B.2.2.8 String.prototype.fontsize ( size ), https://tc39.es/ecma262/#sec-string.prototype.fontsize
JS_DEFINE_OLD_NATIVE_FUNCTION(StringPrototype::fontsize) JS_DEFINE_NATIVE_FUNCTION(StringPrototype::fontsize)
{ {
return TRY_OR_DISCARD(create_html(global_object, vm.this_value(global_object), "font", "size", vm.argument(0))); return create_html(global_object, vm.this_value(global_object), "font", "size", vm.argument(0));
} }
// B.2.2.9 String.prototype.italics ( ), https://tc39.es/ecma262/#sec-string.prototype.italics // B.2.2.9 String.prototype.italics ( ), https://tc39.es/ecma262/#sec-string.prototype.italics
JS_DEFINE_OLD_NATIVE_FUNCTION(StringPrototype::italics) JS_DEFINE_NATIVE_FUNCTION(StringPrototype::italics)
{ {
return TRY_OR_DISCARD(create_html(global_object, vm.this_value(global_object), "i", String::empty(), Value())); return create_html(global_object, vm.this_value(global_object), "i", String::empty(), Value());
} }
// B.2.2.10 String.prototype.link ( url ), https://tc39.es/ecma262/#sec-string.prototype.link // B.2.2.10 String.prototype.link ( url ), https://tc39.es/ecma262/#sec-string.prototype.link
JS_DEFINE_OLD_NATIVE_FUNCTION(StringPrototype::link) JS_DEFINE_NATIVE_FUNCTION(StringPrototype::link)
{ {
return TRY_OR_DISCARD(create_html(global_object, vm.this_value(global_object), "a", "href", vm.argument(0))); return create_html(global_object, vm.this_value(global_object), "a", "href", vm.argument(0));
} }
// B.2.2.11 String.prototype.small ( ), https://tc39.es/ecma262/#sec-string.prototype.small // B.2.2.11 String.prototype.small ( ), https://tc39.es/ecma262/#sec-string.prototype.small
JS_DEFINE_OLD_NATIVE_FUNCTION(StringPrototype::small) JS_DEFINE_NATIVE_FUNCTION(StringPrototype::small)
{ {
return TRY_OR_DISCARD(create_html(global_object, vm.this_value(global_object), "small", String::empty(), Value())); return create_html(global_object, vm.this_value(global_object), "small", String::empty(), Value());
} }
// B.2.2.12 String.prototype.strike ( ), https://tc39.es/ecma262/#sec-string.prototype.strike // B.2.2.12 String.prototype.strike ( ), https://tc39.es/ecma262/#sec-string.prototype.strike
JS_DEFINE_OLD_NATIVE_FUNCTION(StringPrototype::strike) JS_DEFINE_NATIVE_FUNCTION(StringPrototype::strike)
{ {
return TRY_OR_DISCARD(create_html(global_object, vm.this_value(global_object), "strike", String::empty(), Value())); return create_html(global_object, vm.this_value(global_object), "strike", String::empty(), Value());
} }
// B.2.2.13 String.prototype.sub ( ), https://tc39.es/ecma262/#sec-string.prototype.sub // B.2.2.13 String.prototype.sub ( ), https://tc39.es/ecma262/#sec-string.prototype.sub
JS_DEFINE_OLD_NATIVE_FUNCTION(StringPrototype::sub) JS_DEFINE_NATIVE_FUNCTION(StringPrototype::sub)
{ {
return TRY_OR_DISCARD(create_html(global_object, vm.this_value(global_object), "sub", String::empty(), Value())); return create_html(global_object, vm.this_value(global_object), "sub", String::empty(), Value());
} }
// B.2.2.14 String.prototype.sup ( ), https://tc39.es/ecma262/#sec-string.prototype.sup // B.2.2.14 String.prototype.sup ( ), https://tc39.es/ecma262/#sec-string.prototype.sup
JS_DEFINE_OLD_NATIVE_FUNCTION(StringPrototype::sup) JS_DEFINE_NATIVE_FUNCTION(StringPrototype::sup)
{ {
return TRY_OR_DISCARD(create_html(global_object, vm.this_value(global_object), "sup", String::empty(), Value())); return create_html(global_object, vm.this_value(global_object), "sup", String::empty(), Value());
} }
// 22.1.3.11 String.prototype.localeCompare ( that [ , reserved1 [ , reserved2 ] ] ), https://tc39.es/ecma262/#sec-string.prototype.localecompare // 22.1.3.11 String.prototype.localeCompare ( that [ , reserved1 [ , reserved2 ] ] ), https://tc39.es/ecma262/#sec-string.prototype.localecompare
// NOTE: This is the minimum localeCompare implementation for engines without ECMA-402. // NOTE: This is the minimum localeCompare implementation for engines without ECMA-402.
JS_DEFINE_OLD_NATIVE_FUNCTION(StringPrototype::locale_compare) JS_DEFINE_NATIVE_FUNCTION(StringPrototype::locale_compare)
{ {
auto string = ak_string_from(vm, global_object); auto string = TRY(ak_string_from(vm, global_object));
if (!string.has_value()) auto that_string = TRY(vm.argument(0).to_string(global_object));
return {};
auto that_string = TRY_OR_DISCARD(vm.argument(0).to_string(global_object));
// FIXME: Actually compare the string not just according to their bits. // FIXME: Actually compare the string not just according to their bits.
if (string == that_string) if (string == that_string)
return Value(0); return Value(0);
if (string.value() < that_string) if (string < that_string)
return Value(-1); return Value(-1);
return Value(1); return Value(1);

View file

@ -27,53 +27,53 @@ public:
virtual ~StringPrototype() override; virtual ~StringPrototype() override;
private: private:
JS_DECLARE_OLD_NATIVE_FUNCTION(char_at); JS_DECLARE_NATIVE_FUNCTION(char_at);
JS_DECLARE_OLD_NATIVE_FUNCTION(char_code_at); JS_DECLARE_NATIVE_FUNCTION(char_code_at);
JS_DECLARE_OLD_NATIVE_FUNCTION(code_point_at); JS_DECLARE_NATIVE_FUNCTION(code_point_at);
JS_DECLARE_OLD_NATIVE_FUNCTION(repeat); JS_DECLARE_NATIVE_FUNCTION(repeat);
JS_DECLARE_OLD_NATIVE_FUNCTION(starts_with); JS_DECLARE_NATIVE_FUNCTION(starts_with);
JS_DECLARE_OLD_NATIVE_FUNCTION(ends_with); JS_DECLARE_NATIVE_FUNCTION(ends_with);
JS_DECLARE_OLD_NATIVE_FUNCTION(index_of); JS_DECLARE_NATIVE_FUNCTION(index_of);
JS_DECLARE_OLD_NATIVE_FUNCTION(to_locale_lowercase); JS_DECLARE_NATIVE_FUNCTION(to_locale_lowercase);
JS_DECLARE_OLD_NATIVE_FUNCTION(to_locale_uppercase); JS_DECLARE_NATIVE_FUNCTION(to_locale_uppercase);
JS_DECLARE_OLD_NATIVE_FUNCTION(to_lowercase); JS_DECLARE_NATIVE_FUNCTION(to_lowercase);
JS_DECLARE_OLD_NATIVE_FUNCTION(to_uppercase); JS_DECLARE_NATIVE_FUNCTION(to_uppercase);
JS_DECLARE_OLD_NATIVE_FUNCTION(to_string); JS_DECLARE_NATIVE_FUNCTION(to_string);
JS_DECLARE_OLD_NATIVE_FUNCTION(value_of); JS_DECLARE_NATIVE_FUNCTION(value_of);
JS_DECLARE_OLD_NATIVE_FUNCTION(pad_start); JS_DECLARE_NATIVE_FUNCTION(pad_start);
JS_DECLARE_OLD_NATIVE_FUNCTION(pad_end); JS_DECLARE_NATIVE_FUNCTION(pad_end);
JS_DECLARE_OLD_NATIVE_FUNCTION(substring); JS_DECLARE_NATIVE_FUNCTION(substring);
JS_DECLARE_OLD_NATIVE_FUNCTION(substr); JS_DECLARE_NATIVE_FUNCTION(substr);
JS_DECLARE_OLD_NATIVE_FUNCTION(trim); JS_DECLARE_NATIVE_FUNCTION(trim);
JS_DECLARE_OLD_NATIVE_FUNCTION(trim_start); JS_DECLARE_NATIVE_FUNCTION(trim_start);
JS_DECLARE_OLD_NATIVE_FUNCTION(trim_end); JS_DECLARE_NATIVE_FUNCTION(trim_end);
JS_DECLARE_OLD_NATIVE_FUNCTION(concat); JS_DECLARE_NATIVE_FUNCTION(concat);
JS_DECLARE_OLD_NATIVE_FUNCTION(includes); JS_DECLARE_NATIVE_FUNCTION(includes);
JS_DECLARE_OLD_NATIVE_FUNCTION(slice); JS_DECLARE_NATIVE_FUNCTION(slice);
JS_DECLARE_OLD_NATIVE_FUNCTION(split); JS_DECLARE_NATIVE_FUNCTION(split);
JS_DECLARE_OLD_NATIVE_FUNCTION(last_index_of); JS_DECLARE_NATIVE_FUNCTION(last_index_of);
JS_DECLARE_OLD_NATIVE_FUNCTION(at); JS_DECLARE_NATIVE_FUNCTION(at);
JS_DECLARE_OLD_NATIVE_FUNCTION(match); JS_DECLARE_NATIVE_FUNCTION(match);
JS_DECLARE_OLD_NATIVE_FUNCTION(match_all); JS_DECLARE_NATIVE_FUNCTION(match_all);
JS_DECLARE_OLD_NATIVE_FUNCTION(replace); JS_DECLARE_NATIVE_FUNCTION(replace);
JS_DECLARE_OLD_NATIVE_FUNCTION(replace_all); JS_DECLARE_NATIVE_FUNCTION(replace_all);
JS_DECLARE_OLD_NATIVE_FUNCTION(search); JS_DECLARE_NATIVE_FUNCTION(search);
JS_DECLARE_OLD_NATIVE_FUNCTION(anchor); JS_DECLARE_NATIVE_FUNCTION(anchor);
JS_DECLARE_OLD_NATIVE_FUNCTION(big); JS_DECLARE_NATIVE_FUNCTION(big);
JS_DECLARE_OLD_NATIVE_FUNCTION(blink); JS_DECLARE_NATIVE_FUNCTION(blink);
JS_DECLARE_OLD_NATIVE_FUNCTION(bold); JS_DECLARE_NATIVE_FUNCTION(bold);
JS_DECLARE_OLD_NATIVE_FUNCTION(fixed); JS_DECLARE_NATIVE_FUNCTION(fixed);
JS_DECLARE_OLD_NATIVE_FUNCTION(fontcolor); JS_DECLARE_NATIVE_FUNCTION(fontcolor);
JS_DECLARE_OLD_NATIVE_FUNCTION(fontsize); JS_DECLARE_NATIVE_FUNCTION(fontsize);
JS_DECLARE_OLD_NATIVE_FUNCTION(italics); JS_DECLARE_NATIVE_FUNCTION(italics);
JS_DECLARE_OLD_NATIVE_FUNCTION(link); JS_DECLARE_NATIVE_FUNCTION(link);
JS_DECLARE_OLD_NATIVE_FUNCTION(small); JS_DECLARE_NATIVE_FUNCTION(small);
JS_DECLARE_OLD_NATIVE_FUNCTION(strike); JS_DECLARE_NATIVE_FUNCTION(strike);
JS_DECLARE_OLD_NATIVE_FUNCTION(sub); JS_DECLARE_NATIVE_FUNCTION(sub);
JS_DECLARE_OLD_NATIVE_FUNCTION(sup); JS_DECLARE_NATIVE_FUNCTION(sup);
JS_DECLARE_OLD_NATIVE_FUNCTION(locale_compare); JS_DECLARE_NATIVE_FUNCTION(locale_compare);
JS_DECLARE_OLD_NATIVE_FUNCTION(symbol_iterator); JS_DECLARE_NATIVE_FUNCTION(symbol_iterator);
}; };
} }