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

Commit

Permalink
fix($mdInteraction): clean up events on $rootScope destroy (#11641)
Browse files Browse the repository at this point in the history
this prevents unit tests from leaking memory

Fixes: #11493

<!-- 
Filling out this template is required! Do not delete it when submitting a Pull Request! Without this information, your Pull Request may be auto-closed.
-->
## PR Checklist
Please check that your PR fulfills the following requirements:
- [x] The commit message follows [our guidelines](https://github.com/angular/material/blob/master/.github/CONTRIBUTING.md#-commit-message-format)
- [ ] Tests for the changes have been added or this is not a bug fix / enhancement
- [ ] Docs have been added, updated, or were not required

## PR Type
What kind of change does this PR introduce?
<!-- Please check the one that applies to this PR using "x". -->
```
[x] Bugfix
[ ] Enhancement
[ ] Documentation content changes
[ ] Code style update (formatting, local variables)
[ ] Refactoring (no functional changes, no api changes)
[ ] Build related changes
[ ] CI related changes
[ ] Infrastructure changes
[ ] Other... Please describe:
```

## What is the current behavior?

Currently the $mdInteraction service registers when invoked. This causes a memory leak in unit tests because nothing is in place to clean up the events.

<!-- Please describe the current behavior that you are modifying and link to one or more relevant issues. -->
Issue Number: #11493

## What is the new behavior?

Now on the $destroy event of rootScope the events registered will be unregistered.

## Does this PR introduce a breaking change?
```
[ ] Yes
[x] No
```
<!-- If this PR contains a breaking change, please describe the impact and migration path for existing applications below. -->
<!-- Note that breaking changes are highly unlikely to get merged to master unless the validation is clear and the use case is critical. -->

## Other information
  • Loading branch information
codymikol authored and mmalerba committed Mar 14, 2019
1 parent ec9aa25 commit e9e9ece
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 8 deletions.
36 changes: 29 additions & 7 deletions src/core/services/interaction/interaction.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,20 @@ angular
* </hljs>
*
*/
function MdInteractionService($timeout, $mdUtil) {
function MdInteractionService($timeout, $mdUtil, $rootScope) {
this.$timeout = $timeout;
this.$mdUtil = $mdUtil;
this.$rootScope = $rootScope;

// IE browsers can also trigger pointer events, which also leads to an interaction.
this.pointerEvent = 'MSPointerEvent' in window ? 'MSPointerDown' : 'PointerEvent' in window ? 'pointerdown' : null;
this.bodyElement = angular.element(document.body);
this.isBuffering = false;
this.bufferTimeout = null;
this.lastInteractionType = null;
this.lastInteractionTime = null;
this.inputHandler = this.onInputEvent.bind(this);
this.bufferedInputHandler = this.onBufferInputEvent.bind(this);

// Type Mappings for the different events
// There will be three three interaction types
Expand All @@ -65,24 +70,41 @@ function MdInteractionService($timeout, $mdUtil) {
};

this.initializeEvents();
this.$rootScope.$on('$destroy', this.deregister.bind(this));
}

/**
* Removes all event listeners created by $mdInteration on the
* body element.
*/
MdInteractionService.prototype.deregister = function() {

this.bodyElement.off('keydown mousedown', this.inputHandler);

if ('ontouchstart' in document.documentElement) {
this.bodyElement.off('touchstart', this.bufferedInputHandler);
}

if (this.pointerEvent) {
this.bodyElement.off(this.pointerEvent, this.inputHandler);
}

};

/**
* Initializes the interaction service, by registering all interaction events to the
* body element.
*/
MdInteractionService.prototype.initializeEvents = function() {
// IE browsers can also trigger pointer events, which also leads to an interaction.
var pointerEvent = 'MSPointerEvent' in window ? 'MSPointerDown' : 'PointerEvent' in window ? 'pointerdown' : null;

this.bodyElement.on('keydown mousedown', this.onInputEvent.bind(this));
this.bodyElement.on('keydown mousedown', this.inputHandler);

if ('ontouchstart' in document.documentElement) {
this.bodyElement.on('touchstart', this.onBufferInputEvent.bind(this));
this.bodyElement.on('touchstart', this.bufferedInputHandler);
}

if (pointerEvent) {
this.bodyElement.on(pointerEvent, this.onInputEvent.bind(this));
if (this.pointerEvent) {
this.bodyElement.on(this.pointerEvent, this.inputHandler);
}

};
Expand Down
40 changes: 39 additions & 1 deletion src/core/services/interaction/interaction.spec.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
describe("$mdInteraction service", function() {

var $mdInteraction = null;
var $rootScope = null;
var bodyElement = null;
var $timeout = null;

beforeEach(module('material.core'));

beforeEach(inject(function($injector) {
$mdInteraction = $injector.get('$mdInteraction');
$rootScope = $injector.get('$rootScope');
$timeout = $injector.get('$timeout');

bodyElement = angular.element(document.body);
}));
Expand Down Expand Up @@ -75,4 +79,38 @@ describe("$mdInteraction service", function() {

});

});
describe('when $rootScope is destroyed', function () {

var _initialTouchStartEvent = document.documentElement.ontouchstart;

beforeAll(function () {
document.documentElement.ontouchstart = function () {};
});

beforeEach(function () {
$mdInteraction.lastInteractionType = 'initial';
$rootScope.$destroy();
});

afterAll(function () {
document.documentElement.ontouchstart = _initialTouchStartEvent;
});

it('should remove mousedown events', function () {
bodyElement.triggerHandler('mousedown');
expect($mdInteraction.getLastInteractionType()).toEqual('initial');
});

it('should remove keydown events', function () {
bodyElement.triggerHandler('keydown');
expect($mdInteraction.getLastInteractionType()).toEqual('initial');
});

it('should remove touchstart events', function () {
bodyElement.triggerHandler('touchstart');
expect($mdInteraction.getLastInteractionType()).toEqual('initial');
});

});

});

0 comments on commit e9e9ece

Please sign in to comment.