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

Commit d996305

Browse files
randombkpetebacondarwin
authored andcommitted
perf($rootScope): remove history event handler when app is torn down
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
1 parent 79fa7dd commit d996305

File tree

5 files changed

+40
-0
lines changed

5 files changed

+40
-0
lines changed

src/ng/browser.js

+10
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,16 @@ function Browser(window, document, $log, $sniffer) {
264264
return callback;
265265
};
266266

267+
/**
268+
* @private
269+
* Remove popstate and hashchange handler from window.
270+
*
271+
* NOTE: this api is intended for use only by $rootScope.
272+
*/
273+
self.$$applicationDestroyed = function() {
274+
jqLite(window).off('hashchange popstate', cacheStateAndFireUrlChange);
275+
};
276+
267277
/**
268278
* Checks whether the url has changed outside of Angular.
269279
* Needs to be exported to be able to check for changes that have been done in sync,

src/ng/rootScope.js

+5
Original file line numberDiff line numberDiff line change
@@ -878,6 +878,11 @@ function $RootScopeProvider() {
878878
this.$broadcast('$destroy');
879879
this.$$destroyed = true;
880880

881+
if (this === $rootScope) {
882+
//Remove handlers attached to window when $rootScope is removed
883+
$browser.$$applicationDestroyed();
884+
}
885+
881886
incrementWatchersCount(this, -this.$$watchersCount);
882887
for (var eventName in this.$$listenerCount) {
883888
decrementListenerCount(this, this.$$listenerCount[eventName], eventName);

src/ngMock/angular-mocks.js

+1
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ angular.mock.$Browser = function() {
5757
return listener;
5858
};
5959

60+
self.$$applicationDestroyed = angular.noop;
6061
self.$$checkUrlChange = angular.noop;
6162

6263
self.deferredFns = [];

test/ng/browserSpecs.js

+17
Original file line numberDiff line numberDiff line change
@@ -647,6 +647,23 @@ describe('browser', function() {
647647
};
648648
}
649649
});
650+
651+
652+
it("should stop calling callbacks when application has been torn down", function() {
653+
sniffer.history = true;
654+
browser.onUrlChange(callback);
655+
fakeWindow.location.href = 'http://server/new';
656+
657+
browser.$$applicationDestroyed();
658+
659+
fakeWindow.fire('popstate');
660+
expect(callback).not.toHaveBeenCalled();
661+
662+
fakeWindow.fire('hashchange');
663+
fakeWindow.setTimeout.flush();
664+
expect(callback).not.toHaveBeenCalled();
665+
});
666+
650667
});
651668

652669

test/ng/rootScopeSpec.js

+7
Original file line numberDiff line numberDiff line change
@@ -1048,6 +1048,13 @@ describe('Scope', function() {
10481048
}));
10491049

10501050

1051+
it('should call $browser.$$applicationDestroyed when destroying rootScope', inject(function($rootScope, $browser) {
1052+
spyOn($browser, '$$applicationDestroyed');
1053+
$rootScope.$destroy();
1054+
expect($browser.$$applicationDestroyed).toHaveBeenCalledOnce();
1055+
}));
1056+
1057+
10511058
it('should remove first', inject(function($rootScope) {
10521059
first.$destroy();
10531060
$rootScope.$digest();

0 commit comments

Comments
 (0)