Skip to content
This repository has been archived by the owner on Apr 12, 2024. It is now read-only.

Commit

Permalink
perf($rootScope): remove history event handler when app is torn down
Browse files Browse the repository at this point in the history
Remember the popstate and hashchange handler registered with window
when the application bootstraps, and remove it when the application
is torn down

Closes #9897
Closes #9905
  • Loading branch information
randombk authored and petebacondarwin committed Apr 2, 2015
1 parent 79fa7dd commit d996305
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 0 deletions.
10 changes: 10 additions & 0 deletions src/ng/browser.js
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,16 @@ function Browser(window, document, $log, $sniffer) {
return callback;
};

/**
* @private
* Remove popstate and hashchange handler from window.
*
* NOTE: this api is intended for use only by $rootScope.
*/
self.$$applicationDestroyed = function() {
jqLite(window).off('hashchange popstate', cacheStateAndFireUrlChange);
};

/**
* Checks whether the url has changed outside of Angular.
* Needs to be exported to be able to check for changes that have been done in sync,
Expand Down
5 changes: 5 additions & 0 deletions src/ng/rootScope.js
Original file line number Diff line number Diff line change
Expand Up @@ -878,6 +878,11 @@ function $RootScopeProvider() {
this.$broadcast('$destroy');
this.$$destroyed = true;

if (this === $rootScope) {
//Remove handlers attached to window when $rootScope is removed
$browser.$$applicationDestroyed();
}

incrementWatchersCount(this, -this.$$watchersCount);
for (var eventName in this.$$listenerCount) {
decrementListenerCount(this, this.$$listenerCount[eventName], eventName);
Expand Down
1 change: 1 addition & 0 deletions src/ngMock/angular-mocks.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ angular.mock.$Browser = function() {
return listener;
};

self.$$applicationDestroyed = angular.noop;
self.$$checkUrlChange = angular.noop;

self.deferredFns = [];
Expand Down
17 changes: 17 additions & 0 deletions test/ng/browserSpecs.js
Original file line number Diff line number Diff line change
Expand Up @@ -647,6 +647,23 @@ describe('browser', function() {
};
}
});


it("should stop calling callbacks when application has been torn down", function() {
sniffer.history = true;
browser.onUrlChange(callback);
fakeWindow.location.href = 'http://server/new';

browser.$$applicationDestroyed();

fakeWindow.fire('popstate');
expect(callback).not.toHaveBeenCalled();

fakeWindow.fire('hashchange');
fakeWindow.setTimeout.flush();
expect(callback).not.toHaveBeenCalled();
});

});


Expand Down
7 changes: 7 additions & 0 deletions test/ng/rootScopeSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -1048,6 +1048,13 @@ describe('Scope', function() {
}));


it('should call $browser.$$applicationDestroyed when destroying rootScope', inject(function($rootScope, $browser) {
spyOn($browser, '$$applicationDestroyed');
$rootScope.$destroy();
expect($browser.$$applicationDestroyed).toHaveBeenCalledOnce();
}));


it('should remove first', inject(function($rootScope) {
first.$destroy();
$rootScope.$digest();
Expand Down

0 comments on commit d996305

Please sign in to comment.