/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ // This file defines these globals on the window object. // Define them here so that ESLint can find them: /* globals MozXULElement, MozElements */ "use strict"; // This is loaded into chrome windows with the subscript loader. Wrap in // a block to prevent accidentally leaking globals onto `window`. (() => { // Handle customElements.js being loaded as a script in addition to the subscriptLoader // from MainProcessSingleton, to handle pages that can open both before and after // MainProcessSingleton starts. See Bug 1501845. if (window.MozXULElement) { return; } const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm"); const {AppConstants} = ChromeUtils.import("resource://gre/modules/AppConstants.jsm"); // The listener of DOMContentLoaded must be set on window, rather than // document, because the window can go away before the event is fired. // In that case, we don't want to initialize anything, otherwise we // may be leaking things because they will never be destroyed after. let gIsDOMContentLoaded = false; const gElementsPendingConnection = new Set(); window.addEventListener("DOMContentLoaded", () => { gIsDOMContentLoaded = true; for (let element of gElementsPendingConnection) { try { if (element.isConnected) { element.isRunningDelayedConnectedCallback = true; element.connectedCallback(); } } catch (ex) { console.error(ex); } element.isRunningDelayedConnectedCallback = false; } gElementsPendingConnection.clear(); }, { once: true, capture: true }); const gXULDOMParser = new DOMParser(); gXULDOMParser.forceEnableXULXBL(); const MozElements = {}; MozElements.MozElementMixin = Base => class MozElement extends Base { /* * A declarative way to wire up attribute inheritance and automatically generate * the `observedAttributes` getter. For example, if you returned: * { * ".foo": "bar,baz=bat" * } * * Then the base class will automatically return ["bar", "bat"] from `observedAttributes`, * and set up an `attributeChangedCallback` to pass those attributes down onto an element * matching the ".foo" selector. * * See the `inheritAttribute` function for more details on the attribute string format. * * @return {Object} */ static get inheritedAttributes() { return null; } /* * Generate this array based on `inheritedAttributes`, if any. A class is free to override * this if it needs to do something more complex or wants to opt out of this behavior. */ static get observedAttributes() { let {inheritedAttributes} = this; if (!inheritedAttributes) { return []; } let allAttributes = new Set(); for (let sel in inheritedAttributes) { for (let attrName of inheritedAttributes[sel].split(",")) { allAttributes.add(attrName.split("=").pop()); } } return [...allAttributes]; } /* * Provide default lifecycle callback for attribute changes that will inherit attributes * based on the static `inheritedAttributes` Object. This can be overridden by callers. */ attributeChangedCallback(name, oldValue, newValue) { if (!this.isConnectedAndReady || oldValue === newValue || !this.inheritedAttributesCache) { return; } this.inheritAttributes(); } /* * After setting content, calling this will cache the elements from selectors in the * static `inheritedAttributes` Object. It'll also do an initial call to `this.inheritAttributes()`, * so in the simple case, this is the only function you need to call. * * This should be called any time the children that are inheriting attributes changes. For instance, * it's common in a connectedCallback to do something like: * * this.textContent = ""; * this.append(MozXULElement.parseXULToFragment(`