For example:
(function() {
var proxied = window.eval;
window.eval = function() {
return proxied.apply(this, arguments);
};
})();
But this code is not working.
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.)
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.
Although not portable, the following approach works in some places where it otherwise wouldn't (as it satisfies ES5's requirements that A) it be retrieved as a Reference in a MemberExpression, not a Value and B) it results in the ‘standard builtin function.’ — ES5 #15.1.2)
(function() {
var proxied = window.eval
with({get eval(){ console.log('eval called'); return proxied }}) {
/* client code */
}
})()
This obviously only applies if you can wrap the client code in a with() statement; though in many situations, that shouldn't be hard. Obviously, the same approach can shadow window with another object with all of its' properties, and a getter-proxied eval.
Environments that don't support SpiderMonkey's get statement, may be able to use ES5's defineProperty. Look into that yourself.
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);
Maybe I didn't understand the question correctly, but I "override" eval()by creating a myEval() function that has the original eval() inside it and execute addition steps in myEval().
function myEval = function(value){
//do your stuff here
//for example
try {
value = eval(value)
} catch (error) {
console.log(error)
value = NaN
}
return value
}
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.
Related
Recently I was debugging a bit of code that one of my coworkers wrote and found something along the lines of this within a conditional, inside of a larger function.
(function(foo){
...
console.log(foo);
...
})();
So it looks like this very boiled down
function display(db, user, foo) {
if (isValid(db, user) {
(function(foo){
console.log(foo);
})();
}
...
}
Originally it didn't have (); at the end so to my understanding it wasn't even being called but to my broader question, what's the difference between that and something like below? I've seen this syntax a few times but I don't understand how above would be useful for this purpose. My understanding would reason that this just adds unnecessary complexity. Someone please enlighten me!
function display(db, user, foo) {
if (isValid(db, user) {
// without abstract function
console.log(foo);
}
...
}
Thanks :-)
With such a simple example, there is no reason to use an anonymous function like this in node.js or any other JavaScript environment when the inner function could be called directly instead.
When conducting reviews, I often will assume that any console.log (or choose-your-language logging) is accidental. If the surrounding source doesn't do anything of value itself, it is likely only intended to support a (possibly-out-of-date) console.log during development and debugging.
Because JavaScript is single-threaded, constructing an anonymous function of this sort is strictly for scoping. In the case of the original source that didn't have the execution (i.e. it was missing the ()), this is actually a way to "hide" debug code from the runtime while leaving it in-place if a step-through debug ever needed it.
When debugging, it's as easy as adding the ('isValid succeeded') to have it execute all the source inside.
(function(foo){
console.log(foo);
})( /* You're missing a parameter value here; will print 'undefined'. */ );
Sometimes you use an anonymous function to limit the scope of your code. It may come handy if you do not want to pollute the global scope with your variables. Also, it makes dependency injection for testing easier.
Consider the following examples:
var a = 2, b = 3;
function print(x)
{
console.log('x= ', x);
}
print(a+b);
In the above example, the a, b, and print now belongs to the window object. When your code grows it becomes difficult to keep track and avoid of name collisions. The problem becomes even more severe if you are using 3rd party libs etc.
In the example below, your code is wrapped in an anonymous function protecting the global scope. You can also pass parameters to the anonymous function
(function(localParam){
var a = 2, b = 3;
function print(x)
{
console.log('x= ', x);
}
print(a+b);
//also
console.log(localParam); // = safe way to access and global variables
})(globalParam);
win points to window. NS is a temporary namespace for this post. I thought that if I wanted access to setTimeout, I could just copy over the function reference as such:
NS.setTimeout = win.setTimeout;
However, execution will throw an error:
NS_ERROR_XPC_BAD_OP_ON_WN_PROTO: Illegal operation on WrappedNative prototype object # ...
To fix this error, I just did:
NS.setTimeout = function (arg1, arg2) {
return win.setTimeout(arg1, arg2);
};
However, I don't know why this fixed it. I don't know what language mechanics are causing this behavior.
What you want is this :
NS.setTimeout = win.setTimeout.bind(win);
or what you already do, if you want to be compatible with IE8.
Because setTimeout, like many window functions, needs the receiver (this) to be window.
Another IE8 compatible solution, more elegant in my opinion than yours (because it doesn't use the fact you know the number of arguments needed by setTimeout), would be
NS.setTimeout = function(){
return win.setTimeout.apply(win, arguments);
};
The reason why you can't do that is because, when assigining, you're changeing the call context of setTimeout, which isn't allowed.
Nor is it allowed for setInterval, and many of the other native objects/functions. Again: a great rule of thumb: if you don't own the object, don't touch it. Since functions are objects in JS, that rule applies to them, too
check the specs on the global object and its properties/builtin funcitons:
There are certain built-in objects available whenever an ECMAScript program begins execution. One, the global object, is part of the lexical environment of the executing program. Others are accessible as initial properties of the global object.
And so on. But the lexical environment is quite significant. By assigning a reference to the function elsewhere, you could well be masking part of the lexical environment, or exposing too much of the global environment (eg mashups).
This fixed the problem b.c. you are changing the calling object back to the original when you call it.
return win.setTimeout(arg1, arg2);
will set the context ( or this ) back to window where it should be. The other answers are similar in the fact that they change the context to the correct value using bind to apply.
I have this function call passed as a string:
var dcall = "tumbsNav(1)";
Is it possible to execute this dynamically like exec in SQL??
exec(dcall)
eval is the equivalent, but you should NOT use it.
Instead, pass the function like this:
var dcall = function() {tumbsNav(1);};
Then call it with:
dcall();
To do this, you want eval(dcall).
eval can open terribly security holes and performance issues in your program. If you need to use it, that usually means you have designed your program poorly.
Instead, you might keep a reference to the function you want to call and hold an array of arguments and use apply, e.g., tumbsNav.apply(null, [1]);. I don't know your code, so that's most general solution I can offer.
Wherever you're storing
var dcall = "tumbsNav(1)";
You can instead store
var dcall = function() {
return tumbsNav(1);
};
Wherever you were calling it, instead of calling
eval(dcall);
You can instead call
dcall();
The only case this wouldn't work is if tumbsNav wasn't defined at the time var func = ... is called. Then you would have to store the string. If the string is completely under your control, then there's no security hole, but be aware of all the problems mentioned by #Porco
As Kolink mentioned, my example would not cause a problem if tumbsNav was not defined when assigning it with a wrapped anonymous function that calls tumbs. The comment above would only make sense if the example had been the following:
var dcall = tumbsNav, darg = 1;
// later in the code, you can call
dcall(darg) ;
Use eval(dcall).
As others have mentioned eval is considered bad practice. The main reasons for this are
1) Improper use can leave your code vulnerable to injection attacks.
2) Maintaining code becomes more difficult (no line numbers, can't use debugging tools)
3) Executes more slowly (browsers can't compile)
4) Scope becomes impossible to predict.
However, if you understand all these then eval can be very helpful.
Just experimenting with different inheritance techniques in JS, and came across something mildly discomfiting about Crockford's Prototypal Inheritance pattern:
function object(o) {
function F() {}
F.prototype = o;
return new F();
}
var C,
P = {
foo:'bar',
baz: function(){ alert("bang"); }
}
C = object(P);
It's all good - except when you log to console - the object appears as F. I've seen classical emulation in which you can repoint the constructor - is there a similar method to coerce the objects (console) reference?
The issue is that it's referring to the name of the constructor function. This quickly becomes a discussion about function expressions and statements and the name property. Turns out is is completely impossible to create a new named function at runtime without using eval. Names can only be specified using a function statement function fnName(){} and it's not possible to construct that chunk of code dynamically aside from evaling it. var fnExpression = function(){} results in an anonymous function assigned to a variable. The name property of functions is immutable so it's a done deal. Using Function("arg1", "arg2", "return 'fn body';") also only can produce an anonymous function despite being similar to eval.
It's basically just an oversight in the JS spec (Brendan Eich stated he regrets defining the display name the way he did 10 or so years ago) and a solution is being discussed for ES6. This would introduce more semantics for deriving a function's display name for debug tools or perhaps an explicit way to set and adjust it.
For now you have one route: eval, or some other form of late execution of configurable code. (eval by any other name...)
function displayName(name, o){
var F = eval("1&&function "+name+"(){}");
F.prototype = o;
return new F;
}
The function statement alone won't return from eval, but doing 1 && fnStatement coerces the thing into an expression which is returnable.
(Harmony Proxies also allow setting up functions that report names which you can configure without eval but that's not usable except in Node.js and Firefox currently).
I'll make a note here that all those "evil" functions that have been shat upon by Crockford and many others ALL have their place. eval, with, extending natives all enable specific techniques which are otherwise completely impossible and it's not wrong to use them when the occasion is right. It's just likely that most people aren't qualified to make the judgement of when that time is right. In my opinion using eval harmlessly to make up for poor language semantics and tools while waiting for a solution is perfectly acceptable and won't cause you any harm as long as you're not funneling arbitrary code into that eval statement.
If I log the object I can see: Object { foo="bar", baz=function()}, so I don't understand your problem...
Anyway, can use Object.create() instead of Crockford's function:
var P = {
foo:'bar',
baz: function(){ alert("bang"); }
}
var C = Object.create (P);
console.log (C):
Object { foo="bar", baz=function()}
The following seems to be a reasonable use of __caller__:
var foo=1;
function a() {
var foo=2;
function b() {
var foo=3;
foo; // 3
this.foo; // 1, from global
__caller__.foo // 2
}
b();
}
a(); // creates a's execution context
However, __caller__ is not available. Why not? If the global context/variable object can be accessed using this, then why not a's?
Doc says:
The special property __caller__, which returned the activation object of the caller thus allowing to reconstruct the stack, was removed for security reasons.
And it is easy to see why this could be a security disaster in a browser where much of the UI is implemented in JavaScript. Imagine having one of your functions called by an add-on or other chrome. You could look up the call stack and read callers' (potentially sensitive) variables, or even inject JavaScript values into caller functions, potentially subverting them to do something against the user's wishes. Effectively every web page would get chrome security privileges and completely compromise the browser.
You certainly should never have used it in real JavaScript, because it was a non-standard Mozilla-only implementation detail, not to mention incredibly ugly. It does not have the lexical behaviour you normally expect of JS.
I am not really familiar with the subject, but have you tried arguments.callee.caller?
See here: Javascript how do you find the caller function?
In your example, you can argue that things in b should be able to address things in the active instance of a, and it seems reasonable because a encloses b. But if that weren't the case, say you define
function c() {
var foo='hedgehog';
b();
}
that's something else entirely, so your argument looks like it applies to a pretty special case.