2012-08-08 7 views
7

Kann ich den Zugriff einer stringgenerierten Funktion (mithilfe des Konstruktors Function) auf die übergeordneten/globalen Bereiche beschränken?Machen Sie eine Sandbox um Function() in Javascript

Zum Beispiel: der folgende Code, so wie er ist, druckt false, weil die Funktion speichert/ändert die Variable a im Fenster.

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

Kann ich den Zugriff auf Fenster/geordneten Bereich beschränken und es „true“ auszudrucken machen?

Antwort

5

Ich glaube nicht. Sie könnten die Globals nennen Sie in den Parametern schützen wollen, damit sie sie Schatten:

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

Aber die Funktion wird den Zugang zu globalen haben, egal was Sie versuchen, ... das ist, warum es global genannt wird.

Je nachdem, was Sie zu tun versuchen, gibt es andere Work-arounds wie Web-Arbeiter ... und wie immer hidden iframe hacks.

+1

Nun, könnten Sie 'window' und' document' als Parameter definieren die direkten Zugriff zu verhindern, Sie (wie Sie bereits sagten) und dann '' verwenden Sie strict '; 'auf den Code, um implizite Definition von Globals zu verhindern. Das könnte funktionieren. Es verhindert natürlich nicht den Zugriff auf existierende Globals, solange Sie diese nicht über Parameter "beschatten". Vielleicht könnte man über alle 'Fenster'-Eigenschaften iterieren und die Parameterliste automatisch erstellen. –

+0

@FelixKling Klingt gut auf den Nennwert, ich werde ein paar Hacks versuchen, um zu sehen, ob ich immer noch Zugriff auf globale – Esailija

+0

@FelixKling hier ist meine aktuelle, könnte funktionieren, wenn Sie 'Funktion' http://jsfiddle.net Schatten/dFmyd/ – Esailija

2

@ Esailija's Antwort ist richtig. Außerdem würde ich empfehlen, die Anzahl der globalen Variablen zu begrenzen, die Sie zuerst schützen müssen. Setzen Sie alles, was Sie normalerweise im globalen Namespace in einem APP Rahmen setzen würde, die Sie steuern:

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

Es gibt keinen Weg, um vollständig Zugriff auf den globalen Bereich zu beschränken, sondern zumindest auf diese Weise müssen Sie nur ein Objekt schützen : APP.

9

Hier ist eine zusätzliche Idee, die zusammen mit dem Vorschlag von Estagija ziemlich kraftvoll sein könnte (siehe die Kommentare zu seiner Antwort auf die Diskussion).

Sie könnten Dummy-Iframe erstellen und seine Function-Funktion verwenden. Die damit erstellte Funktion hat standardmäßig nur Zugriff auf den Gültigkeitsbereich des iframes, könnte aber trotzdem aus ihr herausbrechen. Glücklicherweise ist es leicht, dies zu verhindern, wie es Eschlija vorgeschlagen hat.

Ich konnte die Funktion vorstellen, so sein:

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

Optional Sie 'use strict'; an den Code voranstellen möchten.


Dies funktioniert zumindest in Chrome. Ob die auf diese Weise geschaffene Funktion Zugriff auf die iframe der globalen Bereich hat oder globalen Bereich der Seite kann leicht mit getestet werden:

(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

Sehr kreativ: D +1 Ich bekomme ':)' in allen außer IE8, wo es wirft eine 'nicht unterstützt Eigenschaft oder Methode Funktion' – Esailija

+0

@Esailija: Danke für die Prüfung (ich habe nicht IE). Vielleicht muss die Quelle des Iframes explizit im IE gesetzt werden ('frame.src = 'about: blank' sollte das tun) oder die Eigenschaft wird nur anders benannt (nicht' contentWindow'). Wenn Sie die Quelle einstellen müssen, müssen Sie vielleicht auf das 'load' Ereignis warten, bevor Sie auf das Fenster zugreifen können, aber natürlich ist es kein Problem,' sandboxed' einen Rückruf für das Ergebnis zu akzeptieren :) –

+0

Ja, Einstellung 'frame .src' funktioniert. – Esailija

Verwandte Themen