Repository: immerjs/immer (js)

Issue:
Error when working with immutable arrays with modified slice() method (`seamless-immutable`)
## 🐛 Bug Report

First of all, thanks for the great tool! I'm working on a large project that has previously used [seamless-immutable](https://github.com/rtfeldman/seamless-immutable) for managing the Redux state. I would like to use `immer` for new code but it seems that `immer` fails when it tries to shallow-copy an array with an overridden `slice()`. The overridden `slice()` produces a new readonly array which is not what `immer` expects.

I would suggest a harmless fix: use `Array.prototype.slice(base)` or `[...base]` instead of `base.slice()` in the `shallowCopy()` method. I think many would benefit from this kind of compatibility. Will be happy to make a PR.

## Link to repro

https://codesandbox.io/s/immer-sandbox-j7ke0

## To Reproduce

Steps to reproduce the behavior: see the error in the sandbox when used in combination with `seamless-immutable`.

## Observed behavior

An error: `"Cannot assign to read only property '0' of object '[object Array]'"`

## Expected behavior

Producing a result as designed.

## Environment

We only accept bug reports against the latest Immer version.

- **Immer version:**
- [x] I filed this report against the _latest_ version of Immer
- [x] Occurs with `setUseProxies(true)`
- [x] Occurs with `setUseProxies(false)` (ES5 only)


Pull request description:
fix: use Array.prototype.slice() for copying arrays. Fixes #650
This small PR addresses an error that occurs when working with immer and seamless-immutable in one project. See #650.

Patch:
diff --git a/src/utils/common.ts b/src/utils/common.ts
index ab3d262..6798074 100644
--- a/src/utils/common.ts
+++ b/src/utils/common.ts
@@ -154,7 +154,7 @@ export function latest(state: ImmerState): any {
 
 /*#__PURE__*/
 export function shallowCopy(base: any) {
-	if (Array.isArray(base)) return base.slice()
+	if (Array.isArray(base)) return Array.prototype.slice.call(base)
 	const descriptors = getOwnPropertyDescriptors(base)
 	delete descriptors[DRAFT_STATE as any]
 	let keys = ownKeys(descriptors)


Test patch:
diff --git a/__tests__/regressions.js b/__tests__/regressions.js
index a8e65c7..9ae9138 100644
--- a/__tests__/regressions.js
+++ b/__tests__/regressions.js
@@ -140,5 +140,23 @@ function runBaseTest(name, useProxies, autoFreeze, useListener) {
 			})
 			expect(result).toEqual(new Set())
 		})
+
+		test("#650 - changes with overridden arr.slice() fail", () => {
+			const data = {
+				foo: [
+					{
+						isActive: false
+					}
+				]
+			}
+			// That's roughly what seamless-immutable does
+			data.foo.slice = (...args) =>
+				Object.freeze(Array.prototype.slice.call(data.foo, ...args))
+
+			const newData = produce(data, draft => {
+				draft.foo[0].isActive = true
+			})
+			expect(newData.foo[0].isActive).toBe(true)
+		})
 	})
 }