54

I have changed my coding style with more complex projects to loading pages (And their embedded scripts) "on demand" recently. However, it is difficult to debug those scripts as when they are loaded like:

jQuery.get('/myModularPage', function(html){ /* insert the loaded page into the DOM */ });

or

$('#some-container').load('/myOtherPage');

These scripts run perfectly, but if I'm debugging, how can I set breakpoints in these dynamically loaded pages and scripts?

BLSully
  • 5,929
  • 1
  • 27
  • 43

4 Answers4

82

Add this to your js files where you want it to break:

debugger;

Then step into/over/out like any other debugger.

Works for dynamically loaded scripts and pages. Only works in Chrome as far as I know.

Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
Squeee123
  • 906
  • 5
  • 6
42

UPDATE

The accepted form is now with a # (hashtag) rather than @ (at symbol)

The syntax was changed to to avoid conflicts with IE conditional compilation statements and some other issues (thanks to Oleksandr Pshenychnyy and Varunkumar Nagarajan for pointing this out)

//#sourceURL=/path/to/file 

This can really be any string that helps you identify the block of code.

An additional good point from JMac:

For me, the js file was being displayed in the sources list within a group called "(no domain)". Might be worth mentioning as I missed it at first!

ORIGINAL

I struggled with the above for about a week before running across this article. It really does work perfectly for my development environment (Chrome 22 as I write this).

Firebug also supports developer-named eval() buffers: just add a line to the end of your eval(expression) like:

//@ sourceURL=foo.js

For example, given this simple html document:

<!DOCTYPE html>
<html>
<body>
    <p>My page's content</p>
    <div id="counter"></div>
    <script type="text/javascript">
        //if this page is loaded into the DOM via ajax 
        //the following code can't be debugged 
        //(or even browsed in dev-tools)

        for(i=0;i<10;i+=1) {
            document.getElementById('counter').innerText = i;
        }

        //but if I add the line below
        //it will "magically" show up in Dev Tools (or Firebug)

        //@ sourceURL=/path/to/my/ajaxed/page
    </script>
<body>
</html>

Things I haven't yet discovered:

  • Does this have to be done for every script block for inline scripts?
  • Does it have to be the last line of the script block? (The article would suggest the answer to this is yes)
BLSully
  • 5,929
  • 1
  • 27
  • 43
  • Very useful! you saved me so many hours!! in my case I'm loading all the scripts in my app getting the data through ajax and injecting the responseText with appendChild to the script tag, appening the //sourceURL= before injecting keeps the code debuggeable. I think jquery should be doing something similar so I believe that this can be automated in jquery also. – MazarD Oct 22 '13 at 16:43
  • 1
    I'd been looking for something like this. It would be nice if Chrome would do this automatically for you, even if it didn't have a user-friendly name associated with it. – jinglesthula Jan 14 '14 at 23:38
  • 1
    what is the pass relative to? – vlio20 Mar 03 '14 at 11:07
  • 1
    This post is a bit outdated. Article posted by @Varunkumar Nagarajan says that //@ syntax was later changed to //# to avoid conflicts with IE conditional compilation statements and some other issues. Please consider updating your answer to not confuse future viewers, since your post is a great answer really. – Sasha May 06 '15 at 13:12
  • @OleksandrPshenychnyy: Updated. Thanks for pinging me to edit – BLSully May 06 '15 at 15:23
  • A simple solution for setting breakpoint in Chrome on a global method name without requiring any code modification was posted here - it may be a new Chrome feature: http://stackoverflow.com/a/34714825/908677 – Elijah Lofgren Jan 18 '17 at 14:41
  • 1
    works if I insert a space after the hash `//# sourceURL=` inside a ` – devio Jun 08 '17 at 08:26
  • @BLSully As devio remarked in the comment above, your update doesn't work. I'm using Firefox and the space is needed for it to work, so `//# sourceURL=` instead of `//#sourceURL=`. Can you edit your answer? – KIKO Software Feb 11 '22 at 12:48
10

This problem looks like it has now been in general solved using the new pragma:

//# sourceURL=filename

Note the 'hash' # rather than the 'at' @ symbol.

By including that line in your source, a reference to it will show up in the debugger!

BLSully
  • 5,929
  • 1
  • 27
  • 43
sdw
  • 623
  • 9
  • 10
4

As you have already mentioned, you can use //@ sourceURL. Chrome doesn't seem to be supporting //@ sourceURL for inline scripts. It does work on eval expressions. This HTML5 article on source maps gives more details about naming eval blocks and naming of any anonymous functions in your code.

Instead of using eval, you can try embedding a script tag or JSONP may be.

jamesmortensen
  • 33,636
  • 11
  • 99
  • 120
Varunkumar Nagarajan
  • 1,807
  • 1
  • 24
  • 43