2012-04-29 10 views
11

Una delle limitazioni di JS che mi infastidisce di più è la scarsa capacità di isolare l'esecuzione del codice.Isola l'esecuzione di JavaScript

Voglio essere in grado di controllare il contesto in cui viene eseguito il codice, qualcosa che ottenere un effetto simile a quello che Script.createContext & Script.runInContext a node.js fa (nodo sta usando il legame con il motore V8, così posso' t emulare la loro implementazione).

Ecco l'qualche ragione per cui voglio isolare l'esecuzione di codice:

  1. isolare il codice dal namespace globale (l'oggetto window e anche la DOM), ma ho comunque bisogno di essere funzione di riferimento in grado chiamare gli oggetti esposti nel contesto che devono essere eseguiti in sincrono, il che rende quasi impossibile l'uso di un WebWorker per l'isolamento.
  2. Isolando l'esecuzione del codice, sarebbe anche possibile rilasciare le sue definizioni quando non più necessarie (gestione della memoria).

So che si può ottenere l'esecuzione in parte isolato da uno script di caricamento in un iframe, questo approccio è però molto pesante e utilizza una memoria molto per una seconda istanza del DOM che non è necessario per quello che sto cercando fare.

Ho bisogno di condividere la definizione del costruttore e anche le definizioni di oggetto che sono condivise tra i contenitori/contesti isolati che entrambi devono essere eseguiti sul thread principale dell'interfaccia utente. Principalmente voglio utilizzare questi contenitori isolati per ospitare plug-in/moduli (mini-applicazioni) che presentano e aggiornano dinamicamente un viewport chiamando i comandi di disegno sul proprio oggetto Context2D.

Se questi contenitori non sono in esecuzione sul thread principale dell'interfaccia utente che wold essere dolorosamente difficile delega chiamate come ctx.measureText() e ctx.drawImage() sarebbe tutto inutile come oggetti immagine non possono essere creati in un Worker.

Qualcuno sa delle specifiche future che renderebbero questo possibile?

Esistono API (nascoste) sul lato del browser che potrebbero essere utilizzate per raggiungere questo obiettivo?

Sarebbe meglio utilizzare una macchina virtuale come Gart Dart VM di Goggle e anche implementare la mia base di codice corrente? Il mio codice attuale è leggermente superiore a 20 000 righe di codice.

sarebbe meglio re-implementare il quadro in *

+4

Avete un * problema * esistente che deve essere risolto in questo modo? [IIABDFI] (http://acronyms.thefreedictionary.com/IIABDFI). – Ryan

+0

D'accordo con il commento, ma downvote è un po 'inutile. – Starx

+0

@minitech In realtà ho un problema con la mancanza di sandox (che è una parola migliore per ciò che ho descritto sopra) nel runtime del browser, perché sto cercando di ottenere un'architettura di plugin per la mia piattaforma lato client, che è scritto in JavaScript e utilizza il runtime del browser per tale. La piattaforma è generica e il suo scopo principale è ospitare l'ambiente per caricare e controllare in modo dinamico plug-in/moduli/mini-applicazioni che fornisce alla piattaforma funzionalità aggiuntive. – Raweden

risposta

3

È possibile isolare il codice da namespace globale con un oggetto semplice funzione self executing:

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

})(); 

Se si desidera avere più quelli di questi contesti di esecuzione e essere in grado di condividere tra di loro, quindi si dovrà renderezvous tramite una posizione pubblicamente nota, o una variabile veramente globale o una proprietà su un oggetto DOM noto o qualcosa del genere. È relativamente comune dichiarare un oggetto spazio dei nomi globale e utilizzare le proprietà al di fuori di esso per qualsiasi accesso alle cose che si condividono tra i moduli. So che non è completamente perfetto, ma funziona.Ecco un esempio di rendevous utilizzando un unico oggetto namespace globale:

// 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

Non sono sicuro se questo è il tipo di isolamento che l'OP sta chiedendo. _ (Ma non sono sicuro di aver capito anche lui) _ – Starx

+0

@Matt, non sto cercando di mantenere il codice dell'OP per tornare alla finestra. È sempre facile. Sto cercando di tenere le altre persone fuori dal codice OP e mantenere il codice dell'OP isolato dal codice di altre persone. – jfriend00

+0

@ jfriend00 Sì, penso che ci sia un po 'di confusione su ciò che l'OP sta cercando – Matt

2

La biblioteca più vicina che ho visto per questo è Caja.

Fondamentalmente, nel codice javascript non rigido, ci sono molti modi per ottenere l'accesso all'oggetto globale (window nei browser), rendendo il vero isolamento un problema molto difficile. Caja fa alcuni trucchi iframing per ricucire questo, ma ad essere onesti non sono esattamente sicuro di come funzioni.

+0

Se si forza la modalità rigorosa, facendo qualcosa come la valutazione di uno script, può essere molto più semplice? –

+0

@BT 'use strict' ha sicuramente migliorato la situazione, ma ci sono ancora così tante cose da dover applicare. È lontano da una garanzia sicura. Ad esempio, invocare il setTimeout o cose simili può essere fatto in modo implicito sulla finestra, anche se lo si sovrascrive: '(function (window) {'use strict'; setTimeout (function() {console.log (this);});} ({})); '<- questo stamperà la finestra globale nonostante l'override lessicale – Matt

+0

Ma per lo stesso token, è possibile eseguire in modo lessicale l'override di' setTimeout' proprio come si fa per la finestra per un risultato più completo. –

1

Il namespace "standard" è un'opzione? Come:

var myNamespace = {}; 

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

Questo approccio è il più semplice a cui riesco a pensare e potrebbe essere la soluzione a molti problemi. Sebbene non sia una vera sandbox, può lasciare il codice meno incline agli errori.

0

Non potresti usare una chiusura come le altre risposte citate e poi usare una shadow dom per garantire che l'utente non possa accedere al resto del dom? Qualcosa di simile a questo:

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) 

Avvertenze:

  • Se si creano altri oggetti globali al di fuori del contesto del codice isolato, è necessario ombra in modo esplicito la variabile come ho fatto con finestra, documenti, ecc, altrimenti il ​​codice isolato sarà per accedervi.
  • Questo non funzionerà nei browser che non hanno shadow dom, ovviamente, a meno che il tuo codice isolato non abbia bisogno di interagire con la dom.
  • Devi stare molto attento che oggetti do do l'accesso al codice isolato a non contenga riferimenti a cose che non hai . A volte questo è un super errore incline a fare.
  • Sto facendo questo suggerimento perché è plausibile che funzioni, ma non ho idea se ci sono modi aggiuntivi per arrivare a cose come la finestra e gli oggetti del documento.