Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LibWeb: Some fixes for constructing customized built-in elements #3426

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 22 additions & 18 deletions Libraries/LibWeb/DOM/ElementFactory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@
#include <LibWeb/HTML/HTMLUnknownElement.h>
#include <LibWeb/HTML/HTMLVideoElement.h>
#include <LibWeb/HTML/Scripting/ExceptionReporter.h>
#include <LibWeb/HTML/WindowOrWorkerGlobalScope.h>
#include <LibWeb/Infra/Strings.h>
#include <LibWeb/MathML/MathMLElement.h>
#include <LibWeb/MathML/TagNames.h>
Expand Down Expand Up @@ -177,6 +178,8 @@ ErrorOr<FixedArray<FlyString>> valid_local_names_for_given_html_element_interfac
return FixedArray<FlyString>::create({ HTML::TagNames::input });
if (html_element_interface_name == "HTMLLabelElement"sv)
return FixedArray<FlyString>::create({ HTML::TagNames::label });
if (html_element_interface_name == "HTMLLegendElement"sv)
return FixedArray<FlyString>::create({ HTML::TagNames::legend });
if (html_element_interface_name == "HTMLLIElement"sv)
return FixedArray<FlyString>::create({ HTML::TagNames::li });
if (html_element_interface_name == "HTMLLinkElement"sv)
Expand All @@ -199,6 +202,8 @@ ErrorOr<FixedArray<FlyString>> valid_local_names_for_given_html_element_interfac
return FixedArray<FlyString>::create({ HTML::TagNames::object });
if (html_element_interface_name == "HTMLOptGroupElement"sv)
return FixedArray<FlyString>::create({ HTML::TagNames::optgroup });
if (html_element_interface_name == "HTMLOptionElement"sv)
return FixedArray<FlyString>::create({ HTML::TagNames::option });
if (html_element_interface_name == "HTMLOutputElement"sv)
return FixedArray<FlyString>::create({ HTML::TagNames::output });
if (html_element_interface_name == "HTMLParagraphElement"sv)
Expand Down Expand Up @@ -231,6 +236,8 @@ ErrorOr<FixedArray<FlyString>> valid_local_names_for_given_html_element_interfac
return FixedArray<FlyString>::create({ HTML::TagNames::td, HTML::TagNames::th });
if (html_element_interface_name == "HTMLTableColElement"sv)
return FixedArray<FlyString>::create({ HTML::TagNames::colgroup, HTML::TagNames::col });
if (html_element_interface_name == "HTMLTableRowElement"sv)
return FixedArray<FlyString>::create({ HTML::TagNames::tr });
if (html_element_interface_name == "HTMLTableElement"sv)
return FixedArray<FlyString>::create({ HTML::TagNames::table });
if (html_element_interface_name == "HTMLTableSectionElement"sv)
Expand Down Expand Up @@ -520,25 +527,20 @@ WebIDL::ExceptionOr<GC::Ref<Element>> create_element(Document& document, FlyStri
{
auto& realm = document.realm();

// 1. If prefix was not given, let prefix be null.
// NOTE: This is already taken care of by `prefix` having a default value.

// 2. If is was not given, let is be null.
// NOTE: This is already taken care of by `is` having a default value.

// 3. Let result be null.
// 1. Let result be null.
// NOTE: We collapse this into just returning an element where necessary.

// 4. Let definition be the result of looking up a custom element definition given document, namespace, localName, and is.
// 2. Let definition be the result of looking up a custom element definition given document, namespace, localName, and is.
auto definition = document.lookup_custom_element_definition(namespace_, local_name, is_value);

// 5. If definition is non-null, and definition’s name is not equal to its local name (i.e., definition represents a customized built-in element), then:
// 3. If definition is non-null, and definition’s name is not equal to its local name (i.e., definition represents a customized built-in element), then:
if (definition && definition->name() != definition->local_name()) {
// 1. Let interface be the element interface for localName and the HTML namespace.
// 2. Set result to a new element that implements interface, with no attributes, namespace set to the HTML namespace,
// namespace prefix set to prefix, local name set to localName, custom element state set to "undefined", custom element definition set to null,
// is value set to is, and node document set to document.
auto element = create_html_element(realm, document, QualifiedName { local_name, prefix, Namespace::HTML });
element->set_is_value(is_value);

// 3. If the synchronous custom elements flag is set, then run this step while catching any exceptions:
if (synchronous_custom_elements_flag) {
Expand All @@ -547,8 +549,9 @@ WebIDL::ExceptionOr<GC::Ref<Element>> create_element(Document& document, FlyStri

// If this step threw an exception, then:
if (upgrade_result.is_throw_completion()) {
// 1. Report the exception.
HTML::report_exception(upgrade_result, realm);
// 1. Report exception for definition’s constructor’s corresponding JavaScript object’s associated realm’s global object.
auto& window_or_worker = as<HTML::WindowOrWorkerGlobalScopeMixin>(HTML::relevant_global_object(definition->constructor().callback));
window_or_worker.report_an_exception(upgrade_result.error_value());

// 2. Set result’s custom element state to "failed".
element->set_custom_element_state(CustomElementState::Failed);
Expand All @@ -563,9 +566,9 @@ WebIDL::ExceptionOr<GC::Ref<Element>> create_element(Document& document, FlyStri
return element;
}

// 6. Otherwise, if definition is non-null, then:
// 4. Otherwise, if definition is non-null, then:
if (definition) {
// 1. If the synchronous custom elements flag is set, then run these steps while catching any exceptions:
// 1. If synchronousCustomElements is true, then run these steps while catching any exceptions:
if (synchronous_custom_elements_flag) {
auto synchronously_upgrade_custom_element = [&]() -> JS::ThrowCompletionOr<GC::Ref<HTML::HTMLElement>> {
// 1. Let C be definition’s constructor.
Expand Down Expand Up @@ -618,8 +621,9 @@ WebIDL::ExceptionOr<GC::Ref<Element>> create_element(Document& document, FlyStri

// If any of these steps threw an exception, then:
if (result.is_throw_completion()) {
// 1. Report the exception.
HTML::report_exception(result, realm);
// 1. Report exception for definition’s constructor’s corresponding JavaScript object’s associated realm’s global object.
auto& window_or_worker = as<HTML::WindowOrWorkerGlobalScopeMixin>(HTML::relevant_global_object(definition->constructor().callback));
window_or_worker.report_an_exception(result.error_value());

// 2. Set result to a new element that implements the HTMLUnknownElement interface, with no attributes, namespace set to the HTML namespace, namespace prefix set to prefix,
// local name set to localName, custom element state set to "failed", custom element definition set to null, is value set to null, and node document set to document.
Expand All @@ -642,7 +646,7 @@ WebIDL::ExceptionOr<GC::Ref<Element>> create_element(Document& document, FlyStri
return element;
}

// 7. Otherwise:
// 5. Otherwise:
// 1. Let interface be the element interface for localName and namespace.
// 2. Set result to a new element that implements interface, with no attributes, namespace set to namespace, namespace prefix set to prefix,
// local name set to localName, custom element state set to "uncustomized", custom element definition set to null, is value set to is,
Expand Down Expand Up @@ -677,8 +681,8 @@ WebIDL::ExceptionOr<GC::Ref<Element>> create_element(Document& document, FlyStri
return element;
}

// 8. Return result.
// NOTE: See step 3.
// 6. Return result.
// NOTE: See step 1.

// https://dom.spec.whatwg.org/#concept-element-interface
// The element interface for any name and namespace is Element, unless stated otherwise.
Expand Down
Loading
Loading