mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 04:17:35 +00:00
LibJS: Make Errors fully spec compliant
The previous handling of the name and message properties specifically was breaking websites that created their own error types and relied on the error prototype working correctly - not assuming an JS::Error this object, that is. The way it works now, and it is supposed to work, is: - Error.prototype.name and Error.prototype.message just have initial string values and are no longer getters/setters - When constructing an error with a message, we create a regular property on the newly created object, so a lookup of the message property will either get it from the object directly or go though the prototype chain - Internal m_name/m_message properties are no longer needed and removed This makes printing errors slightly more complicated, as we can no longer rely on the (safe) internal properties, and cannot trust a property lookup either - get_without_side_effects() is used to solve this, it's not perfect but something we can revisit later. I did some refactoring along the way, there was some really old stuff in there - accessing vm.call_frame().arguments[0] is not something we (have to) do anymore :^) Fixes #6245.
This commit is contained in:
parent
6e9eb0a284
commit
da177c6517
18 changed files with 157 additions and 180 deletions
|
@ -239,18 +239,25 @@ static void print_function(const JS::Object& object, HashTable<JS::Object*>&)
|
|||
out(" {}", static_cast<const JS::NativeFunction&>(object).name());
|
||||
}
|
||||
|
||||
static void print_date(const JS::Object& date, HashTable<JS::Object*>&)
|
||||
static void print_date(const JS::Object& object, HashTable<JS::Object*>&)
|
||||
{
|
||||
print_type("Date");
|
||||
out(" \033[34;1m{}\033[0m", static_cast<const JS::Date&>(date).string());
|
||||
out(" \033[34;1m{}\033[0m", static_cast<const JS::Date&>(object).string());
|
||||
}
|
||||
|
||||
static void print_error(const JS::Object& object, HashTable<JS::Object*>&)
|
||||
static void print_error(const JS::Object& object, HashTable<JS::Object*>& seen_objects)
|
||||
{
|
||||
auto& error = static_cast<const JS::Error&>(object);
|
||||
print_type(error.name());
|
||||
if (!error.message().is_empty())
|
||||
out(" \033[31;1m{}\033[0m", error.message());
|
||||
auto name = object.get_without_side_effects(vm->names.name).value_or(JS::js_undefined());
|
||||
auto message = object.get_without_side_effects(vm->names.message).value_or(JS::js_undefined());
|
||||
if (name.is_accessor() || name.is_native_property() || message.is_accessor() || message.is_native_property()) {
|
||||
print_value(&object, seen_objects);
|
||||
} else {
|
||||
auto name_string = name.to_string_without_side_effects();
|
||||
auto message_string = message.to_string_without_side_effects();
|
||||
print_type(name_string);
|
||||
if (!message_string.is_empty())
|
||||
out(" \033[31;1m{}\033[0m", message_string);
|
||||
}
|
||||
}
|
||||
|
||||
static void print_regexp_object(const JS::Object& object, HashTable<JS::Object*>&)
|
||||
|
@ -498,9 +505,11 @@ static bool parse_and_run(JS::Interpreter& interpreter, const StringView& source
|
|||
}
|
||||
|
||||
auto handle_exception = [&] {
|
||||
auto* exception = vm->exception();
|
||||
vm->clear_exception();
|
||||
out("Uncaught exception: ");
|
||||
print(vm->exception()->value());
|
||||
auto trace = vm->exception()->trace();
|
||||
print(exception->value());
|
||||
auto& trace = exception->trace();
|
||||
if (trace.size() > 1) {
|
||||
unsigned repetitions = 0;
|
||||
for (size_t i = 0; i < trace.size(); ++i) {
|
||||
|
@ -522,7 +531,6 @@ static bool parse_and_run(JS::Interpreter& interpreter, const StringView& source
|
|||
repetitions = 0;
|
||||
}
|
||||
}
|
||||
vm->clear_exception();
|
||||
};
|
||||
|
||||
if (vm->exception()) {
|
||||
|
@ -532,8 +540,8 @@ static bool parse_and_run(JS::Interpreter& interpreter, const StringView& source
|
|||
if (s_print_last_result)
|
||||
print(vm->last_value());
|
||||
if (vm->exception()) {
|
||||
return false;
|
||||
handle_exception();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -738,7 +746,7 @@ int main(int argc, char** argv)
|
|||
OwnPtr<JS::Interpreter> interpreter;
|
||||
|
||||
interrupt_interpreter = [&] {
|
||||
auto error = JS::Error::create(interpreter->global_object(), "Error", "Received SIGINT");
|
||||
auto error = JS::Error::create(interpreter->global_object(), "Received SIGINT");
|
||||
vm->throw_exception(interpreter->global_object(), error);
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue