Skip to content

Commit

Permalink
fix(dialog): leaking MdDialogContainer references (#2944)
Browse files Browse the repository at this point in the history
* fix(dialog): leaking MdDialogContainer references

Fixes an issue that caused the `MdDialogContainer` references to not be cleaned up, and as a result, any of the `MdDialogRef` and `MdDialogConfig` instances as well. The issue seems to come from the fact that a couple of blocks that look like:
```
this._ngZone.onMicrotaskEmpty.first().subscribe(() => {
  this._elementFocusedBeforeDialogWasOpened = document.activeElement;
  this._focusTrap.focusFirstTabbableElement();
});
```

End up being transpiled to:
```
var _this = this;
this._ngZone.onMicrotaskEmpty.first().subscribe(function () {
    _this._elementFocusedBeforeDialogWasOpened = document.activeElement;
    _this._focusTrap.focusFirstTabbableElement();
});
```

This seems to cause the browser to retain the `_this` reference after the dialog has been destroyed.

Fixes #2876.

* chore: add comment about `this` usage in zone
  • Loading branch information
crisbeto authored and tinayuangao committed Mar 29, 2017
1 parent 07bc4ad commit 8e6720b
Showing 1 changed file with 8 additions and 9 deletions.
17 changes: 8 additions & 9 deletions src/lib/dialog/dialog-container.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,10 +118,8 @@ export class MdDialogContainer extends BasePortalHost implements OnDestroy {
// If were to attempt to focus immediately, then the content of the dialog would not yet be
// ready in instances where change detection has to run first. To deal with this, we simply
// wait for the microtask queue to be empty.
this._ngZone.onMicrotaskEmpty.first().subscribe(() => {
this._elementFocusedBeforeDialogWasOpened = document.activeElement as HTMLElement;
this._focusTrap.focusFirstTabbableElement();
});
this._elementFocusedBeforeDialogWasOpened = document.activeElement as HTMLElement;
this._focusTrap.focusFirstTabbableElementWhenReady();
}

/**
Expand Down Expand Up @@ -150,16 +148,17 @@ export class MdDialogContainer extends BasePortalHost implements OnDestroy {
// the dialog was opened. Wait for the DOM to finish settling before changing the focus so
// that it doesn't end up back on the <body>. Also note that we need the extra check, because
// IE can set the `activeElement` to null in some cases.
this._ngZone.onMicrotaskEmpty.first().subscribe(() => {
let toFocus = this._elementFocusedBeforeDialogWasOpened as HTMLElement;
let toFocus = this._elementFocusedBeforeDialogWasOpened as HTMLElement;

// We need to check whether the focus method exists at all, because IE seems to throw an
// exception, even if the element is the document.body.
// We shouldn't use `this` inside of the NgZone subscription, because it causes a memory leak.
let animationStream = this._onAnimationStateChange;

this._ngZone.onMicrotaskEmpty.first().subscribe(() => {
if (toFocus && 'focus' in toFocus) {
toFocus.focus();
}

this._onAnimationStateChange.complete();
animationStream.complete();
});

if (this._focusTrap) {
Expand Down

0 comments on commit 8e6720b

Please sign in to comment.