Joho the BlogBeginner to Beginner: When a Javascript program only works in a debugger - Joho the Blog

Beginner to Beginner: When a Javascript program only works in a debugger

[LATER the same day:] Thanks to expert advice from some generous expert folks in the comments, I found the mistake I was making; I explain it in the comment #5. But, the mystery of why it worked only when run in debug mode remains. (Tom in comment #4 has a good hypothesis.) Nevertheless, I’m sticking with my overall point that for a home-made, one-user project like this, a brute-force, dumb-ass solution sometimes serves. I should maybe mention also that one reason I post about “programming” is precisely because I’m an idiot about it, and I think it’s good to be a beginner in public.

Aaarrrggghhh. I spent way too much time yesterday and today trying to fix a problem with a javascript program the right way. When I finally gave up and did it the wrong way, it worked fine…except for being embarrassingly inelegant.

It’s a mystery. The program doesn’t work ever except if you run it in a debugger and set a breakpoint anywhere in either of the two affected functions. It doesn’t even work if you put an “alert()” into it. It really really wants a breakpoint. This is consistent in both Firefox and Chrome, with Firebug and the integrated Chrome debugger. It only works if you set a breakpoint. It does not work if you do not set a breakpoint. Did I mention Aaaarrrrrrggggghhhhhh?

Some details: I added a function to my little all-crap blog editor. The function (call it FunctionA) gets called when the user (= me and only me) presses a button. FunctionA calls FunctionB to see if the selected text is listed in an array of terms. If so, then FunctionA inserts some text using associated text. (To be more concrete, although it doesn’t matter: If the selected text is the name of someone for whom I have a twitter name, FunctionA builds and inserts a link to the person’s Twitter address.) FunctionB calls one other function (that trims spaces and other cruft) and one method (to temporarily uppercase both the selected text and the name in the database, so that the search won’t be case sensitive, and yes, I’m sure there’s a better way to do that). Then it simply walks through the array, looking for a match.

I googled around and didn’t find much help with the mysterious fact that it only works if I set a breakpoint. People with similar problems can sometimes solve them by using the setTimeout() function, to let the script catch up with itself. But, that’s not really what setTimeout does, apparently. It doesn’t pause the script. Rather, it delays the execution of a particular function while the rest of the script continues merrily on. I also found that a common cause of a similar problem is that your script is trying to access a part of the document that hasn’t been loaded or created yet. But: (a) My script isn’t trying to do that, and (b) If that were the problem, then putting in an alert() would have worked for me, no? The cause might be some multithreaded mystery for which there is no known solution, but I really don’t know. (You might try this.)

So, after looking at some clever recursive setTimeout strategies that I couldn’t figure out how to adapt to my particular script, I had a stupid idea. I put the code from FunctionB — the one that looks the selected text up in an array — straight into FunctionA. So, FunctionA doesn’t call FunctionB. It has within it a copy of the code in FunctionB.

And it works.

It works even though it is just about the definition of “inelegant.” The whole point of every programming language since Turing first ran marked paper off a mental spool is to write functions for any process your script might use more than once. Not only does that save time writing, it makes debugging a billion times easier because you only have to fix it in one place. So my solution to my problem is like telling a chef to beat each egg separately or to suggest reloading a supersoaker after each and every squeeze.

But, dammit, it worked. I don’t know why, and I ‘d say that I don’t care, but, I do. Well, at least I can now get back to wasting my time in marginally less frustrating ways.

Previous: « || Next: »

9 Responses to “Beginner to Beginner: When a Javascript program only works in a debugger”

  1. First, that is the way you do a unicase lookup.

    Second, there’s a bug in your code. When you find it, you’ll understand why the debugger behaved so mysteriously.

    In many years of coding I’ve only had one bug that turned out to be a bug in the system. It almost always is yours. So if you approach it that way you will eventually find it.

    Suggestion — try single stepping thru the code in the debuggervandvwatch what it’s doinign with your data.

  2. You didn’t define “doesn’t work”, so it’s hard to guess what it might be, however one issue I used to have in browser event handlers is that the display and/or DOM wouldn’t get updated until the handler returned. The changes to the content of a DOM element would not be visible to other functions until the handler function itself was finished. Within the handler function itself the change would be visible, but others would not see it yet reflected in the DOM.

  3. Dave, thanks for your first line, which gives me a way to hold my head a little higher. Unfortunately, FunctionB gets used by another function as well, so I’m going to have to insist that my “solution” is as inelegant as my post maintains :)

    Yes, I’m 99.99% sure the problem is a bug in my code. What are the chances otherwise? But, for a project for personal use, solving it with an inelegant blunderbuss seemed to work. Of course, I’d love to know where my code is going wrong, but at least now it’s working.

    Brent, “doesn’t work” means in this case that FunctionB returns -1 (the value to which I initially set my flag variable) when it looks up a name that is in fact in the array, _unless_ I put in a breakpoint, in which case it does the right thing of returning the index of the matching name in the array.

    Dave, oh, I have stepped through the code line by line. Over and over. Altering every variable I could think of. I’ve set a breakpoint at literally every line (one at a time). When I step through it, it works: FunctionB finds the string in the array (it uses a simple “for” loop that looks at every member of the array because the array is never going to get bigger than a few dozen entries). It returns the right number. Then, when I run it _without_ any breakpoints, FunctionB returns -1.

    Brent, I’m not changing the DOM in these functions until after FunctionB has returned its results. If the result is -1, FunctionA exits. Otherwise, FunctionA builds a string based on the number FunctionB returned and inserts it. But FunctionB returns its results before I’ve touched the DOM.

    So, I am certain it’s something I’m doing wrong, especially since I’ve had it fail in two browsers and under two debuggers. I’d love to know what. But, for homebrewed, personal sw, I think the dumbass solution is going to hold me for now.

    Thank you both for jumping in.

  4. I know how frustrating this kind of thing can be! Even though you don’t want to put any more time into this, it might be good to do some more work to track down the problem, for your future knowledge.

    Here’s what I suspect – some object or variable isn’t in scope when funcB is called. But in the debugger, the context is different and somehow that object or variable is in scope.

    Ok, how to proceed? Here’s what I would try at this point. Restore FuncA to call FuncB. Put a return(-99) (or something else distinctive) into funcB after each line in turn. You may be able to skip some, but you get the idea. Or you can use a binary search strategy if the function is long. Capture the return from B with an alert. At some point as you move the return() farther down the code, you will stop getting a -99 and start getting a -1. That’s the line that isn’t working right.

    If you do in fact find an array or other object that isn’t in scope, you can assign that object to the window object (call it thing), say, and use it as window.thing. Or assign it to the document object. Either of these will be in scope for any function you write.

    This procedure may be tedious depending on how lucky you get, but it will let you zero in on the exact problem spot.

    Good luck!

  5. Bingo, Tom.

    The problem — AKA my mistake — turned out to be bush league, of course. I use a global variable to store the currently selected text. It’s set in a function called getSelectedText(). I thought it was being called before FunctionA, but it wasn’t. Therefore, A was passing zilch to B as the name to look up. Lots of functions call getSelectedText(), so the global was getting set accidentally as I was retrying FunctionA.

    This doesn’t explain everything. For one thing, I went back and forth between debugging and not debugging many times without reloading, so it’s not that FunctionA would work after the first try. Why FunctionA would work if and only if I set a breakpoint in FunctionA or FunctionB, is still mysterious, although to my untutored ears, Tom’s explanation — “some object or variable isn’t in scope when funcB is called. But in the debugger, the context is different and somehow that object or variable is in scope” — sounds right, and serves to satisfy my curiosity.

    Thanks to you all.

  6. […] love that David Weinberger is narrating his fumbling programming work on his blog. It’s great for a lot of […]

  7. I agree with Tom’s hypothesis, that installing the debug breakpoint changes the context underpinning the execution of FunctionA, “fixes” the problem. From your description —

    The function (call it FunctionA) gets called when the user (= me and only me) presses a button.

    it sounds like interrupt/ event handling may be a factor in this bizarre behavior.

    I suspect that running without breakpoints from the browser FunctionA dies the death your mistake programmed for it. The act of setting the breakpoint introduces a rewiring of the interrupt chain which moves the consequences of the uninitialized reference to a place that handles it better. Just a thought.

    Inserting a simple —

    console.debug( ‘at FunctionB, this is %o’,this );

    at the head of FunctionB, and comparing plain and breakpoint-assisted results in FireBug may yield an explanation.

  8. I’ve got the same problem with one of my Javascript scripts. It runs fine in debug mode (sans breakpoints), but in the run mode the same function returns different results. The function that is returning different results is this.inherited(arguments);
    I am not sure how the presence of the debugger helps here.

  9. I had similar issue, and your website encourage me to dig more until I found out that my problem was the reference statement of the java script library/file. The java script path I had was only visible during debug mod, but not on a regular run. First though let me tell you that this was happening in Visual Studio 2010 ASP.Net environment. The only thing that I changed for it to work was using the full path, including project directory, instead of what I was using, or commonly used ways like: (“/lib/scriptname.js”, “../lib/scriptname.js” or “~/lib/scriptname.js”).

    The invisible complaint or error was undefined function name that was stored/defined in the external java script file referenced within the ASPX page: reference.

    Good luck!

Web Joho only

Comments (RSS).  RSS icon