Skip to content

Commit a90bc34

Browse files
vaadin-botweb-padawanclaude
authored
refactor: do not throw when calling CSS.registerProperty twice (#12011) (#12014)
Co-authored-by: Serhii Kulykov <iamkulykov@gmail.com> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 6346d48 commit a90bc34

9 files changed

Lines changed: 104 additions & 28 deletions

File tree

packages/charts/src/styles/vaadin-chart-base-styles.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
import '@vaadin/component-base/src/styles/style-props.js';
2020
import '@vaadin/component-base/src/styles/user-colors.js';
2121
import { css, unsafeCSS } from 'lit';
22-
import { addGlobalStyles } from '@vaadin/component-base/src/styles/add-global-styles.js';
22+
import { addGlobalStyles } from '@vaadin/component-base/src/css-utils.js';
2323

2424
/* Tooltip styles, to support `"tooltip": { "outside": true }` config option */
2525
// postcss-lit-disable-next-line
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/**
2+
* @license
3+
* Copyright (c) 2025 - 2026 Vaadin Ltd.
4+
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5+
*/
6+
7+
/**
8+
* Registers a CSS custom property, tolerating the case where the property has
9+
* already been registered. This can happen when a module is evaluated more than
10+
* once (e.g. duplicate bundle chunks or two copies of the library on the page),
11+
* in which case `CSS.registerProperty` throws `InvalidModificationError`. That
12+
* error is caught and logged as a warning rather than allowed to break loading.
13+
*
14+
* @param {PropertyDefinition} definition
15+
*/
16+
export function registerCSSProperty(definition) {
17+
try {
18+
CSS.registerProperty(definition);
19+
} catch (e) {
20+
if (e instanceof DOMException && e.name === 'InvalidModificationError') {
21+
console.warn(`The CSS property ${definition.name} has already been registered.`);
22+
} else {
23+
throw e;
24+
}
25+
}
26+
}
27+
28+
/**
29+
* Add a `<style>` block with given styles to the document.
30+
*
31+
* @param {string} id the id to set on the created element, only for informational purposes
32+
* @param {CSSResultGroup[]} styles the styles to add
33+
*/
34+
export const addGlobalStyles = (id, ...styles) => {
35+
const styleTag = document.createElement('style');
36+
styleTag.id = id;
37+
styleTag.textContent = styles.map((style) => style.toString()).join('\n');
38+
39+
document.head.insertAdjacentElement('afterbegin', styleTag);
40+
};

packages/component-base/src/styles/add-global-styles.js

Lines changed: 0 additions & 19 deletions
This file was deleted.

packages/component-base/src/styles/style-props.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
55
*/
66
import { css } from 'lit';
7-
import { addGlobalStyles } from './add-global-styles.js';
7+
import { addGlobalStyles, registerCSSProperty } from '../css-utils.js';
88

99
// NOTE: Base color CSS custom properties are explicitly registered as `<color>`
1010
// here to avoid performance issues in Aura. Aura overrides these properties with
@@ -18,7 +18,7 @@ import { addGlobalStyles } from './add-global-styles.js';
1818
'--vaadin-border-color-secondary',
1919
'--vaadin-background-color',
2020
].forEach((propertyName) => {
21-
CSS.registerProperty({
21+
registerCSSProperty({
2222
name: propertyName,
2323
syntax: '<color>',
2424
inherits: true,

packages/component-base/src/styles/user-colors.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
55
*/
66
import { css } from 'lit';
7-
import { addGlobalStyles } from './add-global-styles.js';
7+
import { addGlobalStyles } from '../css-utils.js';
88

99
addGlobalStyles(
1010
'vaadin-base-user-colors',
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import { expect } from '@vaadin/chai-plugins';
2+
import sinon from 'sinon';
3+
import { registerCSSProperty } from '../src/css-utils.js';
4+
5+
describe('registerCSSProperty', () => {
6+
let warn;
7+
let counter = 0;
8+
9+
// CSS property registration is global and cannot be undone within a page,
10+
// so use a unique name per test to keep tests order-independent.
11+
function uniqueName() {
12+
counter += 1;
13+
return `--test-register-style-property-${counter}`;
14+
}
15+
16+
beforeEach(() => {
17+
warn = sinon.stub(console, 'warn');
18+
});
19+
20+
afterEach(() => {
21+
warn.restore();
22+
});
23+
24+
it('should register a property once without warning', () => {
25+
const name = uniqueName();
26+
registerCSSProperty({ name, syntax: '<number>', inherits: false, initialValue: '0' });
27+
28+
expect(warn.called).to.be.false;
29+
});
30+
31+
it('should not throw when the same property is registered twice', () => {
32+
const name = uniqueName();
33+
const definition = { name, syntax: '<number>', inherits: false, initialValue: '0' };
34+
35+
registerCSSProperty(definition);
36+
expect(() => registerCSSProperty(definition)).to.not.throw();
37+
});
38+
39+
it('should warn when the same property is registered twice', () => {
40+
const name = uniqueName();
41+
const definition = { name, syntax: '<number>', inherits: false, initialValue: '0' };
42+
43+
registerCSSProperty(definition);
44+
registerCSSProperty(definition);
45+
46+
expect(warn.calledOnce).to.be.true;
47+
expect(warn.firstCall.args[0]).to.include(name);
48+
});
49+
50+
it('should rethrow errors other than InvalidModificationError', () => {
51+
expect(() => registerCSSProperty({ name: uniqueName(), syntax: '<not-a-syntax>' })).to.throw();
52+
});
53+
});

packages/form-layout/src/styles/vaadin-form-layout-base-styles.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@
55
*/
66
import '@vaadin/component-base/src/styles/style-props.js';
77
import { css } from 'lit';
8-
import { addGlobalStyles } from '@vaadin/component-base/src/styles/add-global-styles.js';
8+
import { addGlobalStyles, registerCSSProperty } from '@vaadin/component-base/src/css-utils.js';
99

10-
CSS.registerProperty({
10+
registerCSSProperty({
1111
name: '--_min-width-labels-aside',
1212
syntax: '<length>',
1313
inherits: false,

packages/vaadin-themable-mixin/lumo-injection-mixin.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
* Copyright (c) 2021 - 2026 Vaadin Ltd.
44
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
55
*/
6+
import { registerCSSProperty } from '@vaadin/component-base/src/css-utils.js';
67
import { getLumoInjectorPropName, LumoInjector } from './src/lumo-injector.js';
78

89
/**
@@ -48,7 +49,7 @@ export const LumoInjectionMixin = (superClass) =>
4849
// so that changing it to 1 would inject styles to instances
4950
// Use `inherits: true` so that property defined on `<html>`
5051
// would apply to components instances within shadow roots
51-
CSS.registerProperty({
52+
registerCSSProperty({
5253
name: propName,
5354
syntax: '<number>',
5455
inherits: true,

packages/vaadin-themable-mixin/src/theme-detector.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,18 @@
33
* Copyright (c) 2000 - 2026 Vaadin Ltd.
44
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
55
*/
6+
import { registerCSSProperty } from '@vaadin/component-base/src/css-utils.js';
67
import { CSSPropertyObserver } from './css-property-observer.js';
78

89
// Register CSS custom properties for observing theme changes
9-
CSS.registerProperty({
10+
registerCSSProperty({
1011
name: '--vaadin-aura-theme',
1112
syntax: '<number>',
1213
inherits: true,
1314
initialValue: '0',
1415
});
1516

16-
CSS.registerProperty({
17+
registerCSSProperty({
1718
name: '--vaadin-lumo-theme',
1819
syntax: '<number>',
1920
inherits: true,

0 commit comments

Comments
 (0)