mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2026-04-19 02:10:26 +00:00
Inline JS-to-JS frames no longer live in the raw execution context vector, so LibWeb callers that need to inspect or pop contexts now go through VM helpers instead of peeking into that storage directly. This keeps the execution context bookkeeping encapsulated while preserving existing microtask and realm-entry checks.
67 lines
2.6 KiB
C++
67 lines
2.6 KiB
C++
/*
|
|
* Copyright (c) 2025, Shannon Booth <shannon@serenityos.org>
|
|
* Copyright (c) 2025, Sam Atkins <sam@ladybird.org>
|
|
*
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*/
|
|
|
|
#include <LibJS/Runtime/VM.h>
|
|
#include <LibWeb/HTML/ErrorInformation.h>
|
|
|
|
namespace Web::HTML {
|
|
|
|
// https://html.spec.whatwg.org/multipage/webappapis.html#extract-error
|
|
ErrorInformation extract_error_information(JS::VM& vm, JS::Value exception)
|
|
{
|
|
// 1. Let attributes be an empty map keyed by IDL attributes.
|
|
ErrorInformation attributes;
|
|
|
|
// 2. Set attributes[error] to exception.
|
|
attributes.error = exception;
|
|
|
|
// 3. Set attributes[message], attributes[filename], attributes[lineno], and attributes[colno] to
|
|
// implementation-defined values derived from exception.
|
|
attributes.message = [&] {
|
|
if (auto object = exception.as_if<JS::Object>()) {
|
|
if (MUST(object->has_own_property(vm.names.message))) {
|
|
auto message = object->get_without_side_effects(vm.names.message);
|
|
return message.to_string_without_side_effects();
|
|
}
|
|
}
|
|
|
|
return MUST(String::formatted("Uncaught exception: {}", exception));
|
|
}();
|
|
|
|
// FIXME: This offset is relative to the javascript source. Other browsers appear to do it relative
|
|
// to the entire source document! Calculate that somehow.
|
|
|
|
// NB: If we got an Error object, then try and extract the information from the location the object was made.
|
|
if (auto object = exception.as_if<JS::Object>(); object && object->error_data()) {
|
|
for (auto const& frame : object->error_data()->traceback()) {
|
|
auto source_range = frame.source_range();
|
|
if (source_range.start.line != 0 || source_range.start.column != 0) {
|
|
attributes.filename = MUST(String::from_byte_string(source_range.filename()));
|
|
attributes.lineno = source_range.start.line;
|
|
attributes.colno = source_range.start.column;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
// NB: Otherwise, we fall back to try and find the location of the invocation of the function itself.
|
|
else {
|
|
for (auto const& frame : vm.stack_trace()) {
|
|
if (frame.source_range.has_value()) {
|
|
auto const& source_range = *frame.source_range;
|
|
attributes.filename = MUST(String::from_byte_string(source_range.filename()));
|
|
attributes.lineno = source_range.start.line;
|
|
attributes.colno = source_range.start.column;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// 4. Return attributes.
|
|
return attributes;
|
|
}
|
|
|
|
}
|