Skip to content

Commit 88e98f5

Browse files
Fix issue with Tailwind modifying global state (#9294)
* 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. * Add failing test * Undo defaults change * wip * Fix shared mutation problem * Update changelog Co-authored-by: Jordan Pittman <jordan@cryptica.me>
1 parent db50bbb commit 88e98f5

File tree

3 files changed

+29
-1
lines changed

3 files changed

+29
-1
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2727
- Don't output duplicate utilities ([#9208](https://github.com/tailwindlabs/tailwindcss/pull/9208))
2828
- Fix `fontFamily` config TypeScript types ([#9214](https://github.com/tailwindlabs/tailwindcss/pull/9214))
2929
- Handle variants on complex selector utilities ([#9262](https://github.com/tailwindlabs/tailwindcss/pull/9262))
30+
- Don't mutate shared config objects ([#9294](https://github.com/tailwindlabs/tailwindcss/pull/9294))
3031

3132
## [3.1.8] - 2022-08-05
3233

src/util/resolveConfig.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ function mergeWith(target, ...sources) {
2929

3030
if (merged === undefined) {
3131
if (isObject(target[k]) && isObject(source[k])) {
32-
target[k] = mergeWith(target[k], source[k], customizer)
32+
target[k] = mergeWith({}, target[k], source[k], customizer)
3333
} else {
3434
target[k] = source[k]
3535
}

tests/resolveConfig.test.js

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1763,3 +1763,30 @@ test('all helpers can be destructured from the first function argument', () => {
17631763
},
17641764
})
17651765
})
1766+
1767+
test('does not duplicate extended configs every time resolveConfig is called', () => {
1768+
let shared = {
1769+
foo: { bar: { baz: [{ color: 'red' }] } },
1770+
}
1771+
1772+
const createConfig = (color) =>
1773+
resolveConfig([
1774+
{
1775+
theme: {
1776+
foo: shared.foo,
1777+
extend: {
1778+
foo: { bar: { baz: { color } } },
1779+
},
1780+
},
1781+
},
1782+
])
1783+
1784+
createConfig('orange')
1785+
createConfig('yellow')
1786+
createConfig('green')
1787+
1788+
const result = createConfig('blue')
1789+
1790+
expect(shared.foo.bar.baz).toMatchObject([{ color: 'red' }])
1791+
expect(result.theme.foo.bar.baz).toMatchObject([{ color: 'red' }, { color: 'blue' }])
1792+
})

0 commit comments

Comments
 (0)