2012-04-29 16 views
11

Una de las limitaciones de JS que más me molesta es la poca capacidad de aislar la ejecución del código.Aislar la ejecución de JavaScript

Quiero ser capaz de controlar el contexto en el que se ejecuta el código, algo que logran un efecto similar a lo que Script.createContext & Script.runInContext en Node.js qué (nodo es el uso de la unión al motor V8, así que puedo' emular su implementación).

Aquí es el alguna razón por la que quiero para aislar la ejecución de código:

  1. aislar el código del espacio de nombres global (el objeto window y también la DOM), pero sin embargo tienen que ser función de referencia capaces invoca objetos expuestos en el contexto que deben ejecutarse sincrónicamente, lo que hace que sea casi imposible utilizar un WebWorker para el aislamiento.
  2. Al aislar la ejecución del código, también es posible desasignar sus definiciones cuando ya no sea necesario (gestión de la memoria).

Sé que uno puede lograr la ejecución en parte aisladas por el guión de carga en un iframe, sin embargo este enfoque es muy pesado y utiliza una memoria mucho para una segunda instancia del DOM que no se necesita para lo que intento que hacer.

Necesito compartir la definición del constructor y también las definiciones del objeto que se comparten entre los contenedores/contextos aislados que ambos deben ejecutarse en el hilo de la interfaz de usuario principal. Principalmente, quiero utilizar estos contenedores aislados para alojar complementos/módulos (miniaplicaciones) que cada uno presenta y actualiza dinámicamente una ventana gráfica llamando comandos de dibujo en su propio objeto Context2D.

Si estos contenedores no se están ejecutando en el hilo principal interfaz de usuario que Wold ser dolorosamente difícil de proxy llama como ctx.measureText()ctx.drawImage() y sería inútil como todos los objetos de imagen no se pueden crear en un Worker.

¿Alguien sabe de la especificación futura que haría esto posible?

¿Hay alguna API actual (oculta) del lado del navegador que pueda usarse para lograr esto?

¿Sería mejor utilizar una máquina virtual como Goggle's Dart VM y también volver a implementar mi base de código actual? Mi código base actual es ligeramente superior a 20 000 líneas de código.

sería mejor volver a aplicar el marco en *

+4

¿Tiene un problema * * que deba solucionarse así? [IIABDFI] (http://acronyms.thefreedictionary.com/IIABDFI). – Ryan

+0

Estoy de acuerdo con el comentario, pero el voto a favor es un poco innecesario. – Starx

+0

@minitech Realmente tengo un problema con la falta de sandoxes (que es una mejor palabra para describir lo que describí anteriormente) en el tiempo de ejecución del navegador, debido a que estoy tratando de lograr una arquitectura de complemento para mi plataforma del lado del cliente, que está escrito en JavaScript y utiliza el tiempo de ejecución del navegador para tal. La plataforma es genérica y su propósito principal es hospedar el entorno para cargar y controlar dinámicamente los complementos/módulos/mini-aplicaciones que proporcionan a la plataforma características adicionales. – Raweden

Respuesta

3

Puede aislar el código del espacio de nombres global con una función simple objeto efectiva automáticamente:

(function() { 
    // all your code goes here 
    // nobody outside of your code can reach your top level variables here 
    // your top level variables are not on the window object 

    // this is a protected, but top level variable 
    var x = 3; 

    // if you want anything to be global, you can assign it to the window object. 
    window.myGlobal = {}; 

    function myTopLevelFunction(x,y,z) { 
     // code here 
    } 

})(); 

Si usted quiere tener múltiples Uno de estos contextos de ejecución y poder compartir entre ellos, tendrá que encontrarse en una ubicación conocida públicamente, ya sea una variable verdaderamente global o una propiedad en un objeto DOM conocido o algo así. Es relativamente común declarar un objeto de espacio de nombres global y usar propiedades de eso para cualquier acceso a cosas que está compartiendo entre módulos. Sé que no es completamente perfecto, pero funciona.He aquí un ejemplo de la rendevous utilizando un único objeto de espacio de nombres global:

// module AAA 
(function() { 
    // module AAA code goes here 

    // set up global namespace object and whatever references we want to be global 
    window.myModuleTop = window.myModuleTop || {}; 
    myModuleTop.AAA = {}; 
    myModuleTop.AAA.myFuncA = function() {}; 

})(); 


// module BBB 
(function() { 
    // module BBB code goes here 

    // set up global namespace object and whatever references we want to be global 
    window.myModuleTop = window.myModuleTop || {}; 
    myModuleTop.BBB = {}; 
    myModuleTop.BBB.myFuncB = function() {}; 

})(); 
+0

No estoy seguro de si este es el tipo de aislamiento que OP está pidiendo. _ (Pero no estoy seguro de entenderlo también) _ – Starx

+0

@Matt, no estoy tratando de evitar que el código del OP regrese a la ventana. Eso es siempre fácil. Estoy tratando de mantener a otras personas fuera del código del OP y mantener el código del OP aislado del código de otras personas. – jfriend00

+0

@ jfriend00 sí, creo que hay algo de confusión en lo que busca el OP – Matt

2

La biblioteca más cercana que he visto para esto es Caja.

Básicamente, en el código javascript no estricto, hay muchas maneras de obtener acceso al objeto global (window en los navegadores), haciendo que el aislamiento verdadero sea un problema muy difícil. Caja hace algunos trucos para enmarcar esto, pero para ser sincero, no estoy exactamente seguro de cómo funciona.

+0

Si forzas el modo estricto, al hacer algo como evaluar un guión, ¿puede ser mucho más fácil? –

+0

@BT 'use strict' sin duda ha mejorado la situación, pero todavía hay tantas cosas que tendrías que parchar. Está lejos de ser una garantía segura. Por ejemplo, invocar setTimeout o cosas similares se puede hacer en la ventana implícitamente, incluso si lo reemplaza: '(function (window) {'use strict'; setTimeout (function() {console.log (this);});} ({})); '<- esto imprimirá la ventana global a pesar de la anulación léxica – Matt

+0

Pero de la misma manera, podría reemplazar léxicamente' setTimeout' tal como lo hace para la ventana para obtener un resultado más completo. –

1

¿El espacio de nombres "estándar" es una opción? Me gusta:

var myNamespace = {}; 

myNamespace.myFunc = function() { return true; } 

Este enfoque es el más simple que puedo pensar y puede ser la solución a muchos problemas. Aunque no es una caja de arena real, puede dejar que el código sea menos propenso a errores.

0

¿No podría usar un cierre como otras respuestas mencionadas y luego usar una sombra dom para asegurarse de que el usuario no pueda acceder al resto del dom? Algo como esto:

var containerNode = someDomNode 
var root = containerNode.createShadowRoot() 
;(function(root){ 
    var window = null, document = null, history = null, 
     screen = null, navigator = null, location = null 

    // isolated code goes here 

})(root) 

Advertencias:

  • Si crea otros objetos globales fuera del contexto del código aislado, que necesita a la sombra de forma explícita la variable como lo hice con ventana, documento, etc., de lo contrario, el código aislado será acceder a él.
  • Esto no funcionará en los navegadores que no tienen shadow dom obviamente, a menos que su código aislado no necesite interactuar con el dom en absoluto.
  • Tienes que tener mucho cuidado de que los objetos que do dan acceso al código aislado no contengan referencias a cosas que no quieres querer que tengan acceso. A veces esto es súper error propenso a hacer.
  • Estoy haciendo esta sugerencia porque es plausible que funcione, pero no tengo idea de si hay otras maneras de llegar a cosas como la ventana y los objetos del documento.
Cuestiones relacionadas