1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
| const INTERNAL = Symbol('internal')
function createDraftstate(targetState) { if (Array.isArray(targetState) !== true && typeof targetState === 'object') { return Object.assign({}, targetState) } else if (Array.isArray(targetState)) { return [...targetState] } else { return targetState } }
function produce(targetState, producer) { let proxyState = toProxy(targetState) producer(proxyState); const internal = proxyState[INTERNAL]; return internal.changed ? internal.draftstate : internal.targetState }
function toProxy(targetState, backTracking = () => { }) { let internal = { targetState, keyToProxy: {}, changed: false, draftstate: createDraftstate(targetState), } console.log(">>> targetState is", targetState) return new Proxy(targetState, { get(_, key) { console.log('>>> getter key is', key) if (key === INTERNAL) { return internal } const val = targetState[key]; if (key in internal.keyToProxy) { return internal.keyToProxy[key] } else { console.log('>>> val is', val) internal.keyToProxy[key] = toProxy(val, () => { console.log(">>> trigger proxy", key) internal.changed = true; const proxyChild = internal.keyToProxy[key]; internal.draftstate[key] = proxyChild[INTERNAL].draftstate; backTracking() }) } return internal.keyToProxy[key] }, set(_, key, value) { console.log(">>> set", key, value, targetState) internal.changed = true; internal.draftstate[key] = value backTracking() return true } }) }
module.exports = { produce }
|