mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 00:27:45 +00:00
LibWeb: Make DOMException GC-allocated
This commit is contained in:
parent
0e47754ac8
commit
497ead37bc
58 changed files with 307 additions and 278 deletions
|
@ -7,6 +7,7 @@
|
|||
|
||||
#include <AK/ExtraMathConstants.h>
|
||||
#include <LibWeb/HTML/Canvas/CanvasPath.h>
|
||||
#include <LibWeb/HTML/Window.h>
|
||||
|
||||
namespace Web::HTML {
|
||||
|
||||
|
@ -38,17 +39,17 @@ void CanvasPath::bezier_curve_to(double cp1x, double cp1y, double cp2x, double c
|
|||
DOM::ExceptionOr<void> CanvasPath::arc(float x, float y, float radius, float start_angle, float end_angle, bool counter_clockwise)
|
||||
{
|
||||
if (radius < 0)
|
||||
return DOM::IndexSizeError::create(String::formatted("The radius provided ({}) is negative.", radius));
|
||||
return DOM::IndexSizeError::create(m_self.global_object(), String::formatted("The radius provided ({}) is negative.", radius));
|
||||
return ellipse(x, y, radius, radius, 0, start_angle, end_angle, counter_clockwise);
|
||||
}
|
||||
|
||||
DOM::ExceptionOr<void> CanvasPath::ellipse(float x, float y, float radius_x, float radius_y, float rotation, float start_angle, float end_angle, bool counter_clockwise)
|
||||
{
|
||||
if (radius_x < 0)
|
||||
return DOM::IndexSizeError::create(String::formatted("The major-axis radius provided ({}) is negative.", radius_x));
|
||||
return DOM::IndexSizeError::create(m_self.global_object(), String::formatted("The major-axis radius provided ({}) is negative.", radius_x));
|
||||
|
||||
if (radius_y < 0)
|
||||
return DOM::IndexSizeError::create(String::formatted("The minor-axis radius provided ({}) is negative.", radius_y));
|
||||
return DOM::IndexSizeError::create(m_self.global_object(), String::formatted("The minor-axis radius provided ({}) is negative.", radius_y));
|
||||
|
||||
if (constexpr float tau = M_TAU; (!counter_clockwise && (end_angle - start_angle) >= tau)
|
||||
|| (counter_clockwise && (start_angle - end_angle) >= tau)) {
|
||||
|
|
|
@ -30,9 +30,13 @@ public:
|
|||
Gfx::Path const& path() const { return m_path; }
|
||||
|
||||
protected:
|
||||
CanvasPath() = default;
|
||||
explicit CanvasPath(Bindings::PlatformObject& self)
|
||||
: m_self(self)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
Bindings::PlatformObject& m_self;
|
||||
Gfx::Path m_path;
|
||||
};
|
||||
|
||||
|
|
|
@ -53,14 +53,14 @@ DOM::ExceptionOr<void> CanvasGradient::add_color_stop(double offset, String cons
|
|||
{
|
||||
// 1. If the offset is less than 0 or greater than 1, then throw an "IndexSizeError" DOMException.
|
||||
if (offset < 0 || offset > 1)
|
||||
return DOM::IndexSizeError::create("CanvasGradient color stop offset out of bounds");
|
||||
return DOM::IndexSizeError::create(global_object(), "CanvasGradient color stop offset out of bounds");
|
||||
|
||||
// 2. Let parsed color be the result of parsing color.
|
||||
auto parsed_color = Color::from_string(color);
|
||||
|
||||
// 3. If parsed color is failure, throw a "SyntaxError" DOMException.
|
||||
if (!parsed_color.has_value())
|
||||
return DOM::SyntaxError::create("Could not parse color for CanvasGradient");
|
||||
return DOM::SyntaxError::create(global_object(), "Could not parse color for CanvasGradient");
|
||||
|
||||
// 4. Place a new stop on the gradient, at offset offset relative to the whole gradient, and with the color parsed color.
|
||||
m_color_stops.append(ColorStop { offset, parsed_color.value() });
|
||||
|
|
|
@ -29,6 +29,7 @@ JS::NonnullGCPtr<CanvasRenderingContext2D> CanvasRenderingContext2D::create(HTML
|
|||
|
||||
CanvasRenderingContext2D::CanvasRenderingContext2D(HTML::Window& window, HTMLCanvasElement& element)
|
||||
: PlatformObject(window.realm())
|
||||
, CanvasPath(static_cast<Bindings::PlatformObject&>(*this))
|
||||
, m_element(element)
|
||||
{
|
||||
set_prototype(&window.cached_web_prototype("CanvasRenderingContext2D"));
|
||||
|
@ -326,11 +327,11 @@ DOM::ExceptionOr<JS::GCPtr<ImageData>> CanvasRenderingContext2D::get_image_data(
|
|||
{
|
||||
// 1. If either the sw or sh arguments are zero, then throw an "IndexSizeError" DOMException.
|
||||
if (width == 0 || height == 0)
|
||||
return DOM::IndexSizeError::create("Width and height must not be zero");
|
||||
return DOM::IndexSizeError::create(global_object(), "Width and height must not be zero");
|
||||
|
||||
// 2. If the CanvasRenderingContext2D's origin-clean flag is set to false, then throw a "SecurityError" DOMException.
|
||||
if (!m_origin_clean)
|
||||
return DOM::SecurityError::create("CanvasRenderingContext2D is not origin-clean");
|
||||
return DOM::SecurityError::create(global_object(), "CanvasRenderingContext2D is not origin-clean");
|
||||
|
||||
// 3. Let imageData be a new ImageData object.
|
||||
// 4. Initialize imageData given sw, sh, settings set to settings, and defaultColorSpace set to this's color space.
|
||||
|
@ -548,7 +549,7 @@ DOM::ExceptionOr<CanvasImageSourceUsability> check_usability_of_image(CanvasImag
|
|||
[](JS::Handle<HTMLCanvasElement> const& canvas_element) -> DOM::ExceptionOr<Optional<CanvasImageSourceUsability>> {
|
||||
// If image has either a horizontal dimension or a vertical dimension equal to zero, then throw an "InvalidStateError" DOMException.
|
||||
if (canvas_element->width() == 0 || canvas_element->height() == 0)
|
||||
return DOM::InvalidStateError::create("Canvas width or height is zero");
|
||||
return DOM::InvalidStateError::create(canvas_element->global_object(), "Canvas width or height is zero");
|
||||
return Optional<CanvasImageSourceUsability> {};
|
||||
}));
|
||||
if (usability.has_value())
|
||||
|
|
|
@ -126,7 +126,7 @@ DOM::ExceptionOr<void> DOMStringMap::set_value_of_new_named_property(String cons
|
|||
if (current_character == '-' && character_index + 1 < name.length()) {
|
||||
auto next_character = name[character_index + 1];
|
||||
if (is_ascii_lower_alpha(next_character))
|
||||
return DOM::SyntaxError::create("Name cannot contain a '-' followed by a lowercase character.");
|
||||
return DOM::SyntaxError::create(global_object(), "Name cannot contain a '-' followed by a lowercase character.");
|
||||
}
|
||||
|
||||
// 2. For each ASCII upper alpha in name, insert a U+002D HYPHEN-MINUS character (-) before the character and replace the character with the same character converted to ASCII lowercase.
|
||||
|
|
|
@ -104,7 +104,7 @@ DOM::ExceptionOr<void> HTMLElement::set_content_editable(String const& content_e
|
|||
set_attribute(HTML::AttributeNames::contenteditable, "false");
|
||||
return {};
|
||||
}
|
||||
return DOM::SyntaxError::create("Invalid contentEditable value, must be 'true', 'false', or 'inherit'");
|
||||
return DOM::SyntaxError::create(global_object(), "Invalid contentEditable value, must be 'true', 'false', or 'inherit'");
|
||||
}
|
||||
|
||||
void HTMLElement::set_inner_text(StringView text)
|
||||
|
|
|
@ -40,11 +40,11 @@ DOM::ExceptionOr<void> HTMLOptionsCollection::add(HTMLOptionOrOptGroupElement el
|
|||
|
||||
// 1. If element is an ancestor of the select element on which the HTMLOptionsCollection is rooted, then throw a "HierarchyRequestError" DOMException.
|
||||
if (resolved_element->is_ancestor_of(root()))
|
||||
return DOM::HierarchyRequestError::create("The provided element is an ancestor of the root select element.");
|
||||
return DOM::HierarchyRequestError::create(global_object(), "The provided element is an ancestor of the root select element.");
|
||||
|
||||
// 2. If before is an element, but that element isn't a descendant of the select element on which the HTMLOptionsCollection is rooted, then throw a "NotFoundError" DOMException.
|
||||
if (before_element && !before_element->is_descendant_of(root()))
|
||||
return DOM::NotFoundError::create("The 'before' element is not a descendant of the root select element.");
|
||||
return DOM::NotFoundError::create(global_object(), "The 'before' element is not a descendant of the root select element.");
|
||||
|
||||
// 3. If element and before are the same element, then return.
|
||||
if (before_element && (resolved_element.ptr() == before_element.ptr()))
|
||||
|
|
|
@ -103,7 +103,7 @@ DOM::ExceptionOr<void> HTMLTableElement::set_t_head(HTMLTableSectionElement* the
|
|||
VERIFY(thead);
|
||||
|
||||
if (thead->local_name() != TagNames::thead)
|
||||
return DOM::HierarchyRequestError::create("Element is not thead");
|
||||
return DOM::HierarchyRequestError::create(global_object(), "Element is not thead");
|
||||
|
||||
// FIXME: The spec requires deleting the current thead if thead is null
|
||||
// Currently the wrapper generator doesn't send us a nullable value
|
||||
|
@ -190,7 +190,7 @@ DOM::ExceptionOr<void> HTMLTableElement::set_t_foot(HTMLTableSectionElement* tfo
|
|||
VERIFY(tfoot);
|
||||
|
||||
if (tfoot->local_name() != TagNames::tfoot)
|
||||
return DOM::HierarchyRequestError::create("Element is not tfoot");
|
||||
return DOM::HierarchyRequestError::create(global_object(), "Element is not tfoot");
|
||||
|
||||
// FIXME: The spec requires deleting the current tfoot if tfoot is null
|
||||
// Currently the wrapper generator doesn't send us a nullable value
|
||||
|
@ -286,7 +286,7 @@ DOM::ExceptionOr<JS::NonnullGCPtr<HTMLTableRowElement>> HTMLTableElement::insert
|
|||
auto rows_length = rows->length();
|
||||
|
||||
if (index < -1 || index > (long)rows_length) {
|
||||
return DOM::IndexSizeError::create("Index is negative or greater than the number of rows");
|
||||
return DOM::IndexSizeError::create(global_object(), "Index is negative or greater than the number of rows");
|
||||
}
|
||||
auto& tr = static_cast<HTMLTableRowElement&>(*DOM::create_element(document(), TagNames::tr, Namespace::HTML));
|
||||
if (rows_length == 0 && !has_child_of_type<HTMLTableRowElement>()) {
|
||||
|
@ -313,7 +313,7 @@ DOM::ExceptionOr<void> HTMLTableElement::delete_row(long index)
|
|||
|
||||
// 1. If index is less than −1 or greater than or equal to the number of elements in the rows collection, then throw an "IndexSizeError" DOMException.
|
||||
if (index < -1 || index >= (long)rows_length)
|
||||
return DOM::IndexSizeError::create("Index is negative or greater than or equal to the number of rows");
|
||||
return DOM::IndexSizeError::create(global_object(), "Index is negative or greater than or equal to the number of rows");
|
||||
|
||||
// 2. If index is −1, then remove the last element in the rows collection from its parent, or do nothing if the rows collection is empty.
|
||||
if (index == -1) {
|
||||
|
|
|
@ -43,7 +43,7 @@ DOM::ExceptionOr<JS::NonnullGCPtr<HTMLTableRowElement>> HTMLTableSectionElement:
|
|||
|
||||
// 1. If index is less than −1 or greater than the number of elements in the rows collection, throw an "IndexSizeError" DOMException.
|
||||
if (index < -1 || index > rows_collection_size)
|
||||
return DOM::IndexSizeError::create("Index is negative or greater than the number of rows");
|
||||
return DOM::IndexSizeError::create(global_object(), "Index is negative or greater than the number of rows");
|
||||
|
||||
// 2. Let table row be the result of creating an element given this element's node document, tr, and the HTML namespace.
|
||||
auto& table_row = static_cast<HTMLTableRowElement&>(*DOM::create_element(document(), TagNames::tr, Namespace::HTML));
|
||||
|
@ -67,7 +67,7 @@ DOM::ExceptionOr<void> HTMLTableSectionElement::delete_row(long index)
|
|||
|
||||
// 1. If index is less than −1 or greater than or equal to the number of elements in the rows collection, then throw an "IndexSizeError" DOMException.
|
||||
if (index < -1 || index >= rows_collection_size)
|
||||
return DOM::IndexSizeError::create("Index is negative or greater than or equal to the number of rows");
|
||||
return DOM::IndexSizeError::create(global_object(), "Index is negative or greater than or equal to the number of rows");
|
||||
|
||||
// 2. If index is −1, then remove the last element in the rows collection from this element, or do nothing if the rows collection is empty.
|
||||
if (index == -1) {
|
||||
|
|
|
@ -50,7 +50,7 @@ DOM::ExceptionOr<void> History::shared_history_push_replace_state(JS::Value, Str
|
|||
|
||||
// 2. If document is not fully active, then throw a "SecurityError" DOMException.
|
||||
if (!m_associated_document->is_fully_active())
|
||||
return DOM::SecurityError::create("Cannot perform pushState or replaceState on a document that isn't fully active.");
|
||||
return DOM::SecurityError::create(global_object(), "Cannot perform pushState or replaceState on a document that isn't fully active.");
|
||||
|
||||
// 3. Optionally, return. (For example, the user agent might disallow calls to these methods that are invoked on a timer,
|
||||
// or from event listeners that are not triggered in response to a clear user action, or that are invoked in rapid succession.)
|
||||
|
|
|
@ -17,6 +17,7 @@ JS::NonnullGCPtr<Path2D> Path2D::create_with_global_object(HTML::Window& window,
|
|||
// https://html.spec.whatwg.org/multipage/canvas.html#dom-path2d
|
||||
Path2D::Path2D(HTML::Window& window, Optional<Variant<JS::Handle<Path2D>, String>> const& path)
|
||||
: PlatformObject(window.realm())
|
||||
, CanvasPath(static_cast<Bindings::PlatformObject&>(*this))
|
||||
{
|
||||
set_prototype(&window.cached_web_prototype("Path2D"));
|
||||
|
||||
|
|
|
@ -109,6 +109,7 @@ JS::Completion ClassicScript::run(RethrowErrors rethrow_errors)
|
|||
// 1. Clean up after running script with settings.
|
||||
settings.clean_up_after_running_script();
|
||||
|
||||
dbgln("rethrow");
|
||||
// 2. Rethrow evaluationStatus.[[Value]].
|
||||
return JS::throw_completion(*evaluation_status.value());
|
||||
}
|
||||
|
@ -118,15 +119,17 @@ JS::Completion ClassicScript::run(RethrowErrors rethrow_errors)
|
|||
// 1. Clean up after running script with settings.
|
||||
settings.clean_up_after_running_script();
|
||||
|
||||
dbgln("network error");
|
||||
|
||||
// 2. Throw a "NetworkError" DOMException.
|
||||
return Bindings::throw_dom_exception_if_needed(vm, [] {
|
||||
return DOM::NetworkError::create("Script error.");
|
||||
}).release_error();
|
||||
return throw_completion(DOM::NetworkError::create(settings.global_object(), "Script error."));
|
||||
}
|
||||
|
||||
// 3. Otherwise, rethrow errors is false. Perform the following steps:
|
||||
VERIFY(rethrow_errors == RethrowErrors::No);
|
||||
|
||||
dbgln("no rethrow, stat: {}", evaluation_status.value().value().to_string_without_side_effects());
|
||||
|
||||
// 1. Report the exception given by evaluationStatus.[[Value]] for script.
|
||||
report_exception(evaluation_status);
|
||||
|
||||
|
|
|
@ -1067,11 +1067,8 @@ JS_DEFINE_NATIVE_FUNCTION(Window::btoa)
|
|||
Vector<u8> byte_string;
|
||||
byte_string.ensure_capacity(string.length());
|
||||
for (u32 code_point : Utf8View(string)) {
|
||||
if (code_point > 0xff) {
|
||||
return Bindings::throw_dom_exception_if_needed(vm, [] {
|
||||
return DOM::InvalidCharacterError::create("Data contains characters outside the range U+0000 and U+00FF");
|
||||
}).release_error();
|
||||
}
|
||||
if (code_point > 0xff)
|
||||
return throw_completion(DOM::InvalidCharacterError::create(vm.current_realm()->global_object(), "Data contains characters outside the range U+0000 and U+00FF"));
|
||||
byte_string.append(code_point);
|
||||
}
|
||||
|
||||
|
|
|
@ -65,7 +65,7 @@ DOM::ExceptionOr<JS::NonnullGCPtr<Worker>> Worker::create(FlyString const& scrip
|
|||
// 4. If this fails, throw a "SyntaxError" DOMException.
|
||||
if (!url.is_valid()) {
|
||||
dbgln_if(WEB_WORKER_DEBUG, "WebWorker: Invalid URL loaded '{}'.", script_url);
|
||||
return DOM::SyntaxError::create("url is not valid");
|
||||
return DOM::SyntaxError::create(document.global_object(), "url is not valid");
|
||||
}
|
||||
|
||||
// 5. Let worker URL be the resulting URL record.
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include <LibWeb/Forward.h>
|
||||
#include <LibWeb/HTML/EventHandler.h>
|
||||
#include <LibWeb/HTML/EventNames.h>
|
||||
#include <LibWeb/HTML/Window.h>
|
||||
#include <LibWeb/HTML/WorkerGlobalScope.h>
|
||||
#include <LibWeb/HTML/WorkerLocation.h>
|
||||
#include <LibWeb/HTML/WorkerNavigator.h>
|
||||
|
@ -129,7 +130,7 @@ DOM::ExceptionOr<String> WorkerGlobalScope::btoa(String const& data) const
|
|||
byte_string.ensure_capacity(data.length());
|
||||
for (u32 code_point : Utf8View(data)) {
|
||||
if (code_point > 0xff)
|
||||
return DOM::InvalidCharacterError::create("Data contains characters outside the range U+0000 and U+00FF");
|
||||
return DOM::InvalidCharacterError::create(global_object(), "Data contains characters outside the range U+0000 and U+00FF");
|
||||
byte_string.append(code_point);
|
||||
}
|
||||
|
||||
|
@ -149,7 +150,7 @@ DOM::ExceptionOr<String> WorkerGlobalScope::atob(String const& data) const
|
|||
|
||||
// 2. If decodedData is failure, then throw an "InvalidCharacterError" DOMException.
|
||||
if (decoded_data.is_error())
|
||||
return DOM::InvalidCharacterError::create("Input string is not valid base64 data");
|
||||
return DOM::InvalidCharacterError::create(global_object(), "Input string is not valid base64 data");
|
||||
|
||||
// 3. Return decodedData.
|
||||
// decode_base64() returns a byte string. LibJS uses UTF-8 for strings. Use Latin1Decoder to convert bytes 128-255 to UTF-8.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue