Страницы

Поиск по вопросам

суббота, 11 апреля 2020 г.

Динамическое создание переменных, собственная область видимости, как выполнить функцию в песочнице?

#песочница #sandbox #javascript

                    
Есть необходимость выполнять анонимную функцию (на клиенте) в ограниченной области
видимости с собственными переменными окружения (без доступа к глобальным переменным).
Переопределение контекста 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 можно добавить в начале кэширование имеющихся прототипов встроенных
объектов, затем создается песочница, выполняется (в ней прототипы меняются как угодно),
а после отработки песочницы, прототипы откатываются к закешированному состоянию. И
поэтому не важно будет, какие методы в прототипах были созданы в песочнице, после ее
отработки, они будут удалены (откатятся к состоянию до ее создания).    


Ответы

Ответ 1



Последний пример не подходит вот ещё почему - (function(window, document){window=(function(){return this;})() })(null, null) Ваш шанс - iframe на другом домене(посмотрите как сделаны песочницы типа jsfiddle jsbin plnkr). Обновление Зачем это кстати надо? Вот, например, webworkers не имеют доступа к DOM, window и document, правда создание их на лету немного похоже на eval, но зато работать будет, с eval навреное я погорячился, strict не заметил. Но http://jsfiddle.net/oceog/z99z7zkc/ (и наверняка еще что-то можно забыть). Обновление 2 Мне кажется это скорее академический интерес может представлять нежели чем практический, "даже переопределять прототипы встроенных объектов на время работы песочницы" это, мне кажется не сработает без полной изоляции (iframe,woekers) т.к. либо это будет бесполезным (Например, [] не будет подхватывать Array.prototype) либо/и можно будет изменить через свойство __proto__ http://jsfiddle.net/oceog/zgzt1nsw/3/ Обновление 3 В функцию sandbox можно добавить в начале кэширование имеющихся прототипов встроенных объектов В общем мое мнение - против злонамеренных не победить, в конце концов есть getters/setters и прочее, сделают unmutable или как там и всё, а для тествого фреймворка, который посему-то печется о своих переменных и не хочет тесты в отдельном треде пускать прокатит. Вы в этом явно больше моего знаете, не могу понять только какая практическая ценность. выбраться из примера - в общем куча дыр все равно остается. @vldmir спасибо кстати, познавательно было.

Комментариев нет:

Отправить комментарий