Skip to content

Commit 86a8fee

Browse files
crisbetommalerba
authored andcommitted
fix(snack-bar): handle large numbers passed in as duration (#17239)
Handles very large numbers being passed in as a snack bar duration (e.g. `Infinity`). We need to cap the duration, otherwise the browser will revert it back to 1 if it's too large. Fixes #17234.
1 parent 3476f51 commit 86a8fee

File tree

2 files changed

+19
-1
lines changed

2 files changed

+19
-1
lines changed

src/material/snack-bar/snack-bar-ref.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ export interface MatSnackBarDismiss {
1717
dismissedByAction: boolean;
1818
}
1919

20+
/** Maximum amount of milliseconds that can be passed into setTimeout. */
21+
const MAX_TIMEOUT = Math.pow(2, 31) - 1;
22+
2023
/**
2124
* Reference to a snack bar dispatched from the snack bar service.
2225
*/
@@ -85,7 +88,9 @@ export class MatSnackBarRef<T> {
8588

8689
/** Dismisses the snack bar after some duration */
8790
_dismissAfter(duration: number): void {
88-
this._durationTimeoutId = setTimeout(() => this.dismiss(), duration);
91+
// Note that we need to cap the duration to the maximum value for setTimeout, because
92+
// it'll revert to 1 if somebody passes in something greater (e.g. `Infinity`). See #17234.
93+
this._durationTimeoutId = setTimeout(() => this.dismiss(), Math.min(duration, MAX_TIMEOUT));
8994
}
9095

9196
/** Marks the snackbar as opened */

src/material/snack-bar/snack-bar.spec.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -496,6 +496,19 @@ describe('MatSnackBar', () => {
496496
expect(overlayContainerElement.childElementCount).toBe(0);
497497
}));
498498

499+
it('should cap the timeout to the maximum accepted delay in setTimeout', fakeAsync(() => {
500+
const config = new MatSnackBarConfig();
501+
config.duration = Infinity;
502+
snackBar.open('content', 'test', config);
503+
viewContainerFixture.detectChanges();
504+
spyOn(window, 'setTimeout').and.callThrough();
505+
tick(100);
506+
507+
expect(window.setTimeout).toHaveBeenCalledWith(jasmine.any(Function), Math.pow(2, 31) - 1);
508+
509+
flush();
510+
}));
511+
499512
describe('with custom component', () => {
500513
it('should open a custom component', () => {
501514
const snackBarRef = snackBar.openFromComponent(BurritosNotification);

0 commit comments

Comments
 (0)