Skip to content

Commit

Permalink
Merge pull request #1437 from capricorn86/1436-lots-of-npe-errors-log…
Browse files Browse the repository at this point in the history
…ged-by-mutationlistener

fix: [#1336] Adds check for if Window and MutationObserver has been d…
  • Loading branch information
capricorn86 committed May 14, 2024
2 parents 5b527c2 + e00852c commit 909069b
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 6 deletions.
10 changes: 8 additions & 2 deletions packages/happy-dom/src/mutation-observer/MutationListener.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export default class MutationListener {
#window: BrowserWindow;
#observer: MutationObserver;
#callback: (record: MutationRecord[], observer: MutationObserver) => void;
#records: MutationRecord[] = [];
#records: MutationRecord[] | null = [];
#immediate: NodeJS.Immediate | null = null;

/**
Expand Down Expand Up @@ -46,13 +46,19 @@ export default class MutationListener {
* @param record Record.
*/
public report(record: MutationRecord): void {
if (!this.#records) {
return;
}

this.#records.push(record);

if (this.#immediate) {
this.#window.cancelAnimationFrame(this.#immediate);
}

this.#immediate = this.#window.requestAnimationFrame(() => {
const records = this.#records;
if (records.length > 0) {
if (records?.length > 0) {
this.#records = [];
this.#callback(records, this.#observer);
}
Expand Down
35 changes: 31 additions & 4 deletions packages/happy-dom/test/mutation-observer/MutationObserver.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -307,13 +307,40 @@ describe('MutationObserver', () => {
const observer = new MutationObserver((mutationRecords) => {
records = mutationRecords;
});
observer.observe(div, { attributes: true });
const span = document.createElement('span');
const text = document.createTextNode('old');

window.close();
span.appendChild(text);
div.appendChild(span);

div.setAttribute('attr', 'value');
document.body.appendChild(div);

await new Promise((resolve) => setTimeout(resolve, 1));
observer.observe(div, {
attributes: true,
childList: true,
subtree: true,
characterData: true,
attributeOldValue: true,
characterDataOldValue: true
});

text.textContent = 'new1';
div.setAttribute('attr', 'value1');

await Promise.all([
window.happyDOM.close(),
(async () => {
text.textContent = 'new2';
div.setAttribute('attr', 'value2');
})(),
new Promise((resolve) => setTimeout(resolve, 10))
]);

text.textContent = 'new3';
div.removeChild(span);
div.setAttribute('attr', 'value3');

await new Promise((resolve) => setTimeout(resolve, 10));

expect(records).toEqual([]);
});
Expand Down

0 comments on commit 909069b

Please sign in to comment.