mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 06:17:35 +00:00
WebContent+LibWeb+LibJS: Report exceptions to the JS console
Print exceptions passed to `HTML::report_exception` in the JS console Refactored `ExceptionReporter`: in order to report exception now you need to pass the relevant realm in it. For passed `JS::Value` we now create `JS::Error` object to print value as the error message.
This commit is contained in:
parent
2eb6dbd4f0
commit
40aad77ab1
14 changed files with 86 additions and 58 deletions
|
@ -453,6 +453,12 @@ void Console::output_debug_message([[maybe_unused]] LogLevel log_level, [[maybe_
|
|||
#endif
|
||||
}
|
||||
|
||||
void Console::report_exception(JS::Error const& exception, bool in_promise) const
|
||||
{
|
||||
if (m_client)
|
||||
m_client->report_exception(exception, in_promise);
|
||||
}
|
||||
|
||||
ThrowCompletionOr<String> Console::value_vector_to_string(MarkedVector<Value> const& values)
|
||||
{
|
||||
auto& vm = realm().vm();
|
||||
|
|
|
@ -82,6 +82,7 @@ public:
|
|||
ThrowCompletionOr<Value> time_end();
|
||||
|
||||
void output_debug_message(LogLevel log_level, String output) const;
|
||||
void report_exception(JS::Error const&, bool) const;
|
||||
|
||||
private:
|
||||
ThrowCompletionOr<String> value_vector_to_string(MarkedVector<Value> const&);
|
||||
|
@ -108,7 +109,8 @@ public:
|
|||
ThrowCompletionOr<MarkedVector<Value>> formatter(MarkedVector<Value> const& args);
|
||||
virtual ThrowCompletionOr<Value> printer(Console::LogLevel log_level, PrinterArguments) = 0;
|
||||
|
||||
virtual void add_css_style_to_current_message(StringView) {};
|
||||
virtual void add_css_style_to_current_message(StringView) { }
|
||||
virtual void report_exception(JS::Error const&, bool) { }
|
||||
|
||||
virtual void clear() = 0;
|
||||
virtual void end_group() = 0;
|
||||
|
|
|
@ -36,11 +36,10 @@ String MarkupGenerator::html_from_value(Value value)
|
|||
return output_html.to_string();
|
||||
}
|
||||
|
||||
String MarkupGenerator::html_from_error(Object& object)
|
||||
String MarkupGenerator::html_from_error(Error const& object, bool in_promise)
|
||||
{
|
||||
StringBuilder output_html;
|
||||
HashTable<Object*> seen_objects;
|
||||
error_to_html(object, output_html, seen_objects);
|
||||
error_to_html(object, output_html, in_promise);
|
||||
return output_html.to_string();
|
||||
}
|
||||
|
||||
|
@ -70,8 +69,6 @@ void MarkupGenerator::value_to_html(Value value, StringBuilder& output_html, Has
|
|||
return function_to_html(object, output_html, seen_objects);
|
||||
if (is<Date>(object))
|
||||
return date_to_html(object, output_html, seen_objects);
|
||||
if (is<Error>(object))
|
||||
return error_to_html(object, output_html, seen_objects);
|
||||
return object_to_html(object, output_html, seen_objects);
|
||||
}
|
||||
|
||||
|
@ -145,19 +142,35 @@ void MarkupGenerator::date_to_html(Object const& date, StringBuilder& html_outpu
|
|||
html_output.appendff("Date {}", to_date_string(static_cast<Date const&>(date).date_value()));
|
||||
}
|
||||
|
||||
void MarkupGenerator::error_to_html(Object const& object, StringBuilder& html_output, HashTable<Object*>&)
|
||||
void MarkupGenerator::trace_to_html(TracebackFrame const& traceback_frame, StringBuilder& html_output)
|
||||
{
|
||||
auto& vm = object.vm();
|
||||
auto name = object.get_without_side_effects(vm.names.name).value_or(js_undefined());
|
||||
auto message = object.get_without_side_effects(vm.names.message).value_or(js_undefined());
|
||||
if (name.is_accessor() || message.is_accessor()) {
|
||||
html_output.append(wrap_string_in_style(Value(&object).to_string_without_side_effects(), StyleType::Invalid));
|
||||
} else {
|
||||
auto name_string = name.to_string_without_side_effects();
|
||||
auto message_string = message.to_string_without_side_effects();
|
||||
html_output.append(wrap_string_in_style(String::formatted("[{}]", name_string), StyleType::Invalid));
|
||||
if (!message_string.is_empty())
|
||||
html_output.appendff(": {}", escape_html_entities(message_string));
|
||||
auto function_name = escape_html_entities(traceback_frame.function_name);
|
||||
auto [line, column, _] = traceback_frame.source_range.start;
|
||||
auto get_filename_from_path = [&](StringView filename) -> StringView {
|
||||
auto last_slash_index = filename.find_last('/');
|
||||
return last_slash_index.has_value() ? filename.substring_view(*last_slash_index + 1) : filename;
|
||||
};
|
||||
auto filename = escape_html_entities(get_filename_from_path(traceback_frame.source_range.filename));
|
||||
auto trace = String::formatted("at {} ({}:{}:{})", function_name, filename, line, column);
|
||||
|
||||
html_output.appendff(" {}<br>", trace);
|
||||
}
|
||||
|
||||
void MarkupGenerator::error_to_html(Error const& error, StringBuilder& html_output, bool in_promise)
|
||||
{
|
||||
auto& vm = error.vm();
|
||||
auto name = error.get_without_side_effects(vm.names.name).value_or(js_undefined());
|
||||
auto message = error.get_without_side_effects(vm.names.message).value_or(js_undefined());
|
||||
auto name_string = name.to_string_without_side_effects();
|
||||
auto message_string = message.to_string_without_side_effects();
|
||||
auto uncaught_message = String::formatted("Uncaught {}[{}]: ", in_promise ? "(in promise) " : "", name_string);
|
||||
|
||||
html_output.append(wrap_string_in_style(uncaught_message, StyleType::Invalid));
|
||||
html_output.appendff("{}<br>", message_string.is_empty() ? "\"\"" : escape_html_entities(message_string));
|
||||
|
||||
for (size_t i = 0; i < error.traceback().size() - min(error.traceback().size(), 3); i++) {
|
||||
auto& traceback_frame = error.traceback().at(i);
|
||||
trace_to_html(traceback_frame, html_output);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include <AK/HashTable.h>
|
||||
#include <AK/String.h>
|
||||
#include <LibJS/Forward.h>
|
||||
#include <LibJS/Runtime/Error.h>
|
||||
|
||||
namespace JS {
|
||||
|
||||
|
@ -16,7 +17,7 @@ class MarkupGenerator {
|
|||
public:
|
||||
static String html_from_source(StringView);
|
||||
static String html_from_value(Value);
|
||||
static String html_from_error(Object&);
|
||||
static String html_from_error(Error const&, bool);
|
||||
|
||||
private:
|
||||
enum class StyleType {
|
||||
|
@ -37,7 +38,8 @@ private:
|
|||
static void object_to_html(Object const&, StringBuilder& output_html, HashTable<Object*>&);
|
||||
static void function_to_html(Object const&, StringBuilder& output_html, HashTable<Object*>&);
|
||||
static void date_to_html(Object const&, StringBuilder& output_html, HashTable<Object*>&);
|
||||
static void error_to_html(Object const&, StringBuilder& output_html, HashTable<Object*>&);
|
||||
static void error_to_html(Error const&, StringBuilder& output_html, bool in_promise);
|
||||
static void trace_to_html(TracebackFrame const&, StringBuilder& output_html);
|
||||
|
||||
static String style_from_style_type(StyleType);
|
||||
static StyleType style_type_for_token(Token);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue