@webcomponents/custom-elements
Version:
HTML Custom Elements Polyfill
66 lines (55 loc) • 1.85 kB
JavaScript
import CustomElementInternals from './CustomElementInternals.js';
export default class DocumentConstructionObserver {
constructor(internals, doc) {
/**
* @type {!CustomElementInternals}
*/
this._internals = internals;
/**
* @type {!Document}
*/
this._document = doc;
/**
* @type {MutationObserver|undefined}
*/
this._observer = undefined;
// Simulate tree construction for all currently accessible nodes in the
// document.
this._internals.patchAndUpgradeTree(this._document);
if (this._document.readyState === 'loading') {
this._observer = new MutationObserver(this._handleMutations.bind(this));
// Nodes created by the parser are given to the observer *before* the next
// task runs. Inline scripts are run in a new task. This means that the
// observer will be able to handle the newly parsed nodes before the inline
// script is run.
this._observer.observe(this._document, {
childList: true,
subtree: true,
});
}
}
disconnect() {
if (this._observer) {
this._observer.disconnect();
}
}
/**
* @param {!Array<!MutationRecord>} mutations
*/
_handleMutations(mutations) {
// Once the document's `readyState` is 'interactive' or 'complete', all new
// nodes created within that document will be the result of script and
// should be handled by patching.
const readyState = this._document.readyState;
if (readyState === 'interactive' || readyState === 'complete') {
this.disconnect();
}
for (let i = 0; i < mutations.length; i++) {
const addedNodes = mutations[i].addedNodes;
for (let j = 0; j < addedNodes.length; j++) {
const node = addedNodes[j];
this._internals.patchAndUpgradeTree(node);
}
}
}
}