1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-27 02:27:43 +00:00

LibWeb: Make DOMException GC-allocated

This commit is contained in:
Andreas Kling 2022-09-04 16:56:15 +02:00
parent 0e47754ac8
commit 497ead37bc
58 changed files with 307 additions and 278 deletions

View file

@ -4,8 +4,6 @@
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibWeb/Bindings/DOMExceptionWrapper.h>
#include <LibWeb/Bindings/Wrapper.h>
#include <LibWeb/DOM/AbortSignal.h>
#include <LibWeb/DOM/Document.h>
#include <LibWeb/DOM/EventDispatcher.h>
@ -45,7 +43,7 @@ void AbortSignal::signal_abort(JS::Value reason)
if (!reason.is_undefined())
m_abort_reason = reason;
else
m_abort_reason = wrap(realm(), AbortError::create("Aborted without reason"));
m_abort_reason = wrap(realm(), AbortError::create(global_object(), "Aborted without reason"));
// 3. For each algorithm in signals abort algorithms: run algorithm.
for (auto& algorithm : m_abort_algorithms)

View file

@ -38,7 +38,7 @@ ExceptionOr<String> CharacterData::substring_data(size_t offset, size_t count) c
// 2. If offset is greater than length, then throw an "IndexSizeError" DOMException.
if (offset > length)
return DOM::IndexSizeError::create("Substring offset out of range.");
return DOM::IndexSizeError::create(global_object(), "Substring offset out of range.");
// 3. If offset plus count is greater than length, return a string whose value is the code units from the offsetth code unit
// to the end of nodes data, and then return.
@ -57,7 +57,7 @@ ExceptionOr<void> CharacterData::replace_data(size_t offset, size_t count, Strin
// 2. If offset is greater than length, then throw an "IndexSizeError" DOMException.
if (offset > length)
return DOM::IndexSizeError::create("Replacement offset out of range.");
return DOM::IndexSizeError::create(global_object(), "Replacement offset out of range.");
// 3. If offset plus count is greater than length, then set count to length minus offset.
if (offset + count > length)

View file

@ -0,0 +1,34 @@
/*
* Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibWeb/DOM/DOMException.h>
#include <LibWeb/HTML/Window.h>
namespace Web::DOM {
JS::NonnullGCPtr<DOMException> DOMException::create(JS::Object& global_object, FlyString const& name, FlyString const& message)
{
auto& window = verify_cast<HTML::Window>(global_object);
return *window.heap().allocate<DOMException>(window.realm(), window, name, message);
}
JS::NonnullGCPtr<DOMException> DOMException::create_with_global_object(JS::Object& global_object, FlyString const& message, FlyString const& name)
{
auto& window = verify_cast<HTML::Window>(global_object);
return *window.heap().allocate<DOMException>(window.realm(), window, name, message);
}
DOMException::DOMException(HTML::Window& window, FlyString const& name, FlyString const& message)
: PlatformObject(window.realm())
, m_name(name)
, m_message(message)
{
set_prototype(&window.cached_web_prototype("DOMException"));
}
DOMException::~DOMException() = default;
}

View file

@ -7,20 +7,19 @@
#pragma once
#include <AK/FlyString.h>
#include <AK/NonnullRefPtr.h>
#include <AK/RefCounted.h>
#include <LibWeb/Bindings/Wrappable.h>
#include <LibJS/Runtime/VM.h>
#include <LibWeb/Bindings/PlatformObject.h>
namespace Web::DOM {
#define TRY_OR_RETURN_OOM(expression) \
({ \
auto _temporary_result = (expression); \
if (_temporary_result.is_error()) { \
VERIFY(_temporary_result.error().code() == ENOMEM); \
return DOM::UnknownError::create("Out of memory."sv); \
} \
_temporary_result.release_value(); \
#define TRY_OR_RETURN_OOM(global_object, expression) \
({ \
auto _temporary_result = (expression); \
if (_temporary_result.is_error()) { \
VERIFY(_temporary_result.error().code() == ENOMEM); \
return DOM::UnknownError::create(global_object, "Out of memory."sv); \
} \
_temporary_result.release_value(); \
})
// The following have a legacy code value but *don't* produce it as
@ -99,48 +98,52 @@ static u16 get_legacy_code_for_name(FlyString const& name)
}
// https://webidl.spec.whatwg.org/#idl-DOMException
class DOMException final
: public RefCounted<DOMException>
, public Bindings::Wrappable {
public:
using WrapperType = Bindings::DOMExceptionWrapper;
class DOMException final : public Bindings::PlatformObject {
WEB_PLATFORM_OBJECT(DOMException, Bindings::PlatformObject);
static NonnullRefPtr<DOMException> create(FlyString const& name, FlyString const& message)
{
return adopt_ref(*new DOMException(name, message));
}
public:
static JS::NonnullGCPtr<DOMException> create(JS::Object& global_object, FlyString const& name, FlyString const& message);
// JS constructor has message first, name second
static NonnullRefPtr<DOMException> create_with_global_object(HTML::Window&, FlyString const& message, FlyString const& name)
{
return adopt_ref(*new DOMException(name, message));
}
// FIXME: This is a completely pointless footgun, let's use the same order for both factories.
static JS::NonnullGCPtr<DOMException> create_with_global_object(JS::Object& global_object, FlyString const& message, FlyString const& name);
static JS::NonnullGCPtr<DOMException> create(JS::Realm& realm, FlyString const& message);
virtual ~DOMException() override;
FlyString const& name() const { return m_name; }
FlyString const& message() const { return m_message; }
u16 code() const { return get_legacy_code_for_name(m_name); }
protected:
DOMException(FlyString const& name, FlyString const& message)
: m_name(name)
, m_message(message)
{
}
DOMException(HTML::Window&, FlyString const& name, FlyString const& message);
private:
FlyString m_name;
FlyString m_message;
};
#define __ENUMERATE(ErrorName) \
class ErrorName final { \
public: \
static NonnullRefPtr<DOMException> create(FlyString const& message) \
{ \
return DOMException::create(#ErrorName, message); \
} \
#define __ENUMERATE(ErrorName) \
class ErrorName final { \
public: \
static JS::NonnullGCPtr<DOMException> create(JS::Object& global_object, FlyString const& message) \
{ \
return DOMException::create(global_object, #ErrorName, message); \
} \
};
ENUMERATE_DOM_EXCEPTION_ERROR_NAMES
#undef __ENUMERATE
}
WRAPPER_HACK(DOMException, Web::DOM)
namespace Web {
inline JS::Completion throw_completion(JS::NonnullGCPtr<DOM::DOMException> exception)
{
return JS::throw_completion(JS::Value(static_cast<JS::Object*>(exception.ptr())));
}
}

View file

@ -105,7 +105,7 @@ JS::NonnullGCPtr<Document> DOMImplementation::create_html_document(String const&
// https://dom.spec.whatwg.org/#dom-domimplementation-createdocumenttype
ExceptionOr<JS::NonnullGCPtr<DocumentType>> DOMImplementation::create_document_type(String const& qualified_name, String const& public_id, String const& system_id)
{
TRY(Document::validate_qualified_name(qualified_name));
TRY(Document::validate_qualified_name(global_object(), qualified_name));
auto document_type = DocumentType::create(document());
document_type->set_name(qualified_name);
document_type->set_public_id(public_id);

View file

@ -234,9 +234,9 @@ void DOMTokenList::set_value(String value)
ExceptionOr<void> DOMTokenList::validate_token(StringView token) const
{
if (token.is_empty())
return SyntaxError::create("Non-empty DOM tokens are not allowed");
return SyntaxError::create(global_object(), "Non-empty DOM tokens are not allowed");
if (any_of(token, is_ascii_space))
return InvalidCharacterError::create("DOM tokens containing ASCII whitespace are not allowed");
return InvalidCharacterError::create(global_object(), "DOM tokens containing ASCII whitespace are not allowed");
return {};
}

View file

@ -349,11 +349,11 @@ ExceptionOr<void> Document::run_the_document_write_steps(String input)
{
// 1. If document is an XML document, then throw an "InvalidStateError" DOMException.
if (m_type == Type::XML)
return DOM::InvalidStateError::create("write() called on XML document.");
return DOM::InvalidStateError::create(global_object(), "write() called on XML document.");
// 2. If document's throw-on-dynamic-markup-insertion counter is greater than 0, then throw an "InvalidStateError" DOMException.
if (m_throw_on_dynamic_markup_insertion_counter > 0)
return DOM::InvalidStateError::create("throw-on-dynamic-markup-insertion-counter greater than zero.");
return DOM::InvalidStateError::create(global_object(), "throw-on-dynamic-markup-insertion-counter greater than zero.");
// 3. If document's active parser was aborted is true, then return.
if (m_active_parser_was_aborted)
@ -384,18 +384,18 @@ ExceptionOr<Document*> Document::open(String const&, String const&)
{
// 1. If document is an XML document, then throw an "InvalidStateError" DOMException exception.
if (m_type == Type::XML)
return DOM::InvalidStateError::create("open() called on XML document.");
return DOM::InvalidStateError::create(global_object(), "open() called on XML document.");
// 2. If document's throw-on-dynamic-markup-insertion counter is greater than 0, then throw an "InvalidStateError" DOMException.
if (m_throw_on_dynamic_markup_insertion_counter > 0)
return DOM::InvalidStateError::create("throw-on-dynamic-markup-insertion-counter greater than zero.");
return DOM::InvalidStateError::create(global_object(), "throw-on-dynamic-markup-insertion-counter greater than zero.");
// FIXME: 3. Let entryDocument be the entry global object's associated Document.
auto& entry_document = *this;
// 4. If document's origin is not same origin to entryDocument's origin, then throw a "SecurityError" DOMException.
if (origin() != entry_document.origin())
return DOM::SecurityError::create("Document.origin() not the same as entryDocument's.");
return DOM::SecurityError::create(global_object(), "Document.origin() not the same as entryDocument's.");
// 5. If document has an active parser whose script nesting level is greater than 0, then return document.
if (m_parser && m_parser->script_nesting_level() > 0)
@ -455,11 +455,11 @@ ExceptionOr<void> Document::close()
{
// 1. If document is an XML document, then throw an "InvalidStateError" DOMException exception.
if (m_type == Type::XML)
return DOM::InvalidStateError::create("close() called on XML document.");
return DOM::InvalidStateError::create(global_object(), "close() called on XML document.");
// 2. If document's throw-on-dynamic-markup-insertion counter is greater than 0, then throw an "InvalidStateError" DOMException.
if (m_throw_on_dynamic_markup_insertion_counter > 0)
return DOM::InvalidStateError::create("throw-on-dynamic-markup-insertion-counter greater than zero.");
return DOM::InvalidStateError::create(global_object(), "throw-on-dynamic-markup-insertion-counter greater than zero.");
// 3. If there is no script-created parser associated with the document, then return.
if (!m_parser)
@ -563,7 +563,7 @@ HTML::HTMLElement* Document::body()
ExceptionOr<void> Document::set_body(HTML::HTMLElement* new_body)
{
if (!is<HTML::HTMLBodyElement>(new_body) && !is<HTML::HTMLFrameSetElement>(new_body))
return DOM::HierarchyRequestError::create("Invalid document body element, must be 'body' or 'frameset'");
return DOM::HierarchyRequestError::create(global_object(), "Invalid document body element, must be 'body' or 'frameset'");
auto* existing_body = body();
if (existing_body) {
@ -573,7 +573,7 @@ ExceptionOr<void> Document::set_body(HTML::HTMLElement* new_body)
auto* document_element = this->document_element();
if (!document_element)
return DOM::HierarchyRequestError::create("Missing document element");
return DOM::HierarchyRequestError::create(global_object(), "Missing document element");
(void)TRY(document_element->append_child(*new_body));
return {};
@ -1073,7 +1073,7 @@ JS::Value Document::run_javascript(StringView source, StringView filename)
DOM::ExceptionOr<JS::NonnullGCPtr<Element>> Document::create_element(String const& tag_name)
{
if (!is_valid_name(tag_name))
return DOM::InvalidCharacterError::create("Invalid character in tag name.");
return DOM::InvalidCharacterError::create(global_object(), "Invalid character in tag name.");
// FIXME: Let namespace be the HTML namespace, if this is an HTML document or thiss content type is "application/xhtml+xml", and null otherwise.
return DOM::create_element(*this, tag_name, Namespace::HTML);
@ -1085,7 +1085,7 @@ DOM::ExceptionOr<JS::NonnullGCPtr<Element>> Document::create_element(String cons
DOM::ExceptionOr<JS::NonnullGCPtr<Element>> Document::create_element_ns(String const& namespace_, String const& qualified_name)
{
// 1. Let namespace, prefix, and localName be the result of passing namespace and qualifiedName to validate and extract.
auto extracted_qualified_name = TRY(validate_and_extract(namespace_, qualified_name));
auto extracted_qualified_name = TRY(validate_and_extract(global_object(), namespace_, qualified_name));
// FIXME: 2. Let is be null.
// FIXME: 3. If options is a dictionary and options["is"] exists, then set is to it.
@ -1166,7 +1166,7 @@ DOM::ExceptionOr<JS::NonnullGCPtr<Event>> Document::create_event(String const& i
// 3. If constructor is null, then throw a "NotSupportedError" DOMException.
if (!event) {
return DOM::NotSupportedError::create("No constructor for interface found");
return DOM::NotSupportedError::create(global_object(), "No constructor for interface found");
}
// FIXME: 4. If the interface indicated by constructor is not exposed on the relevant global object of this, then throw a "NotSupportedError" DOMException.
@ -1226,7 +1226,7 @@ ExceptionOr<JS::NonnullGCPtr<Node>> Document::import_node(JS::NonnullGCPtr<Node>
{
// 1. If node is a document or shadow root, then throw a "NotSupportedError" DOMException.
if (is<Document>(*node) || is<ShadowRoot>(*node))
return DOM::NotSupportedError::create("Cannot import a document or shadow root.");
return DOM::NotSupportedError::create(global_object(), "Cannot import a document or shadow root.");
// 2. Return a clone of node, with this and the clone children flag set if deep is true.
return node->clone_node(this, deep);
@ -1273,10 +1273,10 @@ void Document::adopt_node(Node& node)
ExceptionOr<JS::NonnullGCPtr<Node>> Document::adopt_node_binding(JS::NonnullGCPtr<Node> node)
{
if (is<Document>(*node))
return DOM::NotSupportedError::create("Cannot adopt a document into a document");
return DOM::NotSupportedError::create(global_object(), "Cannot adopt a document into a document");
if (is<ShadowRoot>(*node))
return DOM::HierarchyRequestError::create("Cannot adopt a shadow root into a document");
return DOM::HierarchyRequestError::create(global_object(), "Cannot adopt a shadow root into a document");
if (is<DocumentFragment>(*node) && verify_cast<DocumentFragment>(*node).host())
return node;
@ -1665,14 +1665,14 @@ bool Document::is_valid_name(String const& name)
}
// https://dom.spec.whatwg.org/#validate
ExceptionOr<Document::PrefixAndTagName> Document::validate_qualified_name(String const& qualified_name)
ExceptionOr<Document::PrefixAndTagName> Document::validate_qualified_name(JS::Object& global_object, String const& qualified_name)
{
if (qualified_name.is_empty())
return InvalidCharacterError::create("Empty string is not a valid qualified name.");
return InvalidCharacterError::create(global_object, "Empty string is not a valid qualified name.");
Utf8View utf8view { qualified_name };
if (!utf8view.validate())
return InvalidCharacterError::create("Invalid qualified name.");
return InvalidCharacterError::create(global_object, "Invalid qualified name.");
Optional<size_t> colon_offset;
@ -1682,19 +1682,19 @@ ExceptionOr<Document::PrefixAndTagName> Document::validate_qualified_name(String
auto code_point = *it;
if (code_point == ':') {
if (colon_offset.has_value())
return InvalidCharacterError::create("More than one colon (:) in qualified name.");
return InvalidCharacterError::create(global_object, "More than one colon (:) in qualified name.");
colon_offset = utf8view.byte_offset_of(it);
at_start_of_name = true;
continue;
}
if (at_start_of_name) {
if (!is_valid_name_start_character(code_point))
return InvalidCharacterError::create("Invalid start of qualified name.");
return InvalidCharacterError::create(global_object, "Invalid start of qualified name.");
at_start_of_name = false;
continue;
}
if (!is_valid_name_character(code_point))
return InvalidCharacterError::create("Invalid character in qualified name.");
return InvalidCharacterError::create(global_object, "Invalid character in qualified name.");
}
if (!colon_offset.has_value())
@ -1704,10 +1704,10 @@ ExceptionOr<Document::PrefixAndTagName> Document::validate_qualified_name(String
};
if (*colon_offset == 0)
return InvalidCharacterError::create("Qualified name can't start with colon (:).");
return InvalidCharacterError::create(global_object, "Qualified name can't start with colon (:).");
if (*colon_offset >= (qualified_name.length() - 1))
return InvalidCharacterError::create("Qualified name can't end with colon (:).");
return InvalidCharacterError::create(global_object, "Qualified name can't end with colon (:).");
return Document::PrefixAndTagName {
.prefix = qualified_name.substring_view(0, *colon_offset),

View file

@ -328,7 +328,7 @@ public:
FlyString prefix;
FlyString tag_name;
};
static ExceptionOr<PrefixAndTagName> validate_qualified_name(String const& qualified_name);
static ExceptionOr<PrefixAndTagName> validate_qualified_name(JS::Object& global_object, String const& qualified_name);
JS::NonnullGCPtr<NodeIterator> create_node_iterator(Node& root, unsigned what_to_show, JS::GCPtr<NodeFilter>);
JS::NonnullGCPtr<TreeWalker> create_tree_walker(Node& root, unsigned what_to_show, JS::GCPtr<NodeFilter>);

View file

@ -87,7 +87,7 @@ ExceptionOr<void> Element::set_attribute(FlyString const& name, String const& va
// 1. If qualifiedName does not match the Name production in XML, then throw an "InvalidCharacterError" DOMException.
// FIXME: Proper name validation
if (name.is_empty())
return InvalidCharacterError::create("Attribute name must not be empty");
return InvalidCharacterError::create(global_object(), "Attribute name must not be empty");
// 2. If this is in the HTML namespace and its node document is an HTML document, then set qualifiedName to qualifiedName in ASCII lowercase.
// FIXME: Handle the second condition, assume it is an HTML document for now.
@ -118,14 +118,14 @@ ExceptionOr<void> Element::set_attribute(FlyString const& name, String const& va
}
// https://dom.spec.whatwg.org/#validate-and-extract
ExceptionOr<QualifiedName> validate_and_extract(FlyString namespace_, FlyString qualified_name)
ExceptionOr<QualifiedName> validate_and_extract(JS::Object& global_object, FlyString namespace_, FlyString qualified_name)
{
// 1. If namespace is the empty string, then set it to null.
if (namespace_.is_empty())
namespace_ = {};
// 2. Validate qualifiedName.
TRY(Document::validate_qualified_name(qualified_name));
TRY(Document::validate_qualified_name(global_object, qualified_name));
// 3. Let prefix be null.
FlyString prefix = {};
@ -142,19 +142,19 @@ ExceptionOr<QualifiedName> validate_and_extract(FlyString namespace_, FlyString
// 6. If prefix is non-null and namespace is null, then throw a "NamespaceError" DOMException.
if (!prefix.is_null() && namespace_.is_null())
return NamespaceError::create("Prefix is non-null and namespace is null.");
return NamespaceError::create(global_object, "Prefix is non-null and namespace is null.");
// 7. If prefix is "xml" and namespace is not the XML namespace, then throw a "NamespaceError" DOMException.
if (prefix == "xml"sv && namespace_ != Namespace::XML)
return NamespaceError::create("Prefix is 'xml' and namespace is not the XML namespace.");
return NamespaceError::create(global_object, "Prefix is 'xml' and namespace is not the XML namespace.");
// 8. If either qualifiedName or prefix is "xmlns" and namespace is not the XMLNS namespace, then throw a "NamespaceError" DOMException.
if ((qualified_name == "xmlns"sv || prefix == "xmlns"sv) && namespace_ != Namespace::XMLNS)
return NamespaceError::create("Either qualifiedName or prefix is 'xmlns' and namespace is not the XMLNS namespace.");
return NamespaceError::create(global_object, "Either qualifiedName or prefix is 'xmlns' and namespace is not the XMLNS namespace.");
// 9. If namespace is the XMLNS namespace and neither qualifiedName nor prefix is "xmlns", then throw a "NamespaceError" DOMException.
if (namespace_ == Namespace::XMLNS && !(qualified_name == "xmlns"sv || prefix == "xmlns"sv))
return NamespaceError::create("Namespace is the XMLNS namespace and neither qualifiedName nor prefix is 'xmlns'.");
return NamespaceError::create(global_object, "Namespace is the XMLNS namespace and neither qualifiedName nor prefix is 'xmlns'.");
// 10. Return namespace, prefix, and localName.
return QualifiedName { local_name, prefix, namespace_ };
@ -164,7 +164,7 @@ ExceptionOr<QualifiedName> validate_and_extract(FlyString namespace_, FlyString
ExceptionOr<void> Element::set_attribute_ns(FlyString const& namespace_, FlyString const& qualified_name, String const& value)
{
// 1. Let namespace, prefix, and localName be the result of passing namespace and qualifiedName to validate and extract.
auto extracted_qualified_name = TRY(validate_and_extract(namespace_, qualified_name));
auto extracted_qualified_name = TRY(validate_and_extract(global_object(), namespace_, qualified_name));
// FIXME: 2. Set an attribute value for this using localName, value, and also prefix and namespace.
@ -195,7 +195,7 @@ DOM::ExceptionOr<bool> Element::toggle_attribute(FlyString const& name, Optional
// 1. If qualifiedName does not match the Name production in XML, then throw an "InvalidCharacterError" DOMException.
// FIXME: Proper name validation
if (name.is_empty())
return InvalidCharacterError::create("Attribute name must not be empty");
return InvalidCharacterError::create(global_object(), "Attribute name must not be empty");
// 2. If this is in the HTML namespace and its node document is an HTML document, then set qualifiedName to qualifiedName in ASCII lowercase.
// FIXME: Handle the second condition, assume it is an HTML document for now.
@ -439,7 +439,7 @@ DOM::ExceptionOr<bool> Element::matches(StringView selectors) const
{
auto maybe_selectors = parse_selector(CSS::Parser::ParsingContext(static_cast<ParentNode&>(const_cast<Element&>(*this))), selectors);
if (!maybe_selectors.has_value())
return DOM::SyntaxError::create("Failed to parse selector");
return DOM::SyntaxError::create(global_object(), "Failed to parse selector");
auto sel = maybe_selectors.value();
for (auto& s : sel) {
@ -454,7 +454,7 @@ DOM::ExceptionOr<DOM::Element const*> Element::closest(StringView selectors) con
{
auto maybe_selectors = parse_selector(CSS::Parser::ParsingContext(static_cast<ParentNode&>(const_cast<Element&>(*this))), selectors);
if (!maybe_selectors.has_value())
return DOM::SyntaxError::create("Failed to parse selector");
return DOM::SyntaxError::create(global_object(), "Failed to parse selector");
auto matches_selectors = [](CSS::SelectorList const& selector_list, Element const* element) {
for (auto& selector : selector_list) {

View file

@ -170,7 +170,7 @@ private:
template<>
inline bool Node::fast_is<Element>() const { return is_element(); }
ExceptionOr<QualifiedName> validate_and_extract(FlyString namespace_, FlyString qualified_name);
ExceptionOr<QualifiedName> validate_and_extract(JS::Object& global_object, FlyString namespace_, FlyString qualified_name);
}

View file

@ -228,10 +228,10 @@ ExceptionOr<bool> EventTarget::dispatch_event_binding(Event& event)
{
// 1. If events dispatch flag is set, or if its initialized flag is not set, then throw an "InvalidStateError" DOMException.
if (event.dispatched())
return DOM::InvalidStateError::create("The event is already being dispatched.");
return DOM::InvalidStateError::create(global_object(), "The event is already being dispatched.");
if (!event.initialized())
return DOM::InvalidStateError::create("Cannot dispatch an uninitialized event.");
return DOM::InvalidStateError::create(global_object(), "Cannot dispatch an uninitialized event.");
// 2. Initialize events isTrusted attribute to false.
event.set_is_trusted(false);

View file

@ -49,7 +49,7 @@ public:
{
}
ExceptionOr(NonnullRefPtr<DOMException> exception)
ExceptionOr(JS::NonnullGCPtr<DOMException> exception)
: m_exception(move(exception))
{
}
@ -59,8 +59,8 @@ public:
{
}
ExceptionOr(Variant<SimpleException, NonnullRefPtr<DOMException>> exception)
: m_exception(move(exception).template downcast<Empty, SimpleException, NonnullRefPtr<DOMException>>())
ExceptionOr(Variant<SimpleException, JS::NonnullGCPtr<DOMException>> exception)
: m_exception(move(exception).template downcast<Empty, SimpleException, JS::NonnullGCPtr<DOMException>>())
{
}
@ -78,9 +78,9 @@ public:
return m_result.release_value();
}
Variant<SimpleException, NonnullRefPtr<DOMException>> exception() const
Variant<SimpleException, JS::NonnullGCPtr<DOMException>> exception() const
{
return m_exception.template downcast<SimpleException, NonnullRefPtr<DOMException>>();
return m_exception.template downcast<SimpleException, JS::NonnullGCPtr<DOMException>>();
}
bool is_exception() const
@ -90,12 +90,12 @@ public:
// These are for compatibility with the TRY() macro in AK.
[[nodiscard]] bool is_error() const { return is_exception(); }
Variant<SimpleException, NonnullRefPtr<DOMException>> release_error() { return exception(); }
Variant<SimpleException, JS::NonnullGCPtr<DOMException>> release_error() { return exception(); }
private:
Optional<ValueType> m_result;
// https://webidl.spec.whatwg.org/#idl-exceptions
Variant<Empty, SimpleException, NonnullRefPtr<DOMException>> m_exception {};
Variant<Empty, SimpleException, JS::NonnullGCPtr<DOMException>> m_exception {};
};
template<>

View file

@ -93,7 +93,7 @@ ExceptionOr<Attribute const*> NamedNodeMap::remove_named_item(StringView qualifi
// 2. If attr is null, then throw a "NotFoundError" DOMException.
if (!attribute)
return NotFoundError::create(String::formatted("Attribute with name '{}' not found", qualified_name));
return NotFoundError::create(global_object(), String::formatted("Attribute with name '{}' not found", qualified_name));
// 3. Return attr.
return nullptr;
@ -137,7 +137,7 @@ ExceptionOr<Attribute const*> NamedNodeMap::set_attribute(Attribute& attribute)
{
// 1. If attrs element is neither null nor element, throw an "InUseAttributeError" DOMException.
if ((attribute.owner_element() != nullptr) && (attribute.owner_element() != &associated_element()))
return InUseAttributeError::create("Attribute must not already be in use"sv);
return InUseAttributeError::create(global_object(), "Attribute must not already be in use"sv);
// 2. Let oldAttr be the result of getting an attribute given attrs namespace, attrs local name, and element.
// FIXME: When getNamedItemNS is implemented, use that instead.

View file

@ -310,24 +310,24 @@ ExceptionOr<void> Node::ensure_pre_insertion_validity(JS::NonnullGCPtr<Node> nod
{
// 1. If parent is not a Document, DocumentFragment, or Element node, then throw a "HierarchyRequestError" DOMException.
if (!is<Document>(this) && !is<DocumentFragment>(this) && !is<Element>(this))
return DOM::HierarchyRequestError::create("Can only insert into a document, document fragment or element");
return DOM::HierarchyRequestError::create(global_object(), "Can only insert into a document, document fragment or element");
// 2. If node is a host-including inclusive ancestor of parent, then throw a "HierarchyRequestError" DOMException.
if (node->is_host_including_inclusive_ancestor_of(*this))
return DOM::HierarchyRequestError::create("New node is an ancestor of this node");
return DOM::HierarchyRequestError::create(global_object(), "New node is an ancestor of this node");
// 3. If child is non-null and its parent is not parent, then throw a "NotFoundError" DOMException.
if (child && child->parent() != this)
return DOM::NotFoundError::create("This node is not the parent of the given child");
return DOM::NotFoundError::create(global_object(), "This node is not the parent of the given child");
// FIXME: All the following "Invalid node type for insertion" messages could be more descriptive.
// 4. If node is not a DocumentFragment, DocumentType, Element, or CharacterData node, then throw a "HierarchyRequestError" DOMException.
if (!is<DocumentFragment>(*node) && !is<DocumentType>(*node) && !is<Element>(*node) && !is<Text>(*node) && !is<Comment>(*node) && !is<ProcessingInstruction>(*node))
return DOM::HierarchyRequestError::create("Invalid node type for insertion");
return DOM::HierarchyRequestError::create(global_object(), "Invalid node type for insertion");
// 5. If either node is a Text node and parent is a document, or node is a doctype and parent is not a document, then throw a "HierarchyRequestError" DOMException.
if ((is<Text>(*node) && is<Document>(this)) || (is<DocumentType>(*node) && !is<Document>(this)))
return DOM::HierarchyRequestError::create("Invalid node type for insertion");
return DOM::HierarchyRequestError::create(global_object(), "Invalid node type for insertion");
// 6. If parent is a document, and any of the statements below, switched on the interface node implements, are true, then throw a "HierarchyRequestError" DOMException.
if (is<Document>(this)) {
@ -338,18 +338,18 @@ ExceptionOr<void> Node::ensure_pre_insertion_validity(JS::NonnullGCPtr<Node> nod
auto node_element_child_count = verify_cast<DocumentFragment>(*node).child_element_count();
if ((node_element_child_count > 1 || node->has_child_of_type<Text>())
|| (node_element_child_count == 1 && (has_child_of_type<Element>() || is<DocumentType>(child.ptr()) || (child && child->has_following_node_of_type_in_tree_order<DocumentType>())))) {
return DOM::HierarchyRequestError::create("Invalid node type for insertion");
return DOM::HierarchyRequestError::create(global_object(), "Invalid node type for insertion");
}
} else if (is<Element>(*node)) {
// Element
// If parent has an element child, child is a doctype, or child is non-null and a doctype is following child.
if (has_child_of_type<Element>() || is<DocumentType>(child.ptr()) || (child && child->has_following_node_of_type_in_tree_order<DocumentType>()))
return DOM::HierarchyRequestError::create("Invalid node type for insertion");
return DOM::HierarchyRequestError::create(global_object(), "Invalid node type for insertion");
} else if (is<DocumentType>(*node)) {
// DocumentType
// parent has a doctype child, child is non-null and an element is preceding child, or child is null and parent has an element child.
if (has_child_of_type<DocumentType>() || (child && child->has_preceding_node_of_type_in_tree_order<Element>()) || (!child && has_child_of_type<Element>()))
return DOM::HierarchyRequestError::create("Invalid node type for insertion");
return DOM::HierarchyRequestError::create(global_object(), "Invalid node type for insertion");
}
}
@ -482,7 +482,7 @@ ExceptionOr<JS::NonnullGCPtr<Node>> Node::pre_remove(JS::NonnullGCPtr<Node> chil
{
// 1. If childs parent is not parent, then throw a "NotFoundError" DOMException.
if (child->parent() != this)
return DOM::NotFoundError::create("Child does not belong to this node");
return DOM::NotFoundError::create(global_object(), "Child does not belong to this node");
// 2. Remove child.
child->remove();
@ -607,25 +607,25 @@ ExceptionOr<JS::NonnullGCPtr<Node>> Node::replace_child(JS::NonnullGCPtr<Node> n
{
// If parent is not a Document, DocumentFragment, or Element node, then throw a "HierarchyRequestError" DOMException.
if (!is<Document>(this) && !is<DocumentFragment>(this) && !is<Element>(this))
return DOM::HierarchyRequestError::create("Can only insert into a document, document fragment or element");
return DOM::HierarchyRequestError::create(global_object(), "Can only insert into a document, document fragment or element");
// 2. If node is a host-including inclusive ancestor of parent, then throw a "HierarchyRequestError" DOMException.
if (node->is_host_including_inclusive_ancestor_of(*this))
return DOM::HierarchyRequestError::create("New node is an ancestor of this node");
return DOM::HierarchyRequestError::create(global_object(), "New node is an ancestor of this node");
// 3. If childs parent is not parent, then throw a "NotFoundError" DOMException.
if (child->parent() != this)
return DOM::NotFoundError::create("This node is not the parent of the given child");
return DOM::NotFoundError::create(global_object(), "This node is not the parent of the given child");
// FIXME: All the following "Invalid node type for insertion" messages could be more descriptive.
// 4. If node is not a DocumentFragment, DocumentType, Element, or CharacterData node, then throw a "HierarchyRequestError" DOMException.
if (!is<DocumentFragment>(*node) && !is<DocumentType>(*node) && !is<Element>(*node) && !is<Text>(*node) && !is<Comment>(*node) && !is<ProcessingInstruction>(*node))
return DOM::HierarchyRequestError::create("Invalid node type for insertion");
return DOM::HierarchyRequestError::create(global_object(), "Invalid node type for insertion");
// 5. If either node is a Text node and parent is a document, or node is a doctype and parent is not a document, then throw a "HierarchyRequestError" DOMException.
if ((is<Text>(*node) && is<Document>(this)) || (is<DocumentType>(*node) && !is<Document>(this)))
return DOM::HierarchyRequestError::create("Invalid node type for insertion");
return DOM::HierarchyRequestError::create(global_object(), "Invalid node type for insertion");
// If parent is a document, and any of the statements below, switched on the interface node implements, are true, then throw a "HierarchyRequestError" DOMException.
if (is<Document>(this)) {
@ -636,18 +636,18 @@ ExceptionOr<JS::NonnullGCPtr<Node>> Node::replace_child(JS::NonnullGCPtr<Node> n
auto node_element_child_count = verify_cast<DocumentFragment>(*node).child_element_count();
if ((node_element_child_count > 1 || node->has_child_of_type<Text>())
|| (node_element_child_count == 1 && (first_child_of_type<Element>() != child || child->has_following_node_of_type_in_tree_order<DocumentType>()))) {
return DOM::HierarchyRequestError::create("Invalid node type for insertion");
return DOM::HierarchyRequestError::create(global_object(), "Invalid node type for insertion");
}
} else if (is<Element>(*node)) {
// Element
// parent has an element child that is not child or a doctype is following child.
if (first_child_of_type<Element>() != child || child->has_following_node_of_type_in_tree_order<DocumentType>())
return DOM::HierarchyRequestError::create("Invalid node type for insertion");
return DOM::HierarchyRequestError::create(global_object(), "Invalid node type for insertion");
} else if (is<DocumentType>(*node)) {
// DocumentType
// parent has a doctype child that is not child, or an element is preceding child.
if (first_child_of_type<DocumentType>() != node || child->has_preceding_node_of_type_in_tree_order<Element>())
return DOM::HierarchyRequestError::create("Invalid node type for insertion");
return DOM::HierarchyRequestError::create(global_object(), "Invalid node type for insertion");
}
}
@ -791,7 +791,7 @@ ExceptionOr<JS::NonnullGCPtr<Node>> Node::clone_node_binding(bool deep)
{
// 1. If this is a shadow root, then throw a "NotSupportedError" DOMException.
if (is<ShadowRoot>(*this))
return NotSupportedError::create("Cannot clone shadow root");
return NotSupportedError::create(global_object(), "Cannot clone shadow root");
// 2. Return a clone of this, with the clone children flag set if deep is true.
return clone_node(nullptr, deep);

View file

@ -4,6 +4,7 @@
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibJS/Runtime/Realm.h>
#include <LibWeb/DOM/NodeFilter.h>
#include <LibWeb/HTML/Window.h>

View file

@ -4,7 +4,6 @@
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibWeb/Bindings/DOMExceptionWrapper.h>
#include <LibWeb/Bindings/IDLAbstractOperations.h>
#include <LibWeb/DOM/Document.h>
#include <LibWeb/DOM/Node.h>
@ -131,7 +130,7 @@ JS::ThrowCompletionOr<NodeFilter::Result> NodeIterator::filter(Node& node)
{
// 1. If traversers active flag is set, then throw an "InvalidStateError" DOMException.
if (m_active)
return JS::throw_completion(wrap(shape().realm(), InvalidStateError::create("NodeIterator is already active")));
return JS::throw_completion(wrap(shape().realm(), InvalidStateError::create(global_object(), "NodeIterator is already active")));
// 2. Let n be nodes nodeType attribute value 1.
auto n = node.node_type() - 1;

View file

@ -11,6 +11,7 @@
#include <LibWeb/DOM/ParentNode.h>
#include <LibWeb/DOM/StaticNodeList.h>
#include <LibWeb/Dump.h>
#include <LibWeb/HTML/Window.h>
#include <LibWeb/Namespace.h>
namespace Web::DOM {
@ -19,7 +20,7 @@ ExceptionOr<JS::GCPtr<Element>> ParentNode::query_selector(StringView selector_t
{
auto maybe_selectors = parse_selector(CSS::Parser::ParsingContext(*this), selector_text);
if (!maybe_selectors.has_value())
return DOM::SyntaxError::create("Failed to parse selector");
return DOM::SyntaxError::create(global_object(), "Failed to parse selector");
auto selectors = maybe_selectors.value();
@ -42,7 +43,7 @@ ExceptionOr<JS::NonnullGCPtr<NodeList>> ParentNode::query_selector_all(StringVie
{
auto maybe_selectors = parse_selector(CSS::Parser::ParsingContext(*this), selector_text);
if (!maybe_selectors.has_value())
return DOM::SyntaxError::create("Failed to parse selector");
return DOM::SyntaxError::create(global_object(), "Failed to parse selector");
auto selectors = maybe_selectors.value();

View file

@ -137,11 +137,11 @@ ExceptionOr<void> Range::set_start_or_end(Node& node, u32 offset, StartOrEnd sta
// 1. If node is a doctype, then throw an "InvalidNodeTypeError" DOMException.
if (is<DocumentType>(node))
return InvalidNodeTypeError::create("Node cannot be a DocumentType.");
return InvalidNodeTypeError::create(global_object(), "Node cannot be a DocumentType.");
// 2. If offset is greater than nodes length, then throw an "IndexSizeError" DOMException.
if (offset > node.length())
return IndexSizeError::create(String::formatted("Node does not contain a child at offset {}", offset));
return IndexSizeError::create(global_object(), String::formatted("Node does not contain a child at offset {}", offset));
// 3. Let bp be the boundary point (node, offset).
@ -196,7 +196,7 @@ ExceptionOr<void> Range::set_start_before(Node& node)
// 2. If parent is null, then throw an "InvalidNodeTypeError" DOMException.
if (!parent)
return InvalidNodeTypeError::create("Given node has no parent.");
return InvalidNodeTypeError::create(global_object(), "Given node has no parent.");
// 3. Set the start of this to boundary point (parent, nodes index).
return set_start_or_end(*parent, node.index(), StartOrEnd::Start);
@ -210,7 +210,7 @@ ExceptionOr<void> Range::set_start_after(Node& node)
// 2. If parent is null, then throw an "InvalidNodeTypeError" DOMException.
if (!parent)
return InvalidNodeTypeError::create("Given node has no parent.");
return InvalidNodeTypeError::create(global_object(), "Given node has no parent.");
// 3. Set the start of this to boundary point (parent, nodes index plus 1).
return set_start_or_end(*parent, node.index() + 1, StartOrEnd::Start);
@ -224,7 +224,7 @@ ExceptionOr<void> Range::set_end_before(Node& node)
// 2. If parent is null, then throw an "InvalidNodeTypeError" DOMException.
if (!parent)
return InvalidNodeTypeError::create("Given node has no parent.");
return InvalidNodeTypeError::create(global_object(), "Given node has no parent.");
// 3. Set the end of this to boundary point (parent, nodes index).
return set_start_or_end(*parent, node.index(), StartOrEnd::End);
@ -238,7 +238,7 @@ ExceptionOr<void> Range::set_end_after(Node& node)
// 2. If parent is null, then throw an "InvalidNodeTypeError" DOMException.
if (!parent)
return InvalidNodeTypeError::create("Given node has no parent.");
return InvalidNodeTypeError::create(global_object(), "Given node has no parent.");
// 3. Set the end of this to boundary point (parent, nodes index plus 1).
return set_start_or_end(*parent, node.index() + 1, StartOrEnd::End);
@ -254,11 +254,11 @@ ExceptionOr<i16> Range::compare_boundary_points(u16 how, Range const& source_ran
// - END_TO_START,
// then throw a "NotSupportedError" DOMException.
if (how != HowToCompareBoundaryPoints::START_TO_START && how != HowToCompareBoundaryPoints::START_TO_END && how != HowToCompareBoundaryPoints::END_TO_END && how != HowToCompareBoundaryPoints::END_TO_START)
return NotSupportedError::create(String::formatted("Expected 'how' to be one of START_TO_START (0), START_TO_END (1), END_TO_END (2) or END_TO_START (3), got {}", how));
return NotSupportedError::create(global_object(), String::formatted("Expected 'how' to be one of START_TO_START (0), START_TO_END (1), END_TO_END (2) or END_TO_START (3), got {}", how));
// 2. If thiss root is not the same as sourceRanges root, then throw a "WrongDocumentError" DOMException.
if (&root() != &source_range.root())
return WrongDocumentError::create("This range is not in the same tree as the source range.");
return WrongDocumentError::create(global_object(), "This range is not in the same tree as the source range.");
JS::GCPtr<Node> this_point_node;
u32 this_point_offset = 0;
@ -339,7 +339,7 @@ ExceptionOr<void> Range::select(Node& node)
// 2. If parent is null, then throw an "InvalidNodeTypeError" DOMException.
if (!parent)
return InvalidNodeTypeError::create("Given node has no parent.");
return InvalidNodeTypeError::create(global_object(), "Given node has no parent.");
// 3. Let index be nodes index.
auto index = node.index();
@ -381,7 +381,7 @@ ExceptionOr<void> Range::select_node_contents(Node const& node)
{
// 1. If node is a doctype, throw an "InvalidNodeTypeError" DOMException.
if (is<DocumentType>(node))
return InvalidNodeTypeError::create("Node cannot be a DocumentType.");
return InvalidNodeTypeError::create(global_object(), "Node cannot be a DocumentType.");
// 2. Let length be the length of node.
auto length = node.length();
@ -474,11 +474,11 @@ ExceptionOr<bool> Range::is_point_in_range(Node const& node, u32 offset) const
// 2. If node is a doctype, then throw an "InvalidNodeTypeError" DOMException.
if (is<DocumentType>(node))
return InvalidNodeTypeError::create("Node cannot be a DocumentType.");
return InvalidNodeTypeError::create(global_object(), "Node cannot be a DocumentType.");
// 3. If offset is greater than nodes length, then throw an "IndexSizeError" DOMException.
if (offset > node.length())
return IndexSizeError::create(String::formatted("Node does not contain a child at offset {}", offset));
return IndexSizeError::create(global_object(), String::formatted("Node does not contain a child at offset {}", offset));
// 4. If (node, offset) is before start or after end, return false.
auto relative_position_to_start = position_of_boundary_point_relative_to_other_boundary_point(node, offset, m_start_container, m_start_offset);
@ -495,15 +495,15 @@ ExceptionOr<i16> Range::compare_point(Node const& node, u32 offset) const
{
// 1. If nodes root is different from thiss root, then throw a "WrongDocumentError" DOMException.
if (&node.root() != &root())
return WrongDocumentError::create("Given node is not in the same document as the range.");
return WrongDocumentError::create(global_object(), "Given node is not in the same document as the range.");
// 2. If node is a doctype, then throw an "InvalidNodeTypeError" DOMException.
if (is<DocumentType>(node))
return InvalidNodeTypeError::create("Node cannot be a DocumentType.");
return InvalidNodeTypeError::create(global_object(), "Node cannot be a DocumentType.");
// 3. If offset is greater than nodes length, then throw an "IndexSizeError" DOMException.
if (offset > node.length())
return IndexSizeError::create(String::formatted("Node does not contain a child at offset {}", offset));
return IndexSizeError::create(global_object(), String::formatted("Node does not contain a child at offset {}", offset));
// 4. If (node, offset) is before start, return 1.
auto relative_position_to_start = position_of_boundary_point_relative_to_other_boundary_point(node, offset, m_start_container, m_start_offset);
@ -636,7 +636,7 @@ ExceptionOr<JS::NonnullGCPtr<DocumentFragment>> Range::extract()
// 12. If any member of contained children is a doctype, then throw a "HierarchyRequestError" DOMException.
for (auto const& child : contained_children) {
if (is<DocumentType>(*child))
return DOM::HierarchyRequestError::create("Contained child is a DocumentType");
return DOM::HierarchyRequestError::create(global_object(), "Contained child is a DocumentType");
}
JS::GCPtr<Node> new_node;
@ -783,7 +783,7 @@ ExceptionOr<void> Range::insert(JS::NonnullGCPtr<Node> node)
if ((is<ProcessingInstruction>(*m_start_container) || is<Comment>(*m_start_container))
|| (is<Text>(*m_start_container) && !m_start_container->parent_node())
|| m_start_container.ptr() == node.ptr()) {
return DOM::HierarchyRequestError::create("Range has inappropriate start node for insertion");
return DOM::HierarchyRequestError::create(global_object(), "Range has inappropriate start node for insertion");
}
// 2. Let referenceNode be null.
@ -854,11 +854,11 @@ ExceptionOr<void> Range::surround_contents(JS::NonnullGCPtr<Node> new_parent)
if (is<Text>(*end_non_text_node))
end_non_text_node = end_non_text_node->parent_node();
if (start_non_text_node != end_non_text_node)
return InvalidStateError::create("Non-Text node is partially contained in range.");
return InvalidStateError::create(global_object(), "Non-Text node is partially contained in range.");
// 2. If newParent is a Document, DocumentType, or DocumentFragment node, then throw an "InvalidNodeTypeError" DOMException.
if (is<Document>(*new_parent) || is<DocumentType>(*new_parent) || is<DocumentFragment>(*new_parent))
return InvalidNodeTypeError::create("Invalid parent node type");
return InvalidNodeTypeError::create(global_object(), "Invalid parent node type");
// 3. Let fragment be the result of extracting this.
auto fragment = TRY(extract());
@ -962,7 +962,7 @@ ExceptionOr<JS::NonnullGCPtr<DocumentFragment>> Range::clone_the_contents()
// 12. If any member of contained children is a doctype, then throw a "HierarchyRequestError" DOMException.
for (auto const& child : contained_children) {
if (is<DocumentType>(*child))
return DOM::HierarchyRequestError::create("Contained child is a DocumentType");
return DOM::HierarchyRequestError::create(global_object(), "Contained child is a DocumentType");
}
// 13. If first partially contained child is a CharacterData node, then:

View file

@ -23,17 +23,17 @@ StaticRange::StaticRange(Node& start_container, u32 start_offset, Node& end_cont
StaticRange::~StaticRange() = default;
// https://dom.spec.whatwg.org/#dom-staticrange-staticrange
ExceptionOr<StaticRange*> StaticRange::create_with_global_object(HTML::Window& window_object, StaticRangeInit& init)
ExceptionOr<StaticRange*> StaticRange::create_with_global_object(HTML::Window& window, StaticRangeInit& init)
{
// 1. If init["startContainer"] or init["endContainer"] is a DocumentType or Attr node, then throw an "InvalidNodeTypeError" DOMException.
if (is<DocumentType>(*init.start_container) || is<Attribute>(*init.start_container))
return DOM::InvalidNodeTypeError::create("startContainer cannot be a DocumentType or Attribute node.");
return DOM::InvalidNodeTypeError::create(window, "startContainer cannot be a DocumentType or Attribute node.");
if (is<DocumentType>(*init.end_container) || is<Attribute>(*init.end_container))
return DOM::InvalidNodeTypeError::create("endContainer cannot be a DocumentType or Attribute node.");
return DOM::InvalidNodeTypeError::create(window, "endContainer cannot be a DocumentType or Attribute node.");
// 2. Set thiss start to (init["startContainer"], init["startOffset"]) and end to (init["endContainer"], init["endOffset"]).
return window_object.heap().allocate<StaticRange>(window_object.realm(), *init.start_container, init.start_offset, *init.end_container, init.end_offset);
return window.heap().allocate<StaticRange>(window.realm(), *init.start_container, init.start_offset, *init.end_container, init.end_offset);
}
}

View file

@ -50,7 +50,7 @@ ExceptionOr<JS::NonnullGCPtr<Text>> Text::split_text(size_t offset)
// 2. If offset is greater than length, then throw an "IndexSizeError" DOMException.
if (offset > length)
return DOM::IndexSizeError::create("Split offset is greater than length");
return DOM::IndexSizeError::create(global_object(), "Split offset is greater than length");
// 3. Let count be length minus offset.
auto count = length - offset;

View file

@ -4,9 +4,7 @@
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibWeb/Bindings/DOMExceptionWrapper.h>
#include <LibWeb/Bindings/IDLAbstractOperations.h>
#include <LibWeb/Bindings/Wrapper.h>
#include <LibWeb/DOM/DOMException.h>
#include <LibWeb/DOM/Document.h>
#include <LibWeb/DOM/Node.h>
@ -233,7 +231,7 @@ JS::ThrowCompletionOr<NodeFilter::Result> TreeWalker::filter(Node& node)
{
// 1. If traversers active flag is set, then throw an "InvalidStateError" DOMException.
if (m_active)
return JS::throw_completion(wrap(shape().realm(), InvalidStateError::create("NodeIterator is already active")));
return JS::throw_completion(wrap(shape().realm(), InvalidStateError::create(global_object(), "NodeIterator is already active")));
// 2. Let n be nodes nodeType attribute value 1.
auto n = node.node_type() - 1;