argencoders-notevil
Version:
Evaluate javascript like the built-in eval() method but safely
112 lines (95 loc) • 2.64 kB
JavaScript
var names = ['Object', 'String', 'Boolean', 'Number', 'RegExp', 'Date', 'Array', 'Function']
var immutable = {string: 'String', boolean: 'Boolean', number: 'Number' }
var primitives = names.map(getGlobal)
var protos = primitives.map(getProto)
var protoReplacements = {}
module.exports = Primitives
function Primitives(context){
if (this instanceof Primitives){
this.context = context
for (var i=0;i<names.length;i++){
if (!this.context[names[i]]){
this.context[names[i]] = wrap(primitives[i])
}
}
} else {
return new Primitives(context)
}
}
Primitives.prototype.replace = function(value){
var primIndex = primitives.indexOf(value)
var protoIndex = protos.indexOf(value)
if (~primIndex){
var name = names[primIndex]
return this.context[name]
} else if (~protoIndex) {
var name = names[protoIndex]
return this.context[name].prototype
} else {
return value
}
}
Primitives.prototype.getPropertyObject = function(object, property){
if (immutable[typeof object]){
return this.getPrototypeOf(object)
}
return object
}
Primitives.prototype.isPrimitive = function(value){
return !!~primitives.indexOf(value) || !!~protos.indexOf(value)
}
Primitives.prototype.getPrototypeOf = function(value){
if (value == null){ // handle null and undefined
return value
}
var immutableType = immutable[typeof value]
if (immutableType){
var proto = this.context[immutableType].prototype
} else {
var proto = Object.getPrototypeOf(value)
}
if (!proto || proto === Object.prototype){
return null
} else {
var replacement = this.replace(proto)
if (replacement === value){
replacement = this.replace(Object.prototype)
}
return replacement
}
}
Primitives.prototype.applyNew = function(func, args){
if (func.wrapped){
var prim = Object.getPrototypeOf(func)
var instance = new (Function.prototype.bind.apply(prim, arguments))
setProto(instance, func.prototype)
return instance
} else {
return new (Function.prototype.bind.apply(func, arguments))
}
}
function getProto(func){
return func.prototype
}
function getGlobal(str){
return global[str]
}
function setProto(obj, proto){
obj.__proto__ = proto
}
function wrap(prim){
var proto = Object.create(prim.prototype)
var result = function() {
if (this instanceof result){
prim.apply(this, arguments)
} else {
var instance = prim.apply(null, arguments)
setProto(instance, proto)
return instance
}
}
setProto(result, prim)
result.prototype = proto
result.wrapped = true
return result
}