From 1e8081632b54f5cdfed38dacefc421e48d86450f Mon Sep 17 00:00:00 2001 From: Arman Jivanyan Date: Tue, 16 Dec 2025 10:59:06 +0400 Subject: [PATCH 1/4] add catch to avoid error in windows --- .../devextreme/js/__internal/ui/themes.ts | 2 ++ .../tests/DevExpress.ui/themes.tests.js | 36 +++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/packages/devextreme/js/__internal/ui/themes.ts b/packages/devextreme/js/__internal/ui/themes.ts index 0bba28d28db5..8eda8fafe8e8 100644 --- a/packages/devextreme/js/__internal/ui/themes.ts +++ b/packages/devextreme/js/__internal/ui/themes.ts @@ -60,6 +60,8 @@ function readThemeMarker(): string | null { return null; } return result.substr(THEME_MARKER_PREFIX.length); + } catch (e) { + return null; } finally { element.remove(); } diff --git a/packages/devextreme/testing/tests/DevExpress.ui/themes.tests.js b/packages/devextreme/testing/tests/DevExpress.ui/themes.tests.js index 6e36c92a7ebd..4e261a99b5d1 100644 --- a/packages/devextreme/testing/tests/DevExpress.ui/themes.tests.js +++ b/packages/devextreme/testing/tests/DevExpress.ui/themes.tests.js @@ -825,3 +825,39 @@ QUnit.module('initialized method', (hooks) => { }); }); }); + +QUnit.module('readThemeMarker error handling', () => { + test('readThemeMarker returns null when getComputedStyle throws an error', function(assert) { + const done = assert.async(); + const originalGetComputedStyle = window.getComputedStyle; + window.getComputedStyle = function() { throw new Error('getComputedStyle fails'); }; + + try { + themes.resetTheme(); + const value = themes.current(); + assert.strictEqual(value, null, 'current() returns null on getComputedStyle error'); + } finally { + window.getComputedStyle = originalGetComputedStyle; + done(); + } + }); + + test('waitForThemeLoad resolves even if getComputedStyle continuously throws', function(assert) { + const done = assert.async(); + const originalGetComputedStyle = window.getComputedStyle; + window.getComputedStyle = function() { throw new Error('boom'); }; + + const TEST_TIMEOUT = 30; + themes.resetTheme(); + themes.setDefaultTimeout(TEST_TIMEOUT); + + themes.ready(() => { + assert.strictEqual(themes.current(), null, 'theme remains null after timeout with errors'); + window.getComputedStyle = originalGetComputedStyle; + themes.setDefaultTimeout(defaultTimeout); + done(); + }); + + themes.waitForThemeLoad('some.nonexistent.theme'); + }); +}); From 8044515a672ce3c1703ba947093b44106e8bab3f Mon Sep 17 00:00:00 2001 From: Arman Jivanyan Date: Tue, 23 Dec 2025 13:08:07 +0400 Subject: [PATCH 2/4] add a little more specific check --- packages/devextreme/js/__internal/ui/themes.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/devextreme/js/__internal/ui/themes.ts b/packages/devextreme/js/__internal/ui/themes.ts index 8eda8fafe8e8..6f48c84879cb 100644 --- a/packages/devextreme/js/__internal/ui/themes.ts +++ b/packages/devextreme/js/__internal/ui/themes.ts @@ -50,6 +50,9 @@ function readThemeMarker(): string | null { let result: string; try { + if (!window?.getComputedStyle) { + return null; + } result = window.getComputedStyle(element.get(0)).fontFamily; if (!result) { return null; From db240678318c3fc5c8dfab2a99ca05187af8c55e Mon Sep 17 00:00:00 2001 From: Arman Jivanyan Date: Tue, 23 Dec 2025 13:29:00 +0400 Subject: [PATCH 3/4] remove catch --- packages/devextreme/js/__internal/ui/themes.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/devextreme/js/__internal/ui/themes.ts b/packages/devextreme/js/__internal/ui/themes.ts index 6f48c84879cb..537b6e7f29a9 100644 --- a/packages/devextreme/js/__internal/ui/themes.ts +++ b/packages/devextreme/js/__internal/ui/themes.ts @@ -63,8 +63,6 @@ function readThemeMarker(): string | null { return null; } return result.substr(THEME_MARKER_PREFIX.length); - } catch (e) { - return null; } finally { element.remove(); } From 7de7d975abfaf1da7f8f5a0d805e3edf74e2185c Mon Sep 17 00:00:00 2001 From: Arman Jivanyan Date: Tue, 23 Dec 2025 13:54:29 +0400 Subject: [PATCH 4/4] fix tests --- .../testing/tests/DevExpress.ui/themes.tests.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/devextreme/testing/tests/DevExpress.ui/themes.tests.js b/packages/devextreme/testing/tests/DevExpress.ui/themes.tests.js index 4e261a99b5d1..3e98fd22e59e 100644 --- a/packages/devextreme/testing/tests/DevExpress.ui/themes.tests.js +++ b/packages/devextreme/testing/tests/DevExpress.ui/themes.tests.js @@ -830,12 +830,12 @@ QUnit.module('readThemeMarker error handling', () => { test('readThemeMarker returns null when getComputedStyle throws an error', function(assert) { const done = assert.async(); const originalGetComputedStyle = window.getComputedStyle; - window.getComputedStyle = function() { throw new Error('getComputedStyle fails'); }; + window.getComputedStyle = undefined; try { themes.resetTheme(); const value = themes.current(); - assert.strictEqual(value, null, 'current() returns null on getComputedStyle error'); + assert.strictEqual(value, null, 'current() returns null on getComputedStyle being undefined'); } finally { window.getComputedStyle = originalGetComputedStyle; done(); @@ -845,14 +845,14 @@ QUnit.module('readThemeMarker error handling', () => { test('waitForThemeLoad resolves even if getComputedStyle continuously throws', function(assert) { const done = assert.async(); const originalGetComputedStyle = window.getComputedStyle; - window.getComputedStyle = function() { throw new Error('boom'); }; + window.getComputedStyle = undefined; const TEST_TIMEOUT = 30; themes.resetTheme(); themes.setDefaultTimeout(TEST_TIMEOUT); themes.ready(() => { - assert.strictEqual(themes.current(), null, 'theme remains null after timeout with errors'); + assert.strictEqual(themes.current(), null, 'theme remains null after timeout'); window.getComputedStyle = originalGetComputedStyle; themes.setDefaultTimeout(defaultTimeout); done();