Thread UTF-16 string input through JSON, script parsing, Date parsing, Intl option parsing, Temporal parsing, and the helper library boundaries that feed those parsers. Preserve ASCII fast paths where the source data is known to be ASCII.
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_utf16_string_without_side_effects().to_utf8();
|
|
}
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
}
|