customs.js 5.1 KB

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