Repository navigation
fix(compat/values): treat sparse array holes as undefined for compatibility - #1894
Merged
Merged
Conversation
…bility
`values` returned `Object.values(object)`, and the built-in skips array holes.
Lodash's `values` is `baseValues(object, keys(object))`, so it materializes
every index:
const array = [10, , 30];
lodash.values(array) // [10, undefined, 30]
compat.values(array) // [10, 30]
compat's own `keys` already models this correctly -- `arrayLikeKeys` builds
`times(object.length, ...)` and returns every index for an array -- so `values`
was the only side left on the built-in, and `keys(a).length === values(a).length`
did not hold for a sparse array. `zipObject(keys(o), values(o))` silently paired
the wrong values with the wrong keys.
Read through `keys` instead.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
gwennlbh
pushed a commit
to cigaleapp/cigale
that referenced
this pull request
Aug 3, 2026
##### [v1.50.0](https://github.com/toss/es-toolkit/blob/HEAD/CHANGELOG.md#Version-v1500) Released on July 24th, 2026. - Added the `es-toolkit/types` entrypoint: a declaration-only module of compile-time type utilities TypeScript lacks natively — `ValueOf`, `Simplify`, `Writable`, `NonEmptyArray`, `DeepPartial`, and `DeepReadonly`. (\[[#1818](toss/es-toolkit#1818)]) - Added `flow` to `es-toolkit/fp`, a reusable data-last composition built on `pipe`. (\[[#1812](toss/es-toolkit#1812)]) The following bring `es-toolkit/compat` closer to Lodash. Behavior for the affected edge cases now matches Lodash, so results may differ if you relied on the previous output. - Fixed `compat/intersectionBy` to dedupe a single array (including by the iteratee) and to keep results consistent with Lodash. (\[[#1935](toss/es-toolkit#1935)]) - Fixed `compat/findIndex` and `compat/findLastIndex` to coerce a `NaN` `fromIndex` to `0` and to convert `fromIndex` to an integer. (\[[#1828](toss/es-toolkit#1828)], \[[#1834](toss/es-toolkit#1834)], \[[#1938](toss/es-toolkit#1938)]) - Fixed `compat/lastIndexOf` to coerce `fromIndex` like Lodash. (\[[#1832](toss/es-toolkit#1832)]) - Fixed `compat/every` to treat a falsy, non-nullish `doesMatch` as a `_.property` shorthand instead of identity. (\[[#1940](toss/es-toolkit#1940)]) - Fixed `compat/nth` to support string inputs. (\[[#1833](toss/es-toolkit#1833)]) - Fixed `compat/inRange` to not throw on a lone negative bound. (\[[#1835](toss/es-toolkit#1835)]) - Fixed `compat/toArray` to convert `Set`s to arrays like Lodash. (\[[#1840](toss/es-toolkit#1840)]) - Fixed `compat/values` to treat sparse array holes as `undefined`. (\[[#1894](toss/es-toolkit#1894)]) - Fixed `compat/maxBy` and `compat/minBy` to restore Lodash-compatible comparison. (\[[#1893](toss/es-toolkit#1893)]) - Fixed `compat/includes` to exclude the `length` property when matching array-like values. (\[[#1886](toss/es-toolkit#1886)]) - Fixed the case functions to split ordinal numbers like Lodash, and to count string size and padding by code points for multi-byte characters. (\[[#1836](toss/es-toolkit#1836)], \[[#1852](toss/es-toolkit#1852)], \[[#1853](toss/es-toolkit#1853)]) - Fixed `compat/unset` to not treat an own literal dotted key as a deep path. (\[[#1808](toss/es-toolkit#1808)]) - Moved `compat/flattenDepth`'s flattening logic out of `flatten`. (\[[#1847](toss/es-toolkit#1847)]) - Restored the standalone `eq` and `templateSettings` entry points. (\[[#1895](toss/es-toolkit#1895)]) - Fixed `deburr` to remove all combining diacritical marks, matching Lodash. (\[[#1807](toss/es-toolkit#1807)]) - Fixed `partition` to accept any predicate return value, like `Array.prototype.filter`. (\[[#1937](toss/es-toolkit#1937)]) - Fixed `has` and `hasIn` to prioritize nullish literal keys over paths. (\[[#1810](toss/es-toolkit#1810)]) - Fixed `invokeMap` to normalize a string path via `toPath` for `this` binding. (\[[#1814](toss/es-toolkit#1814)]) - Fixed `isDeepKey` to detect deep keys with stricter patterns. (\[[#1621](toss/es-toolkit#1621)]) - Fixed `unzipWith` to return an empty array instead of throwing on empty input. (\[[#1816](toss/es-toolkit#1816)]) - Improved documentation, JSDoc accuracy, and internal refactoring across `compat` and `fp`. (\[[#1817](toss/es-toolkit#1817)], \[[#1820](toss/es-toolkit#1820)], \[[#1822](toss/es-toolkit#1822)], \[[#1823](toss/es-toolkit#1823)], \[[#1825](toss/es-toolkit#1825)], \[[#1829](toss/es-toolkit#1829)], \[[#1830](toss/es-toolkit#1830)], \[[#1842](toss/es-toolkit#1842)], \[[#1845](toss/es-toolkit#1845)], \[[#1851](toss/es-toolkit#1851)], \[[#1858](toss/es-toolkit#1858)], \[[#1867](toss/es-toolkit#1867)], \[[#1879](toss/es-toolkit#1879)]) We sincerely thank [@Antoliny0919](https://github.com/Antoliny0919), [@raon0211](https://github.com/raon0211), [@dayongkr](https://github.com/dayongkr), [@spokodev](https://github.com/spokodev), [@sarathfrancis90](https://github.com/sarathfrancis90), [@mayur-shenoy](https://github.com/mayur-shenoy), [@mahirhir](https://github.com/mahirhir), [@kojesung](https://github.com/kojesung), [@Hprogram](https://github.com/Hprogram), [@BangDori](https://github.com/BangDori), and everyone else who contributed. We appreciate your great efforts! Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
compat/valuesdisagrees with lodash on sparse arrays.valuesreturnsObject.values(object), and the built-in skips holes; lodash'svaluesisbaseValues(object, keys(object)), which materializes every index.This is the same class of fix as #1773 (
compat/difference), applied tovalues.Reproduce
It also breaks an invariant inside compat, without needing lodash as a reference —
keysandvaluesdisagree about the same object:So
zipObject(keys(o), values(o))pairs key'1'with30and key'2'withundefined.Changes
valuesnow reads throughkeysinstead ofObject.values.keys/arrayLikeKeysalready buildstimes(object.length, ...)and returns every index for an array, so this makesvaluesuse the same iteration model rather than adding a second one.forloop and adds no dependencies.values.spec.ts, mirroring the one from fix(compat/difference): treat sparse array holes as undefined for compability #1773. It asserts both the lodash-matching value and thekeys().length === values().lengthinvariant.Behavior for dense arrays, plain objects, array-likes (
{0:'a',1:'b',length:2}→['a','b',2], thelengthleaking in exactly as lodash does), strings, andargumentsobjects is unchanged — the existing tests cover all of those and still pass.Test results
Baseline on
mainis 4424 passed | 2 skipped; the extra passing test is the new one.yarn tsc --noEmitis clean. I didn't runyarn lint --fix:yarn lintreports the same 2477 problems (8 errors, 2469 warnings) on untouchedmainas it does with this change, so none of them are from this PR.Disclosure: I found this with the help of an AI coding assistant, by differential-testing
compatagainst lodash 4.18.1. The repros and test runs above are ones I ran myself against this branch.