Skip to content

Commit 38ab960

Browse files
authored
fix: [#1578] Fixes bug where child nodes of HTMLSelectElement and HTMLFormElement had the wrong reference to the parent (#1579)
1 parent 8f74989 commit 38ab960

File tree

4 files changed

+81
-3
lines changed

4 files changed

+81
-3
lines changed

packages/happy-dom/src/nodes/html-select-element/HTMLSelectElement.ts

+2
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ export default class HTMLSelectElement extends HTMLElement {
2929
public [PropertySymbol.options]: HTMLOptionsCollection | null = null;
3030
public [PropertySymbol.selectedOptions]: HTMLCollection<HTMLOptionElement> | null = null;
3131
public [PropertySymbol.selectedIndex]: number = -1;
32+
public [PropertySymbol.proxy]: HTMLSelectElement;
3233

3334
// Events
3435
public onchange: (event: Event) => void | null = null;
@@ -195,6 +196,7 @@ export default class HTMLSelectElement extends HTMLElement {
195196
}
196197
});
197198

199+
this[PropertySymbol.proxy] = proxy;
198200
this[PropertySymbol.selectNode] = proxy;
199201

200202
return proxy;

packages/happy-dom/src/nodes/node/Node.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -512,7 +512,7 @@ export default class Node extends EventTarget {
512512
node[PropertySymbol.parentNode][PropertySymbol.removeChild](node);
513513
}
514514

515-
node[PropertySymbol.parentNode] = this;
515+
node[PropertySymbol.parentNode] = this[PropertySymbol.proxy] || this;
516516

517517
node[PropertySymbol.clearCache]();
518518

@@ -647,7 +647,7 @@ export default class Node extends EventTarget {
647647
newNode[PropertySymbol.parentNode][PropertySymbol.removeChild](newNode);
648648
}
649649

650-
newNode[PropertySymbol.parentNode] = this;
650+
newNode[PropertySymbol.parentNode] = this[PropertySymbol.proxy] || this;
651651

652652
newNode[PropertySymbol.clearCache]();
653653

@@ -1061,7 +1061,7 @@ export default class Node extends EventTarget {
10611061
* 2. Let node1 be other and node2 be this.
10621062
*/
10631063
let node1: Node = otherNode;
1064-
let node2: Node = this;
1064+
let node2: Node = this[PropertySymbol.proxy] || this;
10651065

10661066
/**
10671067
* 3. Let attr1 and attr2 be null.

packages/happy-dom/test/nodes/html-form-element/HTMLFormElement.test.ts

+40
Original file line numberDiff line numberDiff line change
@@ -1157,6 +1157,46 @@ describe('HTMLFormElement', () => {
11571157
});
11581158
});
11591159

1160+
describe('appendChild()', () => {
1161+
it('Sets "parentNode" of child elements to the proxy and not the original element.', () => {
1162+
const child = document.createElement('input');
1163+
const child2 = document.createElement('textarea');
1164+
const child3 = document.createElement('select');
1165+
1166+
element.appendChild(child);
1167+
element.appendChild(child2);
1168+
element.appendChild(child3);
1169+
1170+
expect(child.parentNode).toBe(element);
1171+
expect(child2.parentNode).toBe(element);
1172+
expect(child3.parentNode).toBe(element);
1173+
1174+
expect(child.parentElement).toBe(element);
1175+
expect(child2.parentElement).toBe(element);
1176+
expect(child3.parentElement).toBe(element);
1177+
});
1178+
});
1179+
1180+
describe('insertBefore()', () => {
1181+
it('Sets "parentNode" of child elements to the proxy and not the original element.', () => {
1182+
const child = document.createElement('input');
1183+
const child2 = document.createElement('textarea');
1184+
const child3 = document.createElement('select');
1185+
1186+
element.appendChild(child);
1187+
element.appendChild(child2);
1188+
element.insertBefore(child3, child2);
1189+
1190+
expect(child.parentNode).toBe(element);
1191+
expect(child2.parentNode).toBe(element);
1192+
expect(child3.parentNode).toBe(element);
1193+
1194+
expect(child.parentElement).toBe(element);
1195+
expect(child2.parentElement).toBe(element);
1196+
expect(child3.parentElement).toBe(element);
1197+
});
1198+
});
1199+
11601200
for (const method of ['checkValidity', 'reportValidity']) {
11611201
describe(`${method}()`, () => {
11621202
it('Validates the form.', () => {

packages/happy-dom/test/nodes/html-select-element/HTMLSelectElement.test.ts

+36
Original file line numberDiff line numberDiff line change
@@ -515,6 +515,24 @@ describe('HTMLSelectElement', () => {
515515
expect((<Event>(<unknown>dispatchedEvent)).type).toBe('change');
516516
expect(element.selectedIndex).toBe(0);
517517
});
518+
519+
it('Sets "parentNode" of child elements to the proxy and not the original element.', () => {
520+
const option1 = <HTMLOptionElement>document.createElement('option');
521+
const option2 = <HTMLOptionElement>document.createElement('option');
522+
const option3 = <HTMLOptionElement>document.createElement('option');
523+
524+
element.appendChild(option1);
525+
element.appendChild(option2);
526+
element.appendChild(option3);
527+
528+
expect(option1.parentNode).toBe(element);
529+
expect(option2.parentNode).toBe(element);
530+
expect(option3.parentNode).toBe(element);
531+
532+
expect(option1.parentElement).toBe(element);
533+
expect(option2.parentElement).toBe(element);
534+
expect(option3.parentElement).toBe(element);
535+
});
518536
});
519537

520538
describe(`insertBefore()`, () => {
@@ -569,6 +587,24 @@ describe('HTMLSelectElement', () => {
569587
expect(element.item(1) === option2).toBe(true);
570588
expect(element.item(2) === option3).toBe(true);
571589
});
590+
591+
it('Sets "parentNode" of child elements to the proxy and not the original element.', () => {
592+
const option1 = <HTMLOptionElement>document.createElement('option');
593+
const option2 = <HTMLOptionElement>document.createElement('option');
594+
const option3 = <HTMLOptionElement>document.createElement('option');
595+
596+
element.appendChild(option1);
597+
element.appendChild(option2);
598+
element.insertBefore(option3, option2);
599+
600+
expect(option1.parentNode).toBe(element);
601+
expect(option2.parentNode).toBe(element);
602+
expect(option3.parentNode).toBe(element);
603+
604+
expect(option1.parentElement).toBe(element);
605+
expect(option2.parentElement).toBe(element);
606+
expect(option3.parentElement).toBe(element);
607+
});
572608
});
573609

574610
describe(`removeChild()`, () => {

0 commit comments

Comments
 (0)