Make document.createElement and createElementNS case-insensitive for HTML NS

This could more cleanly be applied to page.createElementNS, but that would add
overhead to the parser. Alternative would be to pass a comptime flag to
page.createElementNS (e.g. like the from_parser we pass elsewhere).
This commit is contained in:
Karl Seguin
2026-02-07 17:21:11 +08:00
parent aca3fae6b1
commit 5abcecbc9b
3 changed files with 27 additions and 13 deletions

View File

@@ -2,12 +2,16 @@
<body></body> <body></body>
<script src="../testing.js"></script> <script src="../testing.js"></script>
<script id=createElement> <script id=createElement>
const div = document.createElement('div'); const div1 = document.createElement('div');
testing.expectEqual("DIV", div.tagName); testing.expectEqual(true, div1 instanceof HTMLDivElement);
div.id = "hello"; testing.expectEqual("DIV", div1.tagName);
div1.id = "hello";
testing.expectEqual(null, $('#hello')); testing.expectEqual(null, $('#hello'));
document.getElementsByTagName('body')[0].appendChild(div); const div2 = document.createElement('DIV');
testing.expectEqual(div, $('#hello')); testing.expectEqual(true, div2 instanceof HTMLDivElement);
document.getElementsByTagName('body')[0].appendChild(div1);
testing.expectEqual(div1, $('#hello'));
</script> </script>

View File

@@ -2,9 +2,15 @@
<body></body> <body></body>
<script src="../testing.js"></script> <script src="../testing.js"></script>
<script id=createElementNS> <script id=createElementNS>
const htmlDiv = document.createElementNS('http://www.w3.org/1999/xhtml', 'div'); const htmlDiv1 = document.createElementNS('http://www.w3.org/1999/xhtml', 'div');
testing.expectEqual('DIV', htmlDiv.tagName); testing.expectEqual('DIV', htmlDiv1.tagName);
testing.expectEqual('http://www.w3.org/1999/xhtml', htmlDiv.namespaceURI); testing.expectEqual(true, htmlDiv1 instanceof HTMLDivElement);
testing.expectEqual('http://www.w3.org/1999/xhtml', htmlDiv1.namespaceURI);
const htmlDiv2 = document.createElementNS('http://www.w3.org/1999/xhtml', 'DIV');
testing.expectEqual('DIV', htmlDiv2.tagName);
testing.expectEqual(true, htmlDiv2 instanceof HTMLDivElement);
testing.expectEqual('http://www.w3.org/1999/xhtml', htmlDiv2.namespaceURI);
const svgRect = document.createElementNS('http://www.w3.org/2000/svg', 'RecT'); const svgRect = document.createElementNS('http://www.w3.org/2000/svg', 'RecT');
testing.expectEqual('RecT', svgRect.tagName); testing.expectEqual('RecT', svgRect.tagName);

View File

@@ -125,14 +125,16 @@ const CreateElementOptions = struct {
pub fn createElement(self: *Document, name: []const u8, options_: ?CreateElementOptions, page: *Page) !*Element { pub fn createElement(self: *Document, name: []const u8, options_: ?CreateElementOptions, page: *Page) !*Element {
try validateElementName(name); try validateElementName(name);
const namespace: Element.Namespace = blk: { const ns: Element.Namespace, const normalized_name = blk: {
if (self._type == .html) { if (self._type == .html) {
break :blk .html; break :blk .{ .html, std.ascii.lowerString(&page.buf, name) };
} }
// Generic and XML documents create XML elements // Generic and XML documents create XML elements
break :blk .xml; break :blk .{ .xml, name };
}; };
const node = try page.createElementNS(namespace, name, null); // HTML documents are case-insensitive - lowercase the tag name
const node = try page.createElementNS(ns, normalized_name, null);
const element = node.as(Element); const element = node.as(Element);
// Track owner document if it's not the main document // Track owner document if it's not the main document
@@ -151,7 +153,9 @@ pub fn createElement(self: *Document, name: []const u8, options_: ?CreateElement
pub fn createElementNS(self: *Document, namespace: ?[]const u8, name: []const u8, page: *Page) !*Element { pub fn createElementNS(self: *Document, namespace: ?[]const u8, name: []const u8, page: *Page) !*Element {
try validateElementName(name); try validateElementName(name);
const node = try page.createElementNS(Element.Namespace.parse(namespace), name, null); const ns = Element.Namespace.parse(namespace);
const normalized_name = if (ns == .html) std.ascii.lowerString(&page.buf, name) else name;
const node = try page.createElementNS(ns, normalized_name, null);
// Track owner document if it's not the main document // Track owner document if it's not the main document
if (self != page.document) { if (self != page.document) {