This post will describe how to set breakpoint in before any javascript method call from console.
- GitHub repository: https://github.com/andrijac/break-js
- break.js: https://github.com/andrijac/break-js/blob/master/break.js
- break.min.js: https://github.com/andrijac/break-js/blob/master/break.min.js
In post:
TL;DR
Background #
To make a long story short, I was working on a big single page web application a year ago, with huge javascript code base. Whenever I wanted to set a breakpoint in editor/dev tools/firebug, it took time to find the function. Either because it took time for source viewer to load (because of huge javascript files), or to locate in which file is function of interest.
So I have started inserting debugger;
directive to my scripts when I need to break.
The problem was, then I wanted to remove the directive, I had find the directive, remove it or comment it out, and to reload the page, but as we were working on SPA, I basically had to restart my debugging sessions.
I also tried to make a global flag, and based on flag to set enable the debugger:
1 2 3 4 5 6 7 |
|
Whenever I wanted to turn debugger on, I could just set in console:
1
|
|
Problem was I did not really like to have this function call all over the code.
Also, I wanted to have control where will code break, so I was then forced to go back and remove breakpoint()
calls.
Implementation #
The goal is to make a function that can insert a breakpoint before the call of any function we are interested in, which is accessible from global object.
Function needs to do following:
- Save reference to original function
- Override original function with wrapper.
- Option to restore original function and remove breakpoint.
Let’s say we have following object structure:
1 2 3 4 5 6 7 |
|
Path to func
function is through foo.bar.func
.
This is usually a case in huge javascript libraries such as Ext.js (Sencha), YUI etc.
To be able to set breakpoint, I would need to set debugger;
right before foo.bar.func
call.
So, I thought it would be nice to wrap foo.bar.func
function in new function:
1 2 3 4 |
|
But wrapper also needs to be called foo.bar.func
, because if function is called it has to actually call wrapper.
But if wrapper is set to foo.bar.func
, it means it will override the original function, so we need save a reference to original function somewhere.
How to save a reference to a function?
I could pass into wrapper a direct reference to function and assign it to variable, but instead I am passing in a function name. The reason for this is because I need to access a function dynamically and also I will need a key to reference back to original function.
You will see what I mean as I go further in post. I might change this in the future and be able to pass direct reference to function in wrapper.
Ok, as I have only function name, only way I found (at the moment) to call a function was by compiling a new Function object that calls a function.
You could easily call a global function by name through window
object (in browser):
1
|
|
This works if function is on global object, but if function in inside another object, this will not work.
So, to invoke foo.bar.func
:
1 2 3 4 |
|
Now we have original function reference assigned to variable and we can override function with wrapper. Wrapper should look like this:
1 2 3 4 5 6 7 8 9 10 11 12 |
|
Override function:
1
|
|
“Break” function #
Finally, “break” function:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
|
Usage #
To set the breakpoint:
1
|
|
To remove the breakpoint:
1
|
|
Potentially, we could add this function to console
object:
1 2 3 |
|
Repository is at: https://github.com/andrijac/break-js
HTH