w3c / DOM-Parsing

DOM Parsing and Serialization
https://w3c.github.io/DOM-Parsing/
Other
27 stars 14 forks source link

Prefix collision issues in serialization algorithms #75

Open bwrrp opened 11 months ago

bwrrp commented 11 months ago

While revisiting the XML serialization spec I found a few more bugs in it that can lead to serialization issues:

prefix redeclaration confusion

const root = document.appendChild(document.createElementNS('ns1', 'pre:root'));
const child = root.appendChild(document.createElementNS('ns2', 'pre:child'));
child.appendChild(document.createElementNS('ns1', 'grandChild'));

This currently results in grandChild being assigned the pre prefix without redeclaring it, which places it in ns2 instead of ns1.

Firefox assigns a new a0 prefix to child here to avoid this. Chrome redeclares the pre prefix on grandChild back to ns2.

Chrome's behavior seems to more closely match the author's intent in that it preserves all prefixes as specified. To match that, the algorithm should likely keep track of the prefix to namespace mapping in addition to the currently tracked inverse mapping, and use that to check if the prefix it wants to use needs to be redeclared.

generated prefix collisions

const root = document.appendChild(document.createElementNS('ns1', 'ns1:root'));
root.setAttributeNS('ns2', 'attr', 'value');

This currently results in two declarations for the ns1 prefix on the root element, one for ns1 produced as part of serializing the element, one for ns2 produced for the generated prefix ns1. That is not well-formed.

Firefox and Chrome both assigns a new prefix to attr here to fix this. In Firefox the prefix is a0, Chrome uses ns2.

To fix, the "generate a prefix" algorithm should probably check whether the prefix it intends to generate isn't declared already. If there is an existing local declaration for the prefix, it can loop to try a higher prefix index, matching Chrome's behavior.

bwrrp commented 11 months ago

Apologies, the second issue seems to have been reported already as #44, although the repro steps here are simpler. I did not find mention of the first issue elsewhere.