addon-sdk/source/lib/sdk/deprecated/api-utils.js

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     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 http://mozilla.org/MPL/2.0/. */
     5 "use strict";
     6 module.metadata = {
     7   "stability": "deprecated"
     8 };
    10 const memory = require("./memory");
    12 const { merge } = require("../util/object");
    13 const { union } = require("../util/array");
    14 const { isNil, isRegExp } = require("../lang/type");
    16 // The possible return values of getTypeOf.
    17 const VALID_TYPES = [
    18   "array",
    19   "boolean",
    20   "function",
    21   "null",
    22   "number",
    23   "object",
    24   "string",
    25   "undefined",
    26   "regexp"
    27 ];
    29 const { isArray } = Array;
    31 /**
    32  * Returns a validated options dictionary given some requirements.  If any of
    33  * the requirements are not met, an exception is thrown.
    34  *
    35  * @param  options
    36  *         An object, the options dictionary to validate.  It's not modified.
    37  *         If it's null or otherwise falsey, an empty object is assumed.
    38  * @param  requirements
    39  *         An object whose keys are the expected keys in options.  Any key in
    40  *         options that is not present in requirements is ignored.  Each value
    41  *         in requirements is itself an object describing the requirements of
    42  *         its key.  There are four optional keys in this object:
    43  *           map: A function that's passed the value of the key in options.
    44  *                map's return value is taken as the key's value in the final
    45  *                validated options, is, and ok.  If map throws an exception
    46  *                it's caught and discarded, and the key's value is its value in
    47  *                options.
    48  *           is:  An array containing any number of the typeof type names.  If
    49  *                the key's value is none of these types, it fails validation.
    50  *                Arrays, null and regexps are identified by the special type names
    51  *                "array", "null", "regexp"; "object" will not match either.  No type
    52  *                coercion is done.
    53  *           ok:  A function that's passed the key's value.  If it returns
    54  *                false, the value fails validation.
    55  *           msg: If the key's value fails validation, an exception is thrown.
    56  *                This string will be used as its message.  If undefined, a
    57  *                generic message is used, unless is is defined, in which case
    58  *                the message will state that the value needs to be one of the
    59  *                given types.
    60  * @return An object whose keys are those keys in requirements that are also in
    61  *         options and whose values are the corresponding return values of map
    62  *         or the corresponding values in options.  Note that any keys not
    63  *         shared by both requirements and options are not in the returned
    64  *         object.
    65  */
    66 exports.validateOptions = function validateOptions(options, requirements) {
    67   options = options || {};
    68   let validatedOptions = {};
    70   for (let key in requirements) {
    71     let isOptional = false;
    72     let mapThrew = false;
    73     let req = requirements[key];
    74     let [optsVal, keyInOpts] = (key in options) ?
    75                                [options[key], true] :
    76                                [undefined, false];
    77     if (req.map) {
    78       try {
    79         optsVal = req.map(optsVal);
    80       }
    81       catch (err) {
    82         if (err instanceof RequirementError)
    83           throw err;
    85         mapThrew = true;
    86       }
    87     }
    88     if (req.is) {
    89       let types = req.is;
    91       if (!isArray(types) && isArray(types.is))
    92         types = types.is;
    94       if (isArray(types)) {
    95         isOptional = ['undefined', 'null'].every(v => ~types.indexOf(v));
    97         // Sanity check the caller's type names.
    98         types.forEach(function (typ) {
    99           if (VALID_TYPES.indexOf(typ) < 0) {
   100             let msg = 'Internal error: invalid requirement type "' + typ + '".';
   101             throw new Error(msg);
   102           }
   103         });
   104         if (types.indexOf(getTypeOf(optsVal)) < 0)
   105           throw new RequirementError(key, req);
   106       }
   107     }
   109     if (req.ok && ((!isOptional || !isNil(optsVal)) && !req.ok(optsVal)))
   110       throw new RequirementError(key, req);
   112     if (keyInOpts || (req.map && !mapThrew && optsVal !== undefined))
   113       validatedOptions[key] = optsVal;
   114   }
   116   return validatedOptions;
   117 };
   119 exports.addIterator = function addIterator(obj, keysValsGenerator) {
   120   obj.__iterator__ = function(keysOnly, keysVals) {
   121     let keysValsIterator = keysValsGenerator.call(this);
   123     // "for (.. in ..)" gets only keys, "for each (.. in ..)" gets values,
   124     // and "for (.. in Iterator(..))" gets [key, value] pairs.
   125     let index = keysOnly ? 0 : 1;
   126     while (true)
   127       yield keysVals ? keysValsIterator.next() : keysValsIterator.next()[index];
   128   };
   129 };
   131 // Similar to typeof, except arrays, null and regexps are identified by "array" and
   132 // "null" and "regexp", not "object".
   133 let getTypeOf = exports.getTypeOf = function getTypeOf(val) {
   134   let typ = typeof(val);
   135   if (typ === "object") {
   136     if (!val)
   137       return "null";
   138     if (isArray(val))
   139       return "array";
   140     if (isRegExp(val))
   141       return "regexp";
   142   }
   143   return typ;
   144 }
   146 function RequirementError(key, requirement) {
   147   Error.call(this);
   149   this.name = "RequirementError";
   151   let msg = requirement.msg;
   152   if (!msg) {
   153     msg = 'The option "' + key + '" ';
   154     msg += requirement.is ?
   155            "must be one of the following types: " + requirement.is.join(", ") :
   156            "is invalid.";
   157   }
   159   this.message = msg;
   160 }
   161 RequirementError.prototype = Object.create(Error.prototype);
   163 let string = { is: ['string', 'undefined', 'null'] };
   164 exports.string = string;
   166 let number = { is: ['number', 'undefined', 'null'] };
   167 exports.number = number;
   169 let boolean = { is: ['boolean', 'undefined', 'null'] };
   170 exports.boolean = boolean;
   172 let object = { is: ['object', 'undefined', 'null'] };
   173 exports.object = object;
   175 let isTruthyType = type => !(type === 'undefined' || type === 'null');
   176 let findTypes = v => { while (!isArray(v) && v.is) v = v.is; return v };
   178 function required(req) {
   179   let types = (findTypes(req) || VALID_TYPES).filter(isTruthyType);
   181   return merge({}, req, {is: types});
   182 }
   183 exports.required = required;
   185 function optional(req) {
   186   req = merge({is: []}, req);
   187   req.is = findTypes(req).filter(isTruthyType).concat('undefined', 'null');
   189   return req;
   190 }
   191 exports.optional = optional;
   193 function either(...types) {
   194   return union.apply(null, types.map(findTypes));
   195 }
   196 exports.either = either;

mercurial