Skip to content

Commit bc3583b

Browse files
authored
fix: [#1750] Fixes issue where an error was thrown for xmlns or unknown prefixes in Element.setAttribute (#1767)
* fix: [#1750] Fixes issue where an error was thrown for attributes xlink or an unknown prefix during parsing of HTML * fix: [#1750] Fixes issue where an error was thrown for xmlns or unknown prefixes in Element.setAttribute * fix: [#1750] Fixes issue where an error was thrown for xmlns or unknown prefixes in Element.setAttribute
1 parent 150a590 commit bc3583b

File tree

2 files changed

+56
-8
lines changed

2 files changed

+56
-8
lines changed

packages/happy-dom/src/nodes/element/Element.ts

+36-8
Original file line numberDiff line numberDiff line change
@@ -704,15 +704,43 @@ export default class Element
704704
{ method: 'setAttribute', instance: 'Element' }
705705
);
706706
name = String(name);
707+
707708
const namespaceURI = this[PropertySymbol.namespaceURI];
708-
// TODO: Is it correct to check for namespaceURI === NamespaceURI.svg?
709-
const attribute =
710-
namespaceURI === NamespaceURI.html &&
711-
this[PropertySymbol.ownerDocument][PropertySymbol.contentType] === 'text/html'
712-
? this[PropertySymbol.ownerDocument].createAttribute(name)
713-
: this[PropertySymbol.ownerDocument].createAttributeNS(null, name);
714-
attribute[PropertySymbol.value] = String(value);
715-
this[PropertySymbol.attributes].setNamedItem(attribute);
709+
710+
if (namespaceURI === NamespaceURI.html) {
711+
const attribute = this[PropertySymbol.ownerDocument].createAttribute(name);
712+
attribute[PropertySymbol.value] = String(value);
713+
this[PropertySymbol.attributes][PropertySymbol.setNamedItem](attribute);
714+
} else {
715+
const nameParts = name.split(':');
716+
let attributeNamespaceURI = null;
717+
718+
// In the XML namespace, the attribute "xmlns" should be set to the "http://www.w3.org/2000/xmlns/" namespace and "xlink" to the "http://www.w3.org/1999/xlink" namespace.
719+
switch (nameParts[0]) {
720+
case 'xmlns':
721+
attributeNamespaceURI =
722+
!nameParts[1] || nameParts[1] === 'xlink' ? NamespaceURI.xmlns : null;
723+
break;
724+
case 'xlink':
725+
attributeNamespaceURI = NamespaceURI.xlink;
726+
break;
727+
}
728+
729+
const attribute = NodeFactory.createNode(
730+
this[PropertySymbol.ownerDocument],
731+
this[PropertySymbol.window].Attr
732+
);
733+
734+
attribute[PropertySymbol.namespaceURI] = attributeNamespaceURI;
735+
attribute[PropertySymbol.name] = name;
736+
attribute[PropertySymbol.localName] =
737+
attributeNamespaceURI && nameParts[1] ? nameParts[1] : name;
738+
attribute[PropertySymbol.prefix] =
739+
attributeNamespaceURI && nameParts[1] ? nameParts[0] : null;
740+
attribute[PropertySymbol.value] = String(value);
741+
742+
this[PropertySymbol.attributes][PropertySymbol.setNamedItem](attribute);
743+
}
716744
}
717745

718746
/**

packages/happy-dom/test/nodes/element/Element.test.ts

+20
Original file line numberDiff line numberDiff line change
@@ -1706,6 +1706,26 @@ describe('Element', () => {
17061706
expect(element.getAttribute('data-custom')).toBe('1'); // common custom attribute pattern
17071707
});
17081708

1709+
it('Sets SVG attribute "xmlns:xlink" on an element.', () => {
1710+
const div = document.createElement('div');
1711+
1712+
div.innerHTML =
1713+
'<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><use/></svg>';
1714+
1715+
div.children[0].setAttribute('xmlns:xlink', 'test');
1716+
div.children[0].children[0].setAttribute('xlink:href', '#a');
1717+
1718+
expect(div.children[0].getAttributeNode('xmlns:xlink')?.namespaceURI).toBe(
1719+
NamespaceURI.xmlns
1720+
);
1721+
expect(div.children[0].getAttribute('xmlns:xlink')).toBe('test');
1722+
1723+
expect(div.children[0].children[0].getAttributeNode('xlink:href')?.namespaceURI).toBe(
1724+
NamespaceURI.xlink
1725+
);
1726+
expect(div.children[0].children[0].getAttribute('xlink:href')).toBe('#a');
1727+
});
1728+
17091729
it('Throws an error when given an invalid character in the attribute name', () => {
17101730
try {
17111731
element.setAttribute('☺', '1');

0 commit comments

Comments
 (0)