Skip to content

Commit 218e646

Browse files
AtkinsSJawesomekling
authored andcommitted
LibWeb/HTML: Extract ErrorInformation struct into its own files
This is used from a few different places in the spec.
1 parent c1c24e8 commit 218e646

File tree

4 files changed

+97
-66
lines changed

4 files changed

+97
-66
lines changed

Libraries/LibWeb/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -474,6 +474,7 @@ set(SOURCES
474474
HTML/ElementInternals.cpp
475475
HTML/EmbedderPolicy.cpp
476476
HTML/ErrorEvent.cpp
477+
HTML/ErrorInformation.cpp
477478
HTML/EventHandler.cpp
478479
HTML/EventLoop/EventLoop.cpp
479480
HTML/EventLoop/Task.cpp
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/*
2+
* Copyright (c) 2025, Shannon Booth <shannon@serenityos.org>
3+
* Copyright (c) 2025, Sam Atkins <sam@ladybird.org>
4+
*
5+
* SPDX-License-Identifier: BSD-2-Clause
6+
*/
7+
8+
#include <LibJS/Runtime/VM.h>
9+
#include <LibWeb/HTML/ErrorInformation.h>
10+
11+
namespace Web::HTML {
12+
13+
// https://html.spec.whatwg.org/multipage/webappapis.html#extract-error
14+
ErrorInformation extract_error_information(JS::VM& vm, JS::Value exception)
15+
{
16+
// 1. Let attributes be an empty map keyed by IDL attributes.
17+
ErrorInformation attributes;
18+
19+
// 2. Set attributes[error] to exception.
20+
attributes.error = exception;
21+
22+
// 3. Set attributes[message], attributes[filename], attributes[lineno], and attributes[colno] to
23+
// implementation-defined values derived from exception.
24+
attributes.message = [&] {
25+
if (exception.is_object()) {
26+
auto& object = exception.as_object();
27+
if (MUST(object.has_own_property(vm.names.message))) {
28+
auto message = object.get_without_side_effects(vm.names.message);
29+
return message.to_string_without_side_effects();
30+
}
31+
}
32+
33+
return MUST(String::formatted("Uncaught exception: {}", exception.to_string_without_side_effects()));
34+
}();
35+
36+
// FIXME: This offset is relative to the javascript source. Other browsers appear to do it relative
37+
// to the entire source document! Calculate that somehow.
38+
39+
// NB: If we got an Error object, then try and extract the information from the location the object was made.
40+
if (exception.is_object() && is<JS::Error>(exception.as_object())) {
41+
auto const& error = static_cast<JS::Error&>(exception.as_object());
42+
for (auto const& frame : error.traceback()) {
43+
auto source_range = frame.source_range();
44+
if (source_range.start.line != 0 || source_range.start.column != 0) {
45+
attributes.filename = MUST(String::from_byte_string(source_range.filename()));
46+
attributes.lineno = source_range.start.line;
47+
attributes.colno = source_range.start.column;
48+
break;
49+
}
50+
}
51+
}
52+
// NB: Otherwise, we fall back to try and find the location of the invocation of the function itself.
53+
else {
54+
for (ssize_t i = vm.execution_context_stack().size() - 1; i >= 0; --i) {
55+
auto& frame = vm.execution_context_stack()[i];
56+
if (frame->executable) {
57+
auto source_range = frame->executable->source_range_at(frame->program_counter).realize();
58+
attributes.filename = MUST(String::from_byte_string(source_range.filename()));
59+
attributes.lineno = source_range.start.line;
60+
attributes.colno = source_range.start.column;
61+
break;
62+
}
63+
}
64+
}
65+
66+
// 4. Return attributes.
67+
return attributes;
68+
}
69+
70+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/*
2+
* Copyright (c) 2025, Shannon Booth <shannon@serenityos.org>
3+
* Copyright (c) 2025, Sam Atkins <sam@ladybird.org>
4+
*
5+
* SPDX-License-Identifier: BSD-2-Clause
6+
*/
7+
8+
#pragma once
9+
10+
#include <LibJS/Runtime/Value.h>
11+
12+
namespace Web::HTML {
13+
14+
// https://html.spec.whatwg.org/multipage/webappapis.html#extract-error
15+
struct ErrorInformation {
16+
String message;
17+
String filename;
18+
JS::Value error;
19+
size_t lineno { 0 };
20+
size_t colno { 0 };
21+
};
22+
23+
ErrorInformation extract_error_information(JS::VM&, JS::Value exception);
24+
25+
}

Libraries/LibWeb/HTML/WindowOrWorkerGlobalScope.cpp

Lines changed: 1 addition & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include <LibWeb/Fetch/FetchMethod.h>
2525
#include <LibWeb/HTML/CanvasRenderingContext2D.h>
2626
#include <LibWeb/HTML/ErrorEvent.h>
27+
#include <LibWeb/HTML/ErrorInformation.h>
2728
#include <LibWeb/HTML/EventLoop/EventLoop.h>
2829
#include <LibWeb/HTML/EventSource.h>
2930
#include <LibWeb/HTML/HTMLImageElement.h>
@@ -1151,72 +1152,6 @@ void WindowOrWorkerGlobalScopeMixin::report_error(JS::Value e)
11511152
report_an_exception(e);
11521153
}
11531154

1154-
// https://html.spec.whatwg.org/multipage/webappapis.html#extract-error
1155-
struct ErrorInformation {
1156-
String message;
1157-
String filename;
1158-
JS::Value error;
1159-
size_t lineno { 0 };
1160-
size_t colno { 0 };
1161-
};
1162-
1163-
// https://html.spec.whatwg.org/multipage/webappapis.html#extract-error
1164-
static ErrorInformation extract_error_information(JS::VM& vm, JS::Value exception)
1165-
{
1166-
// 1. Let attributes be an empty map keyed by IDL attributes.
1167-
ErrorInformation attributes;
1168-
1169-
// 2. Set attributes[error] to exception.
1170-
attributes.error = exception;
1171-
1172-
// 3. Set attributes[message], attributes[filename], attributes[lineno], and attributes[colno] to
1173-
// implementation-defined values derived from exception.
1174-
attributes.message = [&] {
1175-
if (exception.is_object()) {
1176-
auto& object = exception.as_object();
1177-
if (MUST(object.has_own_property(vm.names.message))) {
1178-
auto message = object.get_without_side_effects(vm.names.message);
1179-
return message.to_string_without_side_effects();
1180-
}
1181-
}
1182-
1183-
return MUST(String::formatted("Uncaught exception: {}", exception.to_string_without_side_effects()));
1184-
}();
1185-
1186-
// FIXME: This offset is relative to the javascript source. Other browsers appear to do it relative
1187-
// to the entire source document! Calculate that somehow.
1188-
1189-
// If we got an Error object, then try and extract the information from the location the object was made.
1190-
if (exception.is_object() && is<JS::Error>(exception.as_object())) {
1191-
auto const& error = static_cast<JS::Error&>(exception.as_object());
1192-
for (auto const& frame : error.traceback()) {
1193-
auto source_range = frame.source_range();
1194-
if (source_range.start.line != 0 || source_range.start.column != 0) {
1195-
attributes.filename = MUST(String::from_byte_string(source_range.filename()));
1196-
attributes.lineno = source_range.start.line;
1197-
attributes.colno = source_range.start.column;
1198-
break;
1199-
}
1200-
}
1201-
}
1202-
// Otherwise, we fall back to try and find the location of the invocation of the function itself.
1203-
else {
1204-
for (ssize_t i = vm.execution_context_stack().size() - 1; i >= 0; --i) {
1205-
auto& frame = vm.execution_context_stack()[i];
1206-
if (frame->executable) {
1207-
auto source_range = frame->executable->source_range_at(frame->program_counter).realize();
1208-
attributes.filename = MUST(String::from_byte_string(source_range.filename()));
1209-
attributes.lineno = source_range.start.line;
1210-
attributes.colno = source_range.start.column;
1211-
break;
1212-
}
1213-
}
1214-
}
1215-
1216-
// 4. Return attributes.
1217-
return attributes;
1218-
}
1219-
12201155
// https://html.spec.whatwg.org/multipage/webappapis.html#report-an-exception
12211156
void WindowOrWorkerGlobalScopeMixin::report_an_exception(JS::Value exception, OmitError omit_error)
12221157
{

0 commit comments

Comments
 (0)