fix(router): handle scrollRestoration error in restricted environments (#62186)

In this commit, setting `window.history.scrollRestoration` is wrapped in a try-catch block to prevent `SecurityError` exceptions in restricted contexts such as:

- sandboxed iframes
- partially navigated or inactive windows
- test runners, extensions, or content previews

If an error occurs, a runtime warning with error code [2400] is logged to the console. This avoids breaking app initialization and improves cross-browser safety.

Unfortunately, it's not possible to perform any end-to-end testing of this fix.

PR Close #62186
This commit is contained in:
arturovt
2025-06-22 01:03:13 +03:00
committed by Jessica Janiuk
parent e7d259b0dc
commit 65c59dd796
3 changed files with 28 additions and 2 deletions
+2
View File
@@ -53,6 +53,8 @@ export const enum RuntimeErrorCode {
// (undocumented)
REQUIRED_INPUT_MISSING = 2954,
// (undocumented)
SCROLL_RESTORATION_UNSUPPORTED = 2400,
// (undocumented)
SUSPICIOUS_DATE_FORMAT = 2300,
// (undocumented)
TOO_MANY_PRELOADED_IMAGES = 2961,
+3
View File
@@ -38,6 +38,9 @@ export const enum RuntimeErrorCode {
NO_PLURAL_MESSAGE_FOUND = 2308,
VALUE_NOT_A_NUMBER = 2309,
// Miscellaneous errors
SCROLL_RESTORATION_UNSUPPORTED = 2400,
// Keep 2800 - 2900 for Http Errors.
// Image directive errors
+23 -2
View File
@@ -6,7 +6,13 @@
* found in the LICENSE file at https://angular.dev/license
*/
import {inject, ɵɵdefineInjectable, DOCUMENT} from '@angular/core';
import {
inject,
ɵɵdefineInjectable,
DOCUMENT,
ɵformatRuntimeError as formatRuntimeError,
} from '@angular/core';
import {RuntimeErrorCode} from './errors';
/**
* Defines a scroll position manager. Implemented by `BrowserViewportScroller`.
@@ -131,7 +137,22 @@ export class BrowserViewportScroller implements ViewportScroller {
* Disables automatic scroll restoration provided by the browser.
*/
setHistoryScrollRestoration(scrollRestoration: 'auto' | 'manual'): void {
this.window.history.scrollRestoration = scrollRestoration;
try {
this.window.history.scrollRestoration = scrollRestoration;
} catch {
console.warn(
formatRuntimeError(
RuntimeErrorCode.SCROLL_RESTORATION_UNSUPPORTED,
ngDevMode &&
'Failed to set `window.history.scrollRestoration`. ' +
'This may occur when:\n' +
'• The script is running inside a sandboxed iframe\n' +
'• The window is partially navigated or inactive\n' +
'• The script is executed in an untrusted or special context (e.g., test runners, browser extensions, or content previews)\n' +
'Scroll position may not be preserved across navigation.',
),
);
}
}
/**