Insert break point into a javascript file - javascript

I would like to insert break point at a position listed in the below quote. Let's say the below quote belongs to a js file called "test.js". What I would like to do is when I run "node test.js" on the command line, it will break at the break point and then I can inspect all the variables available at the break point.
var a = 4;
function changeA(input) {
var input = 6
[INSERT BREAK POINT HERE]
console.log(input)
};
changeA(a);
console.log(a);
Or is there another way to insert break point to a javascript file?

What you're looking for is the statement debugger;. You can insert that wherever you want, and if you run node debug test.js node will break wherever you placed the debugger; line.
Some of the basic commands once in debugging mode are:
c: continue
n: step next
s: step in
You also have the ability to set breakpoints manually once in debug mode, through the following command: setBreakpoint(line).
Hope this helps!
Resource: NodeJS Debugger API

You can hardcode a breakpoint like this:
debugger;
E.g.:
function changeA(input) {
var input = 6
debugger;
console.log(input)
}
...but you have to be using a debugger for it to mean anything, such as node-inspector. And if you're using a debugger, you can set breakpoints through the debugger itself (rather than hardcoding them).
Here's an example of debugging a very simple NodeJS script via node-inspector:
Script:
var a = +process.argv[2];
var b = +process.argv[3];
var c = a + b;
console.log("c = " + c);
Command to start node-inspector and pass my script a couple of args:
node-debug temp.js 10 20
A browser pops up with a debugging UI and the program paused. I've set a breakpoint through the UI on the var b = ... line, and then stepped passed it once, so I'm sitting on the var c = a + b; line (which hasn't run yet):

If built-in debugger is not something you want to use, you can try Node Inspector which allows you to debug your app using a nice GUI debug interface inside of a browser.

Related

Calling javascript functions in windbg breakpoint-commands

I have a windbg-issue concerning the execution
of a javascript-function as a breakpoint-command.
This observation was made in windbg Preview 10.0.17030.1002
and also in recent versions of windbg
when debugging a native x86 C++ program on Windows 10.
Test Setup
In my javascript-file dbg_test.js I have the following function:
function test()
{
var ctl = host.namespace.Debugger.Utility.Control;
host.diagnostics.debugLog(">>> Test\n");
ctl.ExecuteCommand("g");
}
In windbg, I load the javascript-provider, load my dbg_test.js script
and define a breakpoint-command to call this javascript-function:
bs 0 "dx #$scriptContents.test()"
Expected Behavior
The string ">>> Test" is shown in the output-pane of the command-window
everytime when breakpoint 0 is hit.
The debugger resumes execution.
Observed Behavior
The output ">>> Test" is shown only the first time
when breakpoint 0 is hit.
Subsequently hitting breakpoint 0 does not
produce any output.
Remarks
1) Doing the analogous test with "old style" windbg-commands works fine:
bs 0 ".printf \">>> Test\\n\\n\";g;"
but only after ending and restarting windbg
2) The same behavior is shown when I move the code of function "test" to the function "invokeScript()" and define the breakpoint-command via
bs 0 ".scriptrun d:\\dbg_scripts\\dbg_test.js"
3) Running the script from the windbg-command-line works.
4) Calling javascript-functions as in the test-scenario above worked in previous versions of windbg.
5) It seems that the statement
ctl.ExecuteCommand("g");
is the crucial one: If I comment out this statement, then the breakpoint
is hit every time and the output from
host.diagnostics.debugLog(">>> Test\n");
is shown on each hit of the breakpoint.
Of course, I have to resume the execution manually by pressing F5 or entering the command "g"
Questions
Can someone reproduce this issue ?
Is it legal to use javascript-functions in this way or am I doing something wrong here ?
Your feedback is greatly appreciated!
Kind/Best regards!
I ran into the same problem as you did. I was able to somewhat bypass the problem by declaring a script global variable
var lines = [];
and pushing log messages to this array rather than debug printing them:
lines.push(">>> Test");
In order to see the lines, I created a function
function print_lines() {
for (var line of lines) {
host.diagnostics.debugLog(line + "\n");
}
lines = [];
}
which I called from the prompt like so
dx #$scriptContents.print_lines();
I know that this is not really answering your question, but it might still be helpful for someone else that faces the same problem.

How can I print functions in Node.js the same way Firefox prints functions (namely giving a name)?

var fun1=function(){console.log('hello');}
var fun2=fun1
console.log(fun2);
The above code run in Firefox prints fun2. In Chrome it prints the function body, in Node.js it prints Function.
Why is this difference?
How can I get Firefox's behaviour in Node.js ?
Why I am asking this ?
I am asking this because I would like to debug JS code generated from Idris where the JS runtime uses explicit call stack, and I would like to print the callstack content in a meaningful way and Firefox does that the best but I want to debug code on Node.js hence I would like to get Node.js to print functions as Firefox, how can I do that ?
EDIT:
A typical compiled function looks like this:
var _idris__123_io_95_bind2_125_ = function(oldbase){
var myoldbase = new i$POINTER();
i$valstack_top += 1;
i$ret = new i$CON(65646,[i$valstack[i$valstack_base],i$valstack[i$valstack_base + 1],i$valstack[i$valstack_base + 2],i$valstack[i$valstack_base + 3],i$valstack[i$valstack_base + 4],i$valstack[i$valstack_base + 5]],_idris__123_APPLY0_125_$65646,null);
i$valstack_top = i$valstack_base;
i$valstack_base = oldbase.addr;
}
So here the useful information is the variable name _idris__123_io_95_bind2_125_ itself, and that is what is printed by Firefox, but not by node.js, and that is the problem, Firfox prints useful information, node.js does not.
So the question is, how can I make node.js to print _idris__123_io_95_bind2_125_ for the above function ?
EDIT 2:
Trying some of the suggestions don't work unfortunately :
>cat deb.js
var fun1=function(){console.log('hello');}
var fun2=fun1
console.log(fun2);
console.log(fun2.name);
console.log(fun2.toString());
console.log(fun2+'');
>node deb.js
[Function]
function (){console.log('hello');}
function (){console.log('hello');}
>
you need to convert it to string try this :
console.log(fun2.toString());
UPDATE: Works with v0.12.7 as well. So I guess it would work with all node versions.
In node Following works
function someCoolFuntion (){
/* Some code */
}
var fun1 = someCoolFuntion;
//Show name; Similar to Firefox's behaviour!
console.log(fun1.name)
//Show fullbody; Chrome's behaviour (as shaouari suggested)
console.log(fun1.toString());
Output
Hope this helps!

Show Javascript function filename programmatically

I need to know if there is a way to extract the script name when calling a variable or a function in javascript. The scenario is running chrome through webdriver or node and when calling for example window.jQuery.Animation I would like to get the filename (i.e., jquery.js) where this function is defined. I know in chrome you can click on 'show function code' and jump to the file, however I am looking to do the same in a programmatic way.
Thanks
Maybe an Error object can help here:
var e = new Error;
console.log(e.stack);
The first two lines of the stack:
Error
at Object.<anonymous> (/home/joost/src/test/testfile.js:3:9)
You have no such way of doing that in pure JavaScript.
The different javascript engines (spiderMonkey, V8, ...) will often compile the javascript code in some way, so you will lose such information in the process.
To know where a function comes from, you will require this function's source map. If you don't know them, source maps will map a script to it's originating filename / line number.
The mozilla sourceMap library will help you with that.
Though, you will have to generate a source map for your file that uses jQuery as well.
if your script.js is like
var a = jQuery.method // this is line 10
^ col 9
You will have to execute
var sourceMap = require('source-map');
consumer = new SourceMapConsumer('script.map');
consumer.originalPositionFor({ line: 10, column: 9 })
// { source: 'jQuery.js',
// line: 12971,
// column: 222,
// name: 'whatever' }
You'll be then able to query the original position and filename where that object is declared.

Adjust Node REPL to not clobber prompt on async callback?

When working with the Node REPL console, I'm looking for a way for asynchronous calls to both not lock up the console input, and not clobber the console prompt when they return.
I've seen a few solutions dealing with asynchronous calls in the REPL, where writing your own custom eval function you can check the result of the executed code to see if it's a promise/async object, and just not return until it resolves.
However, I'd like to solve the issue of a repeating background process logging its progress. Ideally I'd like it to behave like the Chrome Javascript console, where if you have a command partially printed on the console prompt, and an async result gets logged, the line you're typing on gets moved one line down, and the log inserted above it.
So, functionally, I'd like to insert the logic that when console.log() is called, the line containing the cursor is first cleared, then the contents of the log() written, and then the REPL prompt (and whatever the user had typed so far onto it) gets re-written on the line following the new output.
Is there any way to hook into the REPL object to accomplish this? Is this some advanced manipulation of the output stream from the REPL (i.e. only possible on terminals that support an "erase to beginning of line" escape code)?
Tapping straight into the Output Stream I managed to get something working like how I wanted:
var server = repl.start({
prompt: '> '
});
server.context.console.log = function(msg) {
var rli = server.rli;
server.outputStream.write('\033[2K\033[1G'); // Erase to beginning of line, and reposition cursor at beginning of line
server.outputStream.write(msg+"\n");
server.outputStream.write(''+rli._prompt+rli.line); // Redraw existing line
server.outputStream.write('\033['+(rli.cursor+rli._promptLength+1)+'G'); // Move the cursor to where it was
}
server.context.doTimeout = function() {
setTimeout(function() {
server.context.console.log('Timeout done!');
}, 2000);
};
Though that all assumes an ANSI-compliant output stream is the output, and feels quite hack-ish, overriding the console.log() function like that. Is there a more compliant way to handle this, or is this the best way?
Still, now I cannot find a modern satisfactory answer on StackOverflow.
After spending a few hours on the internet, I came up with this solution for latest Node (v15.*)
const log = (msg) => {
rl.output.write('\r')
rl.output.write(msg + '\n')
rl.displayPrompt(true)
}
Basically, clear the line, write the log, then display the prompt again. Works perfectly for my case.
Improved solution.
The above works well if the buffered line is not longer than the log. So here is another version that pad the rest of log by space characters
const log = (msg) => {
rl.output.write('\r');
rl.output.write(_.padEnd(msg, process.stdout.columns - 2, ' ') + '\n');
rl.displayPrompt(true);
};
_.padEnd: lodash's padEnd, can be replaced by any lib
Based on #MidnightLightning's older answer.
As of sometime before node v12.15.0 the console.log override would look like:
activeRepl.context.console.log = (msg) => {
const promptOffset = Server._prompt.length + Server.line.length;
Server.outputStream.write('\033[2K\033[1G'); // Erase to beginning of line, and reposition cursor at beginning of line
Server.outputStream.write(msg + "\n");
Server.outputStream.write('' + Server._prompt + Server.line); // Redraw existing line
Server.outputStream.write('\033[' + (promptOffset + 1) + 'G'); // Move the cursor to where it was
};

getting cocos2d-html5 to work with visual studio

<rant> I swear dealing with IDE problems are the worse. Its like all I want to do is get my hands dirty with some code but can't. </rant>
As the title suggest I am trying to get Cocos2d-HTML5 working in Visual Studio 2012. I have coppied the Cocos2d-HTML5 files to my web directory and followed a few of the tutorials but am having a problem with jsloader.js.
Prior to the change below it was not finding the jsloader.js :
FROM: `engineDir: '../cocos2d/',`
TO: `engineDir: '../GridWars/cocos2d/'`
Gridwars is the name of the project
Now it finds jsloader.js but has an error.
Unhandled exception at line 117, column 5 in http://localhost:51244/GridWars/cocos2d/platform/jsloader.js
0x800a138f - JavaScript runtime error: Unable to get property 'loadExtension' of undefined or null reference
for these lines of code:
var d = document;
var c = d.ccConfig;
if (c.loadExtension != null && c.loadExtension == true) {
Which version of Cocos2d-html5 did you used?
It is required to configure your settings in the cocos2d.js file. You may find this file in the template folder.
For example:
var c = {
COCOS2D_DEBUG:2, //0 to turn debug off, 1 for basic debug, and 2 for full debug
box2d:false,
chipmunk:false,
showFPS:true,
loadExtension:false, //**Hey, here is the loadExtension.....**
frameRate:60,
tag:'gameCanvas', //the dom element to run cocos2d on
engineDir:'../cocos2d/',
//SingleEngineFile:'',
appFiles:[
'src/resource.js',
'src/myApp.js'//add your own files in order here
]
};
v2.2 has a similar error. I found that moving a line around in your cocos2d.js file helps.
window.addEventListener('DOMContentLoaded', function () {
...
d.body.appendChild(s);
document.ccConfig = c;
s.id = 'cocos2d-html5';
//else if single file specified, load singlefile
});
Remove the line: document.ccConfig = c; and move it before the window.addEventListener
eg:
document.ccConfig = c;
window.addEventListener('DOMContentLoaded', function () {
// etc
});
The answer was posted on their release notes. I was following one of their tutorials and ended up finding my answer at the bottom of the post.
ANSWER:
in cocos2d.js
look for "s.c = c",
change it to "document.ccConfig = c"
in main.js
look for "config:document.querySelector('#cocos2d-html5')['c'],"
change it to "config:document.ccConfig,"

Categories

Resources