LibJS: Convert to_string() to ThrowCompletionOr

Also update get_function_name() to use ThrowCompletionOr, but this is
not a standard AO and should be refactored out of existence eventually.
This commit is contained in:
Linus Groh 2021-10-12 17:49:01 +01:00
parent 5d38cf4973
commit 4d8912a92b
Notes: sideshowbarker 2024-07-18 02:47:45 +09:00
48 changed files with 171 additions and 415 deletions

View File

@ -141,10 +141,7 @@ JS_DEFINE_NATIVE_FUNCTION(TestRunnerGlobalObject::fuzzilli)
if (!vm.argument_count())
return JS::js_undefined();
auto operation = vm.argument(0).to_string(global_object);
if (vm.exception())
return {};
auto operation = TRY_OR_DISCARD(vm.argument(0).to_string(global_object));
if (operation == "FUZZILLI_CRASH") {
auto type = vm.argument(1).to_i32(global_object);
if (vm.exception())
@ -164,9 +161,7 @@ JS_DEFINE_NATIVE_FUNCTION(TestRunnerGlobalObject::fuzzilli)
fzliout = stdout;
}
auto string = vm.argument(1).to_string(global_object);
if (vm.exception())
return {};
auto string = TRY_OR_DISCARD(vm.argument(1).to_string(global_object));
fprintf(fzliout, "%s\n", string.characters());
fflush(fzliout);
}

View File

@ -906,19 +906,24 @@ static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter
if (!optional) {
if (!parameter.type.nullable) {
scoped_generator.append(R"~~~(
auto @cpp_name@ = @js_name@@js_suffix@.is_null() && @legacy_null_to_empty_string@
? String::empty()
: @js_name@@js_suffix@.to_string(global_object);
if (vm.exception())
@return_statement@
String @cpp_name@;
if (@js_name@@js_suffix@.is_null() && @legacy_null_to_empty_string@) {
@cpp_name@ = String::empty();
} else {
auto to_string_result = @js_name@@js_suffix@.to_string(global_object);
if (to_string_result.is_error())
@return_statement@
@cpp_name@ = to_string_result.release_value();
}
)~~~");
} else {
scoped_generator.append(R"~~~(
String @cpp_name@;
if (!@js_name@@js_suffix@.is_nullish()) {
@cpp_name@ = @js_name@@js_suffix@.to_string(global_object);
if (vm.exception())
auto to_string_result = @js_name@@js_suffix@.to_string(global_object);
if (to_string_result.is_error())
@return_statement@
@cpp_name@ = to_string_result.release_value();
}
)~~~");
}
@ -926,11 +931,14 @@ static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter
scoped_generator.append(R"~~~(
String @cpp_name@;
if (!@js_name@@js_suffix@.is_undefined()) {
@cpp_name@ = @js_name@@js_suffix@.is_null() && @legacy_null_to_empty_string@
? String::empty()
: @js_name@@js_suffix@.to_string(global_object);
if (vm.exception())
@return_statement@
if (@js_name@@js_suffix@.is_null() && @legacy_null_to_empty_string@) {
@cpp_name@ = String::empty();
} else {
auto to_string_result = @js_name@@js_suffix@.to_string(global_object);
if (to_string_result.is_error())
@return_statement@
@cpp_name@ = to_string_result.release_value();
}
})~~~");
if (optional_default_value.has_value() && (!parameter.type.nullable || optional_default_value.value() != "null")) {
scoped_generator.append(R"~~~( else {

View File

@ -18,9 +18,7 @@ TESTJS_GLOBAL_FUNCTION(is_strict_mode, isStrictMode, 0)
TESTJS_GLOBAL_FUNCTION(can_parse_source, canParseSource)
{
auto source = vm.argument(0).to_string(global_object);
if (vm.exception())
return {};
auto source = TRY_OR_DISCARD(vm.argument(0).to_string(global_object));
auto parser = JS::Parser(JS::Lexer(source));
parser.parse_program();
return JS::Value(!parser.has_errors());

View File

@ -13,9 +13,7 @@ TEST_ROOT("Userland/Libraries/LibWasm/Tests");
TESTJS_GLOBAL_FUNCTION(read_binary_wasm_file, readBinaryWasmFile)
{
auto filename = vm.argument(0).to_string(global_object);
if (vm.exception())
return {};
auto filename = TRY_OR_DISCARD(vm.argument(0).to_string(global_object));
auto file = Core::File::open(filename, Core::OpenMode::ReadOnly);
if (file.is_error()) {
vm.throw_exception<JS::TypeError>(global_object, file.error().string());
@ -169,9 +167,7 @@ void WebAssemblyModule::initialize(JS::GlobalObject& global_object)
JS_DEFINE_NATIVE_FUNCTION(WebAssemblyModule::get_export)
{
auto name = vm.argument(0).to_string(global_object);
if (vm.exception())
return {};
auto name = TRY_OR_DISCARD(vm.argument(0).to_string(global_object));
auto this_value = vm.this_value(global_object);
auto object = this_value.to_object(global_object);
if (vm.exception())

View File

@ -40,9 +40,7 @@ TESTJS_MAIN_HOOK()
TESTJS_GLOBAL_FUNCTION(load_local_page, loadLocalPage)
{
auto name = vm.argument(0).to_string(global_object);
if (vm.exception())
return {};
auto name = TRY_OR_DISCARD(vm.argument(0).to_string(global_object));
// Clear the hooks
before_initial_load_hooks.clear();

View File

@ -40,7 +40,7 @@ GUI::Variant SheetModel::data(const GUI::ModelIndex& index, GUI::ModelRole role)
return builder.to_string();
}
}
auto error = value.to_string(cell->sheet().global_object());
auto error = value.to_string_without_side_effects();
// This is annoying, but whatever.
cell->sheet().interpreter().vm().clear_exception();

View File

@ -73,7 +73,7 @@ static void update_function_name(Value value, FlyString const& name)
static_cast<ECMAScriptFunctionObject&>(function).set_name(name);
}
static String get_function_name(GlobalObject& global_object, Value value)
static ThrowCompletionOr<String> get_function_name(GlobalObject& global_object, Value value)
{
if (value.is_symbol())
return String::formatted("[{}]", value.as_symbol().description());
@ -1285,11 +1285,11 @@ ThrowCompletionOr<Value> ClassExpression::class_definition_evaluation(Interprete
TRY(target.define_property_or_throw(property_key, { .value = method_value, .writable = true, .enumerable = false, .configurable = true }));
break;
case ClassMethod::Kind::Getter:
update_function_name(method_value, String::formatted("get {}", get_function_name(global_object, key)));
update_function_name(method_value, String::formatted("get {}", TRY(get_function_name(global_object, key))));
TRY(target.define_property_or_throw(property_key, { .get = &method_function, .enumerable = true, .configurable = true }));
break;
case ClassMethod::Kind::Setter:
update_function_name(method_value, String::formatted("set {}", get_function_name(global_object, key)));
update_function_name(method_value, String::formatted("set {}", TRY(get_function_name(global_object, key))));
TRY(target.define_property_or_throw(property_key, { .set = &method_function, .enumerable = true, .configurable = true }));
break;
default:
@ -2346,7 +2346,7 @@ Value ObjectExpression::execute(Interpreter& interpreter, GlobalObject& global_o
if (value.is_function() && property.is_method())
static_cast<ECMAScriptFunctionObject&>(value.as_function()).set_home_object(object);
String name = get_function_name(global_object, key);
auto name = TRY_OR_DISCARD(get_function_name(global_object, key));
if (property.type() == ObjectProperty::Type::Getter) {
name = String::formatted("get {}", name);
} else if (property.type() == ObjectProperty::Type::Setter) {
@ -2640,9 +2640,7 @@ Value TemplateLiteral::execute(Interpreter& interpreter, GlobalObject& global_ob
auto expr = expression.execute(interpreter, global_object);
if (interpreter.exception())
return {};
auto string = expr.to_string(global_object);
if (interpreter.exception())
return {};
auto string = TRY_OR_DISCARD(expr.to_string(global_object));
string_builder.append(string);
}

View File

@ -929,10 +929,7 @@ ThrowCompletionOr<String> get_substitution(GlobalObject& global_object, Utf16Vie
auto& value = captures[*capture_position - 1];
if (!value.is_undefined()) {
auto value_string = value.to_string(global_object);
if (auto* exception = vm.exception())
return throw_completion(exception->value());
auto value_string = TRY(value.to_string(global_object));
result.append(value_string);
}
@ -960,10 +957,7 @@ ThrowCompletionOr<String> get_substitution(GlobalObject& global_object, Utf16Vie
auto capture = TRY(named_captures.as_object().get(group_name));
if (!capture.is_undefined()) {
auto capture_string = capture.to_string(global_object);
if (auto* exception = vm.exception())
return throw_completion(exception->value());
auto capture_string = TRY(capture.to_string(global_object));
result.append(capture_string);
}

View File

@ -45,9 +45,7 @@ Value AggregateErrorConstructor::construct(FunctionObject& new_target)
auto* aggregate_error = TRY_OR_DISCARD(ordinary_create_from_constructor<AggregateError>(global_object, new_target, &GlobalObject::aggregate_error_prototype));
if (!vm.argument(1).is_undefined()) {
auto message = vm.argument(1).to_string(global_object);
if (vm.exception())
return {};
auto message = TRY_OR_DISCARD(vm.argument(1).to_string(global_object));
MUST(aggregate_error->create_non_enumerable_data_property_or_throw(vm.names.message, js_string(vm, message)));
}

View File

@ -457,9 +457,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::to_locale_string)
if (value.is_nullish())
continue;
auto locale_string_result = TRY_OR_DISCARD(value.invoke(global_object, vm.names.toLocaleString));
auto string = locale_string_result.to_string(global_object);
if (vm.exception())
return {};
auto string = TRY_OR_DISCARD(locale_string_result.to_string(global_object));
builder.append(string);
}
return js_string(vm, builder.to_string());
@ -484,11 +482,8 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::join)
auto length = TRY_OR_DISCARD(length_of_array_like(global_object, *this_object));
String separator = ",";
if (!vm.argument(0).is_undefined()) {
separator = vm.argument(0).to_string(global_object);
if (vm.exception())
return {};
}
if (!vm.argument(0).is_undefined())
separator = TRY_OR_DISCARD(vm.argument(0).to_string(global_object));
StringBuilder builder;
for (size_t i = 0; i < length; ++i) {
if (i > 0)
@ -496,9 +491,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::join)
auto value = TRY_OR_DISCARD(this_object->get(i));
if (value.is_nullish())
continue;
auto string = value.to_string(global_object);
if (vm.exception())
return {};
auto string = TRY_OR_DISCARD(value.to_string(global_object));
builder.append(string);
}

View File

@ -319,9 +319,7 @@ JS_DEFINE_NATIVE_FUNCTION(DateConstructor::parse)
if (!vm.argument_count())
return js_nan();
auto date_string = vm.argument(0).to_string(global_object);
if (vm.exception())
return {};
auto date_string = TRY_OR_DISCARD(vm.argument(0).to_string(global_object));
return parse_date_string(date_string);
}

View File

@ -42,9 +42,7 @@ Value ErrorConstructor::construct(FunctionObject& new_target)
auto* error = TRY_OR_DISCARD(ordinary_create_from_constructor<Error>(global_object, new_target, &GlobalObject::error_prototype));
if (!vm.argument(0).is_undefined()) {
auto message = vm.argument(0).to_string(global_object);
if (vm.exception())
return {};
auto message = TRY_OR_DISCARD(vm.argument(0).to_string(global_object));
MUST(error->create_non_enumerable_data_property_or_throw(vm.names.message, js_string(vm, message)));
}
@ -89,9 +87,7 @@ Value ErrorConstructor::construct(FunctionObject& new_target)
global_object, new_target, &GlobalObject::snake_name##_prototype)); \
\
if (!vm.argument(0).is_undefined()) { \
auto message = vm.argument(0).to_string(global_object); \
if (vm.exception()) \
return {}; \
auto message = TRY_OR_DISCARD(vm.argument(0).to_string(global_object)); \
MUST(error->create_non_enumerable_data_property_or_throw(vm.names.message, js_string(vm, message))); \
} \
\

View File

@ -41,19 +41,13 @@ JS_DEFINE_NATIVE_FUNCTION(ErrorPrototype::to_string)
String name = "Error";
auto name_property = TRY_OR_DISCARD(this_object.get(vm.names.name));
if (!name_property.is_undefined()) {
name = name_property.to_string(global_object);
if (vm.exception())
return {};
}
if (!name_property.is_undefined())
name = TRY_OR_DISCARD(name_property.to_string(global_object));
String message = "";
auto message_property = TRY_OR_DISCARD(this_object.get(vm.names.message));
if (!message_property.is_undefined()) {
message = message_property.to_string(global_object);
if (vm.exception())
return {};
}
if (!message_property.is_undefined())
message = TRY_OR_DISCARD(message_property.to_string(global_object));
if (name.is_empty())
return js_string(vm, message);

View File

@ -41,24 +41,16 @@ RefPtr<FunctionExpression> FunctionConstructor::create_dynamic_function_node(Glo
auto& vm = global_object.vm();
String parameters_source = "";
String body_source = "";
if (vm.argument_count() == 1) {
body_source = vm.argument(0).to_string(global_object);
if (vm.exception())
return {};
}
if (vm.argument_count() == 1)
body_source = TRY_OR_DISCARD(vm.argument(0).to_string(global_object));
if (vm.argument_count() > 1) {
Vector<String> parameters;
for (size_t i = 0; i < vm.argument_count() - 1; ++i) {
parameters.append(vm.argument(i).to_string(global_object));
if (vm.exception())
return {};
}
for (size_t i = 0; i < vm.argument_count() - 1; ++i)
parameters.append(TRY_OR_DISCARD(vm.argument(i).to_string(global_object)));
StringBuilder parameters_builder;
parameters_builder.join(',', parameters);
parameters_source = parameters_builder.build();
body_source = vm.argument(vm.argument_count() - 1).to_string(global_object);
if (vm.exception())
return {};
body_source = TRY_OR_DISCARD(vm.argument(vm.argument_count() - 1).to_string(global_object));
}
auto is_generator = kind == FunctionKind::Generator;
auto source = String::formatted("function{} anonymous({}\n) {{\n{}\n}}", is_generator ? "*" : "", parameters_source, body_source);

View File

@ -347,9 +347,7 @@ JS_DEFINE_NATIVE_FUNCTION(GlobalObject::parse_float)
{
if (vm.argument(0).is_number())
return vm.argument(0);
auto input_string = vm.argument(0).to_string(global_object);
if (vm.exception())
return {};
auto input_string = TRY_OR_DISCARD(vm.argument(0).to_string(global_object));
auto trimmed_string = input_string.trim_whitespace(TrimMode::Left);
for (size_t length = trimmed_string.length(); length > 0; --length) {
// This can't throw, so no exception check is fine.
@ -363,9 +361,7 @@ JS_DEFINE_NATIVE_FUNCTION(GlobalObject::parse_float)
// 19.2.5 parseInt ( string, radix ), https://tc39.es/ecma262/#sec-parseint-string-radix
JS_DEFINE_NATIVE_FUNCTION(GlobalObject::parse_int)
{
auto input_string = vm.argument(0).to_string(global_object);
if (vm.exception())
return {};
auto input_string = TRY_OR_DISCARD(vm.argument(0).to_string(global_object));
// FIXME: There's a bunch of unnecessary string copying here.
double sign = 1;
@ -500,9 +496,7 @@ static String decode(JS::GlobalObject& global_object, const String& string, Stri
// 19.2.6.4 encodeURI ( uri ), https://tc39.es/ecma262/#sec-encodeuri-uri
JS_DEFINE_NATIVE_FUNCTION(GlobalObject::encode_uri)
{
auto uri_string = vm.argument(0).to_string(global_object);
if (vm.exception())
return {};
auto uri_string = TRY_OR_DISCARD(vm.argument(0).to_string(global_object));
auto encoded = encode(global_object, uri_string, ";/?:@&=+$,abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.!~*'()#"sv);
if (vm.exception())
return {};
@ -512,9 +506,7 @@ JS_DEFINE_NATIVE_FUNCTION(GlobalObject::encode_uri)
// 19.2.6.2 decodeURI ( encodedURI ), https://tc39.es/ecma262/#sec-decodeuri-encodeduri
JS_DEFINE_NATIVE_FUNCTION(GlobalObject::decode_uri)
{
auto uri_string = vm.argument(0).to_string(global_object);
if (vm.exception())
return {};
auto uri_string = TRY_OR_DISCARD(vm.argument(0).to_string(global_object));
auto decoded = decode(global_object, uri_string, ";/?:@&=+$,#"sv);
if (vm.exception())
return {};
@ -524,9 +516,7 @@ JS_DEFINE_NATIVE_FUNCTION(GlobalObject::decode_uri)
// 19.2.6.5 encodeURIComponent ( uriComponent ), https://tc39.es/ecma262/#sec-encodeuricomponent-uricomponent
JS_DEFINE_NATIVE_FUNCTION(GlobalObject::encode_uri_component)
{
auto uri_string = vm.argument(0).to_string(global_object);
if (vm.exception())
return {};
auto uri_string = TRY_OR_DISCARD(vm.argument(0).to_string(global_object));
auto encoded = encode(global_object, uri_string, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.!~*'()"sv);
if (vm.exception())
return {};
@ -536,9 +526,7 @@ JS_DEFINE_NATIVE_FUNCTION(GlobalObject::encode_uri_component)
// 19.2.6.3 decodeURIComponent ( encodedURIComponent ), https://tc39.es/ecma262/#sec-decodeuricomponent-encodeduricomponent
JS_DEFINE_NATIVE_FUNCTION(GlobalObject::decode_uri_component)
{
auto uri_string = vm.argument(0).to_string(global_object);
if (vm.exception())
return {};
auto uri_string = TRY_OR_DISCARD(vm.argument(0).to_string(global_object));
auto decoded = decode(global_object, uri_string, ""sv);
if (vm.exception())
return {};
@ -548,9 +536,7 @@ JS_DEFINE_NATIVE_FUNCTION(GlobalObject::decode_uri_component)
// B.2.1.1 escape ( string ), https://tc39.es/ecma262/#sec-escape-string
JS_DEFINE_NATIVE_FUNCTION(GlobalObject::escape)
{
auto string = vm.argument(0).to_string(global_object);
if (vm.exception())
return {};
auto string = TRY_OR_DISCARD(vm.argument(0).to_string(global_object));
StringBuilder escaped;
for (auto code_point : Utf8View(string)) {
if (code_point < 256) {
@ -568,9 +554,7 @@ JS_DEFINE_NATIVE_FUNCTION(GlobalObject::escape)
// B.2.1.2 unescape ( string ), https://tc39.es/ecma262/#sec-unescape-string
JS_DEFINE_NATIVE_FUNCTION(GlobalObject::unescape)
{
auto string = vm.argument(0).to_string(global_object);
if (vm.exception())
return {};
auto string = TRY_OR_DISCARD(vm.argument(0).to_string(global_object));
ssize_t length = string.length();
StringBuilder unescaped(length);
for (auto k = 0; k < length; ++k) {

View File

@ -246,9 +246,7 @@ ThrowCompletionOr<Vector<String>> canonicalize_locale_list(GlobalObject& global_
// iv. Else,
else {
// 1. Let tag be ? ToString(kValue).
tag = key_value.to_string(global_object);
if (auto* exception = vm.exception())
return throw_completion(exception->value());
tag = TRY(key_value.to_string(global_object));
}
// v. If IsStructurallyValidLanguageTag(tag) is false, throw a RangeError exception.

View File

@ -44,9 +44,7 @@ JS_DEFINE_NATIVE_FUNCTION(DisplayNamesPrototype::of)
return {};
// 3. Let code be ? ToString(code).
auto code_string = code.to_string(global_object);
if (vm.exception())
return {};
auto code_string = TRY_OR_DISCARD(code.to_string(global_object));
code = js_string(vm, move(code_string));
// 4. Let code be ? CanonicalCodeForDisplayNames(displayNames.[[Type]], code).

View File

@ -292,9 +292,7 @@ Value LocaleConstructor::construct(FunctionObject& new_target)
// 9. Else,
else {
// a. Let tag be ? ToString(tag).
tag = tag_value.to_string(global_object);
if (vm.exception())
return {};
tag = TRY_OR_DISCARD(tag_value.to_string(global_object));
}
// 10. Set options to ? CoerceOptionsToObject(options).
@ -343,7 +341,7 @@ Value LocaleConstructor::construct(FunctionObject& new_target)
// 24. If kn is not undefined, set kn to ! ToString(kn).
// 25. Set opt.[[kn]] to kn.
if (!kn.is_undefined())
opt.kn = kn.to_string(global_object);
opt.kn = TRY_OR_DISCARD(kn.to_string(global_object));
// 26. Let numberingSystem be ? GetOption(options, "numberingSystem", "string", undefined, undefined).
// 27. If numberingSystem is not undefined, then

View File

@ -65,14 +65,11 @@ String JSONObject::stringify_impl(GlobalObject& global_object, Value value, Valu
if (replacer_value.is_string()) {
item = replacer_value.as_string().string();
} else if (replacer_value.is_number()) {
item = replacer_value.to_string(global_object);
item = MUST(replacer_value.to_string(global_object));
} else if (replacer_value.is_object()) {
auto& value_object = replacer_value.as_object();
if (is<StringObject>(value_object) || is<NumberObject>(value_object)) {
item = replacer_value.to_string(global_object);
if (vm.exception())
return {};
}
if (is<StringObject>(value_object) || is<NumberObject>(value_object))
item = TRY_OR_DISCARD(replacer_value.to_string(global_object));
}
if (!item.is_null() && !list.contains_slow(item)) {
list.append(item);
@ -178,7 +175,7 @@ String JSONObject::serialize_json_property(GlobalObject& global_object, Stringif
return quote_json_string(value.as_string().string());
if (value.is_number()) {
if (value.is_finite_number())
return value.to_string(global_object);
return MUST(value.to_string(global_object));
return "null";
}
if (value.is_bigint()) {
@ -392,9 +389,7 @@ String JSONObject::quote_json_string(String string)
// 25.5.1 JSON.parse ( text [ , reviver ] ), https://tc39.es/ecma262/#sec-json.parse
JS_DEFINE_NATIVE_FUNCTION(JSONObject::parse)
{
auto string = vm.argument(0).to_string(global_object);
if (vm.exception())
return {};
auto string = TRY_OR_DISCARD(vm.argument(0).to_string(global_object));
auto reviver = vm.argument(1);
auto json = JsonValue::from_string(string);

View File

@ -78,11 +78,11 @@ JS_DEFINE_NATIVE_FUNCTION(NumberPrototype::to_fixed)
}
if (!number_value.is_finite_number())
return js_string(vm, number_value.to_string(global_object));
return js_string(vm, TRY_OR_DISCARD(number_value.to_string(global_object)));
auto number = number_value.as_double();
if (fabs(number) >= 1e+21)
return js_string(vm, number_value.to_string(global_object));
return js_string(vm, MUST(number_value.to_string(global_object)));
return js_string(vm, String::formatted("{:0.{1}}", number, static_cast<size_t>(fraction_digits)));
}

View File

@ -7,6 +7,7 @@
#pragma once
#include <AK/FlyString.h>
#include <LibJS/Runtime/Completion.h>
#include <LibJS/Runtime/StringOrSymbol.h>
namespace JS {
@ -33,10 +34,7 @@ public:
return value.as_symbol();
if (value.is_integral_number() && value.as_double() >= 0 && value.as_double() < NumericLimits<u32>::max())
return value.as_u32();
auto string = value.to_string(global_object);
if (string.is_null())
return {};
return string;
return TRY_OR_DISCARD(value.to_string(global_object));
}
PropertyName() { }

View File

@ -148,9 +148,7 @@ RegExpObject* RegExpObject::regexp_initialize(GlobalObject& global_object, Value
if (flags.is_undefined()) {
f = String::empty();
} else {
f = flags.to_string(global_object);
if (vm.exception())
return {};
f = TRY_OR_DISCARD(flags.to_string(global_object));
}
String original_pattern;
@ -160,10 +158,7 @@ RegExpObject* RegExpObject::regexp_initialize(GlobalObject& global_object, Value
original_pattern = String::empty();
parsed_pattern = String::empty();
} else {
original_pattern = pattern.to_string(global_object);
if (vm.exception())
return {};
original_pattern = TRY_OR_DISCARD(pattern.to_string(global_object));
bool unicode = f.find('u').has_value();
parsed_pattern = parse_regex_pattern(original_pattern, unicode);
}

View File

@ -377,14 +377,10 @@ JS_DEFINE_NATIVE_FUNCTION(RegExpPrototype::to_string)
return {};
auto source_attr = TRY_OR_DISCARD(regexp_object->get(vm.names.source));
auto pattern = source_attr.to_string(global_object);
if (vm.exception())
return {};
auto pattern = TRY_OR_DISCARD(source_attr.to_string(global_object));
auto flags_attr = TRY_OR_DISCARD(regexp_object->get(vm.names.flags));
auto flags = flags_attr.to_string(global_object);
if (vm.exception())
return {};
auto flags = TRY_OR_DISCARD(flags_attr.to_string(global_object));
return js_string(vm, String::formatted("/{}/{}", pattern, flags));
}
@ -434,9 +430,7 @@ JS_DEFINE_NATIVE_FUNCTION(RegExpPrototype::symbol_match)
if (!result_object)
return {};
auto match_object = TRY_OR_DISCARD(result_object->get(0));
auto match_str = match_object.to_string(global_object);
if (vm.exception())
return {};
auto match_str = TRY_OR_DISCARD(match_object.to_string(global_object));
TRY_OR_DISCARD(array->create_data_property_or_throw(n, js_string(vm, match_str)));
@ -460,9 +454,8 @@ JS_DEFINE_NATIVE_FUNCTION(RegExpPrototype::symbol_match_all)
auto* constructor = TRY_OR_DISCARD(species_constructor(global_object, *regexp_object, *global_object.regexp_constructor()));
auto flags = TRY_OR_DISCARD(regexp_object->get(vm.names.flags)).to_string(global_object);
if (vm.exception())
return {};
auto flags_value = TRY_OR_DISCARD(regexp_object->get(vm.names.flags));
auto flags = TRY_OR_DISCARD(flags_value.to_string(global_object));
bool global = flags.find('g').has_value();
bool unicode = flags.find('u').has_value();
@ -501,13 +494,8 @@ JS_DEFINE_NATIVE_FUNCTION(RegExpPrototype::symbol_replace)
auto string_view = string.view();
if (!replace_value.is_function()) {
auto replace_string = replace_value.to_string(global_object);
if (vm.exception())
return {};
auto replace_string = TRY_OR_DISCARD(replace_value.to_string(global_object));
replace_value = js_string(vm, move(replace_string));
if (vm.exception())
return {};
}
bool global = TRY_OR_DISCARD(regexp_object->get(vm.names.global)).to_boolean();
@ -537,9 +525,7 @@ JS_DEFINE_NATIVE_FUNCTION(RegExpPrototype::symbol_replace)
break;
auto match_object = TRY_OR_DISCARD(result_object->get(0));
String match_str = match_object.to_string(global_object);
if (vm.exception())
return {};
auto match_str = TRY_OR_DISCARD(match_object.to_string(global_object));
if (match_str.is_empty())
TRY_OR_DISCARD(increment_last_index(global_object, *regexp_object, string_view, unicode));
@ -569,15 +555,8 @@ JS_DEFINE_NATIVE_FUNCTION(RegExpPrototype::symbol_replace)
MarkedValueList captures(vm.heap());
for (size_t n = 1; n <= n_captures; ++n) {
auto capture = TRY_OR_DISCARD(result.get(n));
if (!capture.is_undefined()) {
auto capture_string = capture.to_string(global_object);
if (vm.exception())
return {};
capture = Value(js_string(vm, capture_string));
if (vm.exception())
return {};
}
if (!capture.is_undefined())
capture = js_string(vm, TRY_OR_DISCARD(capture.to_string(global_object)));
captures.append(move(capture));
}
@ -597,10 +576,7 @@ JS_DEFINE_NATIVE_FUNCTION(RegExpPrototype::symbol_replace)
}
auto replace_result = TRY_OR_DISCARD(vm.call(replace_value.as_function(), js_undefined(), move(replacer_args)));
replacement = replace_result.to_string(global_object);
if (vm.exception())
return {};
replacement = TRY_OR_DISCARD(replace_result.to_string(global_object));
} else {
auto named_captures_object = js_undefined();
if (!named_captures.is_undefined()) {
@ -677,9 +653,8 @@ JS_DEFINE_NATIVE_FUNCTION(RegExpPrototype::symbol_split)
auto* constructor = TRY_OR_DISCARD(species_constructor(global_object, *regexp_object, *global_object.regexp_constructor()));
auto flags = TRY_OR_DISCARD(regexp_object->get(vm.names.flags)).to_string(global_object);
if (vm.exception())
return {};
auto flags_value = TRY_OR_DISCARD(regexp_object->get(vm.names.flags));
auto flags = TRY_OR_DISCARD(flags_value.to_string(global_object));
bool unicode = flags.find('u').has_value();
auto new_flags = flags.find('y').has_value() ? move(flags) : String::formatted("{}y", flags);

View File

@ -58,10 +58,7 @@ JS_DEFINE_NATIVE_FUNCTION(RegExpStringIteratorPrototype::next)
if (!match_object)
return {};
auto match_string_value = TRY_OR_DISCARD(match_object->get(0));
auto match_string = match_string_value.to_string(global_object);
if (vm.exception())
return {};
auto match_string = TRY_OR_DISCARD(match_string_value.to_string(global_object));
if (match_string.is_empty()) {
auto last_index = TRY_OR_DISCARD(iterator->regexp_object().get(vm.names.lastIndex)).to_length(global_object);
if (vm.exception())

View File

@ -94,9 +94,8 @@ JS_DEFINE_NATIVE_FUNCTION(StringConstructor::raw)
StringBuilder builder;
for (size_t i = 0; i < literal_segments; ++i) {
auto next_key = String::number(i);
auto next_segment = TRY_OR_DISCARD(raw->get(next_key)).to_string(global_object);
if (vm.exception())
return {};
auto next_segment_value = TRY_OR_DISCARD(raw->get(next_key));
auto next_segment = TRY_OR_DISCARD(next_segment_value.to_string(global_object));
builder.append(next_segment);
@ -105,9 +104,7 @@ JS_DEFINE_NATIVE_FUNCTION(StringConstructor::raw)
if (i < number_of_substituions) {
auto next = vm.argument(i + 1);
auto next_sub = next.to_string(global_object);
if (vm.exception())
return {};
auto next_sub = TRY_OR_DISCARD(next.to_string(global_object));
builder.append(next_sub);
}
}

View File

@ -31,7 +31,7 @@ namespace JS {
static Optional<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)));
return this_value.to_string(global_object);
return TRY_OR_DISCARD(this_value.to_string(global_object));
}
static Utf16String utf16_string_from(VM& vm, GlobalObject& global_object)
@ -564,9 +564,7 @@ JS_DEFINE_NATIVE_FUNCTION(StringPrototype::concat)
StringBuilder builder;
builder.append(*string);
for (size_t i = 0; i < vm.argument_count(); ++i) {
auto string_argument = vm.argument(i).to_string(global_object);
if (vm.exception())
return {};
auto string_argument = TRY_OR_DISCARD(vm.argument(i).to_string(global_object));
builder.append(string_argument);
}
return js_string(vm, builder.to_string());
@ -846,9 +844,7 @@ JS_DEFINE_NATIVE_FUNCTION(StringPrototype::at)
JS_DEFINE_NATIVE_FUNCTION(StringPrototype::symbol_iterator)
{
auto this_object = TRY_OR_DISCARD(require_object_coercible(global_object, vm.this_value(global_object)));
auto string = this_object.to_string(global_object);
if (vm.exception())
return {};
auto string = TRY_OR_DISCARD(this_object.to_string(global_object));
return StringIterator::create(global_object, string);
}
@ -882,9 +878,7 @@ JS_DEFINE_NATIVE_FUNCTION(StringPrototype::match_all)
if (is_regexp) {
auto flags = TRY_OR_DISCARD(regexp.as_object().get("flags"));
auto flags_object = TRY_OR_DISCARD(require_object_coercible(global_object, flags));
auto flags_string = flags_object.to_string(global_object);
if (vm.exception())
return {};
auto flags_string = TRY_OR_DISCARD(flags_object.to_string(global_object));
if (!flags_string.contains("g")) {
vm.throw_exception<TypeError>(global_object, ErrorType::StringNonGlobalRegExp);
return {};
@ -941,10 +935,7 @@ JS_DEFINE_NATIVE_FUNCTION(StringPrototype::replace)
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)));
replacement = result.to_string(global_object);
if (vm.exception())
return {};
replacement = TRY_OR_DISCARD(result.to_string(global_object));
} else {
replacement = TRY_OR_DISCARD(get_substitution(global_object, search_string.view(), string.view(), *position, {}, js_undefined(), replace_value));
}
@ -970,9 +961,7 @@ JS_DEFINE_NATIVE_FUNCTION(StringPrototype::replace_all)
if (is_regexp) {
auto flags = TRY_OR_DISCARD(search_value.as_object().get(vm.names.flags));
auto flags_object = TRY_OR_DISCARD(require_object_coercible(global_object, flags));
auto flags_string = flags_object.to_string(global_object);
if (vm.exception())
return {};
auto flags_string = TRY_OR_DISCARD(flags_object.to_string(global_object));
if (!flags_string.contains("g")) {
vm.throw_exception<TypeError>(global_object, ErrorType::StringNonGlobalRegExp);
return {};
@ -1021,10 +1010,7 @@ JS_DEFINE_NATIVE_FUNCTION(StringPrototype::replace_all)
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)));
replacement = result.to_string(global_object);
if (vm.exception())
return {};
replacement = TRY_OR_DISCARD(result.to_string(global_object));
} else {
replacement = TRY_OR_DISCARD(get_substitution(global_object, search_string.view(), string.view(), position, {}, js_undefined(), replace_value));
}
@ -1066,16 +1052,12 @@ static Value create_html(GlobalObject& global_object, Value string, const String
{
auto& vm = global_object.vm();
TRY_OR_DISCARD(require_object_coercible(global_object, string));
auto str = string.to_string(global_object);
if (vm.exception())
return {};
auto str = TRY_OR_DISCARD(string.to_string(global_object));
StringBuilder builder;
builder.append('<');
builder.append(tag);
if (!attribute.is_empty()) {
auto value_string = value.to_string(global_object);
if (vm.exception())
return {};
auto value_string = TRY_OR_DISCARD(value.to_string(global_object));
builder.append(' ');
builder.append(attribute);
builder.append("=\"");
@ -1176,9 +1158,7 @@ JS_DEFINE_NATIVE_FUNCTION(StringPrototype::locale_compare)
if (!string.has_value())
return {};
auto that_string = vm.argument(0).to_string(global_object);
if (vm.exception())
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.
if (string == that_string)

View File

@ -44,7 +44,7 @@ Value SymbolConstructor::call()
{
if (vm().argument(0).is_undefined())
return js_symbol(heap(), {}, false);
return js_symbol(heap(), vm().argument(0).to_string(global_object()), false);
return js_symbol(heap(), TRY_OR_DISCARD(vm().argument(0).to_string(global_object())), false);
}
// 20.4.1.1 Symbol ( [ description ] ), https://tc39.es/ecma262/#sec-symbol-description
@ -57,7 +57,7 @@ Value SymbolConstructor::construct(FunctionObject&)
// 20.4.2.2 Symbol.for ( key ), https://tc39.es/ecma262/#sec-symbol.for
JS_DEFINE_NATIVE_FUNCTION(SymbolConstructor::for_)
{
String description = vm.argument(0).to_string(global_object);
auto description = TRY_OR_DISCARD(vm.argument(0).to_string(global_object));
return global_object.vm().get_global_symbol(description);
}

View File

@ -297,12 +297,8 @@ ThrowCompletionOr<Value> calendar_era(GlobalObject& global_object, Object& calen
auto result = TRY(Value(&calendar).invoke(global_object, vm.names.era, &date_like));
// 3. If result is not undefined, set result to ? ToString(result).
if (!result.is_undefined()) {
auto result_string = result.to_string(global_object);
if (auto* exception = vm.exception())
return throw_completion(exception->value());
result = js_string(vm, move(result_string));
}
if (!result.is_undefined())
result = js_string(vm, TRY(result.to_string(global_object)));
// 4. Return result.
return result;
@ -362,9 +358,7 @@ ThrowCompletionOr<Object*> to_temporal_calendar(GlobalObject& global_object, Val
}
// 2. Let identifier be ? ToString(temporalCalendarLike).
auto identifier = temporal_calendar_like.to_string(global_object);
if (auto* exception = vm.exception())
return throw_completion(exception->value());
auto identifier = TRY(temporal_calendar_like.to_string(global_object));
// 3. If ! IsBuiltinCalendar(identifier) is false, then
if (!is_builtin_calendar(identifier)) {
@ -510,21 +504,15 @@ String format_calendar_annotation(StringView id, StringView show_calendar)
// 12.1.28 CalendarEquals ( one, two ), https://tc39.es/proposal-temporal/#sec-temporal-calendarequals
ThrowCompletionOr<bool> calendar_equals(GlobalObject& global_object, Object& one, Object& two)
{
auto& vm = global_object.vm();
// 1. If one and two are the same Object value, return true.
if (&one == &two)
return true;
// 2. Let calendarOne be ? ToString(one).
auto calendar_one = Value(&one).to_string(global_object);
if (auto* exception = vm.exception())
return throw_completion(exception->value());
auto calendar_one = TRY(Value(&one).to_string(global_object));
// 3. Let calendarTwo be ? ToString(two).
auto calendar_two = Value(&two).to_string(global_object);
if (auto* exception = vm.exception())
return throw_completion(exception->value());
auto calendar_two = TRY(Value(&two).to_string(global_object));
// 4. If calendarOne is calendarTwo, return true.
if (calendar_one == calendar_two)
@ -543,14 +531,10 @@ ThrowCompletionOr<Object*> consolidate_calendars(GlobalObject& global_object, Ob
return &two;
// 2. Let calendarOne be ? ToString(one).
auto calendar_one = Value(&one).to_string(global_object);
if (auto* exception = vm.exception())
return throw_completion(exception->value());
auto calendar_one = TRY(Value(&one).to_string(global_object));
// 3. Let calendarTwo be ? ToString(two).
auto calendar_two = Value(&two).to_string(global_object);
if (auto* exception = vm.exception())
return throw_completion(exception->value());
auto calendar_two = TRY(Value(&two).to_string(global_object));
// 4. If calendarOne is calendarTwo, return two.
if (calendar_one == calendar_two)

View File

@ -49,9 +49,7 @@ Value CalendarConstructor::construct(FunctionObject& new_target)
auto& global_object = this->global_object();
// 2. Set id to ? ToString(id).
auto identifier = vm.argument(0).to_string(global_object);
if (vm.exception())
return {};
auto identifier = TRY_OR_DISCARD(vm.argument(0).to_string(global_object));
// 3. If ! IsBuiltinCalendar(id) is false, then
if (!is_builtin_calendar(identifier)) {

View File

@ -69,7 +69,7 @@ JS_DEFINE_NATIVE_FUNCTION(CalendarPrototype::id_getter)
auto calendar = vm.this_value(global_object);
// 2. Return ? ToString(calendar).
return js_string(vm, calendar.to_string(global_object));
return js_string(vm, TRY_OR_DISCARD(calendar.to_string(global_object)));
}
// 12.4.4 Temporal.Calendar.prototype.dateFromFields ( fields [ , options ] ), https://tc39.es/proposal-temporal/#sec-temporal.calendar.prototype.datefromfields
@ -637,7 +637,7 @@ JS_DEFINE_NATIVE_FUNCTION(CalendarPrototype::to_json)
auto calendar = vm.this_value(global_object);
// 2. Return ? ToString(calendar).
return js_string(vm, calendar.to_string(global_object));
return js_string(vm, TRY_OR_DISCARD(calendar.to_string(global_object)));
}
// 15.6.2.6 Temporal.Calendar.prototype.era ( temporalDateLike ), https://tc39.es/proposal-temporal/#sec-temporal.calendar.prototype.era

View File

@ -34,8 +34,6 @@ Duration::Duration(double years, double months, double weeks, double days, doubl
// 7.5.1 ToTemporalDuration ( item ), https://tc39.es/proposal-temporal/#sec-temporal-totemporalduration
ThrowCompletionOr<Duration*> to_temporal_duration(GlobalObject& global_object, Value item)
{
auto& vm = global_object.vm();
TemporalDuration result;
// 1. If Type(item) is Object, then
@ -51,9 +49,7 @@ ThrowCompletionOr<Duration*> to_temporal_duration(GlobalObject& global_object, V
// 2. Else,
else {
// a. Let string be ? ToString(item).
auto string = item.to_string(global_object);
if (auto* exception = vm.exception())
return throw_completion(exception->value());
auto string = TRY(item.to_string(global_object));
// b. Let result be ? ParseTemporalDurationString(string).
result = TRY(parse_temporal_duration_string(global_object, string));
@ -451,9 +447,7 @@ ThrowCompletionOr<TemporalDuration> to_limited_temporal_duration(GlobalObject& g
// 1. If Type(temporalDurationLike) is not Object, then
if (!temporal_duration_like.is_object()) {
// a. Let str be ? ToString(temporalDurationLike).
auto str = temporal_duration_like.to_string(global_object);
if (auto* exception = vm.exception())
return throw_completion(exception->value());
auto str = TRY(temporal_duration_like.to_string(global_object));
// b. Let duration be ? ParseTemporalDurationString(str).
duration = TRY(parse_temporal_duration_string(global_object, str));

View File

@ -72,8 +72,6 @@ ThrowCompletionOr<Instant*> create_temporal_instant(GlobalObject& global_object,
// 8.5.3 ToTemporalInstant ( item ), https://tc39.es/proposal-temporal/#sec-temporal-totemporalinstant
ThrowCompletionOr<Instant*> to_temporal_instant(GlobalObject& global_object, Value item)
{
auto& vm = global_object.vm();
// 1. If Type(item) is Object, then
if (item.is_object()) {
// a. If item has an [[InitializedTemporalInstant]] internal slot, then
@ -92,9 +90,7 @@ ThrowCompletionOr<Instant*> to_temporal_instant(GlobalObject& global_object, Val
}
// 2. Let string be ? ToString(item).
auto string = item.to_string(global_object);
if (auto* exception = vm.exception())
return throw_completion(exception->value());
auto string = TRY(item.to_string(global_object));
// 3. Let epochNanoseconds be ? ParseTemporalInstant(string).
auto* epoch_nanoseconds = TRY(parse_temporal_instant(global_object, string));

View File

@ -125,9 +125,7 @@ ThrowCompletionOr<PlainDate*> to_temporal_date(GlobalObject& global_object, Valu
(void)TRY(to_temporal_overflow(global_object, *options));
// 5. Let string be ? ToString(item).
auto string = item.to_string(global_object);
if (auto* exception = vm.exception())
return throw_completion(exception->value());
auto string = TRY(item.to_string(global_object));
// 6. Let result be ? ParseTemporalDateString(string).
auto result = TRY(parse_temporal_date_string(global_object, string));
@ -516,8 +514,6 @@ String pad_iso_year(i32 y)
// 3.5.8 TemporalDateToString ( temporalDate, showCalendar ), https://tc39.es/proposal-temporal/#sec-temporal-temporaldatetostring
ThrowCompletionOr<String> temporal_date_to_string(GlobalObject& global_object, PlainDate& temporal_date, StringView show_calendar)
{
auto& vm = global_object.vm();
// 1. Assert: Type(temporalDate) is Object.
// 2. Assert: temporalDate has an [[InitializedTemporalDate]] internal slot.
@ -531,9 +527,7 @@ ThrowCompletionOr<String> temporal_date_to_string(GlobalObject& global_object, P
auto day = String::formatted("{:02}", temporal_date.iso_day());
// 6. Let calendarID be ? ToString(temporalDate.[[Calendar]]).
auto calendar_id = Value(&temporal_date.calendar()).to_string(global_object);
if (auto* exception = vm.exception())
return throw_completion(exception->value());
auto calendar_id = TRY(Value(&temporal_date.calendar()).to_string(global_object));
// 7. Let calendar be ! FormatCalendarAnnotation(calendarID, showCalendar).
auto calendar = format_calendar_annotation(calendar_id, show_calendar);

View File

@ -187,9 +187,7 @@ ThrowCompletionOr<PlainDateTime*> to_temporal_date_time(GlobalObject& global_obj
(void)TRY(to_temporal_overflow(global_object, *options));
// b. Let string be ? ToString(item).
auto string = item.to_string(global_object);
if (auto* exception = vm.exception())
return throw_completion(exception->value());
auto string = TRY(item.to_string(global_object));
// c. Let result be ? ParseTemporalDateTimeString(string).
result = TRY(parse_temporal_date_time_string(global_object, string));
@ -273,8 +271,6 @@ ThrowCompletionOr<PlainDateTime*> create_temporal_date_time(GlobalObject& global
// 5.5.7 TemporalDateTimeToString ( isoYear, isoMonth, isoDay, hour, minute, second, millisecond, microsecond, nanosecond, calendar, precision, showCalendar ), , https://tc39.es/proposal-temporal/#sec-temporal-temporaldatetimetostring
ThrowCompletionOr<String> temporal_date_time_to_string(GlobalObject& global_object, i32 iso_year, u8 iso_month, u8 iso_day, u8 hour, u8 minute, u8 second, u16 millisecond, u16 microsecond, u16 nanosecond, Value calendar, Variant<StringView, u8> const& precision, StringView show_calendar)
{
auto& vm = global_object.vm();
// 1. Assert: isoYear, isoMonth, isoDay, hour, minute, second, millisecond, microsecond, and nanosecond are integers.
// 2. Let year be ! PadISOYear(isoYear).
@ -287,9 +283,7 @@ ThrowCompletionOr<String> temporal_date_time_to_string(GlobalObject& global_obje
auto seconds = format_seconds_string_part(second, millisecond, microsecond, nanosecond, precision);
// 8. Let calendarID be ? ToString(calendar).
auto calendar_id = calendar.to_string(global_object);
if (auto* exception = vm.exception())
return throw_completion(exception->value());
auto calendar_id = TRY(calendar.to_string(global_object));
// 9. Let calendarString be ! FormatCalendarAnnotation(calendarID, showCalendar).
auto calendar_string = format_calendar_annotation(calendar_id, show_calendar);

View File

@ -154,8 +154,6 @@ ThrowCompletionOr<PlainMonthDay*> create_temporal_month_day(GlobalObject& global
// 10.5.3 TemporalMonthDayToString ( monthDay, showCalendar ), https://tc39.es/proposal-temporal/#sec-temporal-temporalmonthdaytostring
ThrowCompletionOr<String> temporal_month_day_to_string(GlobalObject& global_object, PlainMonthDay& month_day, StringView show_calendar)
{
auto& vm = global_object.vm();
// 1. Assert: Type(monthDay) is Object.
// 2. Assert: monthDay has an [[InitializedTemporalMonthDay]] internal slot.
@ -165,9 +163,7 @@ ThrowCompletionOr<String> temporal_month_day_to_string(GlobalObject& global_obje
auto result = String::formatted("{:02}-{:02}", month_day.iso_month(), month_day.iso_day());
// 6. Let calendarID be ? ToString(monthDay.[[Calendar]]).
auto calendar_id = Value(&month_day.calendar()).to_string(global_object);
if (auto* exception = vm.exception())
return throw_completion(exception->value());
auto calendar_id = TRY(Value(&month_day.calendar()).to_string(global_object));
// 7. If calendarID is not "iso8601", then
if (calendar_id != "iso8601"sv) {

View File

@ -84,9 +84,7 @@ ThrowCompletionOr<PlainTime*> to_temporal_time(GlobalObject& global_object, Valu
auto* calendar = TRY(get_temporal_calendar_with_iso_default(global_object, item_object));
// e. If ? ToString(calendar) is not "iso8601", then
auto calendar_identifier = Value(calendar).to_string(global_object);
if (auto* exception = vm.exception())
return throw_completion(exception->value());
auto calendar_identifier = TRY(Value(calendar).to_string(global_object));
if (calendar_identifier != "iso8601"sv) {
// i. Throw a RangeError exception.
return vm.throw_completion<RangeError>(global_object, ErrorType::TemporalInvalidCalendarIdentifier, calendar_identifier);
@ -101,9 +99,7 @@ ThrowCompletionOr<PlainTime*> to_temporal_time(GlobalObject& global_object, Valu
// 4. Else,
else {
// a. Let string be ? ToString(item).
auto string = item.to_string(global_object);
if (auto* exception = vm.exception())
return throw_completion(exception->value());
auto string = TRY(item.to_string(global_object));
// b. Let result be ? ParseTemporalTimeString(string).
result = TRY(parse_temporal_time_string(global_object, string));

View File

@ -68,9 +68,7 @@ ThrowCompletionOr<PlainYearMonth*> to_temporal_year_month(GlobalObject& global_o
(void)TRY(to_temporal_overflow(global_object, *options));
// 5. Let string be ? ToString(item).
auto string = item.to_string(global_object);
if (auto* exception = vm.exception())
return throw_completion(exception->value());
auto string = TRY(item.to_string(global_object));
// 6. Let result be ? ParseTemporalYearMonthString(string).
auto result = TRY(parse_temporal_year_month_string(global_object, string));
@ -236,8 +234,6 @@ ThrowCompletionOr<PlainYearMonth*> create_temporal_year_month(GlobalObject& glob
// 9.5.8 TemporalYearMonthToString ( yearMonth, showCalendar ), https://tc39.es/proposal-temporal/#sec-temporal-temporalyearmonthtostring
ThrowCompletionOr<String> temporal_year_month_to_string(GlobalObject& global_object, PlainYearMonth& year_month, StringView show_calendar)
{
auto& vm = global_object.vm();
// 1. Assert: Type(yearMonth) is Object.
// 2. Assert: yearMonth has an [[InitializedTemporalYearMonth]] internal slot.
@ -247,9 +243,7 @@ ThrowCompletionOr<String> temporal_year_month_to_string(GlobalObject& global_obj
auto result = String::formatted("{}-{:02}", pad_iso_year(year_month.iso_year()), year_month.iso_month());
// 6. Let calendarID be ? ToString(yearMonth.[[Calendar]]).
auto calendar_id = Value(&year_month.calendar()).to_string(global_object);
if (auto* exception = vm.exception())
return throw_completion(exception->value());
auto calendar_id = TRY(Value(&year_month.calendar()).to_string(global_object));
// 7. If calendarID is not "iso8601", then
if (calendar_id != "iso8601") {

View File

@ -338,9 +338,7 @@ ThrowCompletionOr<Object*> to_temporal_time_zone(GlobalObject& global_object, Va
}
// 2. Let identifier be ? ToString(temporalTimeZoneLike).
auto identifier = temporal_time_zone_like.to_string(global_object);
if (auto* exception = vm.exception())
return throw_completion(exception->value());
auto identifier = TRY(temporal_time_zone_like.to_string(global_object));
// 3. Let result be ? ParseTemporalTimeZone(identifier).
auto result = TRY(parse_temporal_time_zone(global_object, identifier));

View File

@ -49,9 +49,7 @@ Value TimeZoneConstructor::construct(FunctionObject& new_target)
auto& global_object = this->global_object();
// 2. Set identifier to ? ToString(identifier).
auto identifier = vm.argument(0).to_string(global_object);
if (vm.exception())
return {};
auto identifier = TRY_OR_DISCARD(vm.argument(0).to_string(global_object));
String canonical;

View File

@ -45,7 +45,7 @@ JS_DEFINE_NATIVE_FUNCTION(TimeZonePrototype::id_getter)
auto time_zone = vm.this_value(global_object);
// 2. Return ? ToString(timeZone).
return js_string(vm, time_zone.to_string(global_object));
return js_string(vm, TRY_OR_DISCARD(time_zone.to_string(global_object)));
}
// 11.4.4 Temporal.TimeZone.prototype.getOffsetNanosecondsFor ( instant ), https://tc39.es/proposal-temporal/#sec-temporal.timezone.prototype.getoffsetnanosecondsfor
@ -121,7 +121,7 @@ JS_DEFINE_NATIVE_FUNCTION(TimeZonePrototype::to_json)
auto time_zone = vm.this_value(global_object);
// 2. Return ? ToString(timeZone).
return js_string(vm, time_zone.to_string(global_object));
return js_string(vm, TRY_OR_DISCARD(time_zone.to_string(global_object)));
}
}

View File

@ -594,11 +594,8 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::join)
return {};
auto length = typed_array->array_length();
String separator = ",";
if (!vm.argument(0).is_undefined()) {
separator = vm.argument(0).to_string(global_object);
if (vm.exception())
return {};
}
if (!vm.argument(0).is_undefined())
separator = TRY_OR_DISCARD(vm.argument(0).to_string(global_object));
StringBuilder builder;
for (size_t i = 0; i < length; ++i) {
@ -607,9 +604,7 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::join)
auto value = TRY_OR_DISCARD(typed_array->get(i));
if (value.is_nullish())
continue;
auto string = value.to_string(global_object);
if (vm.exception())
return {};
auto string = TRY_OR_DISCARD(value.to_string(global_object));
builder.append(string);
}
@ -1487,9 +1482,7 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::to_locale_string)
if (value.is_nullish())
continue;
auto locale_string_result = TRY_OR_DISCARD(value.invoke(global_object, vm.names.toLocaleString));
auto string = locale_string_result.to_string(global_object);
if (vm.exception())
return {};
auto string = TRY_OR_DISCARD(locale_string_result.to_string(global_object));
builder.append(string);
}
return js_string(vm, builder.to_string());

View File

@ -17,6 +17,7 @@
#include <LibJS/Runtime/BigIntObject.h>
#include <LibJS/Runtime/BooleanObject.h>
#include <LibJS/Runtime/BoundFunction.h>
#include <LibJS/Runtime/Completion.h>
#include <LibJS/Runtime/Error.h>
#include <LibJS/Runtime/FunctionObject.h>
#include <LibJS/Runtime/GlobalObject.h>
@ -326,22 +327,21 @@ PrimitiveString* Value::to_primitive_string(GlobalObject& global_object)
{
if (is_string())
return &as_string();
auto string = to_string(global_object);
if (global_object.vm().exception())
return nullptr;
auto string = TRY_OR_DISCARD(to_string(global_object));
return js_string(global_object.heap(), string);
}
// 7.1.17 ToString ( argument ), https://tc39.es/ecma262/#sec-tostring
String Value::to_string(GlobalObject& global_object) const
ThrowCompletionOr<String> Value::to_string(GlobalObject& global_object) const
{
auto& vm = global_object.vm();
switch (m_type) {
case Type::Undefined:
return "undefined";
return { "undefined"sv };
case Type::Null:
return "null";
return { "null"sv };
case Type::Boolean:
return m_value.as_bool ? "true" : "false";
return { m_value.as_bool ? "true"sv : "false"sv };
case Type::Int32:
return String::number(m_value.as_i32);
case Type::Double:
@ -349,14 +349,13 @@ String Value::to_string(GlobalObject& global_object) const
case Type::String:
return m_value.as_string->string();
case Type::Symbol:
global_object.vm().throw_exception<TypeError>(global_object, ErrorType::Convert, "symbol", "string");
return {};
return vm.throw_completion<TypeError>(global_object, ErrorType::Convert, "symbol", "string");
case Type::BigInt:
return m_value.as_bigint->big_integer().to_base(10);
case Type::Object: {
auto primitive_value = to_primitive(global_object, PreferredType::String);
if (global_object.vm().exception())
return {};
if (auto* exception = vm.exception())
return throw_completion(exception->value());
return primitive_value.to_string(global_object);
}
default:
@ -369,10 +368,7 @@ Utf16String Value::to_utf16_string(GlobalObject& global_object) const
if (m_type == Type::String)
return m_value.as_string->utf16_string();
auto utf8_string = to_string(global_object);
if (global_object.vm().exception())
return {};
auto utf8_string = TRY_OR_DISCARD(to_string(global_object));
return Utf16String(utf8_string);
}
@ -596,7 +592,7 @@ StringOrSymbol Value::to_property_key(GlobalObject& global_object) const
return {};
if (key.is_symbol())
return &key.as_symbol();
return key.to_string(global_object);
return TRY_OR_DISCARD(key.to_string(global_object));
}
i32 Value::to_i32_slow_case(GlobalObject& global_object) const
@ -1100,12 +1096,8 @@ Value add(GlobalObject& global_object, Value lhs, Value rhs)
}
}
if (lhs_primitive.is_string() || rhs_primitive.is_string()) {
auto lhs_string = lhs_primitive.to_string(global_object);
if (vm.exception())
return {};
auto rhs_string = rhs_primitive.to_string(global_object);
if (vm.exception())
return {};
auto lhs_string = TRY_OR_DISCARD(lhs_primitive.to_string(global_object));
auto rhs_string = TRY_OR_DISCARD(rhs_primitive.to_string(global_object));
StringBuilder builder(lhs_string.length() + rhs_string.length());
builder.append(lhs_string);
builder.append(rhs_string);

View File

@ -303,7 +303,7 @@ public:
u64 encoded() const { return m_value.encoded; }
String to_string(GlobalObject&) const;
ThrowCompletionOr<String> to_string(GlobalObject&) const;
Utf16String to_utf16_string(GlobalObject&) const;
PrimitiveString* to_primitive_string(GlobalObject&);
Value to_primitive(GlobalObject&, PreferredType preferred_type = PreferredType::Default) const;

View File

@ -38,9 +38,7 @@ JS_DEFINE_NATIVE_FUNCTION(CSSNamespace::escape)
return {};
}
auto identifier = vm.argument(0).to_string(global_object);
if (vm.exception())
return {};
auto identifier = TRY_OR_DISCARD(vm.argument(0).to_string(global_object));
return JS::js_string(vm, Web::CSS::serialize_an_identifier(identifier));
}
@ -55,17 +53,13 @@ JS_DEFINE_NATIVE_FUNCTION(CSSNamespace::supports)
if (vm.argument_count() >= 2) {
// When the supports(property, value) method is invoked with two arguments property and value:
String property_name = vm.argument(0).to_string(global_object);
if (vm.exception())
return {};
auto property_name = TRY_OR_DISCARD(vm.argument(0).to_string(global_object));
// If property is an ASCII case-insensitive match for any defined CSS property that the UA supports,
// and value successfully parses according to that propertys grammar, return true.
auto property = CSS::property_id_from_string(property_name);
if (property != CSS::PropertyID::Invalid) {
auto value_string = vm.argument(1).to_string(global_object);
if (vm.exception())
return {};
auto value_string = TRY_OR_DISCARD(vm.argument(1).to_string(global_object));
if (parse_css_value({}, value_string, property))
return JS::Value(true);
}
@ -79,9 +73,7 @@ JS_DEFINE_NATIVE_FUNCTION(CSSNamespace::supports)
return JS::Value(false);
} else {
// When the supports(conditionText) method is invoked with a single conditionText argument:
String supports_text = vm.argument(0).to_string(global_object);
if (vm.exception())
return {};
auto supports_text = TRY_OR_DISCARD(vm.argument(0).to_string(global_object));
// If conditionText, parsed and evaluated as a <supports-condition>, would return true, return true.
if (auto supports = parse_css_supports({}, supports_text); supports && supports->matches())

View File

@ -48,9 +48,7 @@ JS::ThrowCompletionOr<bool> CSSStyleDeclarationWrapper::internal_set(JS::Propert
if (property_id == CSS::PropertyID::Invalid)
return Base::internal_set(name, value, receiver);
auto css_text = value.to_string(global_object());
if (auto* exception = vm().exception())
return JS::throw_completion(exception->value());
auto css_text = TRY(value.to_string(global_object()));
impl().set_property(property_id, css_text);
return true;

View File

@ -53,9 +53,7 @@ JS_DEFINE_NATIVE_FUNCTION(LocationObject::href_getter)
JS_DEFINE_NATIVE_FUNCTION(LocationObject::href_setter)
{
auto& window = static_cast<WindowObject&>(global_object);
auto new_href = vm.argument(0).to_string(global_object);
if (vm.exception())
return {};
auto new_href = TRY_OR_DISCARD(vm.argument(0).to_string(global_object));
auto href_url = window.impl().associated_document().parse_url(new_href);
if (!href_url.is_valid()) {
vm.throw_exception<JS::URIError>(global_object, String::formatted("Invalid URL '{}'", new_href));
@ -133,9 +131,7 @@ JS_DEFINE_NATIVE_FUNCTION(LocationObject::reload)
JS_DEFINE_NATIVE_FUNCTION(LocationObject::replace)
{
auto& window = static_cast<WindowObject&>(global_object);
auto url = vm.argument(0).to_string(global_object);
if (vm.exception())
return {};
auto url = TRY_OR_DISCARD(vm.argument(0).to_string(global_object));
// FIXME: This needs spec compliance work.
window.impl().did_call_location_replace({}, move(url));
return JS::js_undefined();

View File

@ -190,11 +190,8 @@ JS_DEFINE_NATIVE_FUNCTION(WindowObject::alert)
if (!impl)
return {};
String message = "";
if (vm.argument_count()) {
message = vm.argument(0).to_string(global_object);
if (vm.exception())
return {};
}
if (vm.argument_count())
message = TRY_OR_DISCARD(vm.argument(0).to_string(global_object));
impl->alert(message);
return JS::js_undefined();
}
@ -205,11 +202,8 @@ JS_DEFINE_NATIVE_FUNCTION(WindowObject::confirm)
if (!impl)
return {};
String message = "";
if (!vm.argument(0).is_undefined()) {
message = vm.argument(0).to_string(global_object);
if (vm.exception())
return {};
}
if (!vm.argument(0).is_undefined())
message = TRY_OR_DISCARD(vm.argument(0).to_string(global_object));
return JS::Value(impl->confirm(message));
}
@ -220,16 +214,10 @@ JS_DEFINE_NATIVE_FUNCTION(WindowObject::prompt)
return {};
String message = "";
String default_ = "";
if (!vm.argument(0).is_undefined()) {
message = vm.argument(0).to_string(global_object);
if (vm.exception())
return {};
}
if (!vm.argument(1).is_undefined()) {
default_ = vm.argument(1).to_string(global_object);
if (vm.exception())
return {};
}
if (!vm.argument(0).is_undefined())
message = TRY_OR_DISCARD(vm.argument(0).to_string(global_object));
if (!vm.argument(1).is_undefined())
default_ = TRY_OR_DISCARD(vm.argument(1).to_string(global_object));
auto response = impl->prompt(message, default_);
if (response.is_null())
return JS::js_null();
@ -252,9 +240,7 @@ JS_DEFINE_NATIVE_FUNCTION(WindowObject::set_interval)
if (vm.argument(0).is_function()) {
callback = &vm.argument(0).as_function();
} else {
auto script_source = vm.argument(0).to_string(global_object);
if (vm.exception())
return {};
auto script_source = TRY_OR_DISCARD(vm.argument(0).to_string(global_object));
// FIXME: This needs more work once we have a environment settings object.
// The spec wants us to use a task for the "run function or script string" part,
// using a NativeFunction for the latter is a workaround so that we can reuse the
@ -293,9 +279,7 @@ JS_DEFINE_NATIVE_FUNCTION(WindowObject::set_timeout)
if (vm.argument(0).is_function()) {
callback = &vm.argument(0).as_function();
} else {
auto script_source = vm.argument(0).to_string(global_object);
if (vm.exception())
return {};
auto script_source = TRY_OR_DISCARD(vm.argument(0).to_string(global_object));
// FIXME: This needs more work once we have a environment settings object.
// The spec wants us to use a task for the "run function or script string" part,
// using a NativeFunction for the latter is a workaround so that we can reuse the
@ -415,9 +399,7 @@ JS_DEFINE_NATIVE_FUNCTION(WindowObject::atob)
vm.throw_exception<JS::TypeError>(global_object, JS::ErrorType::BadArgCountOne, "atob");
return {};
}
auto string = vm.argument(0).to_string(global_object);
if (vm.exception())
return {};
auto string = TRY_OR_DISCARD(vm.argument(0).to_string(global_object));
auto decoded = decode_base64(StringView(string));
// decode_base64() returns a byte string. LibJS uses UTF-8 for strings. Use Latin1Decoder to convert bytes 128-255 to UTF-8.
@ -435,9 +417,7 @@ JS_DEFINE_NATIVE_FUNCTION(WindowObject::btoa)
vm.throw_exception<JS::TypeError>(global_object, JS::ErrorType::BadArgCountOne, "btoa");
return {};
}
auto string = vm.argument(0).to_string(global_object);
if (vm.exception())
return {};
auto string = TRY_OR_DISCARD(vm.argument(0).to_string(global_object));
Vector<u8> byte_string;
byte_string.ensure_capacity(string.length());
@ -593,9 +573,7 @@ JS_DEFINE_NATIVE_FUNCTION(WindowObject::match_media)
auto* impl = impl_from(vm, global_object);
if (!impl)
return {};
auto media = vm.argument(0).to_string(global_object);
if (vm.exception())
return {};
auto media = TRY_OR_DISCARD(vm.argument(0).to_string(global_object));
return wrap(global_object, impl->match_media(move(media)));
}
@ -660,9 +638,7 @@ JS_DEFINE_NATIVE_FUNCTION(WindowObject::scroll)
auto behavior_string_value = TRY_OR_DISCARD(options->get("behavior"));
if (!behavior_string_value.is_undefined())
behavior_string = behavior_string_value.to_string(global_object);
if (vm.exception())
return {};
behavior_string = TRY_OR_DISCARD(behavior_string_value.to_string(global_object));
if (behavior_string != "smooth" && behavior_string != "auto") {
vm.throw_exception<JS::TypeError>(global_object, "Behavior is not one of 'smooth' or 'auto'");
return {};
@ -737,9 +713,7 @@ JS_DEFINE_NATIVE_FUNCTION(WindowObject::scroll_by)
top = top + current_scroll_position.y();
auto behavior_string_value = TRY_OR_DISCARD(options->get("behavior"));
auto behavior_string = behavior_string_value.is_undefined() ? "auto" : behavior_string_value.to_string(global_object);
if (vm.exception())
return {};
auto behavior_string = behavior_string_value.is_undefined() ? "auto" : TRY_OR_DISCARD(behavior_string_value.to_string(global_object));
if (behavior_string != "smooth" && behavior_string != "auto") {
vm.throw_exception<JS::TypeError>(global_object, "Behavior is not one of 'smooth' or 'auto'");
return {};

View File

@ -890,9 +890,7 @@ static bool parse_and_run(JS::Interpreter& interpreter, StringView const& source
static JS::Value load_file_impl(JS::VM& vm, JS::GlobalObject& global_object)
{
auto filename = vm.argument(0).to_string(global_object);
if (vm.exception())
return {};
auto filename = TRY_OR_DISCARD(vm.argument(0).to_string(global_object));
auto file = Core::File::construct(filename);
if (!file->open(Core::OpenMode::ReadOnly)) {
vm.throw_exception<JS::Error>(global_object, String::formatted("Failed to open '{}': {}", filename, file->error_string()));
@ -914,9 +912,7 @@ static JS::Value load_file_impl(JS::VM& vm, JS::GlobalObject& global_object)
static JS::Value load_json_impl(JS::VM& vm, JS::GlobalObject& global_object)
{
auto filename = vm.argument(0).to_string(global_object);
if (vm.exception())
return {};
auto filename = TRY_OR_DISCARD(vm.argument(0).to_string(global_object));
auto file = Core::File::construct(filename);
if (!file->open(Core::OpenMode::ReadOnly)) {
vm.throw_exception<JS::Error>(global_object, String::formatted("Failed to open '{}': {}", filename, file->error_string()));