simple-squiggle

A restricted subset of Squiggle
Log | Files | Refs | README

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 };