function makeMap(str, expectsLowerCase) {
var map = Object.create(null);
var list = str.split(',');
for (var i = 0; i < list.length; i++) {
map[list[i]] = true;
}
return expectsLowerCase ?
function (val) {
return map[val.toLowerCase()];
} :
function (val) {
return map[val];
}
}
var allowedGlobal = makeMap('Infinity,undefined,NaN,isFinite,isNaN,' +
'parseFloat,parseInt,decodeURI,decodeURIComponent,encodeURI,encodeURIComponent,' +
'Math,Number,Date,Array,Object,Boolean,String,RegExp,Map,Set,JSON,Intl,' +
'require');
var hasHandler = {
has: function has(target, key) {
const hasKey = key in target;
const isAllowed = allowedGlobal(key);
return hasKey || !isAllowed;
}
};
var vm = {
foo: -1
};
var vm = new Proxy(vm, hasHandler);
var buildFunction = function (vm, expression) {
var fun = new Function("vm", `
with(vm) {
return ${expression};
}
`);
return function () {
return fun(vm);
};
}
// 尝试访问vm上的foo对象,和全局定义的Math对象
var okExpression = 'Math.abs(foo)';
var okEval = buildFunction(vm, okExpression);
okEval();
// 尝试访问全局的test_foo
window.test_foo = "Hello there";
var errExpression = 'test_foo || window.test_foo';
var errEval = buildFunction(vm, errExpression);
errEval();