fix(js,dom): keep parsed SVG in the SVG namespace so href reflects an SVGAnimatedString

get namespaceURI() derived the namespace from the tag name and only ever
recognised the <svg> root, so every element parsed inside an <svg> subtree
reported the XHTML namespace. get href() gates the SVGAnimatedString
reflection on the SVG namespace, so for parsed content the gate never
opened: href returned a plain string and .animVal/.baseVal were undefined,
making new URL(el.href.animVal) throw. Only createElementNS-built elements
worked, because createElementNS records _ns explicitly.

The tree builder already applies the HTML5 foreign-content rules, so
QualName.ns is correct for parsed SVG; it just was not exposed to JS. Add a
namespace_uri DOM op and read it in get namespaceURI(), keeping _ns as the
override and the old tag-name heuristic as the fallback when no element name
is recorded. Namespaces are immutable, so the result is cached like _lname.

Fixes #484
This commit is contained in:
ulises2k committed 2026-07-25 22:30:38 -03:00
1 parent e314b9b0f3
commit 3a4e3f7d7d
2 files changed
+22 -4

No files matched your search

+8
View File
@@ -303,6 +303,14 @@ fn op_dom_inner(state: &OpState, cmd: String, arg1: String, arg2: String) -> Str
let name = dom.with_node(NodeId::new(nid), |n| n.as_element().map(|name| name.local.as_ref().to_ascii_uppercase())).flatten().unwrap_or_default();
serde_json::to_string(&name).unwrap_or("\"\"".into())
}
// The tree builder already assigns foreign content (an <svg>/<math>
// subtree) its own namespace; expose it so JS does not have to guess
// the namespace from the tag name.
"namespace_uri" => {
let nid = arg1.parse::<u32>().unwrap_or(0);
let ns = dom.with_node(NodeId::new(nid), |n| n.as_element().map(|name| name.ns.as_ref().to_string())).flatten().unwrap_or_default();
serde_json::to_string(&ns).unwrap_or("\"\"".into())
}
"get_attribute" => {
let nid = arg1.parse::<u32>().unwrap_or(0);
let val = dom.with_node(NodeId::new(nid), |n| n.get_attribute(&arg2).map(|s| s.to_string())).flatten();