Спасибо за все идеи, в итоге я просто сделал замену текста в скрипте сборки, который выводит JS, в основном заменяя $ EVAL $ на eval, после того, как все было сжато. Я надеялся на чисто JS-способ, но с таким количеством различных реализаций браузера eval, вероятно, лучше просто оставить eval в покое
Но, основываясь на ответе Димитра и немного повозившись, вот что я нашел.
Похоже, причина, по которой это ['eval'] не сработало, заключается в том, что место, где это происходит, в MooTools JSON.decode, также является внутренним хешем:
var JSON = new Hash({
// snip snip
decode: function(string, secure){
if ($type(string) != 'string' || !string.length) return null;
if (secure && !(/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(string.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, ''))) return null;
return this.eval('(' + string + ')'); // Firefox says: TypeError: this.eval is not a function
}
});
Однако, если я храню локальную область видимости «верхнего уровня» (весь код, включая mootools, выполняется внутри анонимной функции), то это работает:
var TOP = this;
var JSON = new Hash({
// snip snip
decode: function(string, secure){
if ($type(string) != 'string' || !string.length) return null;
if (secure && !(/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(string.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, ''))) return null;
return TOP.eval('(' + string + ')'); // All good, things run within the desired scope.
}
});
Однако в Safari это не работает, поэтому суть в том, что то, что я пытался сделать, нельзя сделать кросс-совместимым. eval - это особая сенсорная функция, и каждый браузер относится к ней по-разному.