Determine function file/line location given reference in NodeJS? - javascript

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());

Related

Create error when calling function does not use the right number of arguments in javascript

I have this function in javascript.
function func_name(param_1, param_2)
{
//blah blah
}
Sometimes, I carelessly call it this way by supplying 1 parameter instead of 2.
func_name(aa);
However, javascript does not produce an error when the script is run. How can I make javascript produce an error or warning when the script is run? This will help one catch bugs more easily.
I am using node.js v6.
You could make use of the arguments object. Each function has an internal object called args, which is an array like object (has a length property) and contains the parameters which we use when we call the function.
function func_name(param_1, param_2){
if(arguments.length!==2){
// Here you can throw an error.
}
}
For further info, please have a look here.

console.log() called on object other than console

I remember that always when I wanted to pass console.log as a callback parameter to some function, it didn't work unless I used the bind() method to bind console to it.
For example:
const callWithTest = callback => callback('test');
callWithTest(console.log); // That didn't use to work.
callWithTest(console.log.bind(console)); // That worked (and works) fine.
See Uncaught TypeError: Illegal invocation in javascript.
However, recently I noticed that console.log() works fine even when called on object other than console. For example:
console.log.call(null, 'test');
logs 'test'.
When and why did it change? Does the specification say anything about it?
Editor's Draft of Console API used to say:
Logging APIs SHOULD all be callable functions allowing them to be passed as arguments to error handling callbacks, forEach methods, etc.
This is no longer included in the current version of the specification.
I thought that Chrome and Node.js changed it to work like in the specification, but it seems that it worked like that even before it.
I'm still curious when did it change and what was the reason of that.
I don't know when the change was made, but I have an idea about why it didn't work.
Consider the following code
callWithTest = callback => callback('test');
var Demo = function () {this.str = 'demo';}
Demo.prototype.getStr = function () { return this.str;}
demo = new Demo ();
demo.getStr(); // returns 'demo'
callWithTest(demo.getStr); // returns undefined
window.str = 'window';
callWithTest(demo.getStr); // returns 'window'
If you trace the code, you will see that when demo.getStr gets called through another function, this refers to window, and sine str is not defined within window, it returns undefined. If you called it directly or bind with demo, this refers to demo and thus it returns 'demo'.
In nodeJS (v6.6.0), there exists a class called Console within the console module which user can explicitly pipe logs into a file (or whatever stream a user like). According to Node.js v6.6.0 api specification,
console = new Console(process.stdout, process.stderr);
Console does not exist in browser as it isn't necessary. The output of console only exists in a canvas used for debugging, and there are exactly one instance of it. User can't, and should not be able to, pipe output of console to any other places as it will become a serious security issue. Because of this, developers can do something within the log function like var x = this.x || console.x as there is exactly one instance of the console object.

Fundamental misunderstanding of how Angular handles a snippet?

I'm having a problem debugging some code in an Angular controller. This function is called when a form is submitted on our checkout page. I'm fairly new to Angular, and I'm a bit confused as to what is going on in this function.
$scope.handleStripe = function(status, response){
PayStripe.processPayment(status, response).then(
function(successMessage){
alert('success', successMessage);
Order.recordOrder(Cart.cart.items, Auth.user.uid)
.then(function(){
PostAffiliatePro.reportSale(Cart.cart.getTotalPrice());
Cart.cart.clearItems();
$scope.mode = 'success';
});
}
);
};
Here's what I think is happening line-by-line...
1) We're declaring a function called handleStripe with two arguments: status and response.
2) A method called processPayment is being called and is inside of an object dependency injected into the controller called PayStripe. .then is opened, so the following lines of code will be executed AFTER the processPayment method is called.
3) Running an anonymous function with an argument of successMessage.
4) I'm confused as to what's happening here, as I've never seen alert called with any arguments other than a message. this page on alert is not much help.
5) A method called recordOrder is called from the object Order which is a dependency of the controller.
6-10) After the recordOrder method is called, the cart is cleared, the sale is reported through another method, and the mode variable contained in the controller's scope is updates to the value success.
I've looked through all of the methods associated with these steps, and I still have some questions.
1) Where are all of these arguments being passed in? Are the arguments passed into the functions pre-declared arguments that will be updated by Angular? I.E. are these variables which Angular defines as the process moves through the queue, and whose values are not user-defined?
2) On line #4, I understand that the second argument is from the argument defined in the function, but what is the combination of these two valued inside the alert() function doing?
3) The fix to the bug that comes from this script depends on me being able to change the value of $scope.mode to something different as soon as the handleStripe function is called, however I have tried to insert such a declaration in multiple places that seem logical with results varying from the script breaking, to nothing happening at all. To me it seems that the logical place to put $scope.mode = 'my-value'; would be between current lines #1 and #2, however this produces the affects I mentioned before.
Finally, I feel I may be missing an overall concept, rather than wrestling with syntax. What is this concept called, if I am missing one, and where can I learn to use it?

why is error in Javascript internal/external file stops the below code too?

The Error in JavaScript internal/external file also stops the below code
For example:
var myObj = {};
myObj.other.getName = function(){
console.log('other is not defined');
};
alert('this will not show');
in above code, the alert will not come as the above code has error.
I added the same code in one file tst1.js and below this add one more file tst2.js. put alert('in tst2.js') in it. the tst2 alert come while tst1 not. it is some what related to
code compilation/interpretation.
It's much appreciated If someone explain me this behavior :)
This is the default behaviour of JavaScript. Avoid errors and the code will run normally.
Also you can handle errors with try...catch: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/try...catch
All JS implementations are, AFAIK, single threaded. This means that all of your code is executed sequentially, on a single thread (logically). If this thread encounters a fatal error, it grinds to a halt. All code that comes after the point where the error occurs is ignored (the JS engine halted, no work is done anymore).
To clarify: it does not matter how many files you have. All of the JS code is stringed together into one big script, and this one script is executed sequentially (execution point starts at line 1 of the first script, and ends at the last line of the last script). Any errors in that code will cause the overall execution to grind to a halt:
//file1.js
var foo = (function()
{
console.log('This file is flawless, but pointless');
}());
//file2.js
foo();//calls previously defined function, assigned to var foo
//file3.js
fudhfsiufhi;//ERROR
//file4.js
foo();//will never get executed, because an error occurred in file3.js
Remove file3, or indeed fix the error, and everything will work as expected.
Allthough JS code is executed/evaluated sequentially, event handlers, callbacks, intervals, and timeouts might lead you to believe otherwise. Couple that with the fact that you have some control over what code is executed when, but not full control, and you get situations that, at first, seem rather counter intuitive. Consider this:
setTimeout(function()
{
massive(syntaxError) -123 + "here";
},0);//zero MS
alert('This will show');
This oddity is well documented, but it has to do with JS having a callback/handler loop, and queue. The setTimeout sets a timeout, to call the anonymous function in 0ms (immediately), but that callback is sent to the queue, which is checked periodically. Before the queue is checked (and the callback invoked), the alert will show. That's why the interval you pass to setTimeout or setInterval is not guaranteed to be exactly N milliseconds.
You can postpone a call to a method somewhat, by adding a call to the queue, like in the snippet above. But when the queue is processed, and what order the queued calls will be performed in are things you have no real say in. No say whatsoever.
It doesn't matter how many files, or how many statements that come before or after the problematic piece of code: there is no thread left to carry on.
The code you posted has a pretty clear error in it: you're assigning a property to other (a property of myObj, but this property is not defined anywhere, let alone defined as an object. Fix it by declaring properties first, before accessing them:
var myObj = {other: {}};//other is an empty object literal
myObj.other.getName = function()
{
console.log('This works');
};
alert('And the alert will show');
Your current code evalutes to:
var myObj = {};//object
var (myObj.other).getName = ...;
//evaluates to undefined
undefined.getName = ...//ERROR
undefined is a primitive value, actually signifying the absence of a value. undefined, therefore, cannot be accessed as an object, it can't be assigned properties.
Note:
This is just for completeness' sake, but JS is indeed single-threaded most of the time, but ECMAScript5 introduced Worker's which allow for some restricted form of multi-threading (without shared state, for example). Read through the MDN documentation on workers if you want to know more.

Nested call to function in Javascript

Intellij IDEA shows a warning when ever I write Javascript like this:
someFunction(someOtherFunction());
But the explanation is not really helpful:
"This inspection reports any Javascript function calls used as
arguments to another function call."
This is something I do frequently, so what's the potential trap hiding there worth warning of? Or if it's just some coding convention, what's the reason for it?
It is a warning because most of the time, you want to pass a function reference as an argument. It is mostly used as a callback:
someFunction(someOtherFunction);
function someFunction(fn){
fn.call();
}
In that example, someOtherFunction() instead of someOtherFunction would not work as expect (unless someOtherFunction returns a function itself).
someFunction(someOtherFunction()); work more like a getter.
someFunction(someOtherFunction());
function someFunction(int){
alert(int === 1);//True;
}
function someOtherFunction(){
return 1;
}
It gives a warning because it is a common mistake for new developers.

Categories