happy-dom
Version:
Happy DOM is a JavaScript implementation of a web browser without its graphical user interface. It includes many web standards from WHATWG DOM and HTML.
113 lines (100 loc) • 2.53 kB
text/typescript
import type IMutationObserverInit from './IMutationObserverInit.js';
import type MutationObserver from './MutationObserver.js';
import type MutationRecord from './MutationRecord.js';
import type Node from '../nodes/node/Node.js';
import type BrowserWindow from '../window/BrowserWindow.js';
import type IMutationListener from './IMutationListener.js';
/**
* Mutation Observer Listener.
*/
export default class MutationObserverListener {
public target: Node;
public options: IMutationObserverInit;
public mutationListener: IMutationListener;
#window: BrowserWindow;
#observer: MutationObserver;
#callback: (record: MutationRecord[], observer: MutationObserver) => void;
#records: MutationRecord[] = [];
#destroyed = false;
#microtaskQueued = false;
/**
* Constructor.
*
* @param init Options.
* @param init.window Window.
* @param init.options Options.
* @param init.target Target.
* @param init.observer Observer.
* @param init.callback Callback.
*/
constructor(init: {
window: BrowserWindow;
options: IMutationObserverInit;
target: Node;
observer: MutationObserver;
callback: (record: MutationRecord[], observer: MutationObserver) => void;
}) {
this.options = init.options;
this.target = init.target;
this.mutationListener = {
options: init.options,
callback: new WeakRef((record: MutationRecord) => this.report(record))
};
this.#window = init.window;
this.#observer = init.observer;
this.#callback = init.callback;
}
/**
* Reports mutations.
*
* @param record Record.
*/
public report(record: MutationRecord): void {
if (this.#destroyed) {
return;
}
this.#records.push(record);
if (this.#microtaskQueued) {
return;
}
this.#window.queueMicrotask(() => {
if (this.#destroyed) {
return;
}
this.#microtaskQueued = false;
const records = this.#records;
if (records?.length > 0) {
this.#records = [];
this.#callback(records, this.#observer);
}
});
this.#microtaskQueued = true;
}
/**
* Destroys the listener.
*/
public takeRecords(): MutationRecord[] {
if (this.#destroyed) {
return [];
}
const records = this.#records;
this.#records = [];
return records;
}
/**
* Destroys the listener.
*/
public destroy(): void {
if (this.#destroyed) {
return;
}
this.#destroyed = true;
this.options = null!;
this.target = null!;
this.mutationListener = null!;
this.#window = null!;
this.#observer = null!;
this.#callback = null!;
this.#records = null!;
}
}