From f4d554d90ffbf0a91de2f886f046188427aa3551 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 6b4908a61daa..9fdaa7f5de22 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 75eb02af9219..f500b6e35dad 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 3a0b0a6d1e1da0f54b6ce690c92e8ce8f5f46135 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 9fdaa7f5de22..284718d961db 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 ae8858b0bbee0ef24edb0ebd9848ec76f5b7afea 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 284718d961db..7a989419dd9f 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 1d976b64007ef4e061bd2b032b6e312e05eeb96d 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 f500b6e35dad..46c2e9821dae 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();