views:

322

answers:

4

For example:

(function() {
      var proxied = window.eval;
      window.eval = function() {
        return proxied.apply(this, arguments);
      };
    })();

But this code is not working.

+7  A: 

You can't. (There is a limited way of doing it, but it's quite limited and doesn't maintain the magic that bobince talks about.)

eval isn't a real JavaScript function in at least one major implementation (IE's JScript, at least not through IE7; haven't tested the new IE8 version), so right off the bat you're going to run into trouble, because you won't be able to call the original via apply (not that that really matters for eval).

The recent ECMAScript 5 specification specifically disallows overriding eval in strict mode (not that you're using strict mode there), which makes me suspect that there are very good reasons for not overriding it.

T.J. Crowder
Strict mode disallows aliasing/overriding `eval` because the interpreter would never be able to tell in advance that a function block contained no hidden uses of `eval`. If a terp (esp. JIT) can be sure a function contains only simple code and no evals, there are a much wider range of optimisations it can perform on the code generated.
bobince
@bobince: Thanks, good to know.
T.J. Crowder
Eval use for dynamic building ExtJs components. example:Ext.data.Connection().request({...,success: function(response, opts){ eval(response.responseText); }})Components are stored on the server.This using in several projects. In the one project return value from "eval" use as incoming parameter for one global method, other - don't using. I need this code to keep the functionality.
ko1ik
@ko1ik: You won't want to solve that problem by overriding `eval`, it'll be a maintenance nightmare. I'm afraid you'll have to go with another approach, such as updating the parts using `eval` to use some function you provide instead, which invokes `eval` if it needs to.
T.J. Crowder
Many thanks!!!!
ko1ik
@k01ik: No worries, good luck.
T.J. Crowder
A: 

Not only should you not do this, but I also think you probably can't. First, eval is a global function, and as such is not a member of window (as you tried above). Secondly as a global function it is highly likely that it is hard-wired into the VM and can't be overwritten.

Timothy Baldridge
Actually, both the 3rd edition spec (1999) and the 5th edition spec (2010) do call it out as a property of the global object (which is `window` in browsers), in section 15.1.2.1. But it's true that it's not reliably *implemented* that way.
T.J. Crowder
TJ is right, all global variables are properties of the window object. Also, hard wired to the VM? There's no VM, javascript does not compile into some VM byte code. Lastly, you can override most global functions or properties, eval is just special.
Juan Mendes
"There's no VM" - that's quite incorrect. Many browsers us JS VMs look at TraceMonkey (firefox) or V8 (chrome), what are those? They're not interpeters since they compile JS code to machine code. But they're not technically compilers since they don't expose the entire machine. They expose a subset (virtual machine) to the code. if that's not a VM...what on earth is?"Eval is just special" - ah so I was correct.
Timothy Baldridge
+6  A: 

eval is magic. Unlike a ‘real’ function, it can read and write local variables in the caller:

function foo() {
    var a= 1;
    eval('a+= 1');
    alert(a); // 2
}

Replace that eval with a proxied function and you've got a problem: the a+= 1 executes in the scope of the proxied function instead of foo. Depending on what's happening in the evaled code that could cause values to go missing, damage to the proxy's local, accidental globals, and so on.

It is, therefore, impossible to replace eval with a fully-working proxy. (For simple cases which don't need the locals, you can kind of get away with it.)

bobince
A: 

I tried this in FireFox 3.6.2 and it appears to work.

I typed this directly in the FireBug command line:

var proxied = eval;
eval = function() { alert("ha"); return proxied.apply(this, arguments);};
eval(7);
Mark Lutton
That doesn't work reliably cross-browser, and even on Firefox, your proxied version will be missing the magic that bobince talks about.
T.J. Crowder
batch is not defined[Break on this error] eval(7); FF 3.6.3pre
ko1ik
I know it's not *supposed* to work. I'm just saying it appears to work.
Mark Lutton