2012-08-08 16 views
7

¿Puedo limitar el acceso de una función generada por cadenas (utilizando el constructor de funciones) a los ámbitos principales/globales?Hacer sandbox alrededor de Function() en Javascript

Por ejemplo: el siguiente código, como está, imprime falso, porque la función está almacenando/modificando la variable a en la ventana.

window.a = 4; 
Function("a=3;")() 
console.log(a === 4); 

¿Podría restringir el acceso a la ventana de alcance/padre y hacer que imprima "verdadero"?

Respuesta

5

No lo creo. Usted podría nombrar las variables globales que desea proteger en los parámetros para que ellos sombra:

window.a = 4; 
Function("a", "a=3;")() 
console.log(a === 4); 

Pero la función que va a tener acceso a lo global, no importa lo que intente ... es por eso que se llama global.

Dependiendo de lo que esté tratando de hacer, hay otras soluciones alternativas, como los trabajadores de la web ... y como siempre, hidden iframe hacks.

+1

Bueno, se podría definir 'window' y' document' como parámetros, para evitar el acceso directo a ellos (como ya dijiste) y luego anteponer ''use strict';' al código para evitar la definición implícita de globales. Aquello podría funcionar. Pero, por supuesto, no impide el acceso a los globales existentes, siempre y cuando no los "oculte" mediante parámetros. Quizás uno podría iterar sobre todas las propiedades de 'ventana' y crear la lista de parámetros automáticamente. –

+0

@FelixKling Suena bien al valor nominal, voy a probar algunos hacks para ver si aún puedo obtener acceso a global – Esailija

+0

@FelixKling aquí está mi actual, podría funcionar si sombreas 'Function' http://jsfiddle.net/dFmyd/ – Esailija

2

@ La respuesta de Esail es correcta. Además, recomendaría limitar el número de variables globales que debe proteger en primer lugar. Poner cualquier cosa que normalmente poner en el espacio de nombres global en un ámbito APP que el control de:

var APP = (function() { 
    return { 
     a: 4 
    }; 
}()); 

No hay manera de limitar totalmente el acceso al ámbito global, pero al menos de esta manera sólo se necesita para proteger un objeto : APP.

9

Aquí hay una idea adicional que podría ser bastante poderosa junto con la propuesta de Esailija (ver los comentarios sobre su respuesta para la discusión).

Puede crear un iframe ficticio y usar su función Function. La función creada con eso solo tendrá acceso al alcance del iframe de manera predeterminada, aunque aún podría salir de él. Afortunadamente es fácil evitar eso, por cierto sugirió Esailija.

me podía imaginar la función que ser así:

function sandboxed(code) { 
    var frame = document.createElement('iframe'); 
    document.body.appendChild(frame); 

    var F = frame.contentWindow.Function, 
     args = Object.keys(frame.contentWindow).join(); 

    document.body.removeChild(frame); 

    return F(args, code)(); 
} 

DEMO

Opcionalmente es posible que desee anteponer 'use strict'; al código.


Esto funciona, al menos en Chrome. Si la función creada de esta manera tiene acceso al ámbito global del marco flotante o el alcance global de la página se puede probar fácilmente con:

(function() { 
    var frame = document.createElement('iframe'); 
    document.body.appendChild(frame); 
    var same = window === frame.contentWindow.Function('return window;')(); 
    alert(same ? ':(' : ':)'); 
    document.body.removeChild(frame); 
}()); 
+1

Muy creativo: D +1 Me sale ':)' en todos excepto IE8, donde arroja una propiedad '' no soporta el método o el método Función' – Esailija

+0

@Esailija: Gracias por probar (no tengo IE). Tal vez la fuente del iframe tiene que establecerse explícitamente en IE ('frame.src = 'about: blank'' debería funcionar) o la propiedad simplemente recibe un nombre diferente (no' contentWindow'). Si tiene que configurar la fuente, tal vez tenga que esperar el evento 'load' antes de poder acceder a la ventana, pero por supuesto no es problema hacer que' sandboxed' acepte una devolución de llamada para el resultado :) –

+0

Sí, setting 'frame .src' funciona. – Esailija

Cuestiones relacionadas