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.

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

mercurial