debug V8 with node-inspector - javascript

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.

Related

TypeError: 'NoneType' object is not subscriptable while invoking execute_script() for Chrome Download Manager through Selenium

I have been using this function https://stackoverflow.com/a/48267887/11220889 for waiting for downloads to finish and returning the file path once finished. And it has been working great until now.
The Function
def every_downloads_chrome(driver):
if not driver.current_url.startswith("chrome://downloads"):
driver.get("chrome://downloads/")
return driver.execute_script('''
var items = downloads.Manager.get().items_;
if (items.every(e => e.state === "COMPLETE"))
return items.map(e => e.file_url);
''')
How its called
paths = WebDriverWait(driver, 120, 1).until(every_downloads_chrome)
Error I'm receiving
TypeError: 'NoneType' object is not subscriptable
So from what I can gather something has changed that has started causing the function to not return a path. I believe this is due to a change within chrome or even more specifically the chrome driver. My two reasons for this assumption is:
1) I had this function in another code that my colleague was using and she called me saying it was producing this error yesterday.
2)Neither code has changed so the change must be in chrome
I would like to keep using this script but if not possible have another function that waits for the downloads to finish and returns the paths and ideally does it all through the driver not through file path since multiple users use my codes on multiple machines.
EDIT: Versions-
Name: selenium
Version: 3.141.0
Name: Chrome Browser
Version: 73.0.3683.86
Name: Chrome Driver
Version: 2.43.600210
Name: System
Version: Windows 10 Pro x64
As per the error message:
TypeError: 'NoneType' object is not subscriptable
Your main issue seems to be incompatibility between the version of the binaries you are using as follows:
You are using chromedriver=2.43
Release Notes of chromedriver=2.43 clearly mentions the following :
Supports Chrome v69-71
You are using chrome=73.0
Release Notes of ChromeDriver v2.46 clearly mentions the following :
Supports Chrome v71-73
So there is a clear mismatch between ChromeDriver v2.43 and the Chrome Browser v73.0
Solution
Upgrade ChromeDriver to current ChromeDriver v2.46 level.
Keep Chrome version at Chrome v73 level. (as per ChromeDriver v2.46 release notes)
Clean your Project Workspace through your IDE and Rebuild your project with required dependencies only.
If your base Web Client version is too old, then uninstall it and install a recent GA and released version of Web Client.
Execute your #Test.
Always invoke driver.quit() within tearDown(){} method to close & destroy the WebDriver and Web Client instances gracefully.
Update
Currently GAed Chrome v73 have some issues and you may like to downgrade to Chrome v72. You can find a couple of relevant discussions in:
Getting Timed out receiving message from renderer: 600.000 When we execute selenium scripts using Jenkins windows service mode
Timed out receiving message from renderer: 10.000 while capturing screenshot using chromedriver and chrome through Jenkins on Windows

JSON undefined on nodejs

I just upgraded node.js to v6.10.3 and tried to run some test code.
var str = '{"foo": "bar"}';
var obj = JSON.parse(str);
console.log(obj.foo);
I saved this to a file test.js and tried running it from the node command prompt.
Windows Script Host says
'JSON' is undefined
I can open a Chrome window, open the debugger, open the console and enter the same code and it runs correctly.
I have searched google and SO for an explanation, and I find a lot of matches on JSON and undefined, but nothing pertaining to this problem in node.
You need to make sure you specify the node executable instead of just the javascript file or double clicking on the javascript file. For example: node test.js. Otherwise Windows will try to use WSH (specifically its JScript engine) to execute the code which contains an older, inferior javascript runtime.

NodeJS breakpoints sometimes not working

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

browserify Error : http.createServer is not a function

I tried to browserify this node js script :
var phantom = require('phantom')
phantom.create(function(ph) {
ph.createPage(function(page) {
page.open("editor.html", function(status) {
console.log("opened diagram? ", status);
page.evaluate(function() {
return document.getElementById("GraphImage").src;
}, function(result) {
//console.log(result);
ph.exit();
});
});
});
});
So I used this command:
browserify myscript.js > bundle.js
and when I run bundle.js from an html file I get this error:
http.createServer is not a function
it seems that browserify does not support httpserver. How can I resolve this problem?
You can't run a web server from inside a web browser. There really isn't anything in the browser that could act like Node's http module. Also it doesn't make sense to run PhantomJS in a browser, because PhantomJS is a web browser.
What is the desired behavior you are trying to accomplish?
Update:
It seems like you are trying to run code intended for Node.js inside a browser instead.
The JavaScript engine inside the browser is much more restrictive than in Node.js, for example you can't access the file system from inside the browser for security reasons (or else you could read the hard drive of anyone who visited your web page).
Browserify does include some "shims" that will put small JS libraries into your code that work in the browser and match the API of Node.js, allowing some Node.js specific JS code to execute in the browser.
In your case, you are requiring Phantom, which seems to in turn require http. Accoring to the Browserify documentation, it will see require('http') and include a shim for the http module (because browser's don't provide an http module of their own).
The Phantom module then tries to call http.createServer() but accoring to the documentation for that http shim:
This module implements http.request, http.get, and most of http.ClientRequest and http.IncomingMessage in addition to http.METHODS and http.STATUS_CODES.
so http.createServer() is not supported by the shim. This also makes sense because a browser would never let you open an http server inside of itself, or else navigation to someone's web site could cause your browser to start serving content to the outside world, which obviously doesn't make sense.
In your comment:
"i want that my node js script can be executed from another JS code"
You don't specify what "other JS code" is running in. If that JS code is already running in Node, then you don't need Browserify at all. If you are trying to have a web browser start up an actual Node.js process, that isn't going to happen, again for obvious security reasons, because browsing to a web page shouldn't have the ability to run any executable on your system.
What Browserify lets you do is take code originally intended for Node.js, and run it in a browser instead, but a t runtime it is executing in the browser, not in Node.js, so you can only use JS code that works within the constraints of the browser's JS runtime.
If you are trying to execute your code in Node.js, then you need to do that by having something start the Node.js executable, either from the command line or by having another program start the process for you, but that can't be done from within a web browser. If you are trying to have users navigate to your web site and then have this code run on their machines in a browser and not in Node.js, then you need to only use modules that work in the browser.

Why does fs.mkdir(); yield an ENOENT error with really long directory names?

I'm using Windows 7 and Node.js.
Example:
fs.mkdir(__dirname + '/users/' + 'asdlfjlasdfjlsdajflasdkjflksadjflasdkjflasdkjflsadkjflaskdjflasdkjfaslkdjfaslkdjfasldkjfsaldkjfaslkdjflasdkjflaskdfjalskdjflsdakjflasd%3Bkjflaksdjfklasdfja%3Bsdlkfjasldkfjlsadkfjklsadjfasldkfjlsadkjflasdkjflasdkjfasdlfjlasdfjlsdajflasdkjflksadjflasdkjflasdkjflsadkjflaskdjflasdkjfaslkdjfaslkdjfasldkjfsaldkjfaslkdjflasdkjflaskdfjalskdjflsdakjflasd%3Bkjflaksdjfklasdfja%3Bsdlkfjasldkfjlsadkfjklsadjfasldkfjlsadkjflasdkjflasdkjfasdlfjlasdfjlsdajflasdkjflksadjflasdkjflasdkjflsadkjflaskdjflasdkjfaslkdjfaslkdjfasldkjfsaldkjfaslkdjflasdkjflaskdfjalskdjflsdakjflasd%3Bkjflaksdjfklasdfja%3Bsdlkfjasldkfjlsadkfjklsadjfasldkfjlsadkjflasdkjflasdkjfasdlfjlasdfjlsdajflasdkjflksadjflasdkjflasdkjflsadkjflaskdjflasdkjfaslkdjfaslkdjfasldkjfsaldkjfaslkdjflasdkjflaskdfjalskdjflsdakjflasd%3Bkjflaksdjfklasdfja%3Bsdlkfjasldkfjlsadkfjklsadjfasldkfjlsadkjflasdkjflasdkjf', function(err) {
if (err && err.code == 'EEXIST') {
// do nothing
} else if (err) throw(err)
});
I have an inkling it has to do with Windows limiting size of directory paths. I've read a few varying accounts of what the actual limit is, but it seems like it's relatively small.
But seriously, why is ENOENT the error code? Is there a way to make sure that in this case the error is because the directory name/path is too long. Is ENOENT only returned by mkdir(); in the case that the directory is too long? I just feel like there should be a better code than ENOENT, because in my (very limited) experience it means that the directory does not exist, not that it can't exist.
P.S. I've somehow managed to make a pretty long directory name, (not quite as long as the one above) on my computer using mkdir(). When I try to delete the file by right clicking, Windows Explorer invariably crashes, and when I use the 'delete' key or drag the file to the Recycle Bin nothing happens. Also, 'del' in the command line says that the name is too long. Any solutions to getting this folder off of my computer?
(The 'users' directory does exist.)
mkdir is a POSIX function, and indeed it's specification says that if the supplied name is too long, it should return ENAMETOOLONG.
Windows is not a POSIX system, though. It does provide a number of wrappers for common POSIX functions - for example there is a mkdir function which MS says is deprecated in favour of the ISO C++ compliant _mkdir function. My guess is that the former actually just calls the latter.
The documentation for the MS implementation of _mkdir only specifies two possible error codes: EEXIST and ENOENT.
My guess is that the implementation of mkdir in windows calls the underlying Win32 CreateDirectory function, then mapped all of the possible error codes from that function into one of the two they have chosen to return from _mkdir.
Node.js is not really playing a role in this. It's fs package is itself a wrapper around the POSIX functions. It is returning the error code that it gets from the Win32 mkdir wrapper.

Categories