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