mirror of
https://github.com/josdejong/mathjs.git
synced 2026-01-18 14:59:29 +00:00
132 lines
4.1 KiB
JavaScript
132 lines
4.1 KiB
JavaScript
'use strict';
|
|
|
|
var hasOwnProperty = require('./object').hasOwnProperty;
|
|
|
|
/**
|
|
* Get a property of a plain object
|
|
* Throws an error in case the object is not a plain object or the
|
|
* property is not defined on the object itself
|
|
* @param {Object} object
|
|
* @param {string} prop
|
|
* @return {*} Returns the property value when safe
|
|
*/
|
|
function getSafeProperty (object, prop) {
|
|
// only allow getting properties of a plain object
|
|
if (isPlainObject(object)) {
|
|
// only allow getting properties defined on the object itself,
|
|
// not inherited from it's prototype.
|
|
if (hasOwnProperty(object, prop)) {
|
|
return object[prop];
|
|
}
|
|
|
|
if (!(prop in object)) {
|
|
// this is a not existing property on a plain object
|
|
return undefined;
|
|
}
|
|
}
|
|
|
|
if (typeof object[prop] === 'function' && isSafeMethod(object, prop)) {
|
|
throw new Error('Cannot access method "' + prop + '" as a property');
|
|
}
|
|
|
|
throw new Error('No access to property "' + prop + '"');
|
|
}
|
|
|
|
/**
|
|
* Set a property on a plain object.
|
|
* Throws an error in case the object is not a plain object or the
|
|
* property would override an inherited property like .constructor or .toString
|
|
* @param {Object} object
|
|
* @param {string} prop
|
|
* @param {*} value
|
|
* @return {*} Returns the value
|
|
*/
|
|
// TODO: merge this function into access.js?
|
|
function setSafeProperty (object, prop, value) {
|
|
// only allow setting properties of a plain object
|
|
if (isPlainObject(object)) {
|
|
// only allow setting properties defined on the object itself,
|
|
// not inherited from it's prototype.
|
|
if (prop in object) {
|
|
// property already exists
|
|
// override when the property is defined on the object itself.
|
|
// don't allow overriding inherited properties like .constructor or .toString
|
|
if (hasOwnProperty(object, prop)) {
|
|
return object[prop] = value;
|
|
}
|
|
}
|
|
else {
|
|
// this is a new property, that's just ok
|
|
return object[prop] = value;
|
|
}
|
|
}
|
|
|
|
throw new Error('No access to property "' + prop + '"');
|
|
}
|
|
|
|
/**
|
|
* Test whether a property is safe to use for an object.
|
|
* For example .toString and .constructor are not safe
|
|
* @param {string} prop
|
|
* @return {boolean} Returns true when safe
|
|
*/
|
|
function isSafeProperty (prop) {
|
|
return !(prop in {});
|
|
}
|
|
|
|
/**
|
|
* Validate whether a method is safe.
|
|
* Throws an error when that's not the case.
|
|
* @param {Object} object
|
|
* @param {string} method
|
|
*/
|
|
// TODO: merge this function into assign.js?
|
|
function validateSafeMethod (object, method) {
|
|
if (!isSafeMethod(object, method)) {
|
|
throw new Error('No access to method "' + method + '"');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Check whether a method is safe.
|
|
* Throws an error when that's not the case (for example for `constructor`).
|
|
* @param {Object} object
|
|
* @param {string} method
|
|
* @return {boolean} Returns true when safe, false otherwise
|
|
*/
|
|
function isSafeMethod (object, method) {
|
|
// test for plain functions defined on the object (instead of a method)
|
|
if (hasOwnProperty(object, method)) {
|
|
return isPlainObject(object);
|
|
}
|
|
else {
|
|
// only allow methods:
|
|
// - defined on the prototype of this object
|
|
// - not defined on the prototype of native Object
|
|
// i.e. constructor, __defineGetter__, hasOwnProperty, etc. are not allowed
|
|
// - calling methods on a function (like bind) is not allowed
|
|
// - A few safe native methods are allowed: toString, valueOf, toLocaleString
|
|
return (object && typeof object !== 'function' &&
|
|
(hasOwnProperty(object.constructor.prototype, method) ||
|
|
hasOwnProperty(object.__proto__, method)) &&
|
|
(!hasOwnProperty(Object.prototype, method) || hasOwnProperty(safeNativeMethods, method)));
|
|
}
|
|
}
|
|
|
|
function isPlainObject (object) {
|
|
return typeof object === 'object' && object && object.constructor === Object;
|
|
}
|
|
|
|
var safeNativeMethods = {
|
|
toString: true,
|
|
valueOf: true,
|
|
toLocaleString: true
|
|
};
|
|
|
|
exports.getSafeProperty = getSafeProperty;
|
|
exports.setSafeProperty = setSafeProperty;
|
|
exports.isSafeProperty = isSafeProperty;
|
|
exports.validateSafeMethod = validateSafeMethod;
|
|
exports.isSafeMethod = isSafeMethod;
|
|
exports.isPlainObject = isPlainObject;
|