Repository: mui/material-ui (TypeScript)
Date: 2019-11-07 06:20:15+00:00
Task type: Bug Fix

Issue:
createMuiTheme modifies previously created theme 
- [x] The issue is present in the latest release.
- [x] I have searched the [issues](https://github.com/mui-org/material-ui/issues) of this repository and believe that this is not a duplicate.

## Current Behavior 😯

When creating multiple themes in succession, previously created themes get modified.
```js
const themeOptionsA = { palette: { background: { paper: "A" } } };
const themeOptionsB = { palette: { background: { paper: "B" } } };
const themeA = createMuiTheme(themeOptionsA); 
// themeA has paper "A"
const themeB = createMuiTheme(themeOptionsB);
// themeA has paper "B" all of a sudden
```

## Expected Behavior 🤔

Don't modify previously created themes.

## Steps to Reproduce 🕹

Created a sandbox which makes this quite obvious: https://codesandbox.io/s/jovial-margulis-zfnxc



Issue discussion:
I assume this is due to: https://github.com/mui-org/material-ui/blob/4d260e8ce7cd4889146ffb22535881cc3718d80e/packages/material-ui/src/styles/createPalette.js#L200

Since clone is set to false, the theme defaults will be modified as the passed in target by the new custom deepmerge implementation, and also the created theme palette object is referencing the properties within the default values from `createPalette` (which get modified on each theme creation). Maybe just setting clone to true might fix it?

Solution patch:
diff --git a/packages/material-ui/src/styles/createPalette.js b/packages/material-ui/src/styles/createPalette.js
--- a/packages/material-ui/src/styles/createPalette.js
+++ b/packages/material-ui/src/styles/createPalette.js
@@ -1,10 +1,10 @@
 import { deepmerge } from '@material-ui/utils';
+import common from '../colors/common';
+import grey from '../colors/grey';
 import indigo from '../colors/indigo';
 import pink from '../colors/pink';
-import grey from '../colors/grey';
 import red from '../colors/red';
-import common from '../colors/common';
-import { getContrastRatio, darken, lighten } from './colorManipulator';
+import { darken, getContrastRatio, lighten } from './colorManipulator';
 
 export const light = {
   // The colors used to style the text.
@@ -196,9 +196,6 @@ export default function createPalette(palette) {
       ...types[type],
     },
     other,
-    {
-      clone: false, // No need to clone deep
-    },
   );
 
   return paletteOutput;


Test patch:
diff --git a/packages/material-ui/src/styles/createPalette.test.js b/packages/material-ui/src/styles/createPalette.test.js
--- a/packages/material-ui/src/styles/createPalette.test.js
+++ b/packages/material-ui/src/styles/createPalette.test.js
@@ -1,7 +1,7 @@
 import { assert } from 'chai';
 import consoleErrorMock from 'test/utils/consoleErrorMock';
-import { indigo, pink, deepOrange, green, red } from '../colors';
-import { lighten, darken } from './colorManipulator';
+import { deepOrange, green, indigo, pink, red } from '../colors';
+import { darken, lighten } from './colorManipulator';
 import createPalette, { dark, light } from './createPalette';
 
 describe('createPalette()', () => {
@@ -432,4 +432,11 @@ describe('createPalette()', () => {
       );
     });
   });
+
+  it('should create a palette with unique object references', () => {
+    const redPalette = createPalette({ background: { paper: 'red' } });
+    const bluePalette = createPalette({ background: { paper: 'blue' } });
+    assert.notStrictEqual(redPalette, bluePalette);
+    assert.notStrictEqual(redPalette.background, bluePalette.background);
+  });
 });