Есть необходимость выполнять анонимную функцию (на клиенте) в ограниченной области видимости с собственными переменными окружения (без доступа к глобальным переменным). Переопределение контекста this не проблема, а вот с переменными мне видится лишь один вариант - это eval. Но так как eval следует оставлять на самый край, решил поинтересоваться у сообщества, нет ли иных вариантов решения проблемы.
Собственно задача:
function sandbox(fn){ // реализация с помощью eval'а
fn = fn.toString();
// необходимо динамически создать переменные внутри fn
fn = '(function(){"use strict"; var window, document; (' + fn + ').call(this);}) ';
fn = eval(fn);
fn.call({}); // например
}
sandbox(function(){
console.log(window, document, this); // вернет undefined, undefined, Object {}
});
За предопределение переменных должна отвечать функция sandbox. То бишь вариант с явным переопределением переменных внутри передаваемой функции не предлагать. Варианты с динамическим созданием фрейма с собственным окружением, как и передача переменных параметрами в функцию
(function(window, document){...})(null, null)
тоже не подходят, ибо это и так все очевидно, а в здесь необходима динамизация этого процесса функцией sandbox. Есть иные пути решения без использования eval?
Заранее спасибо.
Обновление
Это всего-лишь пример. Я знаю пути реализации песочницы через фреймы и воркеры. Меня интересует реализация в общем контексте. И на данный момент известны решения только через eval (или new Function).
По поводу crackSandbox - переопределить можно любые переменные кроме самого eval'a http://jsfiddle.net/zgzt1nsw/1/ Но вопрос не в этом заключается, а в возможных путях решения, избегая eval'a.
Обновление 2
А нужно это, например для фреймворка, в котором можно использовать собственные любые объекты отбрасывая префиксы и прочие вещи, даже переопределять прототипы встроенных объектов на время работы песочницы. По сути это реализация конструкция with, но она deprecated ныне, и посему и ищутся подобные костыли.
Обновление 3
var node = new Node; // объект класса браузера
sandbox(function(){
var node = new Node; // объект класса фреймворка (который будет пробрасываться через sandbox)
});
node.someMethod; // а здесь уже снова объект класса браузера
Но по всей видимости, вариантов иных нет, помимо eval(=new Function), dynamic frame, workers-sandbox
и etc.
Обновление 4
В функцию sandbox можно добавить в начале кэширование имеющихся прототипов встроенных объектов, затем создается песочница, выполняется (в ней прототипы меняются как угодно), а после отработки песочницы, прототипы откатываются к закешированному состоянию. И поэтому не важно будет, какие методы в прототипах были созданы в песочнице, после ее отработки, они будут удалены (откатятся к состоянию до ее создания).