Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
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";
7 module.metadata = {
8 "stability": "deprecated"
9 };
11 // `var` is being used in the module in order to make it reusable in
12 // environments in which `let` and `const` is not yet supported.
14 // Returns `object`'s property value, where `name` is a name of the property.
15 function get(object, name) {
16 return object[name];
17 }
19 // Assigns `value` to the `object`'s property, where `name` is the name of the
20 // property.
21 function set(object, name, value) {
22 return object[name] = value;
23 }
25 /**
26 * Given an `object` containing a property with the given `name`, create
27 * a property descriptor that can be used to define alias/proxy properties
28 * on other objects. A change in the value of an alias will propagate
29 * to the aliased property and vice versa.
30 */
31 function createAliasProperty(object, name) {
32 // Getting own property descriptor of an `object` for the given `name` as
33 // we are going to create proxy analog.
34 var property = Object.getOwnPropertyDescriptor(object, name);
35 var descriptor = {
36 configurable: property.configurable,
37 enumerable: property.enumerable,
38 alias: true
39 };
41 // If the original property has a getter and/or setter, bind a
42 // corresponding getter/setter in the alias descriptor to the original
43 // object, so the `this` object in the getter/setter is the original object
44 // rather than the alias.
45 if ("get" in property && property.get)
46 descriptor.get = property.get.bind(object);
47 if ("set" in property && property.set)
48 descriptor.set = property.set.bind(object);
50 // If original property was a value property.
51 if ("value" in property) {
52 // If original property is a method using it's `object` bounded copy.
53 if (typeof property.value === "function") {
54 descriptor.value = property.value.bind(object);
55 // Also preserving writability of the original property.
56 descriptor.writable = property.writable;
57 }
59 // If the original property was just a data property, we create proxy
60 // accessors using our custom get/set functions to propagate changes to the
61 // original `object` and vice versa.
62 else {
63 descriptor.get = get.bind(null, object, name);
64 descriptor.set = set.bind(null, object, name);
65 }
66 }
67 return descriptor;
68 }
70 // Defines property on `object` object with a name `alias` if given if not
71 // defaults to `name` that represents an alias of `source[name]`. If aliased
72 // property was an assessor or a method `this` pseudo-variable will be `source`
73 // when invoked. If aliased property was a data property changes on any of the
74 // aliases will propagate to the `source[name]` and also other way round.
75 function defineAlias(source, target, name, alias) {
76 return Object.defineProperty(target, alias || name,
77 createAliasProperty(source, name));
78 }
80 /**
81 * Function takes any `object` and returns a proxy for its own public
82 * properties. By default properties are considered to be public if they don't
83 * start with `"_"`, but default behavior can be overridden if needed, by
84 * passing array of public property `names` as a second argument. By default
85 * returned object will be direct decedent of the given `object`'s prototype,
86 * but this can be overridden by passing third optional argument, that will be
87 * used as `prototype` instead.
88 * @param {Object} object
89 * Object to create cortex for.
90 * @param {String[]} [names]
91 * Optional array of public property names.
92 * @param {Object} [prototype]
93 * Optional argument that will be used as `prototype` of the returned object,
94 * if not provided `Object.getPrototypeOf(object)` is used instead.
95 */
96 exports.Cortex = function Cortex(object, names, prototype) {
97 // Creating a cortex object from the given `prototype`, if one was not
98 // provided then `prototype` of a given `object` is used. This allows
99 // consumer to define expected behavior `instanceof`. In common case
100 // `prototype` argument can be omitted to preserve same behavior of
101 // `instanceof` as on original `object`.
102 var cortex = Object.create(prototype || Object.getPrototypeOf(object));
103 // Creating alias properties on the `cortex` object for all the own
104 // properties of the original `object` that are contained in `names` array.
105 // If `names` array is not provided then all the properties that don't
106 // start with `"_"` are aliased.
107 Object.getOwnPropertyNames(object).forEach(function (name) {
108 if ((!names && "_" !== name.charAt(0)) || (names && ~names.indexOf(name)))
109 defineAlias(object, cortex, name);
110 });
111 return cortex;
112 }