fix(svg): expose current element constructors

This commit is contained in:
ldm0
2026-09-23 00:11:52 +08:00
parent e7725feb1c
commit a72a2a68e2
5 changed files with 66 additions and 0 deletions
@@ -92,14 +92,17 @@ pub fn svg_element_interface_name(local_name: &str) -> &'static str {
match local_name {
"a" => "SVGAElement",
"circle" => "SVGCircleElement",
"clipPath" => "SVGClipPathElement",
"defs" => "SVGDefsElement",
"desc" => "SVGDescElement",
"ellipse" => "SVGEllipseElement",
"filter" => "SVGFilterElement",
"foreignObject" => "SVGForeignObjectElement",
"g" => "SVGGElement",
"image" => "SVGImageElement",
"line" => "SVGLineElement",
"linearGradient" => "SVGLinearGradientElement",
"mask" => "SVGMaskElement",
"metadata" => "SVGMetadataElement",
"path" => "SVGPathElement",
"pattern" => "SVGPatternElement",
@@ -115,6 +118,7 @@ pub fn svg_element_interface_name(local_name: &str) -> &'static str {
"title" => "SVGTitleElement",
"tspan" => "SVGTSpanElement",
"use" => "SVGUseElement",
"view" => "SVGViewElement",
_ => "SVGElement",
}
}
+4
View File
@@ -231,9 +231,11 @@ fn html_element_interface_name_covers_replay_tags() {
fn svg_element_interface_name_specializes_standard_elements() {
assert_eq!(svg_element_interface_name("a"), "SVGAElement");
assert_eq!(svg_element_interface_name("circle"), "SVGCircleElement");
assert_eq!(svg_element_interface_name("clipPath"), "SVGClipPathElement");
assert_eq!(svg_element_interface_name("defs"), "SVGDefsElement");
assert_eq!(svg_element_interface_name("desc"), "SVGDescElement");
assert_eq!(svg_element_interface_name("ellipse"), "SVGEllipseElement");
assert_eq!(svg_element_interface_name("filter"), "SVGFilterElement");
assert_eq!(
svg_element_interface_name("foreignObject"),
"SVGForeignObjectElement"
@@ -246,6 +248,7 @@ fn svg_element_interface_name_specializes_standard_elements() {
"SVGLinearGradientElement"
);
assert_eq!(svg_element_interface_name("metadata"), "SVGMetadataElement");
assert_eq!(svg_element_interface_name("mask"), "SVGMaskElement");
assert_eq!(svg_element_interface_name("path"), "SVGPathElement");
assert_eq!(svg_element_interface_name("pattern"), "SVGPatternElement");
assert_eq!(svg_element_interface_name("polygon"), "SVGPolygonElement");
@@ -262,6 +265,7 @@ fn svg_element_interface_name_specializes_standard_elements() {
assert_eq!(svg_element_interface_name("title"), "SVGTitleElement");
assert_eq!(svg_element_interface_name("tspan"), "SVGTSpanElement");
assert_eq!(svg_element_interface_name("use"), "SVGUseElement");
assert_eq!(svg_element_interface_name("view"), "SVGViewElement");
assert_eq!(svg_element_interface_name("style"), "SVGStyleElement");
assert_eq!(svg_element_interface_name("custom"), "SVGElement");
}
@@ -109,12 +109,14 @@ const NODE_BRIDGE_DESCRIPTORS: &[BridgeDescriptor] = &[
ELEMENT_GROUPS,
),
descriptor(web_api_interfaces::SVGAElement::DESCRIPTOR, ELEMENT_GROUPS),
descriptor(web_api_interfaces::SVGClipPathElement::DESCRIPTOR, ELEMENT_GROUPS),
specialized_descriptor(
web_api_interfaces::SVGCircleElement::DESCRIPTOR,
ELEMENT_GROUPS,
SpecializedTemplateInstaller::None,
SVG_GEOMETRY_RUNTIME_INSTALL_GROUPS,
),
descriptor(web_api_interfaces::SVGFilterElement::DESCRIPTOR, ELEMENT_GROUPS),
descriptor(
web_api_interfaces::SVGDefsElement::DESCRIPTOR,
ELEMENT_GROUPS,
@@ -172,6 +174,7 @@ const NODE_BRIDGE_DESCRIPTORS: &[BridgeDescriptor] = &[
web_api_interfaces::SVGStyleElement::DESCRIPTOR,
ELEMENT_GROUPS,
),
descriptor(web_api_interfaces::SVGMaskElement::DESCRIPTOR, ELEMENT_GROUPS),
specialized_descriptor(
web_api_interfaces::SVGPathElement::DESCRIPTOR,
ELEMENT_GROUPS,
@@ -262,6 +265,7 @@ const NODE_BRIDGE_DESCRIPTORS: &[BridgeDescriptor] = &[
web_api_interfaces::SVGUseElement::DESCRIPTOR,
ELEMENT_GROUPS,
),
descriptor(web_api_interfaces::SVGViewElement::DESCRIPTOR, ELEMENT_GROUPS),
specialized_descriptor(
web_api_interfaces::SVGRectElement::DESCRIPTOR,
ELEMENT_GROUPS,
@@ -1518,6 +1518,56 @@ fn svg_owner_svg_element_tracks_the_nearest_svg_fragment_root() {
assert_eq!(result, "ok");
}
#[test]
fn svg_historical_interfaces_keep_current_element_constructors_only() {
let mut vm = new_parsed_test_vm(
"https://svg-historical-interfaces.test/",
"<!doctype html><html><head></head><body></body></html>",
);
let result = vm
.eval(
r#"
(() => {
const assert = (condition, message) => {
if (!condition) throw new Error(message);
};
const ns = "http://www.w3.org/2000/svg";
const interfaces = [
["clipPath", "SVGClipPathElement"],
["filter", "SVGFilterElement"],
["mask", "SVGMaskElement"],
["view", "SVGViewElement"],
];
const removedUnitTypeConstants = [
"SVG_UNIT_TYPE_UNKNOWN",
"SVG_UNIT_TYPE_USERSPACEONUSE",
"SVG_UNIT_TYPE_OBJECTBOUNDINGBOX",
];
for (const [localName, interfaceName] of interfaces) {
const constructor = globalThis[interfaceName];
assert(typeof constructor === "function", `${interfaceName} constructor`);
assert(Object.getPrototypeOf(constructor.prototype) === SVGElement.prototype,
`${interfaceName} prototype parent`);
assert(document.createElementNS(ns, localName) instanceof constructor,
`${localName} interface`);
for (const constant of removedUnitTypeConstants) {
assert(!(constant in constructor), `${interfaceName}.${constant} removed`);
}
}
assert(!("viewTarget" in SVGViewElement.prototype),
"SVGViewElement.prototype.viewTarget removed");
return "ok";
})()
"#,
)
.expect("SVG historical interface probe should evaluate");
assert_eq!(result, "ok");
}
#[test]
fn svg_geometry_queries_use_computed_paths_live_tree_and_kurbo_bounds() {
let mut vm = new_parsed_test_vm(
@@ -376,6 +376,10 @@ interfaces! {
SVGCircleElement: SVGGeometryElement;
SVGDefsElement: SVGGraphicsElement;
SVGDescElement: SVGElement;
SVGClipPathElement: SVGElement;
SVGFilterElement: SVGElement;
SVGMaskElement: SVGElement;
SVGViewElement: SVGElement;
SVGElement: Element;
SVGEllipseElement: SVGGeometryElement;
SVGForeignObjectElement: SVGGraphicsElement;