UNPKG

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