Description
Summary
Color.setStyle() fails to parse several valid CSS color formats and can silently leave the previous color unchanged without warning.
Affected area
Environment
- OS: Windows
- Branch/Repo: three.js local workspace
- Date: 2026-03-17
Verified bugs
- Silent no-op when
rgb/rgba/hsl/hsla model matches but component regex does not.
- CSS Color 4 space/slash syntax is not parsed:
rgb(255 0 0)
rgb(255 0 0 / 0.5)
hsl(120deg 100% 50%)
- Percentage alpha is rejected in rgba-like forms:
- Color model names are case-sensitive:
RGB(255,0,0)
HSL(120,100%,50%)
Reproduction
Run in repo root:
node -e "import { Color } from './src/math/Color.js'; const samples=['rgb(255 0 0)','rgb(255 0 0 / 0.5)','hsl(120deg 100% 50%)','rgb(100%,50%,10%,50%)','RGB(255,0,0)','HSL(120,100%,50%)']; for (const s of samples){ const c=new Color(0x123456); c.setStyle(s); console.log(s,'=>',c.getHexString()); }"
Observed output pattern:
- Most samples keep previous value (
123456) instead of setting a new color.
- Uppercase model names emit unknown model warnings and do not parse.
Expected behavior
- Parse valid CSS color forms (including modern CSS Color 4 forms), or
- If a format is intentionally unsupported, emit a clear warning and do not fail silently.
Actual behavior
- Several valid forms are not parsed.
- In multiple failure paths, method returns
this without warning, leaving stale color values.
Why this matters
- Causes hard-to-debug color bugs when user input comes from CSS values.
- Silent no-op behavior can mask data issues and produce incorrect rendering.
Existing test coverage gap
- Current unit tests mostly cover comma-separated lowercase legacy forms in test/unit/src/math/Color.tests.js.
- No coverage for CSS Color 4 space/slash syntax, uppercase model names, or alpha percentages.
Reproduction steps
1.node -e "import { Color } from './src/math/Color.js'; const samples=['rgb(255 0 0)','rgb(255 0 0 / 0.5)','hsl(120deg 100% 50%)','rgb(100%,50%,10%,50%)','RGB(255,0,0)','HSL(120,100%,50%)']; for (const s of samples){ const c=new Color(0x123456); c.setStyle(s); console.log(s,'=>',c.getHexString()); }" run it
2.Most samples keep previous value (123456) instead of setting a new color.
3.Uppercase model names emit unknown model warnings and do not parse.
Code
node -e "import { Color } from './src/math/Color.js'; const samples=['rgb(255 0 0)','rgb(255 0 0 / 0.5)','hsl(120deg 100% 50%)','rgb(100%,50%,10%,50%)','RGB(255,0,0)','HSL(120,100%,50%)']; for (const s of samples){ const c=new Color(0x123456); c.setStyle(s); console.log(s,'=>',c.getHexString()); }"
Live example
Screenshots
No response
Version
r183.1
Device
Desktop
Browser
Chrome
OS
Windows
Description
Summary
Color.setStyle()fails to parse several valid CSS color formats and can silently leave the previous color unchanged without warning.Affected area
Environment
Verified bugs
rgb/rgba/hsl/hslamodel matches but component regex does not.rgb(255 0 0)rgb(255 0 0 / 0.5)hsl(120deg 100% 50%)rgb(100%,50%,10%,50%)RGB(255,0,0)HSL(120,100%,50%)Reproduction
Run in repo root:
node -e "import { Color } from './src/math/Color.js'; const samples=['rgb(255 0 0)','rgb(255 0 0 / 0.5)','hsl(120deg 100% 50%)','rgb(100%,50%,10%,50%)','RGB(255,0,0)','HSL(120,100%,50%)']; for (const s of samples){ const c=new Color(0x123456); c.setStyle(s); console.log(s,'=>',c.getHexString()); }"Observed output pattern:
123456) instead of setting a new color.Expected behavior
Actual behavior
thiswithout warning, leaving stale color values.Why this matters
Existing test coverage gap
Reproduction steps
1.node -e "import { Color } from './src/math/Color.js'; const samples=['rgb(255 0 0)','rgb(255 0 0 / 0.5)','hsl(120deg 100% 50%)','rgb(100%,50%,10%,50%)','RGB(255,0,0)','HSL(120,100%,50%)']; for (const s of samples){ const c=new Color(0x123456); c.setStyle(s); console.log(s,'=>',c.getHexString()); }" run it
2.Most samples keep previous value (123456) instead of setting a new color.
3.Uppercase model names emit unknown model warnings and do not parse.
Code
node -e "import { Color } from './src/math/Color.js'; const samples=['rgb(255 0 0)','rgb(255 0 0 / 0.5)','hsl(120deg 100% 50%)','rgb(100%,50%,10%,50%)','RGB(255,0,0)','HSL(120,100%,50%)']; for (const s of samples){ const c=new Color(0x123456); c.setStyle(s); console.log(s,'=>',c.getHexString()); }"
Live example
Screenshots
No response
Version
r183.1
Device
Desktop
Browser
Chrome
OS
Windows