LibWeb: Use right interface for custom SVG and MathML elements

The DOM spec gets overridden by both the SVG2 and MathML core specs in
that unknown elements should not inherit DOM::Element, but
SVG::SVGElement and MathML::MathMLElement respectively.
This commit is contained in:
Jelle Raaijmakers 2024-10-31 10:35:07 +01:00 committed by Tim Ledbetter
parent 84fe8d675b
commit 76e638b4ca
Notes: github-actions[bot] 2024-10-31 09:59:53 +00:00
3 changed files with 34 additions and 17 deletions

View file

@ -0,0 +1,3 @@
Element nodeName: FOO namespaceURI: http://www.w3.org/1999/xhtml __proto__: [object HTMLUnknownElement]
Element nodeName: foo namespaceURI: http://www.w3.org/2000/svg __proto__: [object SVGElement]
Element nodeName: foo namespaceURI: http://www.w3.org/1998/Math/MathML __proto__: [object MathMLElement]

View file

@ -0,0 +1,13 @@
<!doctype html>
<script src="../include.js"></script>
<script>
test(() => {
const printElement = (element) => {
println(`Element nodeName: ${element.nodeName} namespaceURI: ${element.namespaceURI} __proto__: ${element.__proto__}`);
};
printElement(document.createElementNS('http://www.w3.org/1999/xhtml', 'foo'));
printElement(document.createElementNS('http://www.w3.org/2000/svg', 'foo'));
printElement(document.createElementNS('http://www.w3.org/1998/Math/MathML', 'foo'));
});
</script>

View file

@ -430,7 +430,7 @@ static JS::NonnullGCPtr<Element> create_html_element(JS::Realm& realm, Document&
return realm.heap().allocate<HTML::HTMLUnknownElement>(realm, document, move(qualified_name));
}
static JS::GCPtr<SVG::SVGElement> create_svg_element(JS::Realm& realm, Document& document, QualifiedName qualified_name)
static JS::NonnullGCPtr<SVG::SVGElement> create_svg_element(JS::Realm& realm, Document& document, QualifiedName qualified_name)
{
auto const& local_name = qualified_name.local_name();
@ -492,17 +492,22 @@ static JS::GCPtr<SVG::SVGElement> create_svg_element(JS::Realm& realm, Document&
if (local_name == SVG::TagNames::image)
return realm.heap().allocate<SVG::SVGImageElement>(realm, document, move(qualified_name));
return nullptr;
// https://svgwg.org/svg2-draft/types.html#ElementsInTheSVGDOM
// Elements in the SVG namespace whose local name does not match an element defined in any
// specification supported by the software must nonetheless implement the SVGElement interface.
return realm.heap().allocate<SVG::SVGElement>(realm, document, move(qualified_name));
}
static JS::GCPtr<MathML::MathMLElement> create_mathml_element(JS::Realm& realm, Document& document, QualifiedName qualified_name)
static JS::NonnullGCPtr<MathML::MathMLElement> create_mathml_element(JS::Realm& realm, Document& document, QualifiedName qualified_name)
{
auto const& local_name = qualified_name.local_name();
// https://w3c.github.io/mathml-core/#dom-and-javascript
// All the nodes representing MathML elements in the DOM must implement, and expose to scripts,
// the following MathMLElement interface.
// https://w3c.github.io/mathml-core/#mathml-elements-and-attributes
// The term MathML element refers to any element in the MathML namespace.
if (local_name.is_one_of(MathML::TagNames::annotation, MathML::TagNames::annotation_xml, MathML::TagNames::maction, MathML::TagNames::math, MathML::TagNames::merror, MathML::TagNames::mfrac, MathML::TagNames::mi, MathML::TagNames::mmultiscripts, MathML::TagNames::mn, MathML::TagNames::mo, MathML::TagNames::mover, MathML::TagNames::mpadded, MathML::TagNames::mphantom, MathML::TagNames::mprescripts, MathML::TagNames::mroot, MathML::TagNames::mrow, MathML::TagNames::ms, MathML::TagNames::mspace, MathML::TagNames::msqrt, MathML::TagNames::mstyle, MathML::TagNames::msub, MathML::TagNames::msubsup, MathML::TagNames::msup, MathML::TagNames::mtable, MathML::TagNames::mtd, MathML::TagNames::mtext, MathML::TagNames::mtr, MathML::TagNames::munder, MathML::TagNames::munderover, MathML::TagNames::semantics))
return realm.heap().allocate<MathML::MathMLElement>(realm, document, move(qualified_name));
return nullptr;
}
// https://dom.spec.whatwg.org/#concept-create-element
WebIDL::ExceptionOr<JS::NonnullGCPtr<Element>> create_element(Document& document, FlyString local_name, Optional<FlyString> namespace_, Optional<FlyString> prefix, Optional<String> is_value, bool synchronous_custom_elements_flag)
@ -654,20 +659,16 @@ WebIDL::ExceptionOr<JS::NonnullGCPtr<Element>> create_element(Document& document
if (namespace_ == Namespace::SVG) {
auto element = create_svg_element(realm, document, qualified_name);
if (element) {
element->set_is_value(move(is_value));
element->set_custom_element_state(CustomElementState::Uncustomized);
return JS::NonnullGCPtr<Element> { *element };
}
return element;
}
if (namespace_ == Namespace::MathML) {
auto element = create_mathml_element(realm, document, qualified_name);
if (element) {
element->set_is_value(move(is_value));
element->set_custom_element_state(CustomElementState::Uncustomized);
return JS::NonnullGCPtr<Element> { *element };
}
return element;
}
// 8. Return result.