NodeJS breakpoints sometimes not working - javascript

We are building a NodeJS 5.5.0 app using the --harmony command line flag to enable ES6. It is a very simple API proxying app so there is no data layer or front-end apart from the API responses themselves. The app is tied together with connect, using Swagger for the API itself. I am using IntelliJ 15 and everything is working well apart from debugging failing to consistently hit my breakpoints. I am finding this quite frustrating and a waste of dev time - perhaps I am missing something here as am new to the Node environment?
Here is my specific example:
app.js:
// requires here
swaggerTools.initializeMiddleware(swaggerDoc, function (middleware) {
// Interpret Swagger resources and attach metadata to request
app.use(middleware.swaggerMetadata());
// Validate Swagger requests
app.use(middleware.swaggerValidator());
// Route validated requests to appropriate controller
app.use(middleware.swaggerRouter(options));
// Serve the Swagger documents and Swagger UI
app.use(middleware.swaggerUi());
// Start the server
http.createServer(app).listen(serverPort, function () {
console.log('Server is listening on port %d', serverPort);
});
});
module.exports = app;
And then somewhere along the line we are using a transformer with object-mapper that runs on every API call:
transformer.js:
'use strict';
(function () {
var util = require('util');
//==> breakpoint #1 on the line below, successfully hit when the app launches
module.exports = function (req, res, data, next) {
console.log('GOT HERE!');
//==> breakpoint #2 on the line below never hit but app hangs here
var operation = req.swagger.operation;
// more code here
};
}).call(this);
Breakpoint #1 always works when the app launches, I skip it and make a call and 'GOT HERE!' is printed in the console as I would expect. The app hangs here indefinitely but I can't inspect any variables and the IDE doesn't register that it has hit the breakpoint. We've tested this outside of the IDE with node-inspector, Chrome tools and the native interactive node debugger but the same issue is present. I have also tested this on multiple versions of Node 4 and 5.
We've had to wrap most of our files with a function wrapper for the time being as we're using blanket for code coverage and it doesn't work without this. I have tried removing the function wrapper in transformer.js above but the debugger still doesn't hit breakpoint #2.
Can anyone please offer some insight on this as I'm out of ideas?

I have found the cause of this. It seems there is a potential bug with the Node debugger when it hits any line with util.inspect() on it it will hang there.
I have confirmed this is an issue in the latest versions of Node 4.2.6 and 5.5.0 as well as nightly builds 5.5.1 and 6.0.0.
See https://github.com/nodejs/node/issues/4906

Related

Meteor - Meteor.Collection.get not defined in production

I'm trying to use Meteor.Collection.get(collection_name) (server side only) in production, it works well in development ; but as soon as I try to build my app with meteor --production, meteor throw
TypeError: Meteor.Collection.get is not a function
I suppose that Meteor.Collection.get was only made for debugging purposes (I can't find anything about it in the official documentation). Any idea how I can use it in production ?
I am not sure, where Meteor.Collection.get comes from in your code but I know the very reliable and long time battle proof dburles:mongo-collection-instances which allows you to retrieve a Mongo.Collection via it's name.
Add the package:
meteor add dburles:mongo-collection-instances
Create a collection:
// server/client
export const MyDocs = new Mongo.Collection('myDocs')
Get the collection:
// anywhere else
const MyDocs = Mongo.Collection.get('myDocs')
It works on the server and the client and runs fine in production.
Documentation: https://github.com/dburles/mongo-collection-instances
Edit: A note on --production
This flag is only there to simulate production minifaction. See the important message here in the docs: https://guide.meteor.com/deployment.html#never-use-production-flag
You should always use meteor build to build a production node app. More to read here: https://guide.meteor.com/deployment.html#custom-deployment

Execute NPM module through cordova

I created an app using cordova and everything is fine, expect I need to use a node module which doesn't have a client-side equivalent because I'm dealing with file write streams etc. I have found Cordova hooks to be my best shot so far, where I create an app_run hook to execute a node file that runs a socket server to listen for events from the client side.
I know, a very longwinded solution, but seems logically correct to me, the issue is that when I do create the server, building the app through Visual Studio 2017, the app launches on my android phone, but VS hangs on the "deploy" stage. I guess that it has to do with the event chain, so I created an asynchronous script like this:
(async function () {
const server = require('http').createServer()
const io = require('socket.io')(server)
io.on('connection', function (socket) {
console.log('heyo')
socket.emit('hello world', 'hi')
})
server.listen(3000, function (err) {
if (err) throw err
console.log('listening on port 3000')
})
})();
but this doesn't seem to work either, somehow VS hangs on "deploy". If anyone can possibly guide me in the right direction, that would be highly appreciated.
PS: I know the title is off, but every time I use StackOverflow to get help with a particular attempt, I'm told to do it another way, so I'll leave it open.
If the goal is to use socket.io in your cordova app, there IS a JS client for the web that you need to use and you don't need to use npm for that, just add a link to your client js file in your index file. (should be in a "client" folder when you init socket.io via npm).
<script src="/socket.io/socket.io.js"></script>
<script>
const socket = io('http://localhost');
</script>
https://socket.io/docs/client-api/

Automate UI testing with Javascript, node - starting & stopping a web server

I'm currently investiagating automated UI testing using JavaScript on windows with node.js and phantom.js and unsurprisingly I've found many frameworks that can help in this regard (casper.js, Buster.js, etc).
The one thing that seems to be missing from the frameworks I have looked at so far is stopping and starting a web server to server the web pages so that testing framework can perform its testing. One exception is WebDriver.js which uses the Selenium standalone server but this relies on a server written Java and at the moment I'd prefer to find a node based solution if at all possible.
From the node perscpective I've looked at Connect.js and also Http-Server (which I particularly like) but the issue is starting and stopping these from a JavaScript test.
I've attempted to create a casper.js test that would interact with a server, run the test and then stop the server but I can't get it to work, here's an example script
var childProcess = require('child_process').spawn('http-server', '/TestSite');
casper.test.begin("Load-page", 1, function suite(test){
casper.start('http://localhost:8080/',function(){
test.assertTitle("test page");
});
casper.run(function(){
test.done();
childProcess.kill();
});
});
I call this from the command line using the following command (casper is in my Path variable):
casperjs Load-page testFile.js
What I was hoping would happen is the http-server would start, casper would start the test and then after the test was run the http-server would be killed.
I've also tried similar with Connect:
var server= connect.createServer(connect.static('/TestSite')).listen(8080)
casper.test.begin("Load-page", 1, function suite(test){
casper.start('http://localhost:8080/',function(){
test.assertTitle("test page");
});
casper.run(function(){
test.done();
server.stop();
});
});
But again with no luck.
I can run the Casper sample tests which work and I've also got Node in my Path as well and can call the REPL from the command prompt.
The directory structure is:
Code
/TestSite
/node_modules
and I run the tests from the Code folder.
Am I simply unable to do this or am I just not getting how it should work?
When you say "no luck" what do you mean?
The connect example looks mostly OK, and I'd prefer it over spawning a subprocess. Bear in mind that listen is potentially async so the server might not be available immediately though. The second param to listen is a callback that will be run once the server is listening - maybe try running the tests in that callback instead?
Pro Tip: Don't rely on port 8080 always being free on whatever machine you're running on - passing in 0 for the port will cause the server to start on a random port, you can then do server.address().port in the listen callback to get the port that was chosen
I managed to get it working using a combination of differebt scripts and using child_process spawn.
I created a script called startServer.js that would start the server using Connect:
var connect = require('connect');
var server= connect.createServer(connect.static('TestSite'));
server.listen(8081);
I created another script runTests.js that would call the server script via spawn and then call Casper, again via spawn, and run all the capser tests that are in a folder called tests relative to where the script is run from.
var child_process = require('child_process');
var stillRunning = true;
var server = child_process.spawn('node', ['createServer.js']);
var casper = child_process.spawn('casperjs', ['test tests']);
casper.stdout.on('data', function(data){
console.log(data.toString());
});
casper.stderr.on('data', function(data){
console.log('Error: ' + data);
});
casper.on('exit', function(code){
server.kill();
process.exit(0);
});
To use this at the command prompt navigate to the folder where the script is and then run node runTests.js and the server will be started and the tests run against the site

debug V8 with node-inspector

I'm trying to debug my JavaScript scripts, which are running in V8, with node-inspector. On the app side, I just did
v8::Debug::EnableAgent("MyApp", 5858);
Node-inspector connects fine and even is able to pause/unpause and to show the code. However, step-wise execution does not work, neither breakpoints and probably a lot of other things. When I try to do such things, I get these errors from Node-inspector:
Node Inspector v0.7.0
Visit http://127.0.0.1:8080/debug?port=5858 to start debugging.
Received request for a method not implemented: Debugger.setSkipAllPauses
Received request for a method not implemented: Debugger.setSkipAllPauses
Received request for a method not implemented: Debugger.setSkipAllPauses
Received request for a method not implemented: Debugger.setBreakpoint
Received request for a method not implemented: Debugger.setBreakpoint
Received request for a method not implemented: Debugger.setBreakpoint
So I guess I'm missing something.
I'm not sure if what I'm trying to do is even supported - because I guess, node-inspector is meant for Node.js and not for arbitrary V8, right? If so, what would be needed to make it work?
Thanks for the help by Miroslav, esp. to run DEBUG=node-inspector:protocol:* node-inspector, I got a bit further. Step-wise execution works now, and breakpoints do to in most cases (except when you select the wrong Source file - see below).
I provided a global process object like this:
// process object: http://nodejs.org/api/process.html#process_process
process.stdout = ...
process.stderr = ...
process._baseDir = ...
process.mainModule = {filename: process._baseDir + "/main.js"}
process.argv = ["myapp.exe", process.mainModule.filename]
process.cwd = function() { return process._baseDir; }
Now I get the error Internal error: TypeError: Cannot read property 'line' of null in the console. In node-inspector, I get this:
Wed, 19 Mar 2014 11:58:43 GMT node-inspector:protocol:v8-debug request: {"seq":170,"type":"request","command":"backtrace","arguments":{"inlineRefs":true,"fromFrame":0,"toFrame":50,"maxStringLength":10000}}
Wed, 19 Mar 2014 11:58:43 GMT node-inspector:protocol:devtools frontend: {"method":"Debugger.setOverlayMessage","id":48}
Wed, 19 Mar 2014 11:58:43 GMT node-inspector:protocol:devtools backend: {"id":48}
Wed, 19 Mar 2014 11:58:43 GMT node-inspector:protocol:v8-debug response: {"seq":41,"request_seq":170,"type":"response","success":false,"message":"Internal error: TypeError: Cannot read property 'line' of null"}
Another thing is that the script files are not always correct. On the C++ side, I'm loading them now like this:
ReturnType execJsFile(const std::string& jsSourceDir, const std::string& extfilename) {
v8::TryCatch try_catch;
std::string fullfilename = jsSourceDir + "/" + extfilename;
std::string sourceStr;
CHECK_RETURN(readFile(fullfilename, sourceStr));
// The origin is for the debugger, e.g. node-inspector. It expects an URL.
Local<String> origin = jsStr("file:///" + fullfilename);
Local<String> source = jsStr(sourceStr);
Local<v8::Script> script = Script::Compile(source, origin);
if(script.IsEmpty()) {
assert(try_catch.HasCaught());
return "JS compile failed: " + jsReportExceptionToString(Isolate::GetCurrent(), &try_catch);;
}
Local<Value> result = script->Run();
if(result.IsEmpty()) {
assert(try_catch.HasCaught());
return "JS script execution failed: " + jsReportExceptionToString(Isolate::GetCurrent(), &try_catch);
}
return true;
}
That puts all files under the file:// domain in the Sources list. However, main.js gets an extra entry under (no domain). When I make the change
process.mainModule = {filename: "file:///" + process._baseDir + "/main.js"}
it goes away, however, that is not how I would have expected ìt to be according to the doc.
When I pause/break the execution in main.js, it shows up in yet another Source [VM] main.js and gets a yellow-ish background.
Also, all files in Sources under file:// get the (function (exports, require, module, __filename, __dirname) { prefix added in the first line of the source. That line does not come from my code but from node-inspector. Why does it add that here? It is esp. strange because my code adds a slightly different prefix ( function(module, exports) {.
Run DEBUG=node-inspector:protocol:* node-inspector and inspect the messages, you might be able to find more information there. You can also try to use an older version, e.g. 0.1.9, it may have less dependencies on Node-specific stuff.
I'd say 95% of Node Inspector code uses V8 protocol only. Look for usages of DebuggerClient.prototype.evaluateGlobal to find where Node-specific functionality is used.
The first thing to change is getResourceTree in lib/PageAgent.js. Either implement your own way of listing all source files (including those not loaded yet), or return an empty tree.
UPDATE
Try Node's CLI debugger first:
$ node debug localhost:5858
To my best knowledge, the CLI debugger uses only the V8 debugger protocol features, nothing Node specific. When you are able to debug your V8 app using the CLI, you will know that any other problems are in Node Inspector and not in your V8 app.
Here is a solution for debugging V8 with node-inspector:
First of all, the latest version (0.12.3) has many extensions for debugging node.js scripts so I used an older version (0.5.0) which has less liability to node.js.
I used the following command to install v0.5.0 in Node.js command prompt:
npm install node-inspector#0.5.0
It is installed in folder "%USERPROFILE%\node_modules" by default.
I added one line of code to %USERPROFILE%\node_modules\node-inspector\lib\PageAgent.js:
getResourceTree: function(params, done) {
return; //return empty tree
...
This completes the installation.
Here is the guide to debug a javascript file executed by using the ClearScript .NET library:
Open a command prompt and execute the following command:
%USERPROFILE%\node_modules\.bin\node-inspector.cmd
You should see the following lines if node-inspector is running successfully.
Node Inspector v0.5.0
info - socket.io started
Visit http://127.0.0.1:8080/debug?port=5858 to start debugging.
Initialize your V8 engine as in the following code line (VB.NET code):
Dim engine As New V8ScriptEngine("global", V8ScriptEngineFlags.EnableDebugging, 9222)
Put a breakpoint right after this line in your code and run your application to reach this breakpoint.
Make sure you have "debugger;" statement in the first line of your JavaScript code.
Open a Chrome browser and navigate to the following address:
http://127.0.0.1:8080/debug?port=9222
Press "Continue Debugging" button in Vİsual Studio toolbar.
Now you should see your script code stopped at the first "debugger;" line in Chrome browser.
You can continue debugging from here.

Node http proxy with proxytable and websockets

I'm trying to get websockets to also work with node-http-proxy. The difference is i'm using a proxytable:
var options = {
router: {
'a.websterten.com': '127.0.0.1:150',
'b.websterten.com' : '127.0.0.1:151',
}
};
var server = httpProxy.createServer(options);
I tried:
server.on('upgrade', function (req, socket, head) {
server.proxy.proxyWebSocketRequest(req, socket, head);
});
But it doesn't seem to work. A quick check to see whether websockets work shows I get Unexpected response code: 400 from Chrome (works fine if I go directly)
Also doing a couple of checks server.on('upgrade',.. doesn't fire on a websocket request
How can I get my proxy server to route websockets correctly?
I've also tried this on node 0.8.23 as well as node 0.10.x (the later versions of node have a memory leak issue, but it wont work on 0.8.23 either)
When you use httpProxy.createServer(), it's not necessary to handle the upgrade event because http-proxy handles it automatically. Thus, your server.on('upgrade', ...) never fires because http-proxy is already handling it internally.
The only time you need to do server.on('upgrade') is when you pass middleware functions to httpProxy.createServer or if you've manually created the server with http.createServer().
In other words, websockets should "just work" through the proxy in your configuration.
However, WebSocket support in http-proxy is currently broken on node v0.10.x because of streams2 (the stream APIs in node core were completely rewritten in 0.10). Also, the most recent release of http-proxy (0.10.2) is broken in node v0.8 because of a botched fix for the streams2 issue.
So you have two options:
Wait for http-proxy to rewrite its internals to cope with streams2.
Downgrade to node v0.8.23 and http-proxy 0.10.1. (At least until #1 happens.)
(You can install old versions of npm modules by running npm install http-proxy#0.10.1.)

Categories