mirror of
https://github.com/lightpanda-io/browser.git
synced 2026-03-22 04:34:44 +00:00
fix DocumentType.remove, MutationRecord.attributeNamespace, createElementNS casing
- add ChildNode.remove() to DocumentType (flips DocumentType-remove.html) - return null for MutationRecord.attributeNamespace on non-namespaced attribute mutations (flips MutationObserver-takeRecords.html) - stop lowercasing in createElementNS per spec — only createElement should ASCII-lowercase for HTML namespace (flips Element/Document-getElementsByTagNameNS.html) - fix getElementsByTagName to use case-insensitive matching for HTML namespace elements
This commit is contained in:
@@ -7,9 +7,11 @@
|
|||||||
testing.expectEqual(true, htmlDiv1 instanceof HTMLDivElement);
|
testing.expectEqual(true, htmlDiv1 instanceof HTMLDivElement);
|
||||||
testing.expectEqual('http://www.w3.org/1999/xhtml', htmlDiv1.namespaceURI);
|
testing.expectEqual('http://www.w3.org/1999/xhtml', htmlDiv1.namespaceURI);
|
||||||
|
|
||||||
|
// Per spec, createElementNS does NOT lowercase — 'DIV' != 'div', so this
|
||||||
|
// creates an HTMLUnknownElement, not an HTMLDivElement.
|
||||||
const htmlDiv2 = document.createElementNS('http://www.w3.org/1999/xhtml', 'DIV');
|
const htmlDiv2 = document.createElementNS('http://www.w3.org/1999/xhtml', 'DIV');
|
||||||
testing.expectEqual('DIV', htmlDiv2.tagName);
|
testing.expectEqual('DIV', htmlDiv2.tagName);
|
||||||
testing.expectEqual(true, htmlDiv2 instanceof HTMLDivElement);
|
testing.expectEqual(false, htmlDiv2 instanceof HTMLDivElement);
|
||||||
testing.expectEqual('http://www.w3.org/1999/xhtml', htmlDiv2.namespaceURI);
|
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');
|
||||||
|
|||||||
@@ -157,8 +157,8 @@ 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 ns = Element.Namespace.parse(namespace);
|
const ns = Element.Namespace.parse(namespace);
|
||||||
const normalized_name = if (ns == .html) std.ascii.lowerString(&page.buf, name) else name;
|
// Per spec, createElementNS does NOT lowercase (unlike createElement).
|
||||||
const node = try page.createElementNS(ns, normalized_name, null);
|
const node = try page.createElementNS(ns, name, null);
|
||||||
|
|
||||||
// Store original URI for unknown namespaces so lookupNamespaceURI can return it
|
// Store original URI for unknown namespaces so lookupNamespaceURI can return it
|
||||||
if (ns == .unknown) {
|
if (ns == .unknown) {
|
||||||
|
|||||||
@@ -74,6 +74,12 @@ pub fn clone(self: *const DocumentType, page: *Page) !*DocumentType {
|
|||||||
return .init(self._name, self._public_id, self._system_id, page);
|
return .init(self._name, self._public_id, self._system_id, page);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn remove(self: *DocumentType, page: *Page) !void {
|
||||||
|
const node = self.asNode();
|
||||||
|
const parent = node.parentNode() orelse return;
|
||||||
|
_ = try parent.removeChild(node, page);
|
||||||
|
}
|
||||||
|
|
||||||
pub const JsApi = struct {
|
pub const JsApi = struct {
|
||||||
pub const bridge = js.Bridge(DocumentType);
|
pub const bridge = js.Bridge(DocumentType);
|
||||||
|
|
||||||
@@ -87,4 +93,5 @@ pub const JsApi = struct {
|
|||||||
pub const name = bridge.accessor(DocumentType.getName, null, .{});
|
pub const name = bridge.accessor(DocumentType.getName, null, .{});
|
||||||
pub const publicId = bridge.accessor(DocumentType.getPublicId, null, .{});
|
pub const publicId = bridge.accessor(DocumentType.getPublicId, null, .{});
|
||||||
pub const systemId = bridge.accessor(DocumentType.getSystemId, null, .{});
|
pub const systemId = bridge.accessor(DocumentType.getSystemId, null, .{});
|
||||||
|
pub const remove = bridge.function(DocumentType.remove, .{});
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -387,9 +387,9 @@ pub const MutationRecord = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn getAttributeNamespace(self: *const MutationRecord) ?[]const u8 {
|
pub fn getAttributeNamespace(self: *const MutationRecord) ?[]const u8 {
|
||||||
if (self._attribute_name != null) {
|
_ = self;
|
||||||
return "http://www.w3.org/1999/xhtml";
|
// Non-namespaced attribute mutations return null. Full namespace tracking
|
||||||
}
|
// for setAttributeNS mutations is not yet implemented.
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -225,8 +225,13 @@ pub fn NodeLive(comptime mode: Mode) type {
|
|||||||
// If we're in `tag_name` mode, then the tag_name isn't
|
// If we're in `tag_name` mode, then the tag_name isn't
|
||||||
// a known tag. It could be a custom element, heading, or
|
// a known tag. It could be a custom element, heading, or
|
||||||
// any generic element. Compare against the element's tag name.
|
// any generic element. Compare against the element's tag name.
|
||||||
|
// Per spec, getElementsByTagName is case-insensitive for HTML
|
||||||
|
// namespace elements, case-sensitive for others.
|
||||||
const el = node.is(Element) orelse return false;
|
const el = node.is(Element) orelse return false;
|
||||||
const element_tag = el.getTagNameLower();
|
const element_tag = el.getTagNameLower();
|
||||||
|
if (el._namespace == .html) {
|
||||||
|
return std.ascii.eqlIgnoreCase(element_tag, self._filter.str());
|
||||||
|
}
|
||||||
return std.mem.eql(u8, element_tag, self._filter.str());
|
return std.mem.eql(u8, element_tag, self._filter.str());
|
||||||
},
|
},
|
||||||
.tag_name_ns => {
|
.tag_name_ns => {
|
||||||
|
|||||||
Reference in New Issue
Block a user