1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 18:37:35 +00:00

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

View file

@ -906,19 +906,24 @@ static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter
if (!optional) { if (!optional) {
if (!parameter.type.nullable) { if (!parameter.type.nullable) {
scoped_generator.append(R"~~~( scoped_generator.append(R"~~~(
auto @cpp_name@ = @js_name@@js_suffix@.is_null() && @legacy_null_to_empty_string@ String @cpp_name@;
? String::empty() if (@js_name@@js_suffix@.is_null() && @legacy_null_to_empty_string@) {
: @js_name@@js_suffix@.to_string(global_object); @cpp_name@ = String::empty();
if (vm.exception()) } else {
@return_statement@ 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 { } else {
scoped_generator.append(R"~~~( scoped_generator.append(R"~~~(
String @cpp_name@; String @cpp_name@;
if (!@js_name@@js_suffix@.is_nullish()) { if (!@js_name@@js_suffix@.is_nullish()) {
@cpp_name@ = @js_name@@js_suffix@.to_string(global_object); auto to_string_result = @js_name@@js_suffix@.to_string(global_object);
if (vm.exception()) if (to_string_result.is_error())
@return_statement@ @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"~~~( scoped_generator.append(R"~~~(
String @cpp_name@; String @cpp_name@;
if (!@js_name@@js_suffix@.is_undefined()) { if (!@js_name@@js_suffix@.is_undefined()) {
@cpp_name@ = @js_name@@js_suffix@.is_null() && @legacy_null_to_empty_string@ if (@js_name@@js_suffix@.is_null() && @legacy_null_to_empty_string@) {
? String::empty() @cpp_name@ = String::empty();
: @js_name@@js_suffix@.to_string(global_object); } else {
if (vm.exception()) auto to_string_result = @js_name@@js_suffix@.to_string(global_object);
@return_statement@ 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")) { if (optional_default_value.has_value() && (!parameter.type.nullable || optional_default_value.value() != "null")) {
scoped_generator.append(R"~~~( else { 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) TESTJS_GLOBAL_FUNCTION(can_parse_source, canParseSource)
{ {
auto source = vm.argument(0).to_string(global_object); auto source = TRY_OR_DISCARD(vm.argument(0).to_string(global_object));
if (vm.exception())
return {};
auto parser = JS::Parser(JS::Lexer(source)); auto parser = JS::Parser(JS::Lexer(source));
parser.parse_program(); parser.parse_program();
return JS::Value(!parser.has_errors()); 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) TESTJS_GLOBAL_FUNCTION(read_binary_wasm_file, readBinaryWasmFile)
{ {
auto filename = vm.argument(0).to_string(global_object); auto filename = TRY_OR_DISCARD(vm.argument(0).to_string(global_object));
if (vm.exception())
return {};
auto file = Core::File::open(filename, Core::OpenMode::ReadOnly); auto file = Core::File::open(filename, Core::OpenMode::ReadOnly);
if (file.is_error()) { if (file.is_error()) {
vm.throw_exception<JS::TypeError>(global_object, file.error().string()); 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) JS_DEFINE_NATIVE_FUNCTION(WebAssemblyModule::get_export)
{ {
auto name = vm.argument(0).to_string(global_object); auto name = TRY_OR_DISCARD(vm.argument(0).to_string(global_object));
if (vm.exception())
return {};
auto this_value = vm.this_value(global_object); auto this_value = vm.this_value(global_object);
auto object = this_value.to_object(global_object); auto object = this_value.to_object(global_object);
if (vm.exception()) if (vm.exception())

View file

@ -40,9 +40,7 @@ TESTJS_MAIN_HOOK()
TESTJS_GLOBAL_FUNCTION(load_local_page, loadLocalPage) TESTJS_GLOBAL_FUNCTION(load_local_page, loadLocalPage)
{ {
auto name = vm.argument(0).to_string(global_object); auto name = TRY_OR_DISCARD(vm.argument(0).to_string(global_object));
if (vm.exception())
return {};
// Clear the hooks // Clear the hooks
before_initial_load_hooks.clear(); 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(); 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. // This is annoying, but whatever.
cell->sheet().interpreter().vm().clear_exception(); 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_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()) if (value.is_symbol())
return String::formatted("[{}]", value.as_symbol().description()); 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 })); TRY(target.define_property_or_throw(property_key, { .value = method_value, .writable = true, .enumerable = false, .configurable = true }));
break; break;
case ClassMethod::Kind::Getter: 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 })); TRY(target.define_property_or_throw(property_key, { .get = &method_function, .enumerable = true, .configurable = true }));
break; break;
case ClassMethod::Kind::Setter: 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 })); TRY(target.define_property_or_throw(property_key, { .set = &method_function, .enumerable = true, .configurable = true }));
break; break;
default: default:
@ -2346,7 +2346,7 @@ Value ObjectExpression::execute(Interpreter& interpreter, GlobalObject& global_o
if (value.is_function() && property.is_method()) if (value.is_function() && property.is_method())
static_cast<ECMAScriptFunctionObject&>(value.as_function()).set_home_object(object); 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) { if (property.type() == ObjectProperty::Type::Getter) {
name = String::formatted("get {}", name); name = String::formatted("get {}", name);
} else if (property.type() == ObjectProperty::Type::Setter) { } 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); auto expr = expression.execute(interpreter, global_object);
if (interpreter.exception()) if (interpreter.exception())
return {}; return {};
auto string = expr.to_string(global_object); auto string = TRY_OR_DISCARD(expr.to_string(global_object));
if (interpreter.exception())
return {};
string_builder.append(string); string_builder.append(string);
} }

View file

@ -929,10 +929,7 @@ ThrowCompletionOr<String> get_substitution(GlobalObject& global_object, Utf16Vie
auto& value = captures[*capture_position - 1]; auto& value = captures[*capture_position - 1];
if (!value.is_undefined()) { if (!value.is_undefined()) {
auto value_string = value.to_string(global_object); auto value_string = TRY(value.to_string(global_object));
if (auto* exception = vm.exception())
return throw_completion(exception->value());
result.append(value_string); 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)); auto capture = TRY(named_captures.as_object().get(group_name));
if (!capture.is_undefined()) { if (!capture.is_undefined()) {
auto capture_string = capture.to_string(global_object); auto capture_string = TRY(capture.to_string(global_object));
if (auto* exception = vm.exception())
return throw_completion(exception->value());
result.append(capture_string); 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)); 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()) { if (!vm.argument(1).is_undefined()) {
auto message = vm.argument(1).to_string(global_object); auto message = TRY_OR_DISCARD(vm.argument(1).to_string(global_object));
if (vm.exception())
return {};
MUST(aggregate_error->create_non_enumerable_data_property_or_throw(vm.names.message, js_string(vm, message))); 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()) if (value.is_nullish())
continue; continue;
auto locale_string_result = TRY_OR_DISCARD(value.invoke(global_object, vm.names.toLocaleString)); auto locale_string_result = TRY_OR_DISCARD(value.invoke(global_object, vm.names.toLocaleString));
auto string = locale_string_result.to_string(global_object); auto string = TRY_OR_DISCARD(locale_string_result.to_string(global_object));
if (vm.exception())
return {};
builder.append(string); builder.append(string);
} }
return js_string(vm, builder.to_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)); auto length = TRY_OR_DISCARD(length_of_array_like(global_object, *this_object));
String separator = ","; String separator = ",";
if (!vm.argument(0).is_undefined()) { if (!vm.argument(0).is_undefined())
separator = vm.argument(0).to_string(global_object); separator = TRY_OR_DISCARD(vm.argument(0).to_string(global_object));
if (vm.exception())
return {};
}
StringBuilder builder; StringBuilder builder;
for (size_t i = 0; i < length; ++i) { for (size_t i = 0; i < length; ++i) {
if (i > 0) if (i > 0)
@ -496,9 +491,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::join)
auto value = TRY_OR_DISCARD(this_object->get(i)); auto value = TRY_OR_DISCARD(this_object->get(i));
if (value.is_nullish()) if (value.is_nullish())
continue; continue;
auto string = value.to_string(global_object); auto string = TRY_OR_DISCARD(value.to_string(global_object));
if (vm.exception())
return {};
builder.append(string); builder.append(string);
} }

View file

@ -319,9 +319,7 @@ JS_DEFINE_NATIVE_FUNCTION(DateConstructor::parse)
if (!vm.argument_count()) if (!vm.argument_count())
return js_nan(); return js_nan();
auto date_string = vm.argument(0).to_string(global_object); auto date_string = TRY_OR_DISCARD(vm.argument(0).to_string(global_object));
if (vm.exception())
return {};
return parse_date_string(date_string); 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)); auto* error = TRY_OR_DISCARD(ordinary_create_from_constructor<Error>(global_object, new_target, &GlobalObject::error_prototype));
if (!vm.argument(0).is_undefined()) { if (!vm.argument(0).is_undefined()) {
auto message = vm.argument(0).to_string(global_object); auto message = TRY_OR_DISCARD(vm.argument(0).to_string(global_object));
if (vm.exception())
return {};
MUST(error->create_non_enumerable_data_property_or_throw(vm.names.message, js_string(vm, message))); 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)); \ global_object, new_target, &GlobalObject::snake_name##_prototype)); \
\ \
if (!vm.argument(0).is_undefined()) { \ if (!vm.argument(0).is_undefined()) { \
auto message = vm.argument(0).to_string(global_object); \ auto message = TRY_OR_DISCARD(vm.argument(0).to_string(global_object)); \
if (vm.exception()) \
return {}; \
MUST(error->create_non_enumerable_data_property_or_throw(vm.names.message, js_string(vm, message))); \ 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"; String name = "Error";
auto name_property = TRY_OR_DISCARD(this_object.get(vm.names.name)); auto name_property = TRY_OR_DISCARD(this_object.get(vm.names.name));
if (!name_property.is_undefined()) { if (!name_property.is_undefined())
name = name_property.to_string(global_object); name = TRY_OR_DISCARD(name_property.to_string(global_object));
if (vm.exception())
return {};
}
String message = ""; String message = "";
auto message_property = TRY_OR_DISCARD(this_object.get(vm.names.message)); auto message_property = TRY_OR_DISCARD(this_object.get(vm.names.message));
if (!message_property.is_undefined()) { if (!message_property.is_undefined())
message = message_property.to_string(global_object); message = TRY_OR_DISCARD(message_property.to_string(global_object));
if (vm.exception())
return {};
}
if (name.is_empty()) if (name.is_empty())
return js_string(vm, message); return js_string(vm, message);

View file

@ -41,24 +41,16 @@ RefPtr<FunctionExpression> FunctionConstructor::create_dynamic_function_node(Glo
auto& vm = global_object.vm(); auto& vm = global_object.vm();
String parameters_source = ""; String parameters_source = "";
String body_source = ""; String body_source = "";
if (vm.argument_count() == 1) { if (vm.argument_count() == 1)
body_source = vm.argument(0).to_string(global_object); body_source = TRY_OR_DISCARD(vm.argument(0).to_string(global_object));
if (vm.exception())
return {};
}
if (vm.argument_count() > 1) { if (vm.argument_count() > 1) {
Vector<String> parameters; Vector<String> parameters;
for (size_t i = 0; i < vm.argument_count() - 1; ++i) { for (size_t i = 0; i < vm.argument_count() - 1; ++i)
parameters.append(vm.argument(i).to_string(global_object)); parameters.append(TRY_OR_DISCARD(vm.argument(i).to_string(global_object)));
if (vm.exception())
return {};
}
StringBuilder parameters_builder; StringBuilder parameters_builder;
parameters_builder.join(',', parameters); parameters_builder.join(',', parameters);
parameters_source = parameters_builder.build(); parameters_source = parameters_builder.build();
body_source = vm.argument(vm.argument_count() - 1).to_string(global_object); body_source = TRY_OR_DISCARD(vm.argument(vm.argument_count() - 1).to_string(global_object));
if (vm.exception())
return {};
} }
auto is_generator = kind == FunctionKind::Generator; auto is_generator = kind == FunctionKind::Generator;
auto source = String::formatted("function{} anonymous({}\n) {{\n{}\n}}", is_generator ? "*" : "", parameters_source, body_source); 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()) if (vm.argument(0).is_number())
return vm.argument(0); return vm.argument(0);
auto input_string = vm.argument(0).to_string(global_object); auto input_string = TRY_OR_DISCARD(vm.argument(0).to_string(global_object));
if (vm.exception())
return {};
auto trimmed_string = input_string.trim_whitespace(TrimMode::Left); auto trimmed_string = input_string.trim_whitespace(TrimMode::Left);
for (size_t length = trimmed_string.length(); length > 0; --length) { for (size_t length = trimmed_string.length(); length > 0; --length) {
// This can't throw, so no exception check is fine. // 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 // 19.2.5 parseInt ( string, radix ), https://tc39.es/ecma262/#sec-parseint-string-radix
JS_DEFINE_NATIVE_FUNCTION(GlobalObject::parse_int) JS_DEFINE_NATIVE_FUNCTION(GlobalObject::parse_int)
{ {
auto input_string = vm.argument(0).to_string(global_object); auto input_string = TRY_OR_DISCARD(vm.argument(0).to_string(global_object));
if (vm.exception())
return {};
// FIXME: There's a bunch of unnecessary string copying here. // FIXME: There's a bunch of unnecessary string copying here.
double sign = 1; 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 // 19.2.6.4 encodeURI ( uri ), https://tc39.es/ecma262/#sec-encodeuri-uri
JS_DEFINE_NATIVE_FUNCTION(GlobalObject::encode_uri) JS_DEFINE_NATIVE_FUNCTION(GlobalObject::encode_uri)
{ {
auto uri_string = vm.argument(0).to_string(global_object); auto uri_string = TRY_OR_DISCARD(vm.argument(0).to_string(global_object));
if (vm.exception())
return {};
auto encoded = encode(global_object, uri_string, ";/?:@&=+$,abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.!~*'()#"sv); auto encoded = encode(global_object, uri_string, ";/?:@&=+$,abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.!~*'()#"sv);
if (vm.exception()) if (vm.exception())
return {}; 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 // 19.2.6.2 decodeURI ( encodedURI ), https://tc39.es/ecma262/#sec-decodeuri-encodeduri
JS_DEFINE_NATIVE_FUNCTION(GlobalObject::decode_uri) JS_DEFINE_NATIVE_FUNCTION(GlobalObject::decode_uri)
{ {
auto uri_string = vm.argument(0).to_string(global_object); auto uri_string = TRY_OR_DISCARD(vm.argument(0).to_string(global_object));
if (vm.exception())
return {};
auto decoded = decode(global_object, uri_string, ";/?:@&=+$,#"sv); auto decoded = decode(global_object, uri_string, ";/?:@&=+$,#"sv);
if (vm.exception()) if (vm.exception())
return {}; 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 // 19.2.6.5 encodeURIComponent ( uriComponent ), https://tc39.es/ecma262/#sec-encodeuricomponent-uricomponent
JS_DEFINE_NATIVE_FUNCTION(GlobalObject::encode_uri_component) JS_DEFINE_NATIVE_FUNCTION(GlobalObject::encode_uri_component)
{ {
auto uri_string = vm.argument(0).to_string(global_object); auto uri_string = TRY_OR_DISCARD(vm.argument(0).to_string(global_object));
if (vm.exception())
return {};
auto encoded = encode(global_object, uri_string, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.!~*'()"sv); auto encoded = encode(global_object, uri_string, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.!~*'()"sv);
if (vm.exception()) if (vm.exception())
return {}; 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 // 19.2.6.3 decodeURIComponent ( encodedURIComponent ), https://tc39.es/ecma262/#sec-decodeuricomponent-encodeduricomponent
JS_DEFINE_NATIVE_FUNCTION(GlobalObject::decode_uri_component) JS_DEFINE_NATIVE_FUNCTION(GlobalObject::decode_uri_component)
{ {
auto uri_string = vm.argument(0).to_string(global_object); auto uri_string = TRY_OR_DISCARD(vm.argument(0).to_string(global_object));
if (vm.exception())
return {};
auto decoded = decode(global_object, uri_string, ""sv); auto decoded = decode(global_object, uri_string, ""sv);
if (vm.exception()) if (vm.exception())
return {}; 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 // B.2.1.1 escape ( string ), https://tc39.es/ecma262/#sec-escape-string
JS_DEFINE_NATIVE_FUNCTION(GlobalObject::escape) JS_DEFINE_NATIVE_FUNCTION(GlobalObject::escape)
{ {
auto string = vm.argument(0).to_string(global_object); auto string = TRY_OR_DISCARD(vm.argument(0).to_string(global_object));
if (vm.exception())
return {};
StringBuilder escaped; StringBuilder escaped;
for (auto code_point : Utf8View(string)) { for (auto code_point : Utf8View(string)) {
if (code_point < 256) { 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 // B.2.1.2 unescape ( string ), https://tc39.es/ecma262/#sec-unescape-string
JS_DEFINE_NATIVE_FUNCTION(GlobalObject::unescape) JS_DEFINE_NATIVE_FUNCTION(GlobalObject::unescape)
{ {
auto string = vm.argument(0).to_string(global_object); auto string = TRY_OR_DISCARD(vm.argument(0).to_string(global_object));
if (vm.exception())
return {};
ssize_t length = string.length(); ssize_t length = string.length();
StringBuilder unescaped(length); StringBuilder unescaped(length);
for (auto k = 0; k < length; ++k) { for (auto k = 0; k < length; ++k) {

View file

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

View file

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

View file

@ -292,9 +292,7 @@ Value LocaleConstructor::construct(FunctionObject& new_target)
// 9. Else, // 9. Else,
else { else {
// a. Let tag be ? ToString(tag). // a. Let tag be ? ToString(tag).
tag = tag_value.to_string(global_object); tag = TRY_OR_DISCARD(tag_value.to_string(global_object));
if (vm.exception())
return {};
} }
// 10. Set options to ? CoerceOptionsToObject(options). // 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). // 24. If kn is not undefined, set kn to ! ToString(kn).
// 25. Set opt.[[kn]] to kn. // 25. Set opt.[[kn]] to kn.
if (!kn.is_undefined()) 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). // 26. Let numberingSystem be ? GetOption(options, "numberingSystem", "string", undefined, undefined).
// 27. If numberingSystem is not undefined, then // 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()) { if (replacer_value.is_string()) {
item = replacer_value.as_string().string(); item = replacer_value.as_string().string();
} else if (replacer_value.is_number()) { } 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()) { } else if (replacer_value.is_object()) {
auto& value_object = replacer_value.as_object(); auto& value_object = replacer_value.as_object();
if (is<StringObject>(value_object) || is<NumberObject>(value_object)) { if (is<StringObject>(value_object) || is<NumberObject>(value_object))
item = replacer_value.to_string(global_object); item = TRY_OR_DISCARD(replacer_value.to_string(global_object));
if (vm.exception())
return {};
}
} }
if (!item.is_null() && !list.contains_slow(item)) { if (!item.is_null() && !list.contains_slow(item)) {
list.append(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()); return quote_json_string(value.as_string().string());
if (value.is_number()) { if (value.is_number()) {
if (value.is_finite_number()) if (value.is_finite_number())
return value.to_string(global_object); return MUST(value.to_string(global_object));
return "null"; return "null";
} }
if (value.is_bigint()) { 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 // 25.5.1 JSON.parse ( text [ , reviver ] ), https://tc39.es/ecma262/#sec-json.parse
JS_DEFINE_NATIVE_FUNCTION(JSONObject::parse) JS_DEFINE_NATIVE_FUNCTION(JSONObject::parse)
{ {
auto string = vm.argument(0).to_string(global_object); auto string = TRY_OR_DISCARD(vm.argument(0).to_string(global_object));
if (vm.exception())
return {};
auto reviver = vm.argument(1); auto reviver = vm.argument(1);
auto json = JsonValue::from_string(string); 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()) 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(); auto number = number_value.as_double();
if (fabs(number) >= 1e+21) 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))); return js_string(vm, String::formatted("{:0.{1}}", number, static_cast<size_t>(fraction_digits)));
} }

View file

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

View file

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

View file

@ -377,14 +377,10 @@ JS_DEFINE_NATIVE_FUNCTION(RegExpPrototype::to_string)
return {}; return {};
auto source_attr = TRY_OR_DISCARD(regexp_object->get(vm.names.source)); auto source_attr = TRY_OR_DISCARD(regexp_object->get(vm.names.source));
auto pattern = source_attr.to_string(global_object); auto pattern = TRY_OR_DISCARD(source_attr.to_string(global_object));
if (vm.exception())
return {};
auto flags_attr = TRY_OR_DISCARD(regexp_object->get(vm.names.flags)); auto flags_attr = TRY_OR_DISCARD(regexp_object->get(vm.names.flags));
auto flags = flags_attr.to_string(global_object); auto flags = TRY_OR_DISCARD(flags_attr.to_string(global_object));
if (vm.exception())
return {};
return js_string(vm, String::formatted("/{}/{}", pattern, flags)); return js_string(vm, String::formatted("/{}/{}", pattern, flags));
} }
@ -434,9 +430,7 @@ JS_DEFINE_NATIVE_FUNCTION(RegExpPrototype::symbol_match)
if (!result_object) if (!result_object)
return {}; return {};
auto match_object = TRY_OR_DISCARD(result_object->get(0)); auto match_object = TRY_OR_DISCARD(result_object->get(0));
auto match_str = match_object.to_string(global_object); auto match_str = TRY_OR_DISCARD(match_object.to_string(global_object));
if (vm.exception())
return {};
TRY_OR_DISCARD(array->create_data_property_or_throw(n, js_string(vm, match_str))); 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* 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); auto flags_value = TRY_OR_DISCARD(regexp_object->get(vm.names.flags));
if (vm.exception()) auto flags = TRY_OR_DISCARD(flags_value.to_string(global_object));
return {};
bool global = flags.find('g').has_value(); bool global = flags.find('g').has_value();
bool unicode = flags.find('u').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(); auto string_view = string.view();
if (!replace_value.is_function()) { if (!replace_value.is_function()) {
auto replace_string = replace_value.to_string(global_object); auto replace_string = TRY_OR_DISCARD(replace_value.to_string(global_object));
if (vm.exception())
return {};
replace_value = js_string(vm, move(replace_string)); 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(); 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; break;
auto match_object = TRY_OR_DISCARD(result_object->get(0)); auto match_object = TRY_OR_DISCARD(result_object->get(0));
String match_str = match_object.to_string(global_object); auto match_str = TRY_OR_DISCARD(match_object.to_string(global_object));
if (vm.exception())
return {};
if (match_str.is_empty()) if (match_str.is_empty())
TRY_OR_DISCARD(increment_last_index(global_object, *regexp_object, string_view, unicode)); 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()); MarkedValueList captures(vm.heap());
for (size_t n = 1; n <= n_captures; ++n) { for (size_t n = 1; n <= n_captures; ++n) {
auto capture = TRY_OR_DISCARD(result.get(n)); auto capture = TRY_OR_DISCARD(result.get(n));
if (!capture.is_undefined()) { if (!capture.is_undefined())
auto capture_string = capture.to_string(global_object); capture = js_string(vm, TRY_OR_DISCARD(capture.to_string(global_object)));
if (vm.exception())
return {};
capture = Value(js_string(vm, capture_string));
if (vm.exception())
return {};
}
captures.append(move(capture)); 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))); auto replace_result = TRY_OR_DISCARD(vm.call(replace_value.as_function(), js_undefined(), move(replacer_args)));
replacement = TRY_OR_DISCARD(replace_result.to_string(global_object));
replacement = replace_result.to_string(global_object);
if (vm.exception())
return {};
} else { } else {
auto named_captures_object = js_undefined(); auto named_captures_object = js_undefined();
if (!named_captures.is_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* 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); auto flags_value = TRY_OR_DISCARD(regexp_object->get(vm.names.flags));
if (vm.exception()) auto flags = TRY_OR_DISCARD(flags_value.to_string(global_object));
return {};
bool unicode = flags.find('u').has_value(); bool unicode = flags.find('u').has_value();
auto new_flags = flags.find('y').has_value() ? move(flags) : String::formatted("{}y", flags); 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) if (!match_object)
return {}; return {};
auto match_string_value = TRY_OR_DISCARD(match_object->get(0)); auto match_string_value = TRY_OR_DISCARD(match_object->get(0));
auto match_string = match_string_value.to_string(global_object); auto match_string = TRY_OR_DISCARD(match_string_value.to_string(global_object));
if (vm.exception())
return {};
if (match_string.is_empty()) { if (match_string.is_empty()) {
auto last_index = TRY_OR_DISCARD(iterator->regexp_object().get(vm.names.lastIndex)).to_length(global_object); auto last_index = TRY_OR_DISCARD(iterator->regexp_object().get(vm.names.lastIndex)).to_length(global_object);
if (vm.exception()) if (vm.exception())

View file

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

View file

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

View file

@ -44,7 +44,7 @@ Value SymbolConstructor::call()
{ {
if (vm().argument(0).is_undefined()) if (vm().argument(0).is_undefined())
return js_symbol(heap(), {}, false); 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 // 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 // 20.4.2.2 Symbol.for ( key ), https://tc39.es/ecma262/#sec-symbol.for
JS_DEFINE_NATIVE_FUNCTION(SymbolConstructor::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); 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)); auto result = TRY(Value(&calendar).invoke(global_object, vm.names.era, &date_like));
// 3. If result is not undefined, set result to ? ToString(result). // 3. If result is not undefined, set result to ? ToString(result).
if (!result.is_undefined()) { if (!result.is_undefined())
auto result_string = result.to_string(global_object); result = js_string(vm, TRY(result.to_string(global_object)));
if (auto* exception = vm.exception())
return throw_completion(exception->value());
result = js_string(vm, move(result_string));
}
// 4. Return result. // 4. Return result.
return result; return result;
@ -362,9 +358,7 @@ ThrowCompletionOr<Object*> to_temporal_calendar(GlobalObject& global_object, Val
} }
// 2. Let identifier be ? ToString(temporalCalendarLike). // 2. Let identifier be ? ToString(temporalCalendarLike).
auto identifier = temporal_calendar_like.to_string(global_object); auto identifier = TRY(temporal_calendar_like.to_string(global_object));
if (auto* exception = vm.exception())
return throw_completion(exception->value());
// 3. If ! IsBuiltinCalendar(identifier) is false, then // 3. If ! IsBuiltinCalendar(identifier) is false, then
if (!is_builtin_calendar(identifier)) { 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 // 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) 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. // 1. If one and two are the same Object value, return true.
if (&one == &two) if (&one == &two)
return true; return true;
// 2. Let calendarOne be ? ToString(one). // 2. Let calendarOne be ? ToString(one).
auto calendar_one = Value(&one).to_string(global_object); auto calendar_one = TRY(Value(&one).to_string(global_object));
if (auto* exception = vm.exception())
return throw_completion(exception->value());
// 3. Let calendarTwo be ? ToString(two). // 3. Let calendarTwo be ? ToString(two).
auto calendar_two = Value(&two).to_string(global_object); auto calendar_two = TRY(Value(&two).to_string(global_object));
if (auto* exception = vm.exception())
return throw_completion(exception->value());
// 4. If calendarOne is calendarTwo, return true. // 4. If calendarOne is calendarTwo, return true.
if (calendar_one == calendar_two) if (calendar_one == calendar_two)
@ -543,14 +531,10 @@ ThrowCompletionOr<Object*> consolidate_calendars(GlobalObject& global_object, Ob
return &two; return &two;
// 2. Let calendarOne be ? ToString(one). // 2. Let calendarOne be ? ToString(one).
auto calendar_one = Value(&one).to_string(global_object); auto calendar_one = TRY(Value(&one).to_string(global_object));
if (auto* exception = vm.exception())
return throw_completion(exception->value());
// 3. Let calendarTwo be ? ToString(two). // 3. Let calendarTwo be ? ToString(two).
auto calendar_two = Value(&two).to_string(global_object); auto calendar_two = TRY(Value(&two).to_string(global_object));
if (auto* exception = vm.exception())
return throw_completion(exception->value());
// 4. If calendarOne is calendarTwo, return two. // 4. If calendarOne is calendarTwo, return two.
if (calendar_one == calendar_two) if (calendar_one == calendar_two)

View file

@ -49,9 +49,7 @@ Value CalendarConstructor::construct(FunctionObject& new_target)
auto& global_object = this->global_object(); auto& global_object = this->global_object();
// 2. Set id to ? ToString(id). // 2. Set id to ? ToString(id).
auto identifier = vm.argument(0).to_string(global_object); auto identifier = TRY_OR_DISCARD(vm.argument(0).to_string(global_object));
if (vm.exception())
return {};
// 3. If ! IsBuiltinCalendar(id) is false, then // 3. If ! IsBuiltinCalendar(id) is false, then
if (!is_builtin_calendar(identifier)) { 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); auto calendar = vm.this_value(global_object);
// 2. Return ? ToString(calendar). // 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 // 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); auto calendar = vm.this_value(global_object);
// 2. Return ? ToString(calendar). // 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 // 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 // 7.5.1 ToTemporalDuration ( item ), https://tc39.es/proposal-temporal/#sec-temporal-totemporalduration
ThrowCompletionOr<Duration*> to_temporal_duration(GlobalObject& global_object, Value item) ThrowCompletionOr<Duration*> to_temporal_duration(GlobalObject& global_object, Value item)
{ {
auto& vm = global_object.vm();
TemporalDuration result; TemporalDuration result;
// 1. If Type(item) is Object, then // 1. If Type(item) is Object, then
@ -51,9 +49,7 @@ ThrowCompletionOr<Duration*> to_temporal_duration(GlobalObject& global_object, V
// 2. Else, // 2. Else,
else { else {
// a. Let string be ? ToString(item). // a. Let string be ? ToString(item).
auto string = item.to_string(global_object); auto string = TRY(item.to_string(global_object));
if (auto* exception = vm.exception())
return throw_completion(exception->value());
// b. Let result be ? ParseTemporalDurationString(string). // b. Let result be ? ParseTemporalDurationString(string).
result = TRY(parse_temporal_duration_string(global_object, 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 // 1. If Type(temporalDurationLike) is not Object, then
if (!temporal_duration_like.is_object()) { if (!temporal_duration_like.is_object()) {
// a. Let str be ? ToString(temporalDurationLike). // a. Let str be ? ToString(temporalDurationLike).
auto str = temporal_duration_like.to_string(global_object); auto str = TRY(temporal_duration_like.to_string(global_object));
if (auto* exception = vm.exception())
return throw_completion(exception->value());
// b. Let duration be ? ParseTemporalDurationString(str). // b. Let duration be ? ParseTemporalDurationString(str).
duration = TRY(parse_temporal_duration_string(global_object, 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 // 8.5.3 ToTemporalInstant ( item ), https://tc39.es/proposal-temporal/#sec-temporal-totemporalinstant
ThrowCompletionOr<Instant*> to_temporal_instant(GlobalObject& global_object, Value item) ThrowCompletionOr<Instant*> to_temporal_instant(GlobalObject& global_object, Value item)
{ {
auto& vm = global_object.vm();
// 1. If Type(item) is Object, then // 1. If Type(item) is Object, then
if (item.is_object()) { if (item.is_object()) {
// a. If item has an [[InitializedTemporalInstant]] internal slot, then // 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). // 2. Let string be ? ToString(item).
auto string = item.to_string(global_object); auto string = TRY(item.to_string(global_object));
if (auto* exception = vm.exception())
return throw_completion(exception->value());
// 3. Let epochNanoseconds be ? ParseTemporalInstant(string). // 3. Let epochNanoseconds be ? ParseTemporalInstant(string).
auto* epoch_nanoseconds = TRY(parse_temporal_instant(global_object, 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)); (void)TRY(to_temporal_overflow(global_object, *options));
// 5. Let string be ? ToString(item). // 5. Let string be ? ToString(item).
auto string = item.to_string(global_object); auto string = TRY(item.to_string(global_object));
if (auto* exception = vm.exception())
return throw_completion(exception->value());
// 6. Let result be ? ParseTemporalDateString(string). // 6. Let result be ? ParseTemporalDateString(string).
auto result = TRY(parse_temporal_date_string(global_object, 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 // 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) 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. // 1. Assert: Type(temporalDate) is Object.
// 2. Assert: temporalDate has an [[InitializedTemporalDate]] internal slot. // 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()); auto day = String::formatted("{:02}", temporal_date.iso_day());
// 6. Let calendarID be ? ToString(temporalDate.[[Calendar]]). // 6. Let calendarID be ? ToString(temporalDate.[[Calendar]]).
auto calendar_id = Value(&temporal_date.calendar()).to_string(global_object); auto calendar_id = TRY(Value(&temporal_date.calendar()).to_string(global_object));
if (auto* exception = vm.exception())
return throw_completion(exception->value());
// 7. Let calendar be ! FormatCalendarAnnotation(calendarID, showCalendar). // 7. Let calendar be ! FormatCalendarAnnotation(calendarID, showCalendar).
auto calendar = format_calendar_annotation(calendar_id, show_calendar); 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)); (void)TRY(to_temporal_overflow(global_object, *options));
// b. Let string be ? ToString(item). // b. Let string be ? ToString(item).
auto string = item.to_string(global_object); auto string = TRY(item.to_string(global_object));
if (auto* exception = vm.exception())
return throw_completion(exception->value());
// c. Let result be ? ParseTemporalDateTimeString(string). // c. Let result be ? ParseTemporalDateTimeString(string).
result = TRY(parse_temporal_date_time_string(global_object, 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 // 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) 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. // 1. Assert: isoYear, isoMonth, isoDay, hour, minute, second, millisecond, microsecond, and nanosecond are integers.
// 2. Let year be ! PadISOYear(isoYear). // 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); auto seconds = format_seconds_string_part(second, millisecond, microsecond, nanosecond, precision);
// 8. Let calendarID be ? ToString(calendar). // 8. Let calendarID be ? ToString(calendar).
auto calendar_id = calendar.to_string(global_object); auto calendar_id = TRY(calendar.to_string(global_object));
if (auto* exception = vm.exception())
return throw_completion(exception->value());
// 9. Let calendarString be ! FormatCalendarAnnotation(calendarID, showCalendar). // 9. Let calendarString be ! FormatCalendarAnnotation(calendarID, showCalendar).
auto calendar_string = format_calendar_annotation(calendar_id, show_calendar); 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 // 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) 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. // 1. Assert: Type(monthDay) is Object.
// 2. Assert: monthDay has an [[InitializedTemporalMonthDay]] internal slot. // 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()); auto result = String::formatted("{:02}-{:02}", month_day.iso_month(), month_day.iso_day());
// 6. Let calendarID be ? ToString(monthDay.[[Calendar]]). // 6. Let calendarID be ? ToString(monthDay.[[Calendar]]).
auto calendar_id = Value(&month_day.calendar()).to_string(global_object); auto calendar_id = TRY(Value(&month_day.calendar()).to_string(global_object));
if (auto* exception = vm.exception())
return throw_completion(exception->value());
// 7. If calendarID is not "iso8601", then // 7. If calendarID is not "iso8601", then
if (calendar_id != "iso8601"sv) { 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)); auto* calendar = TRY(get_temporal_calendar_with_iso_default(global_object, item_object));
// e. If ? ToString(calendar) is not "iso8601", then // e. If ? ToString(calendar) is not "iso8601", then
auto calendar_identifier = Value(calendar).to_string(global_object); auto calendar_identifier = TRY(Value(calendar).to_string(global_object));
if (auto* exception = vm.exception())
return throw_completion(exception->value());
if (calendar_identifier != "iso8601"sv) { if (calendar_identifier != "iso8601"sv) {
// i. Throw a RangeError exception. // i. Throw a RangeError exception.
return vm.throw_completion<RangeError>(global_object, ErrorType::TemporalInvalidCalendarIdentifier, calendar_identifier); 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, // 4. Else,
else { else {
// a. Let string be ? ToString(item). // a. Let string be ? ToString(item).
auto string = item.to_string(global_object); auto string = TRY(item.to_string(global_object));
if (auto* exception = vm.exception())
return throw_completion(exception->value());
// b. Let result be ? ParseTemporalTimeString(string). // b. Let result be ? ParseTemporalTimeString(string).
result = TRY(parse_temporal_time_string(global_object, 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)); (void)TRY(to_temporal_overflow(global_object, *options));
// 5. Let string be ? ToString(item). // 5. Let string be ? ToString(item).
auto string = item.to_string(global_object); auto string = TRY(item.to_string(global_object));
if (auto* exception = vm.exception())
return throw_completion(exception->value());
// 6. Let result be ? ParseTemporalYearMonthString(string). // 6. Let result be ? ParseTemporalYearMonthString(string).
auto result = TRY(parse_temporal_year_month_string(global_object, 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 // 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) 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. // 1. Assert: Type(yearMonth) is Object.
// 2. Assert: yearMonth has an [[InitializedTemporalYearMonth]] internal slot. // 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()); auto result = String::formatted("{}-{:02}", pad_iso_year(year_month.iso_year()), year_month.iso_month());
// 6. Let calendarID be ? ToString(yearMonth.[[Calendar]]). // 6. Let calendarID be ? ToString(yearMonth.[[Calendar]]).
auto calendar_id = Value(&year_month.calendar()).to_string(global_object); auto calendar_id = TRY(Value(&year_month.calendar()).to_string(global_object));
if (auto* exception = vm.exception())
return throw_completion(exception->value());
// 7. If calendarID is not "iso8601", then // 7. If calendarID is not "iso8601", then
if (calendar_id != "iso8601") { 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). // 2. Let identifier be ? ToString(temporalTimeZoneLike).
auto identifier = temporal_time_zone_like.to_string(global_object); auto identifier = TRY(temporal_time_zone_like.to_string(global_object));
if (auto* exception = vm.exception())
return throw_completion(exception->value());
// 3. Let result be ? ParseTemporalTimeZone(identifier). // 3. Let result be ? ParseTemporalTimeZone(identifier).
auto result = TRY(parse_temporal_time_zone(global_object, 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(); auto& global_object = this->global_object();
// 2. Set identifier to ? ToString(identifier). // 2. Set identifier to ? ToString(identifier).
auto identifier = vm.argument(0).to_string(global_object); auto identifier = TRY_OR_DISCARD(vm.argument(0).to_string(global_object));
if (vm.exception())
return {};
String canonical; String canonical;

View file

@ -45,7 +45,7 @@ JS_DEFINE_NATIVE_FUNCTION(TimeZonePrototype::id_getter)
auto time_zone = vm.this_value(global_object); auto time_zone = vm.this_value(global_object);
// 2. Return ? ToString(timeZone). // 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 // 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); auto time_zone = vm.this_value(global_object);
// 2. Return ? ToString(timeZone). // 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 {}; return {};
auto length = typed_array->array_length(); auto length = typed_array->array_length();
String separator = ","; String separator = ",";
if (!vm.argument(0).is_undefined()) { if (!vm.argument(0).is_undefined())
separator = vm.argument(0).to_string(global_object); separator = TRY_OR_DISCARD(vm.argument(0).to_string(global_object));
if (vm.exception())
return {};
}
StringBuilder builder; StringBuilder builder;
for (size_t i = 0; i < length; ++i) { 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)); auto value = TRY_OR_DISCARD(typed_array->get(i));
if (value.is_nullish()) if (value.is_nullish())
continue; continue;
auto string = value.to_string(global_object); auto string = TRY_OR_DISCARD(value.to_string(global_object));
if (vm.exception())
return {};
builder.append(string); builder.append(string);
} }
@ -1487,9 +1482,7 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::to_locale_string)
if (value.is_nullish()) if (value.is_nullish())
continue; continue;
auto locale_string_result = TRY_OR_DISCARD(value.invoke(global_object, vm.names.toLocaleString)); auto locale_string_result = TRY_OR_DISCARD(value.invoke(global_object, vm.names.toLocaleString));
auto string = locale_string_result.to_string(global_object); auto string = TRY_OR_DISCARD(locale_string_result.to_string(global_object));
if (vm.exception())
return {};
builder.append(string); builder.append(string);
} }
return js_string(vm, builder.to_string()); return js_string(vm, builder.to_string());

View file

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

View file

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

View file

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

View file

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

View file

@ -190,11 +190,8 @@ JS_DEFINE_NATIVE_FUNCTION(WindowObject::alert)
if (!impl) if (!impl)
return {}; return {};
String message = ""; String message = "";
if (vm.argument_count()) { if (vm.argument_count())
message = vm.argument(0).to_string(global_object); message = TRY_OR_DISCARD(vm.argument(0).to_string(global_object));
if (vm.exception())
return {};
}
impl->alert(message); impl->alert(message);
return JS::js_undefined(); return JS::js_undefined();
} }
@ -205,11 +202,8 @@ JS_DEFINE_NATIVE_FUNCTION(WindowObject::confirm)
if (!impl) if (!impl)
return {}; return {};
String message = ""; String message = "";
if (!vm.argument(0).is_undefined()) { if (!vm.argument(0).is_undefined())
message = vm.argument(0).to_string(global_object); message = TRY_OR_DISCARD(vm.argument(0).to_string(global_object));
if (vm.exception())
return {};
}
return JS::Value(impl->confirm(message)); return JS::Value(impl->confirm(message));
} }
@ -220,16 +214,10 @@ JS_DEFINE_NATIVE_FUNCTION(WindowObject::prompt)
return {}; return {};
String message = ""; String message = "";
String default_ = ""; String default_ = "";
if (!vm.argument(0).is_undefined()) { if (!vm.argument(0).is_undefined())
message = vm.argument(0).to_string(global_object); message = TRY_OR_DISCARD(vm.argument(0).to_string(global_object));
if (vm.exception()) if (!vm.argument(1).is_undefined())
return {}; default_ = TRY_OR_DISCARD(vm.argument(1).to_string(global_object));
}
if (!vm.argument(1).is_undefined()) {
default_ = vm.argument(1).to_string(global_object);
if (vm.exception())
return {};
}
auto response = impl->prompt(message, default_); auto response = impl->prompt(message, default_);
if (response.is_null()) if (response.is_null())
return JS::js_null(); return JS::js_null();
@ -252,9 +240,7 @@ JS_DEFINE_NATIVE_FUNCTION(WindowObject::set_interval)
if (vm.argument(0).is_function()) { if (vm.argument(0).is_function()) {
callback = &vm.argument(0).as_function(); callback = &vm.argument(0).as_function();
} else { } else {
auto script_source = vm.argument(0).to_string(global_object); auto script_source = TRY_OR_DISCARD(vm.argument(0).to_string(global_object));
if (vm.exception())
return {};
// FIXME: This needs more work once we have a environment settings 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, // 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 // 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()) { if (vm.argument(0).is_function()) {
callback = &vm.argument(0).as_function(); callback = &vm.argument(0).as_function();
} else { } else {
auto script_source = vm.argument(0).to_string(global_object); auto script_source = TRY_OR_DISCARD(vm.argument(0).to_string(global_object));
if (vm.exception())
return {};
// FIXME: This needs more work once we have a environment settings 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, // 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 // 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"); vm.throw_exception<JS::TypeError>(global_object, JS::ErrorType::BadArgCountOne, "atob");
return {}; return {};
} }
auto string = vm.argument(0).to_string(global_object); auto string = TRY_OR_DISCARD(vm.argument(0).to_string(global_object));
if (vm.exception())
return {};
auto decoded = decode_base64(StringView(string)); 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. // 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"); vm.throw_exception<JS::TypeError>(global_object, JS::ErrorType::BadArgCountOne, "btoa");
return {}; return {};
} }
auto string = vm.argument(0).to_string(global_object); auto string = TRY_OR_DISCARD(vm.argument(0).to_string(global_object));
if (vm.exception())
return {};
Vector<u8> byte_string; Vector<u8> byte_string;
byte_string.ensure_capacity(string.length()); byte_string.ensure_capacity(string.length());
@ -593,9 +573,7 @@ JS_DEFINE_NATIVE_FUNCTION(WindowObject::match_media)
auto* impl = impl_from(vm, global_object); auto* impl = impl_from(vm, global_object);
if (!impl) if (!impl)
return {}; return {};
auto media = vm.argument(0).to_string(global_object); auto media = TRY_OR_DISCARD(vm.argument(0).to_string(global_object));
if (vm.exception())
return {};
return wrap(global_object, impl->match_media(move(media))); 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")); auto behavior_string_value = TRY_OR_DISCARD(options->get("behavior"));
if (!behavior_string_value.is_undefined()) if (!behavior_string_value.is_undefined())
behavior_string = behavior_string_value.to_string(global_object); behavior_string = TRY_OR_DISCARD(behavior_string_value.to_string(global_object));
if (vm.exception())
return {};
if (behavior_string != "smooth" && behavior_string != "auto") { if (behavior_string != "smooth" && behavior_string != "auto") {
vm.throw_exception<JS::TypeError>(global_object, "Behavior is not one of 'smooth' or 'auto'"); vm.throw_exception<JS::TypeError>(global_object, "Behavior is not one of 'smooth' or 'auto'");
return {}; return {};
@ -737,9 +713,7 @@ JS_DEFINE_NATIVE_FUNCTION(WindowObject::scroll_by)
top = top + current_scroll_position.y(); top = top + current_scroll_position.y();
auto behavior_string_value = TRY_OR_DISCARD(options->get("behavior")); 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); auto behavior_string = behavior_string_value.is_undefined() ? "auto" : TRY_OR_DISCARD(behavior_string_value.to_string(global_object));
if (vm.exception())
return {};
if (behavior_string != "smooth" && behavior_string != "auto") { if (behavior_string != "smooth" && behavior_string != "auto") {
vm.throw_exception<JS::TypeError>(global_object, "Behavior is not one of 'smooth' or 'auto'"); vm.throw_exception<JS::TypeError>(global_object, "Behavior is not one of 'smooth' or 'auto'");
return {}; 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) static JS::Value load_file_impl(JS::VM& vm, JS::GlobalObject& global_object)
{ {
auto filename = vm.argument(0).to_string(global_object); auto filename = TRY_OR_DISCARD(vm.argument(0).to_string(global_object));
if (vm.exception())
return {};
auto file = Core::File::construct(filename); auto file = Core::File::construct(filename);
if (!file->open(Core::OpenMode::ReadOnly)) { if (!file->open(Core::OpenMode::ReadOnly)) {
vm.throw_exception<JS::Error>(global_object, String::formatted("Failed to open '{}': {}", filename, file->error_string())); 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) static JS::Value load_json_impl(JS::VM& vm, JS::GlobalObject& global_object)
{ {
auto filename = vm.argument(0).to_string(global_object); auto filename = TRY_OR_DISCARD(vm.argument(0).to_string(global_object));
if (vm.exception())
return {};
auto file = Core::File::construct(filename); auto file = Core::File::construct(filename);
if (!file->open(Core::OpenMode::ReadOnly)) { if (!file->open(Core::OpenMode::ReadOnly)) {
vm.throw_exception<JS::Error>(global_object, String::formatted("Failed to open '{}': {}", filename, file->error_string())); vm.throw_exception<JS::Error>(global_object, String::formatted("Failed to open '{}': {}", filename, file->error_string()));