UNPKG

4.91 kBJavaScriptView Raw
1function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
2
3import { hasOwnProperty } from './object';
4/**
5 * Get a property of a plain object
6 * Throws an error in case the object is not a plain object or the
7 * property is not defined on the object itself
8 * @param {Object} object
9 * @param {string} prop
10 * @return {*} Returns the property value when safe
11 */
12
13function getSafeProperty(object, prop) {
14 // only allow getting safe properties of a plain object
15 if (isPlainObject(object) && isSafeProperty(object, prop)) {
16 return object[prop];
17 }
18
19 if (typeof object[prop] === 'function' && isSafeMethod(object, prop)) {
20 throw new Error('Cannot access method "' + prop + '" as a property');
21 }
22
23 throw new Error('No access to property "' + prop + '"');
24}
25/**
26 * Set a property on a plain object.
27 * Throws an error in case the object is not a plain object or the
28 * property would override an inherited property like .constructor or .toString
29 * @param {Object} object
30 * @param {string} prop
31 * @param {*} value
32 * @return {*} Returns the value
33 */
34// TODO: merge this function into access.js?
35
36
37function setSafeProperty(object, prop, value) {
38 // only allow setting safe properties of a plain object
39 if (isPlainObject(object) && isSafeProperty(object, prop)) {
40 object[prop] = value;
41 return value;
42 }
43
44 throw new Error('No access to property "' + prop + '"');
45}
46/**
47 * Test whether a property is safe to use for an object.
48 * For example .toString and .constructor are not safe
49 * @param {string} prop
50 * @return {boolean} Returns true when safe
51 */
52
53
54function isSafeProperty(object, prop) {
55 if (!object || _typeof(object) !== 'object') {
56 return false;
57 } // SAFE: whitelisted
58 // e.g length
59
60
61 if (hasOwnProperty(safeNativeProperties, prop)) {
62 return true;
63 } // UNSAFE: inherited from Object prototype
64 // e.g constructor
65
66
67 if (prop in Object.prototype) {
68 // 'in' is used instead of hasOwnProperty for nodejs v0.10
69 // which is inconsistent on root prototypes. It is safe
70 // here because Object.prototype is a root object
71 return false;
72 } // UNSAFE: inherited from Function prototype
73 // e.g call, apply
74
75
76 if (prop in Function.prototype) {
77 // 'in' is used instead of hasOwnProperty for nodejs v0.10
78 // which is inconsistent on root prototypes. It is safe
79 // here because Function.prototype is a root object
80 return false;
81 }
82
83 return true;
84}
85/**
86 * Validate whether a method is safe.
87 * Throws an error when that's not the case.
88 * @param {Object} object
89 * @param {string} method
90 */
91// TODO: merge this function into assign.js?
92
93
94function validateSafeMethod(object, method) {
95 if (!isSafeMethod(object, method)) {
96 throw new Error('No access to method "' + method + '"');
97 }
98}
99/**
100 * Check whether a method is safe.
101 * Throws an error when that's not the case (for example for `constructor`).
102 * @param {Object} object
103 * @param {string} method
104 * @return {boolean} Returns true when safe, false otherwise
105 */
106
107
108function isSafeMethod(object, method) {
109 if (object === null || object === undefined || typeof object[method] !== 'function') {
110 return false;
111 } // UNSAFE: ghosted
112 // e.g overridden toString
113 // Note that IE10 doesn't support __proto__ and we can't do this check there.
114
115
116 if (hasOwnProperty(object, method) && Object.getPrototypeOf && method in Object.getPrototypeOf(object)) {
117 return false;
118 } // SAFE: whitelisted
119 // e.g toString
120
121
122 if (hasOwnProperty(safeNativeMethods, method)) {
123 return true;
124 } // UNSAFE: inherited from Object prototype
125 // e.g constructor
126
127
128 if (method in Object.prototype) {
129 // 'in' is used instead of hasOwnProperty for nodejs v0.10
130 // which is inconsistent on root prototypes. It is safe
131 // here because Object.prototype is a root object
132 return false;
133 } // UNSAFE: inherited from Function prototype
134 // e.g call, apply
135
136
137 if (method in Function.prototype) {
138 // 'in' is used instead of hasOwnProperty for nodejs v0.10
139 // which is inconsistent on root prototypes. It is safe
140 // here because Function.prototype is a root object
141 return false;
142 }
143
144 return true;
145}
146
147function isPlainObject(object) {
148 return _typeof(object) === 'object' && object && object.constructor === Object;
149}
150
151var safeNativeProperties = {
152 length: true,
153 name: true
154};
155var safeNativeMethods = {
156 toString: true,
157 valueOf: true,
158 toLocaleString: true
159};
160export { getSafeProperty };
161export { setSafeProperty };
162export { isSafeProperty };
163export { validateSafeMethod };
164export { isSafeMethod };
165export { isPlainObject };
\No newline at end of file