Eval is Evil 3

Continuando nossa saga de evitar Eval e conhecer melhor o Javascript, vou brincar com a seguinte situação: parsear um template html escrito com Expression Language da spec JSP.

Imagina o seguinte trecho abaixo:

<c:if test="${sessionScope.cart.numberOfItems > 0}">
  ...
</c:if>

É fácil montarmos um mapa com todas as expressões encontradas entre ${ e } e depois chamar eval para processar, mas como quero evitar essa chamada, o que podemos fazer?

Encontramos na documentação de referência da Mozilla a resposta, especificamente no objeto nativo Function, onde podemos criar uma new Function passando seu corpo como uma string que será executada ao fazer a chamada dessa function. Montei abaixo um exemplo como funciona:


Caso não veja no seu Feedreader, link do github.

3 thoughts on “Eval is Evil 3

  1. Stephen Eilert

    Bem, continua sendo Eval, mas com um bigode postiço (e evil).

    Sugiro expandir o exemplo com a única vantagem dessa construção: a possibilidade de criar funções que aceitam parâmetros:

    Por exemplo:

    var sessionScope = {
    cart: {
    numberOfItems: 10
    }
    }

    var statement = “return scope.cart.numberOfItems > 0”;

    var notsoevil = new Function(“scope”, statement);

    console.log(notsoevil(sessionScope));

    (Aliás, pq “quine”? O termo não foi usado no sentido usual…)

  2. cmilfont Post author

    @Stephen

    Na verdade a chamada de Function não continua evil… quer dizer, eval 🙂

    A própria recomendação da Mozilla esclarece isso:
    https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/eval

    “eval() is also generally slower than the alternatives, since it has to invoke the JS interpreter, while many other constructs are optimized by modern JS engines.”

    É perceptível quando a chamada de eval é realizada, há uma travada no navegador, IE e Firefox sentam bonito. Fora que o contexto de execução de eval:

    “More importantly, third party code can see the scope in which eval() was invoked, which can lead to possible attacks in ways of which the similar Function is not susceptible.”

    O exemplo que fiz foi bem simplório, não tem nem tratamento de ReferenceError por exemplo. Era só para dar a idéia. No lugar desse replace teria alguma rotina para varrer via RegExp e encontrar sentenças…
    Nesse caso aí em específico eu não acho que vale a pena usar argumentos porque quero só uma estratégia de avaliar e executar sentenças.
    Eu vou passar um objeto [como sessionScope] para algum objeto que vai parsear o HTML e ele vai verificar sentenças, não vale a pena fazer um tratamento tão fino.

    O termo quine foi exagero mesmo, na verdade eu estava tentando fazer com quine, mas complicou e resolvi com Function 🙁

Leave a Reply

Your email address will not be published. Required fields are marked *