From 7b820249d64e38636d5b19afa1e168202d611365 Mon Sep 17 00:00:00 2001 From: Philipp Spiess Date: Mon, 3 Feb 2025 16:19:41 +0100 Subject: [PATCH 1/2] Don't crash when setting JS theme value to `null`' --- CHANGELOG.md | 3 +- .../src/compat/apply-config-to-theme.test.ts | 36 +++++++++++++ .../tailwindcss/src/compat/config.test.ts | 51 +++++++++++++++++++ .../src/compat/config/resolve-config.test.ts | 45 ++++++++++++++++ .../src/compat/plugin-functions.ts | 2 +- 5 files changed, 134 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c2686352696a..a8b77ec2a766 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,11 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -- Nothing yet! - ### Fixed - Ensure that the `containers` JS theme key is added to the `--container-*` namespace. ([#16169](https://github.com/tailwindlabs/tailwindcss/pull/16169)) +- Fix a crash when setting JS theme values to `null` ([#16210](https://github.com/tailwindlabs/tailwindcss/pull/16210)) ## [4.0.3] - 2025-02-01 diff --git a/packages/tailwindcss/src/compat/apply-config-to-theme.test.ts b/packages/tailwindcss/src/compat/apply-config-to-theme.test.ts index 23f5c46cb720..619c99182123 100644 --- a/packages/tailwindcss/src/compat/apply-config-to-theme.test.ts +++ b/packages/tailwindcss/src/compat/apply-config-to-theme.test.ts @@ -223,3 +223,39 @@ test('converts opacity modifiers from decimal to percentage values', () => { expect(theme.resolve('20', ['--opacity'])).toEqual('20%') expect(theme.resolve('25', ['--opacity'])).toEqual('25%') }) + +test('handles setting theme keys to null', async () => { + let theme = new Theme() + let design = buildDesignSystem(theme) + + theme.add('--color-blue-400', 'blue', ThemeOptions.DEFAULT) + theme.add('--color-blue-500', '#3b82f6') + theme.add('--color-red-400', 'red', ThemeOptions.DEFAULT) + theme.add('--color-red-500', '#ef4444') + + let { resolvedConfig, replacedThemeKeys } = resolveConfig(design, [ + { + config: { + theme: { + extend: { + colors: { + blue: null, + }, + }, + }, + }, + base: '/root', + reference: false, + }, + ]) + applyConfigToTheme(design, resolvedConfig, replacedThemeKeys) + + expect(theme.namespace('--color')).toMatchInlineSnapshot(` + Map { + "blue-400" => "blue", + "blue-500" => "#3b82f6", + "red-400" => "red", + "red-500" => "#ef4444", + } + `) +}) diff --git a/packages/tailwindcss/src/compat/config.test.ts b/packages/tailwindcss/src/compat/config.test.ts index 4b095c1724f6..eb18cd734f21 100644 --- a/packages/tailwindcss/src/compat/config.test.ts +++ b/packages/tailwindcss/src/compat/config.test.ts @@ -1628,3 +1628,54 @@ test('old theme values are merged with their renamed counterparts in the CSS the expect(didCallPluginFn).toHaveBeenCalled() }) + +test('handles setting theme keys to null', async () => { + let compiler = await compile( + css` + @theme default { + --color-red-50: oklch(0.971 0.013 17.38); + --color-red-100: oklch(0.936 0.032 17.717); + } + @config "./my-config.js"; + @tailwind utilities; + @theme { + --color-red-100: oklch(0.936 0.032 17.717); + --color-red-200: oklch(0.885 0.062 18.334); + } + `, + { + loadModule: async () => { + return { + module: { + theme: { + extend: { + colors: { + red: null, + }, + }, + }, + }, + base: '/root', + } + }, + }, + ) + + expect(compiler.build(['bg-red-50', 'bg-red-100', 'bg-red-200'])).toMatchInlineSnapshot(` + ":root, :host { + --color-red-50: oklch(0.971 0.013 17.38); + --color-red-100: oklch(0.936 0.032 17.717); + --color-red-200: oklch(0.885 0.062 18.334); + } + .bg-red-50 { + background-color: var(--color-red-50); + } + .bg-red-100 { + background-color: var(--color-red-100); + } + .bg-red-200 { + background-color: var(--color-red-200); + } + " + `) +}) diff --git a/packages/tailwindcss/src/compat/config/resolve-config.test.ts b/packages/tailwindcss/src/compat/config/resolve-config.test.ts index 0a1daeee6b49..d96bdc7008b8 100644 --- a/packages/tailwindcss/src/compat/config/resolve-config.test.ts +++ b/packages/tailwindcss/src/compat/config/resolve-config.test.ts @@ -254,3 +254,48 @@ test('theme keys can read from the CSS theme', () => { new Set(['colors', 'accentColor', 'placeholderColor', 'caretColor', 'transitionColor']), ) }) + +test('handles null as theme values', () => { + let theme = new Theme() + theme.add('--color-red-50', 'red') + theme.add('--color-red-100', 'red') + + let design = buildDesignSystem(theme) + + let { resolvedConfig, replacedThemeKeys } = resolveConfig(design, [ + { + config: { + theme: { + colors: ({ theme }) => ({ + // Reads from the --color-* namespace + ...theme('color'), + }), + }, + }, + base: '/root', + reference: false, + }, + { + config: { + theme: { + extend: { + colors: { + red: null, + }, + }, + }, + }, + base: '/root', + reference: false, + }, + ]) + + expect(resolvedConfig).toMatchObject({ + theme: { + colors: { + red: null, + }, + }, + }) + expect(replacedThemeKeys).toEqual(new Set(['colors'])) +}) diff --git a/packages/tailwindcss/src/compat/plugin-functions.ts b/packages/tailwindcss/src/compat/plugin-functions.ts index 9e3917eaaf90..339bd11c6ce7 100644 --- a/packages/tailwindcss/src/compat/plugin-functions.ts +++ b/packages/tailwindcss/src/compat/plugin-functions.ts @@ -224,7 +224,7 @@ function get(obj: any, path: string[]) { let key = path[i] // The key does not exist so concatenate it with the next key - if (obj[key] === undefined) { + if (obj?.[key] === undefined) { if (path[i + 1] === undefined) { return undefined } From 0def5fddcc4b035ac49bfa3607216f127ad65867 Mon Sep 17 00:00:00 2001 From: Philipp Spiess Date: Tue, 4 Feb 2025 14:20:35 +0100 Subject: [PATCH 2/2] Update CHANGELOG.md Co-authored-by: Robin Malfait --- CHANGELOG.md | 1 - 1 file changed, 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f4d547d1aca7..e7eb390a698a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed -- Ensure that the `containers` JS theme key is added to the `--container-*` namespace. ([#16169](https://github.com/tailwindlabs/tailwindcss/pull/16169)) - Fix a crash when setting JS theme values to `null` ([#16210](https://github.com/tailwindlabs/tailwindcss/pull/16210)) - Ensure that the `containers` JS theme key is added to the `--container-*` namespace ([#16169](https://github.com/tailwindlabs/tailwindcss/pull/16169)) - Fix missing `@keyframes` definition ([#16237](https://github.com/tailwindlabs/tailwindcss/pull/16237))