summaryrefslogtreecommitdiffstats
path: root/toolkit/components/utils/FilterExpressions.sys.mjs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
commit26a029d407be480d791972afb5975cf62c9360a6 (patch)
treef435a8308119effd964b339f76abb83a57c29483 /toolkit/components/utils/FilterExpressions.sys.mjs
parentInitial commit. (diff)
downloadfirefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz
firefox-26a029d407be480d791972afb5975cf62c9360a6.zip
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'toolkit/components/utils/FilterExpressions.sys.mjs')
-rw-r--r--toolkit/components/utils/FilterExpressions.sys.mjs137
1 files changed, 137 insertions, 0 deletions
diff --git a/toolkit/components/utils/FilterExpressions.sys.mjs b/toolkit/components/utils/FilterExpressions.sys.mjs
new file mode 100644
index 0000000000..0dba44ec70
--- /dev/null
+++ b/toolkit/components/utils/FilterExpressions.sys.mjs
@@ -0,0 +1,137 @@
+/* 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/. */
+
+const lazy = {};
+
+ChromeUtils.defineESModuleGetters(lazy, {
+ Sampling: "resource://gre/modules/components-utils/Sampling.sys.mjs",
+});
+ChromeUtils.defineModuleGetter(
+ lazy,
+ "mozjexl",
+ "resource://gre/modules/components-utils/mozjexl.js"
+);
+
+function getPrefValue(prefKey, defaultValue) {
+ switch (Services.prefs.getPrefType(prefKey)) {
+ case Ci.nsIPrefBranch.PREF_STRING:
+ return Services.prefs.getStringPref(prefKey);
+
+ case Ci.nsIPrefBranch.PREF_INT:
+ return Services.prefs.getIntPref(prefKey);
+
+ case Ci.nsIPrefBranch.PREF_BOOL:
+ return Services.prefs.getBoolPref(prefKey);
+
+ case Ci.nsIPrefBranch.PREF_INVALID:
+ return defaultValue;
+
+ default:
+ throw new Error(`Error getting pref ${prefKey}.`);
+ }
+}
+
+ChromeUtils.defineLazyGetter(lazy, "jexl", () => {
+ const jexl = new lazy.mozjexl.Jexl();
+ jexl.addTransforms({
+ date: dateString => new Date(dateString),
+ stableSample: lazy.Sampling.stableSample,
+ bucketSample: lazy.Sampling.bucketSample,
+ preferenceValue: getPrefValue,
+ preferenceIsUserSet: prefKey => Services.prefs.prefHasUserValue(prefKey),
+ preferenceExists: prefKey =>
+ Services.prefs.getPrefType(prefKey) != Ci.nsIPrefBranch.PREF_INVALID,
+ keys,
+ length,
+ mapToProperty,
+ regExpMatch,
+ versionCompare,
+ });
+ jexl.addBinaryOp("intersect", 40, operatorIntersect);
+ return jexl;
+});
+
+export var FilterExpressions = {
+ getAvailableTransforms() {
+ return Object.keys(lazy.jexl._transforms);
+ },
+
+ eval(expr, context = {}) {
+ const onelineExpr = expr.replace(/[\t\n\r]/g, " ");
+ return lazy.jexl.eval(onelineExpr, context);
+ },
+};
+
+/**
+ * Return an array of the given object's own keys (specifically, its enumerable
+ * properties), or undefined if the argument isn't an object.
+ * @param {Object} obj
+ * @return {Array[String]|undefined}
+ */
+function keys(obj) {
+ if (typeof obj !== "object" || obj === null) {
+ return undefined;
+ }
+
+ return Object.keys(obj);
+}
+
+/**
+ * Return the length of an array
+ * @param {Array} arr
+ * @return {number}
+ */
+function length(arr) {
+ return Array.isArray(arr) ? arr.length : undefined;
+}
+
+/**
+ * Given an input array and property name, return an array with each element of
+ * the original array replaced with the given property of that element.
+ * @param {Array} arr
+ * @param {string} prop
+ * @return {Array}
+ */
+function mapToProperty(arr, prop) {
+ return Array.isArray(arr) ? arr.map(elem => elem[prop]) : undefined;
+}
+
+/**
+ * Find all the values that are present in both lists. Returns undefined if
+ * the arguments are not both Arrays.
+ * @param {Array} listA
+ * @param {Array} listB
+ * @return {Array|undefined}
+ */
+function operatorIntersect(listA, listB) {
+ if (!Array.isArray(listA) || !Array.isArray(listB)) {
+ return undefined;
+ }
+
+ return listA.filter(item => listB.includes(item));
+}
+
+/**
+ * Matches a string against a regular expression. Returns null if there are
+ * no matches or an Array of matches.
+ * @param {string} str
+ * @param {string} pattern
+ * @param {string} flags
+ * @return {Array|null}
+ */
+function regExpMatch(str, pattern, flags) {
+ const re = new RegExp(pattern, flags);
+ return str.match(re);
+}
+
+/**
+ * Compares v1 to v2 and returns 0 if they are equal, a negative number if
+ * v1 < v2 or a positive number if v1 > v2.
+ * @param {string} v1
+ * @param {string} v2
+ * @return {number}
+ */
+function versionCompare(v1, v2) {
+ return Services.vc.compare(v1, v2);
+}