From 36524eb40bddb732d8d7416cff14180d9a3ab853 Mon Sep 17 00:00:00 2001 From: Remco Haszing Date: Fri, 9 Sep 2022 12:40:49 +0200 Subject: [PATCH 1/6] Fix issue with Tailwind modifying global state When running Tailwind, it modifies the plugin defaults parameters. As a result Tailwind using a Tailwind plugin in the same process twice yields different results. --- src/util/defaults.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/util/defaults.js b/src/util/defaults.js index 1d4aa7b45cfd..73a589edab39 100644 --- a/src/util/defaults.js +++ b/src/util/defaults.js @@ -1,17 +1,18 @@ export function defaults(target, ...sources) { + let copy = { ...target } for (let source of sources) { for (let k in source) { - if (!target?.hasOwnProperty?.(k)) { - target[k] = source[k] + if (!copy?.hasOwnProperty?.(k)) { + copy[k] = source[k] } } for (let k of Object.getOwnPropertySymbols(source)) { - if (!target?.hasOwnProperty?.(k)) { - target[k] = source[k] + if (!copy?.hasOwnProperty?.(k)) { + copy[k] = source[k] } } } - return target + return copy } From eade2de411738e47bcb66c3ca0dcfdaaed767477 Mon Sep 17 00:00:00 2001 From: Jordan Pittman Date: Fri, 9 Sep 2022 10:56:39 -0400 Subject: [PATCH 2/6] Add failing test --- tests/resolveConfig.test.js | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/tests/resolveConfig.test.js b/tests/resolveConfig.test.js index 2c435e5a6eb3..092473549892 100644 --- a/tests/resolveConfig.test.js +++ b/tests/resolveConfig.test.js @@ -1763,3 +1763,30 @@ test('all helpers can be destructured from the first function argument', () => { }, }) }) + +test('does not duplicate extended configs every time resolveConfig is called', () => { + let shared = { + foo: { bar: { baz: [{ color: 'red' }] } }, + } + + const createConfig = (color) => + resolveConfig([ + { + theme: { + foo: shared.foo, + extend: { + foo: { bar: { baz: { color } } }, + }, + }, + }, + ]) + + createConfig('orange') + createConfig('yellow') + createConfig('green') + + const result = createConfig('blue') + + expect(shared.foo.bar.baz).toMatchObject([{ color: 'red' }, { color: 'blue' }]) + expect(result.theme.foo.bar.baz).toMatchObject([{ color: 'red' }, { color: 'blue' }]) +}) From a3996c92418538479309f6e5f0435e92045d8e56 Mon Sep 17 00:00:00 2001 From: Jordan Pittman Date: Fri, 9 Sep 2022 10:59:23 -0400 Subject: [PATCH 3/6] Undo defaults change --- src/util/defaults.js | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/util/defaults.js b/src/util/defaults.js index 73a589edab39..1d4aa7b45cfd 100644 --- a/src/util/defaults.js +++ b/src/util/defaults.js @@ -1,18 +1,17 @@ export function defaults(target, ...sources) { - let copy = { ...target } for (let source of sources) { for (let k in source) { - if (!copy?.hasOwnProperty?.(k)) { - copy[k] = source[k] + if (!target?.hasOwnProperty?.(k)) { + target[k] = source[k] } } for (let k of Object.getOwnPropertySymbols(source)) { - if (!copy?.hasOwnProperty?.(k)) { - copy[k] = source[k] + if (!target?.hasOwnProperty?.(k)) { + target[k] = source[k] } } } - return copy + return target } From 8b673a2d7e8e1bbf05ed451dc2427601a7e68651 Mon Sep 17 00:00:00 2001 From: Jordan Pittman Date: Fri, 9 Sep 2022 11:32:53 -0400 Subject: [PATCH 4/6] wip --- tests/resolveConfig.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/resolveConfig.test.js b/tests/resolveConfig.test.js index 092473549892..60776a39a88b 100644 --- a/tests/resolveConfig.test.js +++ b/tests/resolveConfig.test.js @@ -1787,6 +1787,6 @@ test('does not duplicate extended configs every time resolveConfig is called', ( const result = createConfig('blue') - expect(shared.foo.bar.baz).toMatchObject([{ color: 'red' }, { color: 'blue' }]) + expect(shared.foo.bar.baz).toMatchObject([{ color: 'red' }]) expect(result.theme.foo.bar.baz).toMatchObject([{ color: 'red' }, { color: 'blue' }]) }) From 5455eecc3c752d7333084772f498c27ba74f8459 Mon Sep 17 00:00:00 2001 From: Jordan Pittman Date: Fri, 9 Sep 2022 11:33:31 -0400 Subject: [PATCH 5/6] Fix shared mutation problem --- src/util/resolveConfig.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/util/resolveConfig.js b/src/util/resolveConfig.js index 5472da08876f..11882aadfede 100644 --- a/src/util/resolveConfig.js +++ b/src/util/resolveConfig.js @@ -29,7 +29,7 @@ function mergeWith(target, ...sources) { if (merged === undefined) { if (isObject(target[k]) && isObject(source[k])) { - target[k] = mergeWith(target[k], source[k], customizer) + target[k] = mergeWith({}, target[k], source[k], customizer) } else { target[k] = source[k] } From f50863e1ba94edab69649c90d89b68db21f46a91 Mon Sep 17 00:00:00 2001 From: Jordan Pittman Date: Fri, 9 Sep 2022 11:42:16 -0400 Subject: [PATCH 6/6] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7d549f81f9b2..003147be00c0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Don't output duplicate utilities ([#9208](https://github.com/tailwindlabs/tailwindcss/pull/9208)) - Fix `fontFamily` config TypeScript types ([#9214](https://github.com/tailwindlabs/tailwindcss/pull/9214)) - Handle variants on complex selector utilities ([#9262](https://github.com/tailwindlabs/tailwindcss/pull/9262)) +- Don't mutate shared config objects ([#9294](https://github.com/tailwindlabs/tailwindcss/pull/9294)) ## [3.1.8] - 2022-08-05