6

Steps:

  1. Open page in Firefox 29.0.1 (Windows 7 x64):

    <!doctype html>
    <title>Test</title>
    <script>
        (function () {
            var x = 5, f = function () {
                setTimeout(f, 1000);
            };
            f();
        }());
    </script>
    
  2. Open Developer Tools (F12).

  3. In the Debugger, set a breakpoint on: setTimeout(f, 1000);

  4. Once the breakpoint is hit, evaluate x in the console. The result: undefined

    Screenshot showing when <code>x</code> is evaluated

  5. Reload the page. The breakpoint is hit on the first run of f.

  6. Evaluate x. The result: 5

  7. Resume execution, and when the breakpoint is hit again, evaluate x. Same result: 5

My assumption: If Firefox realizes on the first run of f that x is not needed, then it doesn't store the value of x "with" f. So in subsequent calls to f the value of x is undefined. Interestingly, I see the same behavior in Chrome 35 and IE11.

Question: What is going on? Can I configure Firefox to make x evaluate to its correct value in step 4 (see above)?

feklee
  • 7,555
  • 9
  • 54
  • 72
  • 3
    `x` only exists within your function and you're trying to access it from outside. – Meredith Jun 05 '14 at 20:34
  • I'm not getting this issue. When I step into it, it's evaluating correctly. Fox 23.0.1 built in dev tools. I've experience the debugger not working correctly if you load a page, start debugger, and try to debug from there. I used to have to load the page, load debugger, refresh page to get it to work. – Joe Swindell Jun 05 '14 at 20:38
  • @Meredith I'm accessing `x` from the breakpoint on `setTimeout(f, 1000);`, which is *inside* of the function. – feklee Jun 05 '14 at 20:42
  • @JoeSwindell I am actually talking about the built in *development tools*, not about Firebug. Sorry for the confusion, I got the name wrong. Anyhow, reloading the page with development tools open doesn't solve it for me. To trigger the issue, it is important *not* to have the breakpoint set when loading the page. – feklee Jun 05 '14 at 20:48
  • @feklee Without the breakpoint, you're trying to access x from outside a scope where it's defined. The function() wrapper makes sure that x is not defined in the main scope of the page. If you removed the outer function wrapper, x would be defined. – Patrick Gunderson Jun 05 '14 at 21:37
  • @PatrickGunderson I am evaluating `x` *after* the breakpoint has been hit. – feklee Jun 05 '14 at 21:46
  • but still within the scope of that function. – Patrick Gunderson Jun 05 '14 at 22:17
  • @Qantas94Heavy It's recursive, sort of: There is a delay of 1 sec between calls. – feklee Jun 06 '14 at 06:00
  • See my answer to the same question here: https://stackoverflow.com/questions/31503178/how-get-value-of-variable-that-has-been-optimized-out#answer-53391033 – Elio Nov 20 '18 at 10:35

1 Answers1

6

It seems your assumption is correct. The problem is that the variable has been optimised out or removed when the debugger wasn't running. When you refresh the page with the debugger running, it alllows you to access the inner scopes of functions so that you can debug your code more easily.

This wouldn't be possible if there wasn't a breakpoint there, so the JIT compiler has to be disabled to let you do so. The garbage collector also notes that these can still be referenced in-scope, so doesn't remove these variables.

If the JIT compiler was running, it would recognise that the x variable is not used anywhere and remove that from the code generated. If the JIT compiler was not running, garbage collection (GC) would remove the variable when the GC cycle runs, as there is nothing referencing the variable.

Because it can't undo what it's already done, it is undefined when you hit the breakpoint the first time.

You can't really prevent this occuring, even if you disable the JIT compiler. While technically you could set the garbage collection limits really high to try and stop it doing so or even remove the garbage collection code and rebuild Firefox, that's pretty stupid -- you'd just end up leaking a bunch of memory and that'd be much more hassle than simply refreshing the page.

Interestingly though, Firefox 31 (Aurora) provides a more descriptive error message if you try and do the same thing:

Error: variable has been optimized out
Qantas 94 Heavy
  • 15,750
  • 31
  • 68
  • 83
  • Thanks, especially for the finding that Aurora outputs a more descriptive error message! I just confirmed that on my system. BTW you may remove the first line of your answer: I now also get `undefined`. Possibly there was another issue, or maybe I was in the wrong tab when I copied the error message. – feklee Jun 06 '14 at 10:45
  • That's great to know the details of this behavior, that it warns correctly in Firefox, but I wonder if the more serious bugs like https://bugzilla.mozilla.org/show_bug.cgi?id=977972 , https://bugzilla.mozilla.org/show_bug.cgi?id=582613 have been fixed in this version? Honestly I often have to try Chrome/Chromium for its JS debugger, though everything else is superior in Firefox. – NoBugs Jun 07 '14 at 06:16
  • @NoBugs: sorry, not sure about that -- I don't really use Aurora that much. – Qantas 94 Heavy Jun 08 '14 at 05:56