Skip to content

Commit

Permalink
fix(material/input): resolve memory leak on iOS (#24599)
Browse files Browse the repository at this point in the history
  • Loading branch information
arturovt authored Mar 17, 2022
1 parent d8c7c48 commit 0638419
Showing 1 changed file with 24 additions and 18 deletions.
42 changes: 24 additions & 18 deletions src/material/input/input.ts
Original file line number Diff line number Diff line change
Expand Up @@ -308,24 +308,7 @@ export class MatInput
// exists on iOS, we only bother to install the listener on iOS.
if (_platform.IOS) {
ngZone.runOutsideAngular(() => {
_elementRef.nativeElement.addEventListener('keyup', (event: Event) => {
const el = event.target as HTMLInputElement;

// Note: We specifically check for 0, rather than `!el.selectionStart`, because the two
// indicate different things. If the value is 0, it means that the caret is at the start
// of the input, whereas a value of `null` means that the input doesn't support
// manipulating the selection range. Inputs that don't support setting the selection range
// will throw an error so we want to avoid calling `setSelectionRange` on them. See:
// https://html.spec.whatwg.org/multipage/input.html#do-not-apply
if (!el.value && el.selectionStart === 0 && el.selectionEnd === 0) {
// Note: Just setting `0, 0` doesn't fix the issue. Setting
// `1, 1` fixes it for the first time that you type text and
// then hold delete. Toggling to `1, 1` and then back to
// `0, 0` seems to completely fix it.
el.setSelectionRange(1, 1);
el.setSelectionRange(0, 0);
}
});
_elementRef.nativeElement.addEventListener('keyup', this._iOSKeyupListener);
});
}

Expand Down Expand Up @@ -360,6 +343,10 @@ export class MatInput
if (this._platform.isBrowser) {
this._autofillMonitor.stopMonitoring(this._elementRef.nativeElement);
}

if (this._platform.IOS) {
this._elementRef.nativeElement.removeEventListener('keyup', this._iOSKeyupListener);
}
}

ngDoCheck() {
Expand Down Expand Up @@ -519,4 +506,23 @@ export class MatInput
const element = this._elementRef.nativeElement as HTMLSelectElement;
return this._isNativeSelect && (element.multiple || element.size > 1);
}

private _iOSKeyupListener = (event: Event): void => {
const el = event.target as HTMLInputElement;

// Note: We specifically check for 0, rather than `!el.selectionStart`, because the two
// indicate different things. If the value is 0, it means that the caret is at the start
// of the input, whereas a value of `null` means that the input doesn't support
// manipulating the selection range. Inputs that don't support setting the selection range
// will throw an error so we want to avoid calling `setSelectionRange` on them. See:
// https://html.spec.whatwg.org/multipage/input.html#do-not-apply
if (!el.value && el.selectionStart === 0 && el.selectionEnd === 0) {
// Note: Just setting `0, 0` doesn't fix the issue. Setting
// `1, 1` fixes it for the first time that you type text and
// then hold delete. Toggling to `1, 1` and then back to
// `0, 0` seems to completely fix it.
el.setSelectionRange(1, 1);
el.setSelectionRange(0, 0);
}
};
}

0 comments on commit 0638419

Please sign in to comment.