{"ScriptPreparationCode":"var data = { items: {}, count: 0, keys: [] }\r\n\r\nfor (let index = 0; index \u003C 100; index\u002B\u002B) {\r\n data[index] = { id: index, name: \u0060ITEM-${index}\u0060, value: Math.random() }\r\n data.count\u002B\u002B\r\n data.keys.push(index)\r\n}\r\n\r\nvar NEW_ITEM_ID = data.count \u002B1\r\n\r\nconst isObject = (v) =\u003E v \u0026\u0026 typeof v === \u0027object\u0027;\r\nconst createNode = (key) =\u003E ({ key, next: null });\r\nconst shadowAssign = (obj, { key, next }) =\u003E {\r\n const targe = obj[key]\r\n if (isObject(targe)) {\r\n obj[key] = Array.isArray(targe) ? targe.slice() : Object.assign({}, targe);\r\n\r\n if (next) {\r\n for (const n of Object.values(next)) {\r\n shadowAssign(obj[key], n)\r\n }\r\n }\r\n }\r\n}\r\n\r\nvar produce2 = (baseState, reducer) =\u003E {\r\n let rootNode;\r\n const addModifyPath = (path = \u0027\u0027) =\u003E {\r\n rootNode = rootNode || createNode(\u0027\u0027);\r\n const keyArr = path.split(\u0027.\u0027);\r\n let curNode = rootNode;\r\n\r\n for (let i = 1; i \u003C keyArr.length; i\u002B\u002B) {\r\n const key = keyArr[i]\r\n const childMap = curNode.next = curNode.next || Object.create(null);\r\n const childNode = childMap[key] = childMap[key] || createNode(key);\r\n curNode = childNode;\r\n }\r\n }\r\n\r\n const _Metadata_ = new WeakMap();\r\n const proxyHandler = {\r\n deleteProperty: function (target, property) {\r\n addModifyPath(_Metadata_.get(target));\r\n return Reflect.deleteProperty(target, property);\r\n },\r\n get: function (target, property, receiver) {\r\n if (property === \u0027$\u0027) {\r\n return target;\r\n }\r\n if (!_Metadata_.has(target)) {\r\n _Metadata_.set(target, \u0027\u0027);\r\n }\r\n const result = Reflect.get(target, property, receiver);\r\n if (isObject(result)) {\r\n _Metadata_.set(result, _Metadata_.get(target) \u002B \u0027.\u0027 \u002B property);\r\n return deepProxy(result);\r\n }\r\n return result;\r\n },\r\n has: (target, property) =\u003E Reflect.has(target, property),\r\n ownKeys: (target) =\u003E Reflect.ownKeys(target),\r\n set: function (target, property, value, receiver) {\r\n addModifyPath(_Metadata_.get(target) \u002B \u0027.\u0027 \u002B property);\r\n return Reflect.set(target, property, value, receiver);\r\n },\r\n };\r\n\r\n const deepProxy = (obj) =\u003E new Proxy(obj, proxyHandler);\r\n const draft = deepProxy(baseState);\r\n\r\n reducer(draft);\r\n\r\n const result = { \u0027\u0027: baseState };\r\n if (rootNode) {\r\n shadowAssign(result, rootNode);\r\n }\r\n\r\n return result[\u0027\u0027];\r\n};\r\n\r\nvar produce = immer.default\r\nvar datai = { items: Immutable.Map(data.items), count: data.count, keys: Immutable.List(data.keys) }","TestCases":[{"Name":"immer","Code":"data = produce(data, draft =\u003E {\r\n draft.items[NEW_ITEM_ID] = { id: NEW_ITEM_ID, name: \u0027ITEM-NEW\u0027, value: 0 }\r\n draft.counter\u002B\u002B\r\n draft.keys.push(NEW_ITEM_ID)\r\n})","IsDeferred":false},{"Name":"shallow copy","Code":"data = {\r\n ...data,\r\n items: {\r\n \t...data.items,\r\n \t[NEW_ITEM_ID]: { id: NEW_ITEM_ID, name: \u0027ITEM-NEW\u0027, value: 0 }\r\n },\r\n count: data.count \u002B1,\r\n keys: [ ...data.keys, NEW_ITEM_ID]\r\n}","IsDeferred":false},{"Name":"immutable","Code":"data = {\r\n ...data,\r\n items: data.items.set(NEW_ITEM_ID, { id: NEW_ITEM_ID, name: \u0027ITEM-NEW\u0027, value: 0 }),\r\n count: data.count \u002B 1,\r\n keys: data.items.push(NEW_ITEM_ID)\r\n}","IsDeferred":false},{"Name":"my-immer","Code":"data = produce2(data, draft =\u003E {\r\n draft.items[NEW_ITEM_ID] = { id: NEW_ITEM_ID, name: \u0027ITEM-NEW\u0027, value: 0 }\r\n draft.counter\u002B\u002B\r\n draft.keys.push(NEW_ITEM_ID)\r\n})","IsDeferred":false}]}