Skip to content

Commit 1997a86

Browse files
committed
#1176@patch: Prevent custom element redefinition.
1 parent 8f3bbe1 commit 1997a86

File tree

2 files changed

+14
-5
lines changed

2 files changed

+14
-5
lines changed

packages/happy-dom/src/custom-element/CustomElementRegistry.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,10 @@ export default class CustomElementRegistry {
6161
);
6262
}
6363

64+
if (this._registry[localName]) {
65+
throw new DOMException(`Custom Element: "${localName}" already defined.`);
66+
}
67+
6468
this._registry[localName] = {
6569
elementClass,
6670
extends: options && options.extends ? options.extends.toLowerCase() : null
@@ -124,7 +128,7 @@ export default class CustomElementRegistry {
124128
* Reverse lookup searching for tagName by given element class.
125129
*
126130
* @param elementClass Class constructor.
127-
* @returns First found Tag name or `null`.
131+
* @returns Found Tag name or `null`.
128132
*/
129133
public getName(elementClass: typeof HTMLElement): string | null {
130134
const localName = Object.keys(this._registry).find(

packages/happy-dom/test/custom-element/CustomElementRegistry.test.ts

+9-4
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,11 @@ describe('CustomElementRegistry', () => {
5858
);
5959
});
6060

61+
it('Throws an error if already defined.', () => {
62+
customElements.define('custom-element', CustomElement);
63+
expect(() => customElements.define('custom-element', CustomElement)).toThrow();
64+
});
65+
6166
it('Calls observed attributes and set _observedAttributes as a property on the element class.', () => {
6267
customElements.define('custom-element', CustomElement);
6368
expect(CustomElement.observedAttributesCallCount).toBe(1);
@@ -87,9 +92,9 @@ describe('CustomElementRegistry', () => {
8792
});
8893

8994
describe('whenDefined()', () => {
90-
it('Throws an error if tag name looks invalide', async () => {
95+
it('Throws an error if tag name looks invalid.', async () => {
9196
const tagName = 'element';
92-
expect(async() => await customElements.whenDefined(tagName)).rejects.toThrow();
97+
expect(async () => await customElements.whenDefined(tagName)).rejects.toThrow();
9398
});
9499

95100
it('Returns a promise which is fulfilled when an element is defined.', async () => {
@@ -119,12 +124,12 @@ describe('CustomElementRegistry', () => {
119124
});
120125

121126
describe('createElement()', () => {
122-
it('Case insensitive access via document.createElement()', () => {
127+
it('Case insensitive access via document.createElement().', () => {
123128
customElements.define('custom-element', CustomElement);
124129
expect(document.createElement('CUSTOM-ELEMENT').localName).toBe('custom-element');
125130
});
126131

127-
it('Non-ASCII capital letters in document.createElement()', () => {
132+
it('Non-ASCII capital letters in document.createElement().', () => {
128133
customElements.define('a-Öa', CustomElement);
129134
expect(document.createElement('a-Öa').localName).toMatch(/a-Öa/i);
130135
});

0 commit comments

Comments
 (0)