Finding the line number FROM WHERE the call to current function occured - javascript

I have a lightweight logging function. To keep it simple its something like:
function log(msg){
console && console.log && console.log(msg);
}
which i have in a seperated file "Logging.js".
Now from another file lets say "hello.js" i do:
log("Hello");
Now if i make calls to that function the console will always display Logging.js:2 as the place where the logging occured. So there is no chance to determine from where the message originated. The log message should say hello.js:1.
Is it possible to find out from where the log function is called, find out the line number of the call and then manipulate the line number displayed by the console?
Or is there an easier solution?
Caution, please read carefully: Its NOT about the current line number. It's about the line number from where the function call occured and its about how to manipulate the log output so that it displays the line number FROM WHERE the function has been called. It's not about Errors or catching Errors.
I already postet this question some time ago and it was downvoted and declared as a duplicate of How can I determine the current line number in JavaScript? in no time, but it its not. This question is not about finding the current line number.

You can construct an Error object and look at the "stack" property:
$(function() {
function a() {
b();
}
function b() {
c();
}
function c() {
$('#e').html(new Error().stack.replace(/\n/g, '<br>'));
}
a();
});
JSBin
That'll show:
c#http://jsbin.com/aLuKUSU/1:33
b#http://jsbin.com/aLuKUSU/1:29
a#http://jsbin.com/aLuKUSU/1:25
#http://jsbin.com/aLuKUSU/1:36
b.Callbacks/c#http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js:3
b.Callbacks/p.fireWith#http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js:3
.ready#http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js:3
H#http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js:3
The "stack" property of Error objects is not standardized, but it's available in Firefox, Chrome, IE10+, and Safari 6. (Don't know about mobile browsers.)

Related

Determine function file/line location given reference in NodeJS?

The fact that I can't think of how to do this makes me think it's some sort of anti-pattern, or impossible. If anyone has any better ideas of how to handle my situation, recommendations always welcome.
I have a legacy codebase and at one point I am retrieving function references and calling the function. These function calls are expected to return a result, but sometimes they are missing their return statement. Currently I throw an error if the returned value is nullish but this only gives me a stacktrace to the engine location that is calling the function, not the function itself.
Is there any way that I can determine the file name/number of the function, or force the function to throw an error such that a stacktrace to that actual function is generated?
There is no such feature in the Javascript language. It's not anti-pattern, just not something that the language supports. There is no requirement that a function have a return statement and there is no way to force it to throw an exception if it doesn't return a value.
Without seeing any of the relevant code, I can offer some suggestions:
Set a breakpoint at the line of your code that initiates the function call. Then, trace into the function in the debugger. You can go as far into it as you need to and each time you go step into a new function call, it will show you the file and line number that you're on. I use this technique regularly when I'm confused by some behavior by some module (either built-in to nodejs or an external module I'm using) and it's not immediately clear how to find the right code on Github for it. I just step into it and can immediately see the code and watch it execute line by line as needed for whatever problem I'm investigating.
Assuming this function you're calling expects some arguments, you can give it some sort of bogus arguments that would hopefully trigger it to throw some sort of exception and you could then see the stack trace from that exception. For example, if it was expecting a non-optional object as an argument, you could pass null and see if that triggers an exception. If it was expecting a callback, you could pass a non-function and see if that triggered an exception.
As for the name of the function, if the function has an actual name (it's not anonymous) and fn is your function reference, then you can do console.log(fn.name) and see if there is a name. You could also examine fn.toString() and see if it reveals the source code of the function. Sometimes it will and if the function is a named function that may show you its name. This won't show you what file it's in, but you could perhaps then grep for something you see in the source to find it.
Here's an example from point #3:
function hello() {
return "hi";
}
// create function reference that points to my function
const fn = hello;
// log info on that function reference
console.log(fn.name);
console.log(fn.toString());

Does Function Calls Depend on it's Placement in the Code Structure [duplicate]

Every time console.log is executed, a line saying undefined is appended to the output log.
It happens in both Firefox and Chrome on Windows and Linux.
If you're running console.log() from a JS file, this undefined line should not be appended.
If you're running console.log() from the console itself, it makes sense. This is why: In the console you can type a name of a variable (for example try typing window) and it prints info about it. When you run any void function (like console.log) from the console, it also prints out info about the return value, undefined in this case.
I tested both cases on my Chrome (Mac ver 23.0.1271.101) and indeed I see the undefined line when I run it inside the console. This undefined also appears when I write this line in the console: var bla = "sdfdfs"
Although talkol´s answer is ok, I try to put it more straight:
JavaScript is designed as a dynamic language which means that the type (string, void, boolean …) of a function return value is not pre-defined. If a function does not use a return statement or an empty return statement with no value, JavaScript automatically returns undefined. That means that in JavaScript every function returns something, at least undefined.
So the function console.log() in Chrome console either uses no or an empty return statement, so that the return value of this function is undefined. This function return value gets also displayed in the Chrome console.
[If somebody know where to find the definition of the console.log() function in Google Chrome source code, please comment with the link, then we can even go further and look at the real code, would be nice.]
Sources:
https://stackoverflow.com/a/20915524/1744768
https://developer.mozilla.org/en-US/docs/Web/JavaScript/A_re-introduction_to_JavaScript
Follow the picture to solve this problem:
Ctrl + Shift + J
Console environment in your browser is designed to take the very last statement expression in a program and evaluate it for a value and then show you that value.
The result of an assignment expression is the value that was assigned.
So the JavaScript engine just does an assignment but the console does one extra step which is to set whatever my last statement is, give you that value back. That’s why it prints 2:
In statements that have no return value you get something like undefined.
undefined is the return value of the console.log() in Chrome developer tools. You will get undefined if you do the following in Chrome developer tools, and you will see that you get undefined even though x has the value 3.
> let x = 3
> undefined
What you can do is simply create your own console.log like function with a return to change this behavior when doing a lot of coding in the developer console. Here is an example of what that looks like in the developer console:
console.log('I hate seeing the next line stating the obvious.')
I hate seeing the next line stating the obvious.
undefined
log = function(l){return l}
function log()
if(1 === 2){console.log('1 is not equal to 2.')}else{log('No Shit Sherlock.')}
"No Shit Sherlock."
That undefined you see in console is the return value of the function:
check out these two variants:
This one returns nothing
This one returns something:
Remember one thing. Any function that has some definition will always return something, If you skip the return keyword, it will eventually return undefined when you call it.
If you're using console.log to emit multiple values in a single line, here's a hacky alternative:
var1 + ' ' + var2 + ' ' + var...
(Better ideas welcome, this might blow up in certain circumstances)

Recursion - Call stack fails to pop when testing the maximum stack size

Basically call stack will start to pop out the function calls one by one when the last-in function call returns. But when ever I try to create a call stack nearer to the size of its maximum, An uncaught expression is getting raised.
//Code for testing the stack size
var cnt = 0;
function test(){
//Max stack size is nearer to ~41800
if(cnt++ == 41763){
console.log('finished');
return true;
}
return test();
}
test();
So the above code is throwing an exception for me in chromium Version 49.0.2623.112 m like below,
Uncaught exception
< true
Please not that the above error has no message in it. My question here is,
The last function call in the stack has returned true that means the stack size was not exceeded. why didn't the other function calls in that stack was not returned? And what is the reason for this blank exception message?
The problem here is
console.log('finished');
this adds some extra functions to the call stack that will let the limit exceed, but through exception handling your code gets executed anyway.
Try to run it without console.log and you see you get to the limit and see either a true or an exception.
The console.log is not in specification of javascript, so the behavior is undefined, and can be changed from release to release. So something that happens in your version maybe doesn't happen in ours.
Here is the most likely explanation for what happened: It is certain that console.log will increase the size of stack, and because is the last statement you call before the return, it can produce a Maximum call stack sometimes because you are very close to the limit. That Maximum call can be happen inside the console.log code(who calls something else), and how this error will handle it, it depends on the code of console.log. It seems like the code inside the console.log throws a Uncaught exception when an error happens. Now when you catch an error with try, code continues, that's why the true appears.
Here is an example in jsfiddle where I override the console.log and the results appear in the HTML. You can play by removing the override code of console.log to see how things change. Try this and tell us if the result seems strange again.
It's worth notice that when the Maximum call stack size exceedederror appears it depends on the size of the stack frame too (local variables).
Note: In ECMAScript 6 spec, if a function call is the last action in a function, it will not go in stack, but it will run "immediately", so your code will run without an error for all the numbers, no matter what number you put.

Why does Chrome debugger skip over delete statements?

Why does the Chrome debugger skip over delete statements? The following code will demonstrate the observation if ran in a console.
(function () {
var foo = { bar: true };
debugger;
delete foo.bar;
})();
The answer here is in the nature of the command 'delete' its not a common function as you are used to in js. My guess is that the chrome tools are set to stop on every line that contains an object definition or an object running a method, behind the scenes almost everything one encounters in javascript is an object, however delete is not am object but an operator like '+' or '-'. And the reason it gets skipped is because this will be the only time you will have a line that doesn't throw a error but does not define or call an object.

Is it possible to flush the console (make it print immediately)?

I use Firefox + Firebug for some Javascripting. The text I'm trying to log with console.log does not immediately appear in Firebug's console. It seems like it piles up in a buffer somewhere, and then gets flushed to console in chunks. I have a function that makes a few log calls. Sometimes I get just the first line, sometimes - nothing. I do, however, see the whole bunch of lines when I refresh the page.
Can I flush the console log manually?
The short answer is no. There is no flush. You could clear the console
console.clear();
But I don't think that's what you want. This is most likely from the code. If we can see it, I can revise my answer with better feedback.
If you want to see all the available methods under console, execute this in the command line:
for(var i in console) {
console.log(i);
}
or have a look at the wiki page of the console API.
It's not a Firefox problem, It's a JavaScript problem because execution is delayed and variables are updated so you can see only the last value.
To see immediately the output you need to convert your object in string so it will not change also if object will be updated.
I wrote this easy function :
function printLog(s) {
if (typeof(s) === 'object') {
console.log( JSON.stringify(s) );
} else {
console.log(s);
}
}
The printed output is a string (so you can't interact with it) but it contains the real dynamic object that you want to see at the print time instant.

Categories