Projekt

Obecné

Profil

Stáhnout (3.42 KB) Statistiky
| Větev: | Revize:
1
"use strict";
2

    
3
var originalObject = Object;
4
var originalDefProp = Object.defineProperty;
5
var originalCreate = Object.create;
6

    
7
function defProp(obj, name, value) {
8
  if (originalDefProp) try {
9
    originalDefProp.call(originalObject, obj, name, { value: value });
10
  } catch (definePropertyIsBrokenInIE8) {
11
    obj[name] = value;
12
  } else {
13
    obj[name] = value;
14
  }
15
}
16

    
17
// For functions that will be invoked using .call or .apply, we need to
18
// define those methods on the function objects themselves, rather than
19
// inheriting them from Function.prototype, so that a malicious or clumsy
20
// third party cannot interfere with the functionality of this module by
21
// redefining Function.prototype.call or .apply.
22
function makeSafeToCall(fun) {
23
  if (fun) {
24
    defProp(fun, "call", fun.call);
25
    defProp(fun, "apply", fun.apply);
26
  }
27
  return fun;
28
}
29

    
30
makeSafeToCall(originalDefProp);
31
makeSafeToCall(originalCreate);
32

    
33
var hasOwn = makeSafeToCall(Object.prototype.hasOwnProperty);
34
var numToStr = makeSafeToCall(Number.prototype.toString);
35
var strSlice = makeSafeToCall(String.prototype.slice);
36

    
37
var cloner = function(){};
38
function create(prototype) {
39
  if (originalCreate) {
40
    return originalCreate.call(originalObject, prototype);
41
  }
42
  cloner.prototype = prototype || null;
43
  return new cloner;
44
}
45

    
46
var rand = Math.random;
47
var uniqueKeys = create(null);
48

    
49
function makeUniqueKey() {
50
  // Collisions are highly unlikely, but this module is in the business of
51
  // making guarantees rather than safe bets.
52
  do var uniqueKey = internString(strSlice.call(numToStr.call(rand(), 36), 2));
53
  while (hasOwn.call(uniqueKeys, uniqueKey));
54
  return uniqueKeys[uniqueKey] = uniqueKey;
55
}
56

    
57
function internString(str) {
58
  var obj = {};
59
  obj[str] = true;
60
  return Object.keys(obj)[0];
61
}
62

    
63
// External users might find this function useful, but it is not necessary
64
// for the typical use of this module.
65
exports.makeUniqueKey = makeUniqueKey;
66

    
67
// Object.getOwnPropertyNames is the only way to enumerate non-enumerable
68
// properties, so if we wrap it to ignore our secret keys, there should be
69
// no way (except guessing) to access those properties.
70
var originalGetOPNs = Object.getOwnPropertyNames;
71
Object.getOwnPropertyNames = function getOwnPropertyNames(object) {
72
  for (var names = originalGetOPNs(object),
73
           src = 0,
74
           dst = 0,
75
           len = names.length;
76
       src < len;
77
       ++src) {
78
    if (!hasOwn.call(uniqueKeys, names[src])) {
79
      if (src > dst) {
80
        names[dst] = names[src];
81
      }
82
      ++dst;
83
    }
84
  }
85
  names.length = dst;
86
  return names;
87
};
88

    
89
function defaultCreatorFn(object) {
90
  return create(null);
91
}
92

    
93
function makeAccessor(secretCreatorFn) {
94
  var brand = makeUniqueKey();
95
  var passkey = create(null);
96

    
97
  secretCreatorFn = secretCreatorFn || defaultCreatorFn;
98

    
99
  function register(object) {
100
    var secret; // Created lazily.
101

    
102
    function vault(key, forget) {
103
      // Only code that has access to the passkey can retrieve (or forget)
104
      // the secret object.
105
      if (key === passkey) {
106
        return forget
107
          ? secret = null
108
          : secret || (secret = secretCreatorFn(object));
109
      }
110
    }
111

    
112
    defProp(object, brand, vault);
113
  }
114

    
115
  function accessor(object) {
116
    if (!hasOwn.call(object, brand))
117
      register(object);
118
    return object[brand](passkey);
119
  }
120

    
121
  accessor.forget = function(object) {
122
    if (hasOwn.call(object, brand))
123
      object[brand](passkey, true);
124
  };
125

    
126
  return accessor;
127
}
128

    
129
exports.makeAccessor = makeAccessor;
(4-4/4)