Why is __caller__ unsafe? - javascript

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.

Related

Can we change the execution context of the browser's JavaScript from Window object to something else?

Assume I have a legacy file called module.js which is like this:
a=1;
This by default attaches to the window object polluting the global (actually window) scope when you execute it in the browser.
Is it possible for me to attach it to a different object instead without changing the contents of the source code?
Since the only real problem is the execution context and nothing else, an ideal solution would be something like this:
change execution context from window to module object;
execute the code;
change execution context from module to window object;
If this is not possible, adding wrappers (like IIFE) to the source code is fine as long as the inner contents are not changed. Changing the inner contents needs a full scan of the code which is expensive.
I can, for example, wrap it into a function like this (✓):
function module()
{
a=1;
}
If it is executed in strict mode, I can avoid global scope pollution. However, I can't get hold of the object.
I don't want to do something like this (✗):
module = function module()
{
return a=1;
}
because we need to add return wherever there is an assignment and that means scanning the entire code.
I am just trying to see ways to improve legacy code meant for the browser with minimal effort.
The answer to the first question, no it is not possible to change the default execution context in the browser. window is a special variable and assigning anything else to it will not change default execution context. See Global Object in MDN. And here is an illustration
(function() {
window = {}
a = 5 // leaking declaration
var b = 10
})()
console.log(a) // a is on global scope
//console.log(b) // exception b is not defined in this scope
var b = 5
window = new Object()
window.c = 5
console.log(window.b) // 5
console.log(c) // 5
The answer to the second part about how to work with legacy code, there are many tools which do AST transformation and depending on your goal you should probably use one or more of them.
jscodeshift allows you to write codemods which are functions that receive code and apply transformations to it. This is probably the most powerful tool in this category.
ESLint allows you to set rules (for example no global vars) and have a --fix option which will apply automatic fixes in some cases like changing from single quote to double quotes (this is mostly for style related rules).
prettier is a code formatter only concerned with code appearance: indentation, spaces etc.
AST Explorer an online tool that lets you see the internals of all the above tools very useful to understand how it works and try code on small examples.

How can function references be executed properly (1)?

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.

Basic Javascript Function

I am trying to learn more about Javascript, I have been coding with PHP and making web application for years, I have basic knowledge of JS, most of the JS I have used has been already coded and me just plugging it in until recently, in the past years I have been able to do a lot with jQuery.
I have noticed that Stack Overflow uses jQuery more then most sites I have seen, it is beautiful all the JS functionality they have here.
So a basic question, Stack Overflow uses StackExchange in front of most of the JS code that I have seen on here. What exactly is that doing? To me I would want to say it is like a Class name but I read JS does not have classes.
Here is an example code
StackExchange.debug.log("no cache breaker for " + q);
Can you break this down for me to explain what the StackExchange, debug, log are?
I mean I can tell that log must be a function call but the others?
PS) Please don't move this to META as it is a JS question and not specific to StackOverflow
Also feel free to edit the question title and delete this line if you can think of a better title, thanks
Think of StackExchange as something much like the global jQuery function, "$" (or "jQuery"). It's just a global reference to an object that has functions and other properties.
Thus, "debug" is a property of the global "StackExchange" object, and in turn "log" is a property of the "debug" object. In this case, the "log" property references a function, which clearly is a debugging tool.
It's a debatable point whether JavaScript has "classes" or not, but it definitely has objects. (By "debatable" I mean it's a subject that fills an endless stream of blog posts and Stackoverflow questions :-)
That is, in fact, basic JavaScript. There's nothing super fancy or tricky about it.
Namespaces.
this may be relevant
How do I declare a namespace in JavaScript?
EDITED FOR CLARIFICATION
Before I say ANYTHING, please see How Classical Object-Oriented Programming Translates to Javascript. This is VERY important to understand. Now, that being said, I'll continue :)
Javascript has the unfortunate characteristic that you have to understand the run-time environment very well in order to make sense of why certain syntax is chosen over another that expresses the same thing (in theory). One of the main caveats of the run-time environment of javascript is that it is very easy to get things into the global space unintentionally. Here's two quick examples (these examples assume that you don't have any other code written):
/*
* Example 1
* This example uses 'object literal notation'.
* A link to an article about this is below the example.
* This example shows how easy it is to get into the global space just by
* not declaring variables properly.
*/
var myObj = {
myMethod: function() {
test = 'test'; // oops! now the variable test is in the global
// function space :(
// to avoid this, use var test = 'test'; to keep
// test in the scope of myMethod
}
};
Read about object literal notation.
/*
* Example 2
* This example shows how the infamous 'this' can be misused to accidentally
* get into the global space.
*/
var myConstructor = function() {
this.test = 'test';
};
var myObj1 = new myConstructor(); // 'this' will by 'myObj1'
var myObj2 = myConstructor(); // 'this' will by the global object :(
To see why Example 2 is true, see this.
One of the ways you avoid all of these headaches is by following good patterns that control access to the global scope. As some of the answers have pointed out, you can think of the StackExchange object as being used for namespacing purposes, but in reality, it's most often used to also avoid the problem listed in above example, as well prevent things such as name hoisting. In addition, you can make this 'namespacing' object also behave more like a traditional object from other classical OOP languages if you are intelligent in using closure scopes (taking advantage of the fact that all scopes in javascript are bound to functions, and functions in javascript are first-class data objects). Also, because the global space is so dangerous, it's best to "be a good DOM citizen" and only create one object in the global space that encapsulates all of your logic and data.
Joel and jeff are probably actually setting up closure scopes to do information hiding the javascript way. The below is just an example:
StackExchange = (function() { // give StackExchange it's own scope to prevent
// name hoisting and also to allow for private
// data
var version = '1.0.0'; // version only seen inside function scope
return { // return an object that will become 'StackExchange' and whose
// methods have access to this function's scope (closure)
debug: (function() {
// set up logging function that will be determined based on
// 'someCondition' (not defined in this code)
var loggingFn = (someCondition) : console.log ? alert;
return { // return obj with access to this function scope
log: function(strToLog) {
loggingFn.call(this, strToLog);
}
};
})(), // immediately execute to make object with 'debug' scope access
getVersion: function() {
return version; // this function has access to StackExchange
// scope; therefore, version will be available
}
};
})(); // immediately execute to make object with 'StackExchange' scope access
For more information, see name hoisting and scoping. Also, please read about Prototypical Inheritance in Javascript to understand patterns used to avoid global scoping problems.
This code would define the object necessary to perform the call shown in your example. As you can see, it simply defines an object containing more objects finally containing one or more functions.
var StackExchange = {
debug: {
log: function(whatever) { /* some code */ }
}
};
StackExchange.debug.log("no cache breaker for " + q);
StackExchange is a global object and debug is an another object which is a property of StackExchange object and it has a function called log.
Read more about Objects in JavaScript here.

What advantages does using (function(window, document, undefined) { ... })(window, document) confer? [duplicate]

This question already has answers here:
How does this JavaScript/jQuery syntax work: (function( window, undefined ) { })(window)?
(5 answers)
Closed 8 years ago.
I guess using this pattern is the new hotness, but I don't understand what the advantage is and I don't understand the scoping implications.
The pattern:
(function(window, document, undefined){
window.MyObject = {
methodA: function() { ... },
methodB: function() { ... }
};
})(window, document)
So I have several questions about this.
Is there a particular advantage to encapsulating an object like this?
Why are window and document being fed in instead of just being accessed normally?
Why the heck is undefined being passed in?
Is attaching the object we're creating directly to window a particularly good idea?
I'm used to what I'll call the Crockford style of Javascript encapsulation (because I got it off the Douglas Crockford Javascript videos).
NameSpace.MyObject = function() {
// Private methods
// These methods are available in the closure
// but are not exposed outside the object we'll be returning.
var methodA = function() { ... };
// Public methods
// We return an object that uses our private functions,
// but only exposes the interface we want to be available.
return {
methodB: function() {
var a = methodA();
},
methodC: function() { ... }
}
// Note that we're executing the function here.
}();
Is one of these patterns functionally better than the other? Is the first one an evolution of the other?
Why are window and document being fed in instead of just being accessed normally?
Generally to fasten the identifier resolution process, having them as local variables can help (although IMO the performance improvements may be negligible).
Passing the global object is also a widely used technique on non-browser environments, where you don't have a window identifier at the global scope, e.g.:
(function (global) {
//..
})(this); // this on the global execution context is
// the global object itself
Why the heck is undefined being passed in?
This is made because the undefined global property in ECMAScript 3, is mutable, meaning that someone could change its value affecting your code, for example:
undefined = true; // mutable
(function (undefined) {
alert(typeof undefined); // "undefined", the local identifier
})(); // <-- no value passed, undefined by default
If you look carefully undefined is actually not being passed (there's no argument on the function call), that's one of the reliable ways to get the undefined value, without using the property window.undefined.
The name undefined in JavaScript doesn't mean anything special, is not a keyword like true, false, etc..., it's just an identifier.
Just for the record, in ECMAScript 5, this property was made non-writable...
Is attaching the object we're creating directly to window a particularly good idea?
It's a common way used to declare global properties when you are on another function scope.
This particular style does bring some benefits over the "Crockford" style. Primarily, passing window and document allows the script to be more efficiently minified. A minifier can rename those parameters to single-character names, saving 5 and 7 bytes respectively per reference. This can add up: jQuery references window 33 times and document 91 times. Minifying each token down to one character saves 802 bytes.
Additionally, you do get an execution speed benefit. When I first read #joekarl's assertion that it provides a performance benefit, I thought, "that seems rather spurious." So I profiled the actual performance with a test page. Referencing window one hundred million times, the local variable reference provides a modest 20% speed increase (4200 ms to 3400ms) in Firefox 3.6 and a shocking 31,000% increase (13 sec to 400ms) in Chrome 9.
Of course, you're never going to reference window 100,000,000 times in practice, and even 10,000 direct references only take 1ms in Chrome, so the actual performance gain here is almost completely negligible.
Why the heck is undefined being passed in?
Because (as mentioned by #CMS) the token undefined is actually undefined. Unlike null, it has no special meaning, and you're free to assign to this identifier like any other variable name. (Note, however, that this is no longer true in ECMAScript 5.)
Is attaching the object we're creating directly to window a particularly good idea?
The window object is the global scope, so that's exactly what you're doing at some point, whether or not you explictly write "window." window.Namespace = {}; and Namespace = {}; are equivalent.
I'm with you in using Crockford's style.
To answer your questions
1.Is there a particular advantage to encapsulating an object like this?
The only advantage I can see is by making window and document local variables instead of global variables, you get some added safety by not being able to directly overwrite either one and also some performance gain by them both being local.
2.Why are window and document being fed in instead of just being accessed normally?
Addressed above. Local variables tend to be faster, but with jit compiling these days thats becoming nominal.
3.Why the heck is undefined being passed in?
No clue....
4.Is attaching the object we're creating directly to window a particularly good idea?
Probably not, but I would still stick with Crockford's pattern as attaching the function to the window object exposes it to the rest of the global stack through the window object as opposed to exposing it through a non-standard namespace.
I think this is mostly for code that needs to run in multiple window contexts. Say you have a complex application with lots of iframes and/or child windows. They all need to run the code in MyObject, but you only want to load it once. So you load it in whatever window/frame you choose, but you create a MyObject for each window/frame with references to the proper window and document.
Taking an undefined argument is trying to protect against the fact that undefined can be changed:
undefined = 3;
alert(undefined);
See CMS's answer about how this improves safety.

How to Implement Closures Using SpiderMonkey API?

I've been working with the SpiderMonkey C API and would like to implement a closure in C using their API. The one I would like to implement is fairly complex, but I can't even figure out how to do a simple one such as:
function x() {
var i = 0;
return function() { i++; print(i); };
}
var y = x();
y(); //1
y(); //2
y(); //3
I was wondering if anyone knows how I might do this. I found the JS_NewFunction method, but I don't actually know if that is a step in the right direction. Any help will be appreciated, thanks!
I don't know if there's a pure C way of doing closures or not. I would reccomend though, if you can, to just implement the functionality you need in javascript, and simply evaluate the javascript text in JSAPI. From there, use JSAPI to grab whatever handles/variables you need to implement your host functionality. It's really onerous to do javascripty things using JSAPI, avoid it if you can.
Narrated as if you're probably still interested, a year later.
Knitting my brows furiously at the documentation for JS_GetParent, I see
For some functions, it is used to implement lexical scoping (but this is an implementation detail).
and then, along with a list of API functions that create functions,
Some of these functions allow the application to specify a parent object. If the JSAPI function creating the object has a parent parameter, and the application passes a non-null value to it, then that object becomes the new object's parent. Otherwise, if the context is running any scripts or functions, a default parent object is selected based on those.
I might experiment with this later, but it seems that you might be able to do this either by (merely) creating the function in the API during the execution of the function that you want it to have the scope of.
Otherwise, you might be able to set the lexical scope of a function to some object manually using JS_SetParent, but the documentation keeps ominously calling that use of parents 'internal'.
</necro>

Categories

Resources