Files
tubestation/waterfox/browser/extensions/common/iteratorUtils.jsm
Alex Kontos 8252e45d0f feat: implement privileged extension support
Also includes:

* feat: improve support for bootstrapped extensions
Added support for custom preference pages.
* fix: incorrect loading order for bootstrap loader
* fix: BootstrapLoader

(cherry picked from commit eb40811e464688c7d2fc58a4330272dde1ec7937)
2025-11-03 16:04:54 +00:00

133 lines
4.2 KiB
JavaScript

/* 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 contains helper methods for dealing with XPCOM iterators (arrays
* and enumerators) in JS-friendly ways.
*/
const EXPORTED_SYMBOLS = ["fixIterator", "toXPCOMArray", "toArray"];
var JS_HAS_SYMBOLS = typeof Symbol === "function";
var ITERATOR_SYMBOL = JS_HAS_SYMBOLS ? Symbol.iterator : "@@iterator";
/**
* This function will take a number of objects and convert them to an array.
*
* Currently, we support the following objects:
* Anything you can for (let x of aObj) on
* (e.g. toArray(fixIterator(enum))[4],
* also a NodeList from element.children)
*
* @param aObj The object to convert
*/
function toArray(aObj) {
// Iterable object
if (ITERATOR_SYMBOL in aObj) {
return Array.from(aObj);
}
// New style generator function
if (
typeof aObj == "function" &&
typeof aObj.constructor == "function" &&
aObj.constructor.name == "GeneratorFunction"
) {
return [...aObj()];
}
// We got something unexpected, notify the caller loudly.
throw new Error(
"An unsupported object sent to toArray: " +
("toString" in aObj ? aObj.toString() : aObj)
);
}
/**
* Given a JS array, JS iterator, or one of a variety of XPCOM collections or
* iterators, return a JS iterator suitable for use in a for...of expression.
*
* Currently, we support the following types of XPCOM iterators:
* nsIArray
* nsISimpleEnumerator
*
* Note that old-style JS iterators are explicitly not supported in this
* method, as they are going away.
*
* @param aEnum the enumerator to convert
* @param aIface (optional) an interface to QI each object to prior to
* returning
*
* @note This returns an object that can be used in 'for...of' loops.
* Do not use 'for each...in' or 'for...in'.
* This does *not* return an Array object. To create such an array, use
* let array = toArray(fixIterator(xpcomEnumerator));
*/
function fixIterator(aEnum, aIface) {
// If the input is an array, nsISimpleEnumerator or something that sports Symbol.iterator,
// then the original input is sufficient to directly return. However, if we want
// to support the aIface parameter, we need to do a lazy version of
// Array.prototype.map.
if (
Array.isArray(aEnum) ||
aEnum instanceof Ci.nsISimpleEnumerator ||
ITERATOR_SYMBOL in aEnum
) {
if (!aIface) {
return aEnum[ITERATOR_SYMBOL]();
}
return (function*() {
for (let o of aEnum) {
yield o.QueryInterface(aIface);
}
})();
}
let face = aIface || Ci.nsISupports;
// Figure out which kind of array object we have.
// First try nsIArray (covers nsIMutableArray too).
if (aEnum instanceof Ci.nsIArray) {
return (function*() {
let count = aEnum.length;
for (let i = 0; i < count; i++) {
yield aEnum.queryElementAt(i, face);
}
})();
}
// We got something unexpected, notify the caller loudly.
throw new Error(
"An unsupported object sent to fixIterator: " +
("toString" in aEnum ? aEnum.toString() : aEnum)
);
}
/**
* This function takes an Array object and returns an XPCOM array
* of the desired type. It will *not* work if you extend Array.prototype.
*
* @param aArray the array (anything fixIterator supports) to convert to an XPCOM array
* @param aInterface the type of XPCOM array to convert
*
* @note The returned array is *not* dynamically updated. Changes made to the
* JS array after a call to this function will not be reflected in the
* XPCOM array.
*/
function toXPCOMArray(aArray, aInterface) {
if (aInterface.equals(Ci.nsIMutableArray)) {
let mutableArray = Cc["@mozilla.org/array;1"].createInstance(
Ci.nsIMutableArray
);
for (let item of fixIterator(aArray)) {
mutableArray.appendElement(item);
}
return mutableArray;
}
// We got something unexpected, notify the caller loudly.
throw new Error(
"An unsupported interface requested from toXPCOMArray: " + aInterface
);
}