diff --git a/packages/immutadot/src/nav2/indexNav.js b/packages/immutadot/src/nav2/indexNav.js index 5066340a..178f1cee 100644 --- a/packages/immutadot/src/nav2/indexNav.js +++ b/packages/immutadot/src/nav2/indexNav.js @@ -31,16 +31,16 @@ const get = (pIndex, next) => () => { const unset = (pIndex, next) => () => { const nextUnsetter = next() if (nextUnsetter) { - return onCopy(newValue => { - const index = resolveIndex(pIndex, newValue) + return onCopy(value => { + const index = resolveIndex(pIndex, value) if (index === undefined) return // TODO avoid useless copy ? - newValue[index] = nextUnsetter(newValue[index]) + value[index] = nextUnsetter(value[index]) }) } - return onCopy(newValue => { - const index = resolveIndex(pIndex, newValue) + return onCopy(value => { + const index = resolveIndex(pIndex, value) if (index === undefined) return // TODO avoid useless copy ? - delete newValue[index] + delete value[index] }) } diff --git a/packages/immutadot/src/nav2/propNav.js b/packages/immutadot/src/nav2/propNav.js index 2675dece..4cb39ef0 100644 --- a/packages/immutadot/src/nav2/propNav.js +++ b/packages/immutadot/src/nav2/propNav.js @@ -17,16 +17,17 @@ const get = (key, next) => () => { } } -const unset = (key, next) => () => { +const unsetProp = (key, nextUnsetter) => () => onCopy(newValue => { + newValue[key] = nextUnsetter(newValue[key]) +}) + +const deleteProp = key => () => onCopy(newValue => { + delete newValue[key] +}) + +const unset = (key, next) => { const nextUnsetter = next() - if (nextUnsetter) { - return onCopy(newValue => { - newValue[key] = nextUnsetter(newValue[key]) - }) - } - return onCopy(newValue => { - delete newValue[key] - }) + return nextUnsetter ? unsetProp(key, nextUnsetter) : deleteProp(key) } export const propNav = makeNav({ diff --git a/packages/immutadot/src/nav2/propsNav.js b/packages/immutadot/src/nav2/propsNav.js index 0de5c8fe..122022a2 100644 --- a/packages/immutadot/src/nav2/propsNav.js +++ b/packages/immutadot/src/nav2/propsNav.js @@ -23,29 +23,27 @@ const get = (keys, next) => () => { return value => isNil(value) ? undefined : Object.keys(value).map(key => nextGetter(value[key])) } -const unset = (keys, next) => () => { +const unsetKeys = (keys, nextUnsetter) => () => onCopy(value => { + for (const key of keys) value[key] = nextUnsetter(value[key]) +}) + +const unsetAll = nextUnsetter => () => onCopy(value => { + for (const key of Object.keys(value)) value[key] = nextUnsetter(value[key]) +}) + +const deleteKeys = keys => () => onCopy(value => { + for (const key of keys) delete value[key] +}) + +const deleteAll = () => onCopy(value => { + for (const key of Object.keys(value)) delete value[key] +}) + +const unset = (keys, next) => { const nextUnsetter = next() - if (nextUnsetter) { - if (keys) { - return onCopy((newValue, value) => { - if (isNil(value)) - for (const key of keys) newValue[key] = nextUnsetter(undefined) - else - for (const key of keys) newValue[key] = nextUnsetter(value[key]) - }, true) - } - return onCopy((newValue, value) => { - for (const key of Object.keys(value)) newValue[key] = nextUnsetter(value[key]) - }) - } - if (keys) { - return onCopy(newValue => { - for (const key of keys) delete newValue[key] - }) - } - return onCopy((newValue, value) => { - for (const key of Object.keys(value)) delete newValue[key] - }) + if (nextUnsetter) + return keys ? unsetKeys(keys, nextUnsetter) : unsetAll(nextUnsetter) + return keys ? deleteKeys(keys) : deleteAll } export const propsNav = makeNav({ diff --git a/packages/immutadot/src/nav2/sliceNav.js b/packages/immutadot/src/nav2/sliceNav.js index 841e9dc9..0a0caee3 100644 --- a/packages/immutadot/src/nav2/sliceNav.js +++ b/packages/immutadot/src/nav2/sliceNav.js @@ -16,53 +16,94 @@ const resolveEnd = (pEnd, length, step) => { return resolveIndex(pEnd, length) } +const getRange = (pStart, pEnd, pStep, value) => { + const step = pStep === undefined ? 1 : pStep + const length = getLength(value) + const start = resolveStart(pStart, length, step) + const end = resolveEnd(pEnd, length, step) + if (step > 0) { + if (end <= start) return null + return { + [Symbol.iterator]: () => { + let i = start + return { + next: () => { + if (i < end) { + const res = { + value: i, + done: false, + } + i += step + return res + } + return { done: true } + }, + } + }, + } + } + if (end >= start) return null + return { + [Symbol.iterator]: () => { + let i = start + return { + next: () => { + if (i > end) { + const res = { + value: i, + done: false, + } + i += step + return res + } + return { done: true } + }, + } + }, + } +} + const update = ([pStart, pEnd, pStep], next) => updater => { const nextUpdater = next(updater) - const step = pStep === undefined ? 1 : pStep return onCopy((newValue, value) => { - const length = getLength(value) - const start = resolveStart(pStart, length, step) - const end = resolveEnd(pEnd, length, step) - if (step > 0) { - if (end <= start) return // TODO avoid useless copy - if (isNil(value)) - for (let i = start; i < end; i += step) newValue[i] = nextUpdater(undefined) - else - for (let i = start; i < end; i += step) newValue[i] = nextUpdater(value[i]) - } - if (end >= start) return // TODO avoid useless copy + const range = getRange(pStart, pEnd, pStep, value) + if (!range) return // TODO avoid useless copy if (isNil(value)) - for (let i = start; i > end; i += step) newValue[i] = nextUpdater(undefined) + for (const i of range) newValue[i] = nextUpdater(undefined) else - for (let i = start; i > end; i += step) newValue[i] = nextUpdater(value[i]) + for (const i of range) newValue[i] = nextUpdater(value[i]) }, true) } const get = ([pStart, pEnd, pStep], next) => () => { const nextGetter = next() - const step = pStep === undefined ? 1 : pStep return value => { - const length = getLength(value) - const start = resolveStart(pStart, length, step) - const end = resolveEnd(pEnd, length, step) if (isNil(value)) return [] - let range - if (step > 0) { - if (end <= start) return [] - range = (function* () { - for (let i = start; i < end; i += step) yield i - }()) - } else { - if (end >= start) return [] - range = (function* () { - for (let i = start; i > end; i += step) yield i - }()) - } + const range = getRange(pStart, pEnd, pStep, value) + if (!range) return [] return Array.from(range, i => nextGetter(value[i])) } } +const unsetSlice = (pStart, pEnd, pStep, nextUnsetter) => () => onCopy(value => { + const range = getRange(pStart, pEnd, pStep, value) + if (!range) return // TODO avoid useless copy + for (const i of range) value[i] = nextUnsetter(value[i]) +}) + +const deleteSlice = (pStart, pEnd, pStep) => () => onCopy(value => { + const range = getRange(pStart, pEnd, pStep, value) + if (!range) return // TODO avoid useless copy + for (const i of range) delete value[i] +}) + +const unset = ([pStart, pEnd, pStep], next) => { + const nextUnsetter = next() + return nextUnsetter ? unsetSlice(pStart, pEnd, pStep, nextUnsetter) : deleteSlice(pStart, pEnd, pStep) +} + export const sliceNav = makeNav({ update, get, + unset, })