Node Server debugger code behavior changes when debugging - node.js

I am debugging a Node Server written in typescript in WebStorm 10.0.4 and when stepping through the code, the code execution path completely changes. A variable assignment appears to break and reference a different (incorrect) object and break my code.
I have a class CustomerRoutes.ts which contains different methods to handle POST requests. I register the endpoint:
app.post('/Contacts', jsonParser, CustomerRoutes.postContact);
CustomerRoutes.postContact is a public static function which is defined as:
public static postContact(request, response) {
if(request.body.$type == 'Person') {
CustomerRoutes.postIndividual(request, response);
} else if(request.body.$type == 'Organization') {
CustomerRoutes.postOrganization(request, response);
}
}
CustomerRoutes.postIndividual and CustomerRoutes.postOrganization are both public static functions as well. So when the server is in non-debug mode the code executes as expected and the branching statements are executed. However when stepping through the code the variable CustomerRoutes global variable gets reassigned to the contents of request within the scope of CustomerRoutes.postContact
As you can see in the Variables window of the debugger the variable CustomerRoutes has been redefined twice to the values of request and response. So now when stepping through the code and the functions postIndividual and postOrganization are called, CustomerRoutes does not contain those function and POST fails with an exception and error 500.
I do not believe this is any sort of race/timing condition so it must be a bug in the debugger environment. My hunch is that the typescript variable mappings are not working correctly with the debugger but I am not certain. Has anyone seen an issue like this or an idea on a fix? I have never seen anything like it. I am happy to post more information as requested.

My hunch is that the typescript variable mappings are not working correctly with the debugger but I am not certain.
TypeScript doesn't have proper variable mapping in sourcemaps at the moment. Follow this issue : https://github.com/Microsoft/TypeScript/issues/2859 (also answered it here once : Chrome Typescript debugging references wrong 'this')
Has anyone seen an issue like this or an idea on a fix?
Disable sourcemaps to see what is actually going on in the raw JavaScript.

Related

Why is a global `name` variable declared in typescript and can I avoid using it?

A friend refactored some code and moved the definition of a variable called name from the function's top-level scope into a then's body. This variable was used in a subsequent then which caused a ReferenceError since name was not in scope.
We couldn't understand how the code passed compilation until we saw that typescript/lib.d.ts has the following deceleration:
declare const name: never;
Long story short, I have two questions.
Why is name (as well as length and many other globals) added by default to typescript?
From the surrounding code this seems meant for projects intended to run in a browser, we're a node.js project. Can we opt out from having these declarations added for us?
This seems to be a very old browser behaviour. Referring to the MDN both name and length are properties of the window object.
https://developer.mozilla.org/en-US/docs/Web/API/Window/name
https://developer.mozilla.org/en-US/docs/Web/API/Window/length
In order to get rid of all the DOM-specific declarations, you can set the lib property in your tsconfig accordingly. You cann see all options on this page. Take a look at the --lib flag.
An option to tell TypeScript your code runs on Node.JS would be nice. But it seems not yet implemented: https://github.com/Microsoft/TypeScript/issues/9466

Azure Function: "Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information"

I have an F# Azure Function that is failing, in a bizarre way, and don't know how to approach fixing the issue. I created a minimum repro of the actual case below. The test function is manually triggered and uses FSharp.Compiler.Service as a dependency, as specified in the project.json below:
{
"frameworks": {
"net46":{
"dependencies": {
"FSharp.Compiler.Service": "11.0.6"
}
}
}
}
The run.fsx file looks like this:
open System
open Microsoft.FSharp.Compiler
open Microsoft.FSharp.Compiler.Ast
open Microsoft.FSharp.Compiler.Interactive.Shell
let Run(input: string, log: TraceWriter) =
// code here that uses FsiEvaluationSession
// and runs just fine
log.Info "I RAN"
So far, so good. The part that baffles me is that if I add the following function above Run,
// same dependencies as before
open Microsoft.FSharp.Compiler.Interactive.Shell
let foo (longIdent:LongIdent) =
// version 1
// "FOO"
// version 2
// longIdent.ToString ()
// version 3
longIdent |> List.map string
let Run(input: string, log: TraceWriter) =
// same as before
Uncommenting section 1 alone works fine, uncommenting section 2 alone works fine, uncommenting section 3 causes hell to break loose. The function compiles, but running it causes the following exception:
Exception while executing function: Functions.fsc-1. mscorlib: Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information.
... which is puzzling to me, because
foo isn't even called anywhere
the signature and the 2nd version both use LongIdent, so this type doesn't seem to be the source of the problem.
Any suggestion on how to approach the problem, and what the problem itself might be, would be very appreciated - I don't even know where to start, and the same code runs perfectly fine in a local script.
I believe the reason for this is that Azure Functions SDK depend on FSharp.Compiler.Service (FCS) version 9.0.1. This means that when you try to load a different version of FCS, you will get the already loaded version 9.0.1.
This works as long as the public API of the FCS version you are using matches the public API of version 9.0.1, but when there are differences, it will crash, because your code assumes that the public API looks different. I suppose this might be triggering the issue here, although I'm not 100% sure how (possibly, LongIdent is now a different thing than it was in version 9.0.1?)
The very same issue used to happen with FAKE, which also bundles FCS and prevented loading of different versions. One of the options is to rename the assembly to avoid the clash.
I also got the same error, I solved it by doing the following workaround, please refer if it works for you also.
Right-click on the Project and select properties.
Goto Debug tab and create a profile with the reference to the below
screenshot.
Note: Replace UserName with your username.

Setting debug strings dynamically in Loopback 2.0

I use debug strings for debugging Loopback 2.0 application. Loopback documentation says:
The LoopBack framework has a number of built-in debug strings to help
with debugging. Specify a string on the command-line via an
environment variable as follows:
MacOS and Linux
$ DEBUG=<pattern>[,<pattern>...] node .
Is it possible to change patterns dynamically in runtime? Or is it possible to use environment-specific configuration?
Before I get deeper note that this debug logging facility uses visionmedia's debug module which handles almost all of the logic.
Is it possible to change patterns dynamically in runtime?
Well before any module is loaded, safest and best way I believe is to just manipulate the environmental variables:
if (process.env.NODE_ENV === 'development') {
process.env.DEBUG = process.env.DEBUG + ',loopback:*';
}
Another way would be to load debug and use it's .enable method:
require('debug').enable('loopabck:*');
But note that it only works if you do this before Loopback is required since it only allows changes before it's instances are created, which is in this case before loopback is loaded. Another thing is that, there might be multiple debug modules installed depending on the dependencies and your package manager(npm#3, npm#2 and yarn behave differently). debug might be in your node_modules directory, or it might be in loopback each module, node_modules directory. So make sure you require all instances of it and enable, if you want to do it this way.
Now if don't want to do it on the startup, well API doesn't allow changes in the runtime. You can view the discussion regarding this here. Though there are some dirty ways to go around it, but these might possibly break in the future so be careful.
Firstly, there's a module called hot-debug which supposedly makes require('debug').enable work on previously created instances also, but when I tried it, it didn't work perfectly and it was buggy, but it's possible it might work fine for you.
If that doesn't work for you another way is to override require('debug').log method. If this is defined, debug will call this method instead of console.log with the formatted the arguments. You can set DEBUG=* and then filter it yourself:
require('debug').log = function (string) {
if (string.contains('loopback:security')) {
console.log(string);
}
};
This way will be slow in production though as all the debug output will be formatted before being filtered even though nothing might be outputted to console.
Another thing to override the require('debug').init method. This is called everytime a new debug instance is created. Since every debug instance uses an enabled property to check if it's enabled we can toggle that.
const debug = require('debug');
const { init } = debug;
const instances = [];
debug.init = function(debugInstance) {
init(debugInstance);
instances.push(debugInstance);
};
// You can call this function later to enable a given namespace like loopback.security.acl
function enableNamespace(namespace) {
instances.forEach(instance => {
instance.enabled = instance.namespace === namespace;
});
}
Though there's a lot of improvement can be done on this, but you get the idea.
I can change debug namespace dynamically with the hot-debug module.
In my app, I've just created a function for this :
require('hot-debug')
const debug = require('debug')
function forceDebugNamespaces (namespaces) {
debug.enable(namespaces)
}
// Usage
forceDebugNamespaces('*,-express:*,-nodemon:*,-nodemon')
In my case, I have a config file which allow me to set process.env.DEBUG but I needed to find a way to update debug namespaces without restarting my app (the config file is watched for changed by my app).

Nodejs and implicit global variables?

I'm using some external libraries intended to be used in a browser and they set global variables implicitly like a='a' (without the var).
It seems like when I require certain scripts that do this, sometimes the variable will be accessible outside its scope just like in a browser, but for other scripts the global variable is not accessible outside its own script.
Anyone know how nodejs handles implicit global variables, and why I'm seeing somewhat random behavior? I found surprisingly little on the internet.
I can go into the scripts. write something like
if(typeof exports !== 'undefined' && this.exports !== exports){
var GLOBAL=global;
}
else{
var GLOBAL=window;
}
and then change all implicit references to GLOBAL.reference but these scripts are not my own and every time I want to get the latest version of them I would have to do this over again, which is clearly not desirable.
Using module.exports would be cleaner because then I don't have change all the references, but just add a section of the top of every file that exports the globals, but my original question about how node handles implicit globals is still relevant
I am not sure if this answer will help you, since it is hard to diagnose what is going on with your code, but maybe, some of this reasonings can help you diagnose the actual problem in your code.
The behavior in node is actually similar to that of the browser. If you would declare a variable without the var keyword the variable will be accesible through the global object.
//module foo.js
a = 'Obi-wan';
//module bar.js
require('./foo');
console.log(global.a); //yields Obi-wan
console.log(a); //yields Obi-wan
It is not clear why you say this behavior is not consistent in your code, but if you think about it, the use of global variables is precisely subject to this kind of problems since they are global and everyone could overwrite them at any time, causing as a result this unexpected conditions.
There is one aspect in which node is different from the browser though and that could be affecting the behavior that you see.
In the browser, if you do something like this directly in a JavaScript file:
console.log(this==window); //yields true
But if you do the same thing in a Node.js module:
console.log(this==global); //yields false
Basically, in the outer scope of a Node.js module the this reference points to the current module.exports object.
console.log(this==exports); //yield true
So, chances are that if you are putting data in the global scope (window) in the browser through the use of this, you may end up with a module scope in Node.js instead.
Interestingly, the code inside a function in Node.js behaves pretty much as in the browser, in terms of the use of the global scope.
(function what(){
console.log(this==global); //yields true
})();
This does not directly answer your question but it provides a solution since I don't think it is possible.
I love regexp. They are so powerful:
js = js.replace(/^(\t|\s{4})?(var\s)?(\w+)\s=/gm, function () {
if (arguments[1] || arguments[2]) return (arguments[1] || '') + (arguments[2] || '') + arguments[3] + ' =';
return 'exports.' + arguments[3] + ' =';
});*
JSFiddle here
How does it work? I will retrace my work:
/(\w+)\s=/g will take any var, return 'exports.' + arguments[1] + ' ='; will turn them into an export. Not very good.
/(var\s)?(\w+)\s=/g will take any var, but in the callback we examined first group (var\s). Is it undefined? Then we should export it, else nothing should happen. But what about scopes?
/^(\t|\s{4})?(var\s)?(\w+)\s=/gm now we use indent to determine the scope :)
You should be able to run this regex on your file. Be careful, you need it properly indented, and be aware that I might have forgotten some things.
Ah, the problem was that the global variable that was being declared globally in the browser wasn't being declared via a='a', but with var a='a'. In a browser if the var keyword is used not inside a function it will still declare a global variable. It only declares a local variable if the var keyword is inside a function. Node.js doesn't behave this way, and all var declarations are considered local.
Its ashame node.js does this, it makes it less compatible with browser scripts, for no real reason. (other than allowing people not to have to wrap all their scripts in a function).

Cannot set breakpoint inside function when using require inside closure

Using node-inspector, I'm unable to set breakpoint in the following node.js code. (Content of main.js)
(function() {
require('underscore');
var doSomething = function(callback) {
callback('doSomething Finished');
}
doSomething(function(x) {
console.log(x);
});
}).call(this);
I can easily set a breakpoint on line 2, line 4 or line 8, however no matter how hard I try the debugger won't let me set a break point on line 5 or line 9. To be clear, I'm using the following commands to run node-inspector
node --debug-brk main.js
node-inspector
I also tried to debug in web storm, however the issue persists. If I remove the line require('underscore');, then the problem immediately goes away and I'm able to set break point inside function body again. The problem also goes away if I remove the outermost closure function. It seems that the interaction between require and file level closure is screwing up the node debugging functionality. Has anyone experienced this problem themselves and / or knows any workarounds to be able to break inside function body?
EDIT: My node js version
Tony:~ $ node --version
v0.10.12
Tony:~ $
I ran exactly into the same issue with the same setup.
I've added a breakpoint after the definition of the target-function (that was the only place i could actually add a breakpoint). When the debugger reached that breakpoint and the function was actually defined, i was able to add breakpoints to the actual target-function...
This may not be the answer that you want to hear as it doesn't explain why you can't set any breakpoints, but I would simply remove your require statement from the closure and place it top-level. I would go even further and recommend that you don't use a closure like the one above at all.
The reason is that node uses its own module system, and unlike Javascript in the browser, declaring variables top-level does not pollute the global namespace. This is where require(...) comes in. So, you gain nothing by wrapping your code in an immediately invoked function (unless of course you want your module to be able to run both client side and server side).
I would guess that the reason that you are not able to set any breakpoints is that the V8 runtime is recognizing an unnecessary closure and then optimizing your code for you. The rewritten code may not have the correct source mapping and so breakpoints cannot be set.
So, two suggestions:
require calls are not like regular statements. They are more similar to import statements in Java and are handled specially by the compiler. They should always be top-level in a node file.
No need to wrap your code in an anonymous function when in Node.

Resources