2010-02-03 36 views
7

Aquí está el acuerdo, tenemos una gran biblioteca JS que queremos comprimir, pero YUI compressor no comprime completamente el código si encuentra una declaración "eval" , por temor a que rompa algo más. Eso está muy bien y todo, pero sabemos exactamente lo que está consiguiendo eval'd, por lo que no quiero que esté conservadora porque hay una sentencia eval en MooTools JSON.decodeCómo ejecutar "eval" sin escribir "eval" en JavaScript

Así que, básicamente, la pregunta es, ¿hay alguna forma alternativa (tal vez creativa) de escribir una expresión que devuelve la función eval? Probé unos pocos, pero no dice:

window['eval'](stuff); 
window['e'+'val'](stuff); 
// stuff runs in the global scope, we need local scope 

this['eval'](stuff); 
// this.eval is not a function 

(new Function("with(this) { return " + '(' + stuff + ')' + "}"))() 
// global scope again 

¿Alguna idea? Thx

+0

te estás jodiendo porque 'eval' no se considera una función normal. usted podría ser más astuto que el compresor YUI, pero se encontrará con navegadores que no lo harán o no le permitirán llamar a 'eval' con cualquier otro nombre. –

Respuesta

3

Gracias por todas las ideas, terminé haciendo reemplazo de texto en el script de compilación que genera el JS, básicamente reemplazando $ EVAL $ con eval, después de que todo ha sido comprimido. Esperaba una forma puramente JS, pero con tantas implementaciones diferentes de navegadores eval, probablemente sea mejor simplemente dejar eval solo

Pero, en base a la respuesta de Dimitar y algunos ajustes, esto es lo que encontré. parece que la razón por la cual esta [ 'eval'] no era un trabajo es porque el lugar donde está ocurriendo, en MooTools JSON.decode, es también un interior de un Hash:

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 
} 

}); 

Sin embargo, si guardo el "nivel superior" ámbito local (todo el código, incluyendo mootools, se ejecuta dentro de una función anónima), entonces funciona:

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. 
} 

}); 

sin embargo, esto no funciona en Safari, por lo que la línea de fondo es, lo que intentaba hacer no se puede hacer compatible de forma cruzada. eval es una función táctil especial y cada navegador la trata de manera diferente.

0
var e = "e"; 
window[e+"val"](stuff); 
+0

Eso no funciona, las cosas se ejecutan en el ámbito global. Además, no parece ser portable, webkit emite – adamJLev

+0

'ventana [" e "+" val "] (cosas)'? – elcuco

+0

'window.eval === ventana ['eval'] === ventana ['e' + 'val']' así que no hay dados ... cosas se evalúan en el alcance de la ventana que no es lo que necesitamos – adamJLev

0

Si es posible es posible que desee probar una de las otras bibliotecas de compresión desde YUI no es el único juego en la ciudad más.

Aquí hay un par de artículos sobre las otras herramientas de compresión disponibles.

Microsoft y Google parecen hacer un mejor trabajo que YUI de todos modos.

+0

Gracias para las sugerencias. He jugado con Google Closure, pero es demasiado agresivo para nosotros, cambia el nombre de muchas cosas y rompe el código. Se requeriría algo de tiempo para adaptar el código solo para que se ejecute, y probablemente introduzca nuevos errores. Y sería bueno comprobar las cosas de MS, pero somos una tienda de Java/OSX – adamJLev

+0

El truco con Google Closure es simplemente usar la compresión Simple, y si eso falla, simplemente use el espacio en blanco. Que es una alternativa segura, y simplemente elimina todos los espacios en blanco, lo cual es mejor que nada. –

+0

Eso también funciona con YUI, lo minimiza y todo eso, pero no reemplaza los nombres largos de variables con los más cortos debido a las evaluaciones – adamJLev

1

¿Podría refactorizar las llamadas de evaluación a alguna función de corrección externa que no forme parte del archivo que se está comprimiendo?

3

No estoy seguro si he entendido, pero se puede aplicar una función a un (esto) ámbito local específico:

var x = 5; 

var f = new Function('alert(this.x)'); 

function A(x){ 
    this.x = x; 
    f.apply(this,[]); 
} 

a = new A(10); 

Esto alerta a 10 como F se aplica con A.This

1

soy yo ¿Echando de menos algo?

var noteval = this.eval; // can be defined before the file is loaded 
noteval("alert('not eval. at all');"); 

(function() { 
    console.log(this); 
    noteval("alert('chavs!');"); 
}).bind(window)(); 

(function() { 
    console.log(this); 
    noteval("alert('crappy parents');"); 
}).bind(window.parent)(); 

comprobarlo http://www.jsfiddle.net/nGL79/ con los marcos de diferentes ámbitos como eval.

y específico para mootools:

window["ev"+"al"].pass("alert('what');")(); 
this["ev"+"al"].pass("alert('no!');")(); // local scope too? 

y

var noteval = window["ev"+"al"].create({ 
    bind: this 
}); 

esperanza alguna de que eso ayuda ... espero que no consigue función eval se debe llamar directamente, y no a modo de una función de otro nombre aunque

+0

Gracias por las ideas, al menos ahora entiendo por qué this.eval no funcionaba. Eche un vistazo a mi propia respuesta – adamJLev

0

De esta manera se necesita jQuery.

function NotEval(code, callBack) { 
    $.ajax({ 
     url: 'data:application/javascript;charset=utf-8,' + encodeURIComponent(code), 
     cache:true, 
     success: function (r) { 
      if (typeof callBack === "function") { 
       callBack() 
      } 
     }, 
     error: function (r) { 
      console.log("Eval error"); 
      console.log(r) 
     } 
    }) 
}