3

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

2
  • Google Caja?
    – Sergiks
    17 авг 2014 в 6:47
  • 1
    Google Cajaэто своего рода ретрансляция. С тем же успехом можно использовать и adsafe. Или вовсе написать собственный ретранслятор. Интересовала именно реализация нативными путями. Но по всей видимости, иного способа переопределения переменных в области функции нет, при передачи онной по ссылке.
    – vldmir
    17 авг 2014 в 22:07

1 ответ 1

3

Последний пример не подходит вот ещё почему -

 (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 спасибо кстати, познавательно было.

3
  • если что- ответом я это не ставил, тут нет ответа.
    – zb'
    17 авг 2014 в 12:23
  • > . выбраться из примера Object.toString.call jsfiddle.net/zgzt1nsw/5
    – vldmir
    17 авг 2014 в 22:02
  • Есть еще задачка на подумать, если интересно. Как достать оригинальные нативные объекты браузера (как пример Object, Array, String, Function, etc), и их прототипы, если они были подменены \ изменены, ранее? Известный способ это динамическое создание фрейма - вытаскивание из него нативностей, удаление его на лету. pastebin.com/icW3D9Xw Есть еще мысли относительно реализации? upd. hashcode.ru/questions/354201
    – vldmir
    17 авг 2014 в 22:26

Ваш ответ

By clicking “Отправить ответ”, you agree to our terms of service and acknowledge you have read our privacy policy.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками или задайте свой вопрос.