Bug 21262

Summary: JavaScript Debugger doesn't play nice with functions created with eval/(new Function())
Product: WebKit Reporter: boucher <rboucher>
Component: Web Inspector (Deprecated)Assignee: Nobody <webkit-unassigned>
Status: RESOLVED FIXED    
Severity: Normal CC: aroben, burg, emacemac7, ggaren, kmccullough, pmuellr, tom
Priority: P2    
Version: 528+ (Nightly build)   
Hardware: All   
OS: All   
URL: http://280slides.com

Description boucher 2008-09-30 18:19:46 PDT
In Objective-J, we load all your code using XMLHTTPRequests.  This has the advantage of letting us do import statements asynchronously, and not having to worry about <script> tag placements.

In a desire to work well with the inspector, we specify a function name for each function that we create, in the style of:

$ClassName__methodName_withUnderscores_forColons_

These are correctly displayed in stack traces in the web inspector debugger.  Unfortunately, finding code, either to set a breakpoint on it, or to examine the various methods in a stack trace, is difficult.

When we get the result of the import XHR, we evaluate it with new Function(theCode) (see line 156 of evaluate.js if you're interested). In the inspector, this results in a "(program)" entry in the source list.  Needless to say, a hundred or so of these isn't very useful. Thankfully, the code search mechanism will search and find inside these files, so we can set breakpoints where we need to.  

When we encounter a stack trace, though, clicking on one of these methods in the stack does not bring up the corresponding code.  The line numbers are correct, but it just doesn't jump.  This means manually searching to find the function, and then scanning for the right line, an annoying process. Clicking on more traditionally imported code, like objj_msgSend, does the right thing and jumps to that definition.

So, in summary, I'm talking about two issues,

1) eval'd code has no associated name in the file list

2) functions defined in eval'd code don't jump to their definitions when clicked in the stack trace

The second one seems like something that should be relatively easy to fix, the first is more interesting.  What I'd like is a mechanism for specifying the name associated with this block of code. For example, some special api in eval and new Function that would allow us to attach a name manually, since we know the name of the file the code was imported from.

I'm open to other suggestions, but there doesn't seem to be any reasonable way to try to automatically determine the information, and I know we're not the only ones who would appreciate some functionality like this.
Comment 1 boucher 2008-09-30 18:23:23 PDT
Just noticed, it also doesn't highlight the active line in source that's in "(program)" blocks when you're stepping through the debugger.
Comment 2 Timothy Hatcher 2008-09-30 18:51:37 PDT
No jumping and highlighting is just a bug. Names for eval would be nice. We do want to show something better than (program).
Comment 3 boucher 2008-10-01 22:37:54 PDT
I think perhaps using the first N characters of the first non empty line is a good (first attempt) proxy for a file name.

This means that anyone formatting their code to include newlines can properly label the first line with a comment containing whatever they'd like displayed to the debugger.  Non empty should be defined to exclude empty comment lines (in other words the first line to contain something more than just whitespace, //, /*, or *).

Definitely no substitute for real naming, but perhaps something that would be easy enough to add in for the time being.
Comment 4 Patrick Mueller 2009-06-03 22:15:51 PDT
Patch for supporting for naming evals via the Firefox convention of annotation comment is available in Bug 25475 .  I modified fragment_evaluate_code() in Objective-J.js to append the relevant comment, and got all of the Function()'s named in the script drop-down, and I believe in the call stacks as well.

The change was to augment the aFragment.info property like this, before using with the Function() constructor:

        aFragment.info += "\n//@sourceURL=" + aFragment.file.path + "\n";