pkaminski / digest-hud

Digest performance analysis HUD for AngularJS.
MIT License
111 stars 20 forks source link

fixed undefined reference for timingStack.length #4

Open mrac opened 9 years ago

mrac commented 9 years ago

This should fix the error I get running digest-hud for my app:

TypeError: Cannot read property 'length' of undefined
    at Scope.instrumentedPostDigest [as $$postDigest] (http://localhost:3000/bower_components/angular-digest-hud/digest-hud.js:222:24)
    at runAnimationPostDigest (http://localhost:3000/bower_components/angular-animate/angular-animate.js:538:20)
    at Object.enter (http://localhost:3000/bower_components/angular-animate/angular-animate.js:958:18)
    at Object.enter (http://localhost:3000/bower_components/angular-ui-router/release/angular-ui-router.min.js:7:14016)
    at http://localhost:3000/bower_components/angular-ui-router/release/angular-ui-router.min.js:7:14584
    at publicLinkFn (http://localhost:3000/bower_components/angular/angular.js:6995:29)
    at j (http://localhost:3000/bower_components/angular-ui-router/release/angular-ui-router.min.js:7:14566)
    at http://localhost:3000/bower_components/angular-ui-router/release/angular-ui-router.min.js:7:14890
    at invokeLinkFn (http://localhost:3000/bower_components/angular/angular.js:8258:9)
    at nodeLinkFn (http://localhost:3000/bower_components/angular/angular.js:7768:11) <!-- uiView: header -->

Review on Reviewable

pkaminski commented 9 years ago

Thanks @mrac, but timingStack being an array within a digest cycle is supposed to be an invariant that's assumed throughout the code, so I'd prefer to understand how this could happen before rushing to a fix. Since you can reproduce the exception, could you dig into the sequence of events a bit, perhaps with some console logging? Note that:

  1. timingStack is declared on line 65, and starts out undefined.
  2. The only place it's assigned is line 183 to a literal empty array, so once it's initialized it should never become undefined again.
  3. The instrumentedPostDigest function on your stack is monkeypatched in at the same time as instrumentedDigest, which initializes timingStack.

It almost looks like you're calling digestHudProvider.enable() while a digest is in progress, so instrumentedDigest doesn't get to run before the post-digest phase hits, but that's unsupported and ought to be impossible. Could you look into it or share more details about your code please? Thanks.

strille commented 8 years ago

I got the same undefined error, and it turned out to be because I'm decorating $rootScope.$digest before calling digestHudProvider.enable():

            $provide.decorator('$rootScope', function ($delegate) {
                var _digest = $delegate.$digest;

                $delegate.$digest = function () {
                    // doing some stuff
                    _digest.apply($delegate, arguments);
                };

                return $delegate;
            });

If I call digestHudProvider.enable() after decorating I don't get the error...

pkaminski commented 8 years ago

Interesting. This probably hints at a way towards a fix, but given that there's an easy workaround that's now documented here, perhaps it's best to just leave it be.