Bug 1839170 - Refactor Snap pulling, Add Firefox Snap Core22 and GNOME 42 SDK symbols...
[gecko.git] / dom / manifest / ValueExtractor.sys.mjs
blobd08cd24e1c77f136b9d5babf2fcc63435f0cfef5
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2  * License, v. 2.0. If a copy of the MPL was not distributed with this
3  * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4 /*
5  * Helper functions extract values from manifest members
6  * and reports conformance errors.
7  */
9 export class ValueExtractor {
10   constructor(errors, aBundle) {
11     this.errors = errors;
12     this.domBundle = aBundle;
13   }
15   /**
16    * @param options
17    *        The 'spec' object.
18    * @note  This function takes a 'spec' object and destructures it to extract
19    *        a value. If the value is of the wrong type, it warns the developer
20    *        and returns undefined.
21    *        expectedType: is the type of a JS primitive (string, number, etc.)
22    *        object: is the object from which to extract the value.
23    *        objectName: string used to construct the developer warning.
24    *        property: the name of the property being extracted.
25    *        throwTypeError: boolean, throw a TypeError if the type is incorrect.
26    *        trim: boolean, if the value should be trimmed (used by string type).
27    */
28   extractValue(options) {
29     const { expectedType, object, objectName, property, throwTypeError, trim } =
30       options;
31     const value = object[property];
32     const isArray = Array.isArray(value);
34     // We need to special-case "array", as it's not a JS primitive.
35     const type = isArray ? "array" : typeof value;
36     if (type !== expectedType) {
37       if (type !== "undefined") {
38         const warn = this.domBundle.formatStringFromName(
39           "ManifestInvalidType",
40           [objectName, property, expectedType]
41         );
42         this.errors.push({ warn });
43         if (throwTypeError) {
44           throw new TypeError(warn);
45         }
46       }
47       return undefined;
48     }
50     // Trim string and returned undefined if the empty string.
51     const shouldTrim = expectedType === "string" && value && trim;
52     if (shouldTrim) {
53       return value.trim() || undefined;
54     }
55     return value;
56   }
58   extractColorValue(spec) {
59     const value = this.extractValue(spec);
60     let color;
61     if (InspectorUtils.isValidCSSColor(value)) {
62       const rgba = InspectorUtils.colorToRGBA(value);
63       color =
64         "#" +
65         rgba.r.toString(16).padStart(2, "0") +
66         rgba.g.toString(16).padStart(2, "0") +
67         rgba.b.toString(16).padStart(2, "0") +
68         Math.round(rgba.a * 255)
69           .toString(16)
70           .padStart(2, "0");
71     } else if (value) {
72       const warn = this.domBundle.formatStringFromName(
73         "ManifestInvalidCSSColor",
74         [spec.property, value]
75       );
76       this.errors.push({ warn });
77     }
78     return color;
79   }
81   extractLanguageValue(spec) {
82     let langTag;
83     const value = this.extractValue(spec);
84     if (value !== undefined) {
85       try {
86         langTag = Intl.getCanonicalLocales(value)[0];
87       } catch (err) {
88         const warn = this.domBundle.formatStringFromName(
89           "ManifestLangIsInvalid",
90           [spec.property, value]
91         );
92         this.errors.push({ warn });
93       }
94     }
95     return langTag;
96   }