See source of dynamically added inline scripts in debugger?

187 views
Skip to first unread message

James Burke

unread,
Dec 31, 2006, 2:43:31 AM12/31/06
to Firebug
Instead of using eval() to define some new javascript functions, I'm
trying to use dynamically added script tags and setting the text inside
the script tag. When I do this, I can get Firebug 1.0b8 to stop on an
error, but in the Script tab is blank. However the Watch tab shows some
variables.

Test page here (click the "Execute bad script" button):
http://www.tagneto.org/dojo/ScriptDef.html

I do the weird scriptTag.src= "javascript:..." thing because that at
least got Firebug to break on the error. If I tried doing
scriptTag.text = "function foo(){...", Firebug would not break on the
error but it was reported in the console.

Is it possible to support seeing the source in the Script tab? If it is
possible, any way to get the source to show up and have Firebug stop by
using scriptTag.text instead of using scriptTag.src?

Thank you,
James

Mark Kahn

unread,
Dec 31, 2006, 3:59:23 AM12/31/06
to fir...@googlegroups.com
um...why not just append an external script to the DOM? I'm assuming
you're doing this solely to avoid using eval(), correct? Which means
you're probably getting this from an XMLHTTP request object anyway.
Just do away with that request:

var script = document.createElement('SCRIPT');
script.src = 'whatever.js';
document.getElementsByTagName('HEAD')[0].appendChild(script);

-Mark

James Burke

unread,
Dec 31, 2006, 11:33:24 AM12/31/06
to Firebug
Because dynamically added script tags are not guaranteed to execute in
the order that they are added to the DOM. MSIE executes the scripts in
the order that the browser receives them, which may not be the DOM
order. This causes errors when scripts need to be added in a particular
order.

James

Mark Kahn

unread,
Dec 31, 2006, 3:37:46 PM12/31/06
to fir...@googlegroups.com
do I have to do everything for you? (just kidding)

scripts added in IE have a readystate property. Use it :-) And use
onload for every other browser...

I wrote this quickly but I use the same concept all the time, it's
just heavily integrated into a framework:

var queue = [];
function addScript(src){
queue.push(src);
}
function loadScript(){
if(queue.length==0) return;

var scr = document.createElement('SCRIPT');
scr.src = queue[0];
document.getElementsByTagName('HEAD')[0].appendChild(scr);

if(scr.readyState=='loaded'){
scriptLoaded();
}else{
scr.onreadystatechange = function(){
if(scr.readyState=='complete'){ scriptLoaded(); }
}
scr.onload = scriptLoaded;
}
}
function scriptLoaded(){
queue.shift();
loadScript();
}

-Mark

On 12/31/06, James Burke <tag...@gmail.com> wrote:
>

James Burke

unread,
Dec 31, 2006, 6:34:26 PM12/31/06
to Firebug
I was under the impression that readystate was not fired reliably and
that Safari did not have an onload or readystate that could be checked,
based on this post and its comments:

http://siteexperts.spaces.live.com/Blog/cns!1pNcL8JwTfkkjv4gg6LkVCpw!1925.entry

However, that article might be a little dated. Have you found the
approach you mention to be reliable? Does onload work for Safari now?
If so, I might consider going that route. I also wanted the code to be
defined immediately (doing synchronous loading of dependencies), but I
haven't tested if using inline text in a script tag will be available
immediately, so it may not work out anyway.

Even if your solution turns out to be viable, it still seems like it
would be good for Firebug to be able to handle dynamically added inline
scripts. Or maybe it is best to wait for eval() debugging support in
Firebug 2.0?

Thanks for the info,
James

Mark Kahn

unread,
Dec 31, 2006, 7:06:26 PM12/31/06
to fir...@googlegroups.com
you're right that readystate is not reliably fired. In fact it's not
fired at all if the script is already cached, but that's what this is
for:

if(scr.readyState=='loaded'){
scriptLoaded();

if the script is cached it just checks that and readystate isn't
needed. onload works fine in safari, but I'm not sure about older
versions of it. If it does happen to be an issue you can drop the
onload code altogether:

function loadscript(src){
// create script
if(script.readyState){ // IE
// load like I said in previous post
} else {
// just append the script to the dom and do nothing else
}
}

since IE is the only browser that has a problem with this.
firefox/opera/safari all execute scripts in DOM order.

As for when the scripts come in, doing this will make them
asynchronous, ie your code will continue to run while the script is
loaded. You're correct that the only way around that is using
xmlhttp.

-Mark

On 12/31/06, James Burke <tag...@gmail.com> wrote:
>

dd

unread,
Jan 2, 2007, 6:51:47 PM1/2/07
to Firebug
I'd also like to know if it's possible to set breakpoints and step
through code in script block that was dynamically created. Whether it
was by eval or by createElement('SCRIPT') doesn't really matter too
much. There's script code that's in scope, can be seen in the DOM view
in Firebug, but can't be viewed/accessed in any way I can find.
Considering that this type of dynamic code is 90% of what I'm trying to
debug, I'm getting nowhere at all with Firebug right now :-(

I'm even tempted to see if Venkman has improved to the level of being
able to do anything useful at all, so you can see how desperate I must
be ;-)

Mark Kahn

unread,
Jan 2, 2007, 7:02:32 PM1/2/07
to fir...@googlegroups.com
scripts brought in with createElement('SCRIPT') show up, for me at
least, like any other script.

scripts brought in with xmlhttp and eval'd can't be properly debugged,
they throw errors in the calling script at an offset from the eval()
line. ie if there's an error at line 25 of an eval'd script, it would
show up in the script that has the eval() call 25 lines after the
eval. Pretty much useless.

-Mark

Joe Hewitt

unread,
Jan 2, 2007, 7:18:25 PM1/2/07
to fir...@googlegroups.com
This is one of the most requested features. It is possible to
support eval'd scripts, but tricky. You would probably expect these
scripts to show up in the scripts dropdown, nicely organized by URL
like those included from <script>, but this isn't easily doable. An
eval'd script often has a meaningful identifier in the context of a
framework, like a Dojo package name, but to Firefox it's just a block
of text. So, the question is, how would you as a user locate these
scripts in the first place?

Another problem to solve is to allow debugging eval'd scripts if they
happen to turn up in a call stack. Right now, functions from eval'd
blocks claim their source to be the line of the file where eval() was
called. This is why, for instance, line 10 of your eval'd script
turns out to be line 70 of some other file where eval was called on
line 60. I'm not sure yet what is the way to distinguish a JSD
script object that was eval'd from one that was loaded by a script tag.

- Joe

dd

unread,
Jan 2, 2007, 7:26:57 PM1/2/07
to Firebug
Thanks Joe, I was just putting together an example, now I'll stop :)

My only experience of debugging these kind of things comes from IE.
With Visual Studio .NET you see a list of running documents and as a
child of the document where the eval's came from, there are a number of
script blocks. One per eval statement and they're simply named "eval
code". I look through each of the eval code pseudo "files" to find the
function I'm interested in breaking in and find a line of code and hit
F9. VS manages to track that very well. I've been using VS right back
since the 80's when it was called CodeView so it seems the most natural
thing in the world to me that it works that way. Script blocks created
via createElement it also doesn't manage too well. Luckily my logic
tests for IE and uses eval to create the functions it needs to. For all
else it's dynodes. So I guess I'm not surprised then that Firebug has a
similarly tough time with them. I'd like to stick with using eval but I
was getting all kinds of weird scope problems with eval code blocks not
being able to see each other and that wasn't happening with dynodes.

Mark Kahn

unread,
Jan 2, 2007, 7:37:45 PM1/2/07
to fir...@googlegroups.com
From a naming point of view, why not allow people to name the eval'd
scripts? Something like:

function firebugEval(txt, name){
// name = name of the script
windowEval.apply(arguments.callee.caller||window, arguments);
}
windowEval = window.eval;
eval = firebugEval;

You'd then write:

eval(script, 'my script name');

any browser without firebug will simply ignore the name and eval the
script normally. As dd said, call any unnamed eval scripts just "eval
code".

As for distinguishing the eval code...good luck :-) If all else
fails, however, you might be able to do something like this:

windowEval.apply(arguments.callee.caller||window, ['// some GUID\n'+txt]);

-Mark

Joe Hewitt

unread,
Jan 2, 2007, 7:46:02 PM1/2/07
to fir...@googlegroups.com
I had been thinking of doing something just like this. By overriding
window.eval, we could store the text that is passed to eval in a map,
and look it up by the file/line number where eval was called. That
would also allow us to distinguish eval'd vs. loaded scripts - by
looking up a file/line in the eval map.

I like the idea of supporting the extra argument with the script
name, too.

- Joe

Mark Kahn

unread,
Jan 2, 2007, 8:07:34 PM1/2/07
to fir...@googlegroups.com
yeah, that was the basic idea. I havn't tested this in a while, but I
know that eval.apply doesn't always work properly. overriding it may
be an issue since I'm not sure if arguments.callee.caller always
points to the stack instance of the calling function or the window
instance of that function.

-Mark

On 1/2/07, Joe Hewitt <j...@joehewitt.com> wrote:
>

John J Barton

unread,
Jan 2, 2007, 10:50:15 PM1/2/07
to Firebug
In mozilla bug 332176 and bug 307984 the naming is discussed,
one option was to name the scripts with data: URLs, ie by the
source itself. But I think special code to pick up comments like
dojos would be helpful for many users. Another very important case
is json scripts loaded by XHR.

John J Barton

unread,
Jan 2, 2007, 10:53:20 PM1/2/07
to Firebug
Hi Mark
I read this:
"You cannot indirectly use the eval function by invoking it via a
name other than eval; if you do, a runtime error might occur."
on
http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Functions:eval
So I tried your example and I got a weird error. Do you think it
should work?
John.

Mark Kahn

unread,
Jan 2, 2007, 11:59:53 PM1/2/07
to fir...@googlegroups.com
erm...it did, and it does now, but it didn't a minute ago...I'm confused!

um, okay...it seems to work as long as you don't have "var" in the eval code...

<script>
function newEval(txt){
var args = arguments.callee.caller;


windowEval.apply(arguments.callee.caller || window, arguments);
}
windowEval = window.eval;

window.eval = newEval;

function testNamespace(){
var y=20;
eval('x=15');
alert(x);
}

testNamespace();
</script>

change that to "var x=15" and it breaks...that can obviously cause
some issues... :-(

it works quite well other than that...:

eval('(function(){var test=5;this.test=test})()');
alert(this.test);

got me...not being able to use "var" is obviously a show stopper...damn it

-Mark

Joe Hewitt

unread,
Jan 3, 2007, 12:09:03 AM1/3/07
to fir...@googlegroups.com
There might be hope.  JSD offers an eval() equivalent that allows you to choose which stack frame to evaluate the code in.  If I recall correctly, it does evaluate 'var' statements properly.  I haven't time to try it right now, but you can look at the interface here:

Mark Kahn

unread,
Jan 3, 2007, 12:19:11 AM1/3/07
to fir...@googlegroups.com
I'm not familiar with JSD, but from the looks of this you would still
need to override the existing eval function, correct? Even if you did
that and ran this it would be executing in a stack one level above
where it should be, ie instead of executing from myFunction it would
be executing from the custom eval function.

But you might know a different approach.

If it does work it seems that it'd be perfect since it even allows you
to specify the filename so it's possible (although unlikely - because
it would just be too easy) that no other code would need to be
changed.

-Mark

Kris Zyp

unread,
Jan 3, 2007, 7:15:11 PM1/3/07
to Firebug
I too would love to see the ability to debug eval scripts, since I use
them quite extensively as well (from data from XMLHttpRequests). While
naming them would be nice, I certainly don't think it is necessary from
a user view point. Handling eval code the same way that Microsoft
Script Editor does it would be great with me. Right now, whenever I
have code in an eval that needs to be debugged I always switch over to
MSE since it handles it quite nicely. Certainly would be cool to have
that same ability in Firebug, but I see how the JS VM makes it hard to
do so.
Kris

On Jan 2, 9:19 pm, "Mark Kahn" <cwol...@gmail.com> wrote:
> I'm not familiar with JSD, but from the looks of this you would still
> need to override the existing eval function, correct? Even if you did
> that and ran this it would be executing in a stack one level above
> where it should be, ie instead of executing from myFunction it would
> be executing from the custom eval function.
>
> But you might know a different approach.
>
> If it does work it seems that it'd be perfect since it even allows you
> to specify the filename so it's possible (although unlikely - because
> it would just be too easy) that no other code would need to be
> changed.
>
> -Mark
>
> On 1/3/07, Joe Hewitt <j...@joehewitt.com> wrote:
>
>
>
>
>
> > There might be hope. JSD offers an eval() equivalent that allows you to
> > choose which stack frame to evaluate the code in. If I recall correctly, it
> > does evaluate 'var' statements properly. I haven't time to try it right
> > now, but you can look at the interface here:
>

> >http://lxr.mozilla.org/seamonkey/source/js/jsd/idl/jsdIDebuggerServic...


>
> > On Jan 2, 2007, at 8:59 PM, Mark Kahn wrote:
>
> > <script>
>
> > function newEval(txt){
>
> > var args = arguments.callee.caller;
>
> > windowEval.apply(arguments.callee.caller || window, arguments);
>
> > }
>
> > windowEval = window.eval;
>
> > window.eval = newEval;
>
> > function testNamespace(){
>
> > var y=20;
>
> > eval('x=15');
>
> > alert(x);
>
> > }
>
> > testNamespace();
>

> > </script>- Hide quoted text -- Show quoted text -

Maciek

unread,
Jan 12, 2007, 12:24:48 PM1/12/07
to Firebug
Hi guys,

I believe there's one case in which javascript code and/or data is
arriving dynamically and can safely (at least) be formatted by Firebug:

JSON.

This should probably only work if the MIME type in a given
XMLHTTPRequest response is set to "application/json". If this is the
case and the string contains valid code, that could be a valuable
source of debug help from Firebug. At the moment, Firebug is unaware
that the given string is code, but seeing as we have a MIME type we
could use, it might be possible to introduce that kind of awareness.

CJR

unread,
Jan 28, 2007, 3:02:05 PM1/28/07
to Firebug
Needed this functionality myself and came across this thread, here's
how i have avoided the problem (and it's not pretty):

Under normal circumstances the code is loaded via a synchronous xhr
request, however for Firefox when in 'development mode' i have created
an alternative path, this basically uses the dynamic script element
creation process, to load the code into memory, however because this
method is asynchronous (and would otherwise mess up the program flow),
i still make the call to the server for the script via xhr, this holds
up the script long enough for the script tag method to load the code
so that firebug can see it.

So far this method has worked perfectly, if at some point it fails i
guess i'll have to add a method to the webservice asking for a long
wait ...

CJR.

On Jan 4, 12:15 am, "Kris Zyp" <kris...@gmail.com> wrote:
> I too would love to see the ability to debug eval scripts, since I use
> them quite extensively as well (from data from XMLHttpRequests). While
> naming them would be nice, I certainly don't think it is necessary from

> a user view point. Handling eval code the same way that MicrosoftScriptEditor does it would be great with me. Right now, whenever I

Muppet

unread,
Jan 29, 2007, 12:59:30 AM1/29/07
to Firebug
It appears that no-one here knows how to use Venkman.

Press ctrl+p to "pretty print" when you hit a breakpoint (or debugger
statement) and you can step through all your eval'd scripts to your
heart's content.

bbak...@gmail.com

unread,
Jan 30, 2007, 12:11:29 AM1/30/07
to Firebug
Can I add my vote for debugging of eval code. More and more AJAX
frameworks use the pattern of XHR and eval for dynamic code and hence
the call for this will only get greater.

As for naming the instances, I think the IE debugger idea of simply
having a list of "eval code" is enough for most people. It access to
the source not the external script that is important.

Venkman has a very useful pretty print function for "guesstimating"
the source code however it does not give you a list of "eval code"
objects/. Instead you must set a debugger breakpoint and then pretty
print once you are in that context. IE debugger is a little nicer in
that a running list is created and hence you can set break points in
code from the list

Maybe the Venkman code can be studied to find out how it does its
pretty print source code display.

ps. I love FireBug and the new 1.0 has blown me away. Its just that
the web framework I develop most in (Echo2) uses the XHR/eval pattern
and hence firebugs usefulness is diminished for that.

Kris Zyp

unread,
Jan 30, 2007, 11:52:00 AM1/30/07
to Firebug
When Venkman is in pretty print mode it does a toString (or uneval) on
the current function to show the source. This doesn't uneval the
entire eval code, just the current function (so it doesn't really
provide the functionality that IE script editor does). Previous posts
in this thread have already demonstrated some legitimate ways of
bringing in the source to firebug (overriding window.eval or just
having a custom eval function). There are some issues with them, but I
believe that even a custom eval function would be adequate for most of
us. Presumably, the biggest issue with is to align breakpoints. I
believe that that way it has to be done is to determine the line
number when the custom eval is called, bring in the source into
firebug, and remember the line number for the eval so that all the
line numbers in the evaled source, can be properly realigned. Then
when a breakpoint is set in the evaled source, the line number can
adjusted by the eval line number before being passed to the JSD. In
addition, every time a breakpoint is hit, and the JSD signals firebug,
firebug would need to determine if the breakpoint really occurred at
the given point, or if it was breakpoint from a evaled source. It
would need to do this by checking to see if the current function
matched the function listed in the source, and if it did not, then
iterating through evaled sources until it found a breakpoint/line
number + function match.

Kris Zyp

unread,
Jan 30, 2007, 12:05:01 PM1/30/07
to Firebug
There is also bug (not just a feature request) directly related to
this issue. If you have a breakpoint in your code and you have evaled
code that is executed that has a line number + eval code line number
that happens to coincide with your breakpoint line number, than
firebug will (wrongly) stop at your breakpoint. I know Joe loves test
cases, so to see this in action (and demonstrate the effects of the
previous post), you can see the following test case:
http://www.authenteo.com/test/breakpoint_test.html
Set a breakpoint on line 6 in the js file, and you will clearly see it
stop/break in the wrong function.

Kris Zyp

unread,
Jan 30, 2007, 12:22:27 PM1/30/07
to Firebug
And in case it is not clear how the bug and dynamic scripts are
related, my point is that whenever the JSD signals that a breakpoint
has been hit, firebug can not just assume the line number/source is
correct, but must check to see if the currently executing function
matches the function for the source/line number, and this mechanism is
necessary not only to fix this bug, but to enable debugging of evaled
scripts, so that firebug can go through the (forthcoming) evaled
sources to find the right source for a given breakpoint stop.
I certainly acknowledge this is not a trivial issue to correct/
implement, but I certainly agree with others that is only going to
increase in importance, as dynamic scripting increases in popularity.
Sorry for breaking this up into 3 posts.
Kris
www.authenteo.com

Kris Zyp

unread,
Feb 19, 2007, 12:10:23 PM2/19/07
to Firebug
I wanted to put in a request for the API for the dynamic script
support (once you add it). First of all, I don't think you should
necessarily replace the top level eval function (seems there are too
many difficulties with it and not enough flexibility). I think it
would be best to have an explicit firebug eval function that would
allow firebug to read in the eval (with the known limitations of the
with the firebug eval, such as different handling of var, but with the
extra options as well). I would love to see something like this:
firebugEval(evalString, sourceName, sourceCode, codeChangeHandler)
The first parameter is your normal evalString parameter. The next
three parameters are optional. The sourceName would let you give the
evalled code a name, The sourceCode is a parameter where you could
provide a separate string that is the source code. This would
facilitate situations where the evalString is compressed or the
precompiled. The third parameter would be a function that could handle
changes made to the script. You could then allow editing to scripts
(that provided a codeChangeHandler). This would open amazing
possibilites for actually being able to use firebug as an JavaScript
editor/IDE and actually edit the JavaScript you are debugging right in
the debugger. The provided function callback would then be responsible
for actually taking the altered JavaScript and making any necessary
updates (to the server and client). Using the sourceName as a key, the
codeChangeHandler could also be responsible for calling the eval again
with the replacement function/ source code.
I think having having an explicit eval would not be difficult for us
to use. We could simply write:
if (window.firebugEval)
firebugEval(evalString,evalName,...)
else
eval(evalString);
Anyway, I think this would be an awesome improvement, and solve a lot
of issues with firebug handling dynamic scripts, as well as really
open the possibilities for taking JavaScript to a whole new level of
development ease.


On Jan 30, 9:22 am, "Kris Zyp" <kris...@gmail.com> wrote:
> And in case it is not clear how the bug anddynamicscripts are


> related, my point is that whenever the JSD signals that a breakpoint
> has been hit, firebug can not just assume the line number/source is
> correct, but must check to see if the currently executing function
> matches the function for the source/line number, and this mechanism is
> necessary not only to fix this bug, but to enable debugging of evaled
> scripts, so that firebug can go through the (forthcoming) evaled
> sources to find the right source for a given breakpoint stop.
> I certainly acknowledge this is not a trivial issue to correct/
> implement, but I certainly agree with others that is only going to

> increase in importance, asdynamicscripting increases in popularity.

> Sorry for breaking this up into 3 posts.
> Kriswww.authenteo.com
>
> On Jan 30, 9:05 am, "Kris Zyp" <kris...@gmail.com> wrote:
>
>
>
> > There is also bug (not just a feature request) directly related to
> > this issue. If you have a breakpoint in your code and you have evaled
> > code that is executed that has a line number + eval code line number
> > that happens to coincide with your breakpoint line number, than
> > firebug will (wrongly) stop at your breakpoint. I know Joe loves test
> > cases, so to see this in action (and demonstrate the effects of the
> > previous post), you can see the following test case:http://www.authenteo.com/test/breakpoint_test.html
> > Set a breakpoint on line 6 in the js file, and you will clearly see it

> > stop/break in the wrong function.- Hide quoted text -
>
> - Show quoted text -

bbak...@gmail.com

unread,
Mar 19, 2007, 8:59:31 PM3/19/07
to Firebug
Just to add another issue discovered because of the "lack" of support
for eval code, the profiler function (which is excellent by the way)
can not tell you which parts of the code take what time, Because not
function names are available in eval'ed code.

On Jan 30, 4:11 pm, "bbaker...@gmail.com" <bbaker...@gmail.com> wrote:
> Can I add my vote for debugging ofevalcode. More and more AJAX
> frameworks use the pattern of XHR andevalfor dynamic code and hence


> the call for this will only get greater.
>
> As for naming the instances, I think the IE debugger idea of simply

> having a list of "evalcode" is enough for most people. It access to

Reply all
Reply to author
Forward
0 new messages