wingolog

javascript eval considered crazy

12 January 2012 4:34 PM (javascript | javascriptcore | ecmascript | igalia)

Peoples. I was hacking recently on JavaScriptCore, and I came to a realization: JavaScript's eval is absolutely crazy.

I mean, I thought I knew this before. But... words fail me, so I'll have to show a few examples.

eval and introduced bindings

This probably isn't worth mentioning, as you probably know it, but eval can introduce lexical bindings:

 > var foo = 10;
 > (function (){ eval('var foo=20;'); return foo; })()
 20
 > foo
 10

I find this to be pretty insane already, but I knew about it. You would think though that var x = 10; and eval('var x = 10;'); would be the same, though, but they're not:

 > (function (){ var x = 10; return delete x; })()
 false
 > (function (){ eval('var x = 10;'); return delete x; })()
 true

eval-introduced bindings do not have the DontDelete property set on them, according to the post-hoc language semantics, so unlike proper lexical variables, they may be deleted.

when is eval really eval?

Imagine you are trying to analyze some JavaScript code. If you see eval(...), is it really eval?

Not necessarily.

eval pretends to be a regular, mutable binding, so it can be rebound:

 > eval = print
 > eval('foo')
 foo // printed

or, shadowed lexically:

 > function () { var eval = print; eval('foo'); }
 foo // printed

or, shadowed dynamically:

 > with({'eval': print}) { eval('foo'); }
 foo // printed

You would think that if you can somehow freeze the eval binding on the global object, and verify that there are no with forms, and no statements of the form var eval = ..., that you could guarantee that eval is eval, but that is not the case:

 > Object.freeze(this);
 > (function (x){ return [eval(x), eval(x)]; })('var eval = print; 10')
 var eval = print; 10 // printed, only once!
 10,

(Here the first eval created a local binding for eval, and evaluated to 10. The second eval was actually a print.)

Crazy!!!!

an eval by any other name

So eval is an identifier that can be bound to another value. OK. One would expect to be able to bind another identifier to eval, then. Does that work? It seems to work:

 > var foo = eval;
 > foo('foo') === eval;
 true

But not really:

 > (function (){ var quux = 10; return foo('quux'); } )()
 Exception: ReferenceError: Can't find variable: quux

eval by any other name isn't eval. (More specifically, eval by any other name doesn't have access to lexical scope.)

Note, however, the mere presence of a shadowed declaration of eval doesn't mean that eval isn't eval:

 > var foo = 10
 > (function(x){ var eval = x; var foo = 20; return [x('foo'), eval('foo')] })(eval)
 10,20

Crazy!!!!

strict mode restrictions

ECMAScript 5 introduces "strict mode", which prevents eval from being rebound:

 > (function(){ "use strict"; var eval = print; })
 Exception: SyntaxError: Cannot declare a variable named 'eval' in strict mode.
 > (function(){ "use strict"; eval = print; })
 Exception: SyntaxError: 'eval' cannot be modified in strict mode
 > (function(){ "use strict"; eval('eval = print;'); })()
 Exception: SyntaxError: 'eval' cannot be modified in strict mode
 > (function(x){"use strict"; x.eval = print; return eval('eval');})(this)
 Exception: TypeError: Attempted to assign to readonly property.

But, since strict mode is embedded in "classic mode", it's perfectly fine to mutate eval from outside strict mode, and strict mode has to follow suit:

 > eval = print;
 > (function(){"use strict"; return eval('eval');})()
 eval // printed

The same is true of non-strict lexical bindings for eval:

 > (function(){ var eval = print; (function(){"use strict"; return eval('eval');})();})();
 eval // printed
 > with({'eval':print}) { (function(){ "use strict"; return eval('eval');})() }
 eval // printed

An engine still has to check at run-time that eval is really eval. This crazy behavior will be with us as long as classic mode, which is to say, forever.

Strict-mode eval does have the one saving grace that it cannot introduce lexical bindings, so implementors do get a break there, but it's a poor consolation prize.

in summary

What can an engine do when it sees eval?

Not much. It can't even prove that it is actually eval unless eval is not bound lexically, there is no with, there is no intervening non-strict call to any identifier eval (regardless of whether it is eval or not), and the global object's eval property is bound to the blessed eval function, and is configured as DontDelete and ReadOnly (not the default in web browsers).

But the very fact that an engine sees a call to an identifier eval poisons optimization: because eval can introduce variables, the scope of free variables is no longer lexically apparent, in many cases.

I'll say it again: crazy!!!

27 responses

  1. vitriolix says:

    Nice post. This belongs on wtfjs

  2. Jeff Walden says:

    So much truth here.

    I took a slightly different tack in my own argument for people to not use eval, in that I specifically focused on the optimizations it disabled. This was in the context of a post discussing implementation of proper strict mode variable binding in eval'd code. Nonetheless, we are in agreement that eval is insane, and no one should use it.

    http://whereswalden.com/2011/01/10/new-es5-strict-mode-support-new-vars-created-by-strict-mode-eval-code-are-local-to-that-code-only/

  3. Jeff Walden says:
  4. Benjamin Otte says:

    This post is the perfect example of why I never know if I should love or hate the browser guys - on the one hand they invent something like eval(), on the other hand they make extra sure that links in their blog comments are properly linkified. ;)

  5. John-David Dalton says:

    The behavior you're seeing when you assign `eval` to a variable and execute it is defined by ES5. Indirect calls to `eval` like `var a = eval; a(code)` or `(0, eval)(code)` or `window.eval(code)` are treated as a global evals.
    http://es5.github.com/#x10.4.2

    Juriy Zaytsev (@kangax) has a post on global eval:
    http://perfectionkills.com/global-eval-what-are-the-options/

    and another post examining the `delete` operator and `eval`:
    http://perfectionkills.com/understanding-delete/#deleting_variables_via_eval

  6. Zachary Kessin says:

    This is why most of us say "Eval" really just "Evil" with a spelling mistake. with is also somewhat problematic but that is a different conversation.

    I found if you follow the advice in JS:TGP you will do much better with Javascript

  7. Michael Trotter says:

    Very interesting..

    Although, I just tried this snippet from about (in the node.js interpreter):
    > var foo = 10
    > (function(x){ var eval = x; var foo = 20; return [x('foo'), eval('foo')] })(eval)

    It printed 10, 10

  8. Rauol Iglesias says:

    there is a new post on hyperbole and a half

  9. matt dales says:

    your first example seems flawed.

    var foo = 10; --declares a variable 'foo' in the global scope.
    (function (){
    eval('var foo=20;');
    --using 'var' here declares 'foo' in the local function's scope.
    return foo;
    })()

    foo

    in that example the global var remains 10 and the local version is set to 20 returned and deleted as per normal javascript rules.

  10. Brandon says:

    I'm inclined to agree with Zachary: there's no good reason to use eval. Quite apart from the performance impacts, using it can potentially expose your users to malicious code. Thankfully, browsers have given us there is now another way to parse JSON, but there are still plenty of js "ninjas" out there who think that cleaver uses of eval are a means of demsonstrating their coding prowess.

    Andy, my question to you as a scheme programmer, and language implementer, is whether you think there is a good case for including eval or something similar into the language.

  11. Brandon says:

    On a side note, have you considered implementing a way to edit comments post facto?

  12. Erik says:

    Code generation is one reason to use eval, at least when your language doesn't have real code manipulation (e.g. macros).

    Introducing new variables in it's own external scope is crazy though. (who thought that was a good idea?)

  13. assignment expert says:

    I took a marginally distinctive tack in my own particular contention for individuals to not utilize eval, in that I particularly centered around the enhancements it debilitated. This was with regards to a post talking about usage of legitimate strict mode variable official in eval'd code. The conduct you're seeing when you appoint `eval` to a variable and execute it is characterized by ES5.

  14. buy research proposal says:

    JavaScript is one of my interesting programming language and mainly eval in java script used for evaluating an argument function. Here the crazy thing behind it is very interesting.

  15. Jason says:

    > var foo = 10;
    > (function (){ eval('var foo=20;'); return foo; })()
    20
    > foo
    10

    it was some kind of a function?

  16. merry christmas 2016 images says:
  17. UFC 206 says:

    UFC 206

    UFC 206 live stream, ufc 206 fight card, fight pass, start time, line up, ufc 206 pay per view, prelims, Holloway vs Pettis, live streaming, free, tv, news.

    UFC 206

    UFC 206 Live Stream

    Holloway vs Pettis

    UFC 206 PPV

  18. YO YO says:
  19. NFL Playoffs 2017 says:

    NFL Playoff Schedule 2017

    Watch NFL Playoffs 2017 live. NFL Playoff schedule 2017, Wild Card, divisional Playoffs, NFL Playoff Picture 2017, game times, live stream, score, teams, standings, afc, nfc championship.

    NFL Playoff

    NFL Playoffs 2017

    Playoff Picture 2017

    NFL Playoff schedule 2017

  20. fasfsa says:
  21. ADIL says:
  22. Wantana Buttheat says:

    mendapatkan penghargaan karena berhasil meraih nilai rata-rata tertinggi pada UN 2011.ironsteelcenter.com ironsteelcenter.comHarga besi beton Sni Ulir Polos Harga besi beton Sni Ulir PolosHarga besi hollow Harga besi hollowHarga besi cnp Harga besi cnpHarga besi unp Harga besi unpHarga wiremesh Harga wiremeshHarga besi wf Harga besi wfHarga besi h beam Harga besi h beamHarga Plat besi Harga Plat besiHarga pipa besi baja sch 40 sch 80 Harga pipa besi baja sch 40 sch 80Harga besi siku Harga besi sikuHarga Plat kapal besi baja bki krakatau steel Harga Plat kapal besi baja bki krakatau steelHarga bondek Harga bondekHarga baja ringan Harga baja ringanHarga Atap spandek Harga atap spandekHarga stainless steel Harga stainless steeljasa konstruksi jasa konstruksi besi baja jasa konstruksi gudang jasa konstruksi gedung jasa konstruksi undangan pernikahan undangan pernikahan simpleundangan pernikahan online udangan pernikahan pinkundangan pernikahan unik undangan pernikahan onlineundangan pernikahan murah undangan pernikahan islamiundangan pernikahan islami undangan pernikahan murahundangan pernikahan elegan undangan pernikahan artisundangan pernikahan unik dan murah contoh undangan pernikahan
    www.gudangbesibaja.com www.gudangbesibaja.comHarga besi cnp Harga besi cnpHarga besi h beam baja Harga besi h beam bajaHarga Plat besi plat kapal Harga Plat besi plat kapalHarga besi siku Harga besi sikuHarga besi unp Harga besi unpHarga besi wf baja Harga besi wf bajaHarga besi beton Sni Ulir Polos Harga besi beton Sni Ulir PolosHarga besi hollow Harga besi hollowHarga pipa besi baja sch 40 sch 80 Harga pipa besi baja sch 40 sch 80Harga wiremesh Harga wiremeshHarga bondek Harga bondekHarga besi Wf Baja Harga besi Wf Bajajasa konstruksi baja wf jasa konstruksi jembatan jasa konstruksi bangunan jasa konstruksi undangan pernikahan elegan dan murah undangan pernikahan eleganundangan pernikahan simple undangan pernikahan elegan dan murahundangan pernikahan artis undangan pernikahan putihudangan pernikahan pink undangan pernikahan unik dan murahundangan pernikahan putih undangan pernikahan unikContoh undangan pernikahan undangan pernikahan

    harga besi beton sni toko besi baja harga besi bahan bangunanharga pipa stainless steel pipa galvanis medium a besi bjkujual baja wf tabel baja krakatau steel harga besi ulir 16 mmharga stainless steel harga baja profil per kg harga besi 12 sniharga besi ulir harga besi wire mesh harga besi 8 mmdaftar harga pipa galvanis harga besi hollow stainless harga besi beton 10harga besi wf 200 harga baja hollow harga besi 13 ulirbesi kanal c galvanis steel rangka besi betondaftar harga besi beton harga pipa hollow harga besi kgjual wiremesh besi beam sni besi betonsupplier besi profil baja iwf harga besi behel 8mmbesi baja pipa galvanized harga besi beton 10mm snikonstruksi baja wf jual expanded metal harga besi ulir 10daftar harga besi hollow besi wire mesh harga sikuharga wiremesh profil baja h beam harga besi siku 4x4Supplier besi harga beam 200 besi siku hargaharga besi baja harga besi cnp 100 harga pipa besi hitamharga pipa baja jual besi cnp pipa seamlessbesi beton murah harga besi unp 100 daftar harga pipa stainless steelharga kanal c besi kanal c harga harga pipaharga besi stainless harga besi cnp 125 pipa stainlessharga besi per kg besi u galvanisharga plat stainless steel besi c pipa besi galvanisbesi unp harga besi cnp 150 harga besi hollow untuk pagarjual besi wf kanal c pipa besi hitamharga baja h beam daftar harga besi kanal c harga besi hollow 40x40

  23. james clark says:

    Valentine's Day, also called Saint Valentine's Day or the Feast of Saint Valentine, valentines day is an annual holiday celebrated on February 14.happy valentines day wishes It originated as a Western Christian liturgical feast day honoring one or more early saints named Valentinus, and is recognized as a significant cultural and commercial celebration in many regions around the world, although it is not a public holiday in any country. Valentine's Day is celebrated on February 14 Valentine's Day is also a very popular date for weddings..It is a festival of romantic love and many people give cards, letters, flowers or presents to their spouse or partner. They may also arrange a romantic meal in a restaurant or night in a hotel.valentines day sayings Common symbols of Valentine's Day are hearts, red roses and Cupid.The most common Valentine's Day symbols are the heart, particularly in reds and pinks, and pictures or models of Cupid. Cupid is usually portrayed as a small winged figure with a bow and arrow.Many people celebrate their love for their partner by sending cards or letters, giving gifts or flowers and arranging meals in restaurants or romantic nights in hotels. People who would like to have a romantic relationship with somebody may use the occasion to make this known, often anonymously. Valentine's cards are often decorated with images of hearts,valentines day pictures red roses or Cupid. Common Valentine's Day gifts are flowers chocolates, candy, lingerie and champagne or sparkling wine

  24. Packers vs Falcons says:

    Watch NFC Championship Game 2017 live stream. Packers vs Falcons NFC Championship Game 2017 live stream, streaming, free, game start time, tv channel, odds.

    Packers vs Falcons

    Falcons vs Packers

    NFC Championship Game 2017

    Packers vs Falcons Live Stream

    NFC Championship 2017

    NFC Championship 2017 Live Stream

  25. NFC Championship 2017 says:
  26. happy valentines day says:

    This post gives truly quality information. I’m definitely going to look into it. Really very useful tips are provided here. valentines day poemshappy valentines day messageshappy valentines day wallpapersvalentines day quotes

  27. Toni says:

    Yes, that's it. Maybe as you can't, you might want to explain why that isn't a conflict of interest !cara menurunkan asam urat dan kolesterol
    Corruption, by nature, is a surreptitious offence; it will always be difficult to detect. As with illness, prevention is the best cure. But where prevention fails, good detection mechanisms are necessary."

Leave a Reply