UNPKG

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