What is "debugger" in a lexical sense? - javascript

I just discovered the debugger keyword or whatever it is for JavaScript development, and I'm not clear what it is. Certainly it's not an expression, it has no value. But do I need to put a semi-colon after it? What is it defined as part of? I mean, it's technically like an addition to the language in the chrome runtime, isn't it?
(I know what it does, I just don't know the details of its implementation and how I would explain its lexical nature to someone else.)

It's actually described in ES5 standard - and yes, it's a statement:
Syntax
DebuggerStatement :
debugger;
Semantics
Evaluating the DebuggerStatement production may allow an
implementation to cause a breakpoint when run under a debugger. If a
debugger is not present or active this statement has no observable
effect.
It is evaluated as follows:
If an implementation defined debugging facility is available and enabled, then
Perform an implementation defined debugging action.
Let result be an implementation defined Completion value.
Else
Let result be (normal, empty, empty). Return result.
As a sidenote, most modern browsers - not only Chrome - support this functionality.

Related

how do I go into eval('debugger') mode when already stopped at 'regular' debugger statement?

I recently started to swap out all my debugger statements with eval('debugger') statements. The reason is that with the plain version, not all "factually/theoretically" visible variables are "practically" visible. This happens because of optimization (see earlier SO question).
With this trick, the problem is like "90% solved" - there are some drawbacks. Apart from longer source code, those are:
When third party libraries are involved, it is not feasible, maybe not even possible to have the debugger -> eval('debugger') transformation done there also.
When I would rather set a break point in the debugger itself, instead of changing the code, that cannot be done - or can it?
When I'm already stopped at a "normal" debugger statement (in third party code, or where I forgot one), there is no way to switch to the desired mode - certainly typing eval('debugger') on the console doesn't help. If I want the functionality, I have to change the debugger statement, and run the code again, which might be a whole lot of work
When I stopped at an eval('debugger') statement, but then use the debugger 'step over/into/out' functionality, I 'lost my special status'.
How can I work around this? Is there a way to tell v8 to interpret all debugger statements by eval('debugger')? Is there a trick with which you can 'go into the other mode' - as if the eval('debugger') statement would magically appear as the next statement after the debugger statement where you're stopped? Do command line options to the chrome executable help? Maybe there is a way in firefox?
I learned about the eval('debugger') trick in an answer to a recent SO question of my own
ANNOUNCEMENT
What I'm going to do next is write a little transpiler for usage within node webserver. The transpiler will insert eval('') statements all over the place (by default once at the beginning/body of every function, and more or fewer of them if so specified in the query string.) Then I can set a breakpoint where the eval statement is, do "step into" and then I got what I want. Then I'm going to answer my own question.
Unless of course, someone will beat me to it. That would be most delightful, as I do have other things to do.
V8 developer here.
Is there a way to tell v8 to interpret all debugger statements by eval('debugger')?
There is currently no way to treat debugger statements or breakpoints as eval("debugger"), but it might be feasible to add a flag that does this. You can file a "feature request" bug at crbug.com/v8/new and ask for a flag that forcibly context-allocates all variables for debugging purposes.
(Side note 1: It's the eval part that has an effect here. Instead of eval('debugger') you could write eval(""); debugger; or debugger; other_code(); eval("");, so long as you have eval somewhere in the function.)
(Side note 2: the tension here is that on the one hand, it's Good™ when the behavior of a program when it is being debugged is the same as when it is not being debugged -- otherwise there might be issues that only show up when debugging, or un-debuggable failures in production mode. On the other hand, sometimes certain deviations are explicitly necessary in order to make debugging possible. I'm not sure on which side of the line this one falls. Context-allocating all variables will reduce performance and increase memory consumption, so if/when such a mode becomes available, you will probably have to (or want to) switch back and forth during your development work; which in particular means that this couldn't simply be the default when DevTools are open.)
Is there a trick with which you can 'go into the other mode' - as if the eval('debugger') statement would magically appear as the next statement after the debugger statement where you're stopped?
No, and there can't be. It's not a "mode" or "special status", it's a decision that has to be made when first parsing/compiling the outer function (the one that contained the variable you want to see within an inner function). Once that time has passed, it's too late to change anything (non-context-allocated variables are just gone), and the only option is to reload.
[EDIT in response to comments:
To clarify what I mean by "not a mode, but a decision": from the scope chain's point of view, the situation is essentially the same as:
var inner;
function outer() {
var foo = "foo";
var bar = "bar";
inner = function() {
console.log(bar);
debugger;
}
// "inner();" here is moved below
}
outer();
inner();
at the point when inner() is called, foo is either still there like bar (if it's context-allocated because at compile time of outer V8 determined that inner will need it), or gone (if V8 determined that it's local to outer and nobody else will need it). If inner contains eval, then it might need all outer-scope variables.
--end of EDIT]
This happens because of optimization
Well... because of an optimization, namely being smart about whether to allocate variables on the stack or in the "context object". This is completely unrelated to what is typically referred to as "optimization of a function", i.e. running them through the optimizing compiler. That's why the %NeverOptimizeFunction hack discussed in the other issue had no effect -- it's an unrelated mechanism.

Why in Strict mode in Javascript it isn't allowed to use with statement?

In my js code file when I use with statement in strict mode it shows error:
'with' is not allowed in strict mode.
Strict mode disallowed the with statement for several reasons. Some of them are outlined by Douglas Crockford in his famous with Statement Considered Harmful post: The short version is that when you use an identifier in a with, it's impossible to tell just by looking at the code (static analysis) what that will resolve to, because what it resolves to depends on the contents of the objects in question.
Consider:
with (o1) {
with (o2) {
with (o3) {
foo = "bar";
}
}
}
What happens? Is that setting o3.foo? o2.foo? o1.foo? A global foo?
This makes it difficult or impossible for us humans to reason about the code, and makes it difficult or impossible for JavaScript engines to meaningfully optimize the code.
Use of the with statement is not recommended, as it may be the source of confusing bugs and compatibility issues, is it is forbidden in strict mode
Best practice: Don’t use a with statement. instead try using IIFE
1: http://2ality.com/2011/02/javascript-variable-scoping-and-its.html
you can also take a look at JavaScript’s with statement and why it’s deprecated

Re-assigning a function declaration in javascript

Right now I am debugging some weird errors which occur in my GWT (version 2.5.1) application since Firefox 46. The javascript code generated by GWT contains multiple instances of this pattern:
function nullMethod() {
}
var v;
function f() {
f = nullMethod;
v = { name : 'Joe' };
console.log("called");
}
// this is called from multiple places
console.log((f(), v).name);
console.log((f(), v).name);
console.log((f(), v).name);
Seems that this somehow implements the singleton pattern. But for some reason this does not prevent that the initial declared method is invoked again. The string 'called' is printed to the console multiple times.
But if I try to reproduce this with a little test everything works as expected. The observations from above was made by adding console outputs to the generated code (>5MB).
Now the really weird stuff. If I add "console.log(f.toString())" as the first statement of the function, it prints the intial function on the first invocation. All further invocations print the nullMethod.
Can somebody explain what could be the cause? IE11 works fine. Chrome has the same issue as Firefox 46. I just didn't find old Chrome versions to verify since when this behaviour was introduced. Is it valid to overwrite a function declared this way?
jsbin.com gives a warning on the function re-assignment line:
Line 6: 'f' is a function.
The method f in this case is a Java static initializer. Running it more than once will cause problems in the emulated Java, which expects that this can only run a single time when the class is first referenced or loaded (ignoring classloader issues, since GWT doesnt emulate classloaders).
However, sufficiently old copies of GWT wrap up blocks of code in a try/catch block (iirc this was related to IE6 issues), and at the time, JS scope rules had some ambiguity around them which made this code work consistently, since all browsers supported this. This was known as a "sloppy mode self-defining function".
As part of ES2015, it has been decided that the try block has a different scope than the outer "function-hosted" one (i.e. when you declare something as a function foo() {...}, it exists in a high-level scope). See a ton of discussion on this at https://github.com/tc39/ecma262/issues/162.
This change means that some formerly sane programs no longer work correctly - for a time, this included Google Inbox as well as others.
Updating to a newer version of GWT, or using a custom Linker that no longer wraps each block of top-level JS in old GWT should resolve this. If you still must support whatever ancient browser that requires this behavior (with enough code archeology, I'm sure we could find out why GWT initially did it, but I haven't done this yet), you are going to have to find a compromise that works in both ancient and bleeding edge browsers.

hasOwnProperty and ECMAScript 5 strict mode

I'm curious: anyone knows why the ECMAScript5 specification hasn't tightened more the predefined object prototype's properties in strict mode? For instance, it seems like there's no info regarding the way hasOwnProperty is defined. I've tried redefining it (and tested the code in FF4 beta) and I was able to get away with this. If I didn't do anything wrong, then this means that anyone can still redefine the Object.prototype.hasOwnProperty property and really screw all the code that relies on it for working property...
thoughts on this?
EDIT: a little more info as I dig through the spec...
As I've put in a comment below, you can't really change Object.prototype in strict mode due to the metadata that was applied to it (Writable, Enumerable and Configurable are all set to false) and FF 4 beta (which I'm using to run my tests) does generate the exception.
thanks.
And? I can kill of everything on Object.prototype if I wanted to, don't include such code in your project/site, no do something better, find those idiots who are doing such things and make sure to kick'em in the balls.
I mean, I can even screw up any given Python (2.x) program by doing True = False.
You can never protect against idiots. Never. Try to educate or avoid them.
EDIT
To clarify the impossibility of this, if you encapsulate your script into an anonymous wrapper (as you should do if you use it with other code) the "use strict" will be local to your code.
That means, if the evil idiot code does not use strict mode on its own - and they won't... unless they are total idiots, which I'm not talking about here - they run in ES3 and your beautiful strictness doesn't even exist.

While debugging javascript, is there a way to alert current call stack?

For simple javascript debugging I'll use alerts to show variable values and the like. Is there a way to get the current call stack in javascript to be able to display it in an alert?
Thanks.
Quick and dirty in Gecko-based browsers:
new Error().stack
You can also manually trawl some of the stack using Function.prototype.caller:
var thisFunction = arguments.callee;
var caller = thisFunction.caller;
var callerCaller = caller.caller;
// ...and eventually, assuming no recursion:
var bottomCaller = ...;
assert(bottomCaller.caller === null);
One (possibly large) caveat of the .caller trick is that it doesn't handle recursion -- .caller looks from the top of the stack downward to find the first instance of the function in the stack and then returns its immediate caller, so without being careful you can loop infinitely looking up callers.
Another caveat to caller is that, going forward, if any of your code uses ECMAScript 5's strict mode, the caller property of strict mode functions (or of functions which have themselves been called from strict mode functions) is a so-called "poison pill" which throws a TypeError when accessed. The caller property of "bound" functions (those created by ES5's Function.prototype.bind method) is also a poison pill. These restrictions break the generic stack-walking algorithm, although one could imagine use-specific ways to work around this (entry and exit annotating functions, perhaps).
Do note that stack-walking like this isn't a great idea in production code (as a quick hack for debugging it's fine, tho); at the moment walking up the stack as in the latter example is somewhat expensive in Mozilla's JS engine, and it'll probably throw you out of machine code and back into interpreted code. Also, the stack-walk is O(n2), which might matter if you tend to have complex, deep stacks.
You can use console.trace()
It doesn't display an alert() but print the stacktrace on the debugger console.
Use debugger like Firebug for this if you are in Firefox. Chrome and Opera have build-in debugger. And there are Developers Tools for Internet Explorer.
The best way to debug Javascript is to use Firebug, which includes a full Javascript debugger.
If you're debugging in IE, you can use Visual Web Developer Express (or any other edition of Visual Studio).
If you're debugging IE8, you can use its built-in developer tools, which include a debugger.
It is possible to get the call stack in Javascript; see here.
Have you looked at firebug - and a breakpoint. If it's just for debugging, then this might suffice.
Also - you can have a look Here
This will give you all call stack
working good for me.
var y = 'arguments.callee.caller';
while (eval(y) != undefined) {
stak += eval(y + '.toString()');
y = y + '.caller';
}
alert(stak);
For nodejs debugging, in Visual Studio Code, as of v.1.14.2, it's View->Debug (Ctrl+Shift+D)

Categories