simple-squiggle

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

customs.js (4766B)


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