Dominique Stender: Vergleichsoperationen evaluieren ohne eval()

Hi,

ich muß per JavaScript eine Vergleichsoperation (in einem String) evaluieren, z.B:
var validation = "[WERT] == 'Firma' || [WERT] == 'Familie'";

Der Platzhalter [WERT] wird über Umwege aus HTML Formularfeldern ermittelt, die Strings sind statisch konfiguriert.

Es wäre natürlich ein leichtes, das Ganze über eval(validation) erledigen zu lassen, aber das würde Cross-Site-Scripting Attacken Tür und Tor öffnen und fällt damit leider flach.

Kennt jemand daher entweder
a) eine "Alternative" zu eval(), welche zwar Vergleiche evaluiert, aber kein JavaScript interpretiert oder
b) einen halbwegs elegant zu programmierenden Ansatz, entsprechendes selbst zu entwickeln bzw.
c) sonst irgendwas?

Geforderter Umfang:

  • Vergleiche von Zahlen sowie Strings
  • sämtliche Vergleichsoperatoren die in JavaScript erlaubt sind.
  • verknüpfte Vergleiche über || sowie &&
  • geklammerte Vergleiche

1000 Dank schon mal im Voraus,
Dominique

  1. ich muß per JavaScript eine Vergleichsoperation (in einem String) evaluieren, z.B:
    var validation = "[WERT] == 'Firma' || [WERT] == 'Familie'";

    Der Platzhalter [WERT] wird über Umwege aus HTML Formularfeldern ermittelt, die Strings sind statisch konfiguriert.

    Was heißt über Umwege?

    Kennt jemand daher entweder
    a) eine "Alternative" zu eval(), welche zwar Vergleiche evaluiert, aber kein JavaScript interpretiert oder

    eval ist nur dann nötig, wenn du zur Laufzeit JS Code erzeugst. Andersherum, es gibt keine alternative zu eval, wenn du einen string hast, der JS Code enthält und du ihn ausführen musst. Aber fast immer wenn eval benutz wird liegt das eher daran, das jemand nicht weiß wie man Objekte in JS ansprechen kann.

    b) einen halbwegs elegant zu programmierenden Ansatz, entsprechendes selbst zu entwickeln bzw.

    Was willst du machen?

    Struppi.

    1. ich muß per JavaScript eine Vergleichsoperation (in einem String) evaluieren, z.B:
      var validation = "[WERT] == 'Firma' || [WERT] == 'Familie'";

      Der Platzhalter [WERT] wird über Umwege aus HTML Formularfeldern ermittelt, die Strings sind statisch konfiguriert.

      ...

      eval ist nur dann nötig, wenn du zur Laufzeit JS Code erzeugst.

      Korrektur: wenn ich zur Laufzeit JS Code _ausführen_ will. Erzeugen ist irrelevant

      Andersherum, es gibt keine alternative zu eval, wenn du einen string hast, der JS Code enthält und du ihn ausführen musst.

      Stimmt, das ist aber nicht das was ich will. Lies den ersten Satz im Posting hier nochmal: Ich will logische Vergleiche evaluieren, in welcher Sprache die verfasst sind ist unerheblich. Aber natürlich ist es naheliegend bei JavaScript als Sprache auch die Vergleiche in JS-kompatibler Syntax zu verfassen.

      Aber fast immer wenn eval benutz wird liegt das eher daran, das jemand nicht weiß wie man Objekte in JS ansprechen kann.

      Nur geht es augenscheinlich nicht um Objekte sondern um Werte, aber siehe unten. Im Endeffekt ist der Satz korrekt, aber ich würde ihn umformulieren in "...wenn jemand Werte statt Referenzen auf Werte ansprechen will".

      Was willst du machen?

      Siehe erster Satz. Was ich _nicht_ will ist
      a) JavaScript ausführen.
      b) einen kompletten Lexer/Parser selbst schreiben.

      Mittlerweile habe ich das Problem so gelöst:

      1. Ich ersetze alle Platzhalter à la [WERT] durch document.forms['formname'].elements['WERT'].value
      2. formuliere alle vergleiche um in um in '(' + vergleich + ') ? true : false'
      3. übergebe validation an eval()

      Beispiel:
      var evaluation = eval("(document.forms['formname'].elements['WERT'].value == 'Firma') ? true : false || (document.forms['formname'].elements['WERT'].value == 'Familie') ? true : false;")

      Und voila, eval() nimmt die Werte in den Formularfeldern und vergleicht sie mit den statisch konfigurierten Werten. Ergo:
      a) kein Context-Switching des eval-Lexers
      b) keinen Lexer/Parser selbst geschrieben.

      Ciao,
      Dominique

      1. eval ist nur dann nötig, wenn du zur Laufzeit JS Code erzeugst.

        Korrektur: wenn ich zur Laufzeit JS Code _ausführen_ will. Erzeugen ist irrelevant

        Nein, wenn du ihn nicht erzeugst brauchst du auch eval nicht.

        Aber fast immer wenn eval benutz wird liegt das eher daran, das jemand nicht weiß wie man Objekte in JS ansprechen kann.

        Nur geht es augenscheinlich nicht um Objekte sondern um Werte, aber siehe unten. Im Endeffekt ist der Satz korrekt, aber ich würde ihn umformulieren in "...wenn jemand Werte statt Referenzen auf Werte ansprechen will".

        Was willst du machen?
        Siehe erster Satz. Was ich _nicht_ will ist
        a) JavaScript ausführen.
        b) einen kompletten Lexer/Parser selbst schreiben.

        Mittlerweile habe ich das Problem so gelöst:

        1. Ich ersetze alle Platzhalter à la [WERT] durch document.forms['formname'].elements['WERT'].value
        2. formuliere alle vergleiche um in um in '(' + vergleich + ') ? true : false'
        3. übergebe validation an eval()

        Beispiel:
        var evaluation = eval("(document.forms['formname'].elements['WERT'].value == 'Firma') ? true : false || (document.forms['formname'].elements['WERT'].value == 'Familie') ? true : false;")

        und wozu ist das eval gut?

        var evaluation = !!(document.forms['formname'].elements['WERT'].value == 'Firma' || document.forms['formname'].elements['WERT'].value == 'Familie');

        Und voila, eval() nimmt die Werte in den Formularfeldern und vergleicht sie mit den statisch konfigurierten Werten. Ergo:
        a) kein Context-Switching des eval-Lexers
        b) keinen Lexer/Parser selbst geschrieben.

        c.) völlig überflüssig

        Struppi.

        1. Wenn Du nicht verstehst worum es geht lass die Kommentare doch einfach :). Geh wieder mit mouseOvers spielen.

          Dominique

          1. Wenn Du nicht verstehst worum es geht lass die Kommentare doch einfach :). Geh wieder mit mouseOvers spielen.

            Dann zeit mir mal wo du eval wirklich brauchst, für das was du da zeigst nicht.

            Struppi.

          2. Wenn Du nicht verstehst worum es geht lass die Kommentare doch einfach :). Geh wieder mit mouseOvers spielen.

            Keine Ahnung woher du diese Überheblichkeit nimmst, aber wer nicht weiß wie man eval richtig einsetzt ist sicher nicht in der Lage ein gutes Mausover Skript zu schreiben.

            Was an diesen Zeilen:

            Beispiel:
            var evaluation = eval("(document.forms['formname'].elements['WERT'].value == 'Firma') ? true : false || (document.forms['formname'].elements['WERT'].value == 'Familie') ? true : false;")

            so ungewöhnlich sein soll ist ein rätsel.

            Es ist das gleiche wie:
            var evaluation = document.forms['formname'].elements['WERT'].value == 'Firma' || document.forms['formname'].elements['WERT'].value == 'Familie')

            Nur ca. 10 mal langsamer, schwerer zu debuggen und mehr zu tippen.

            Und voila, eval() nimmt die Werte in den Formularfeldern und vergleicht sie mit den statisch konfigurierten Werten. Ergo:
            a) kein Context-Switching des eval-Lexers
            b) keinen Lexer/Parser selbst geschrieben

            Dafür kannst du aber wesentlich besser als ich, mit tollen, wichtig klingenden  Wörtern um dich werfen.

            Struppi.

      2. eval ist nur dann nötig, wenn du zur Laufzeit JS Code erzeugst.

        Korrektur: wenn ich zur Laufzeit JS Code _ausführen_ will. Erzeugen ist irrelevant

        Mittlerweile habe ich verstanden was du wilst, dank deiner nebulösen Beschreibung war das gar nicht so einfach. Du willst zur Laufzeit einen String mit JS erzeugen und ausführen. Das ist genau das was ich gesagt habe und das ist auch genau der einzige Grund wann eval einen Sinn macht.

        Was willst du machen?
        Siehe erster Satz. Was ich _nicht_ will ist
        a) JavaScript ausführen.

        doch willst du.

        b) einen kompletten Lexer/Parser selbst schreiben.

        ok, das habe ich jetzt kapiert.

        Du willst offensichtlich einen Formularchecker bauen, wo du Variabel die Vergleiche übergeben kannst. Das ganze dürfte so aussehen.

        function checkField(was, vergleich)
        {
             if(!was) return alert('Vergleich nicht möglich:' + was);
             var wert = was.value;
             // ersetzen:
             var string = vergleich.replace(/[WERT]/g, wert);
             var ergebnis = eval(string);
             alert(ergebnis);
        }
        checkField(document.forms['Formular'].elements['xxx'], "'[WERT]' == 'Firma' || '[WERT]' == 'Familie'");

        checkField(document.forms['Formular'].elements['yyy'], "'[WERT]' == 'Firma' || '[WERT]' == 'Familie'");

        Mit einem kleinen Beispiel mit dem man hätte nachvollziehen können was du wirklich willst, wären diese ganzen Mißverständnisse nicht nötig gewesen.

        Struppi.