Skip to content

Fix TypeError in _.max/_.min on nullish collection with numeric iteratee#3018

Open
dkempner wants to merge 1 commit into
jashkenas:masterfrom
dkempner:fix-max-min-null-numeric-iteratee
Open

Fix TypeError in _.max/_.min on nullish collection with numeric iteratee#3018
dkempner wants to merge 1 commit into
jashkenas:masterfrom
dkempner:fix-max-min-null-numeric-iteratee

Conversation

@dkempner

Copy link
Copy Markdown

_.max(null) and _.max(null, _.identity) both return -Infinity, but _.max(null, 0) throws:

_.max(null, 0);
// TypeError: Cannot read properties of null (reading '0')

The fast-path guard in max/min reads typeof obj[0] != 'object' before the obj != null check, so a nullish collection combined with a numeric iteratee dereferences null before the null check can short-circuit. This PR reorders the conditions so the null check comes first; _.max(null, 0) and _.min(null, 0) now fall through to the iteratee branch and return -Infinity/Infinity, consistent with every other nullish-collection case.

No behavior change for non-nullish collections — the numeric fast path and the falsy-iteratee lookup cases (_.max([[1], [2, 3]], 0)) are unaffected, and regression tests for both functions are included. Full test suite passes (208/208).

🤖 Generated with Claude Code

The fast-path guard accessed obj[0] before checking obj != null, so
_.max(null, 0) threw a TypeError instead of returning -Infinity like
_.max(null) and _.max(null, _.identity) do. Reorder the conditions so
the null check comes first.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@jgonggrijp

Copy link
Copy Markdown
Collaborator

Thanks for disclosing that you used a genAI tool, I highly appreciate that.

The proposed change looks sane and correct to me, in fact it is currently a mystery to me why the conditions are in the wrong order. I will be diving in the commit history to figure that out.

In the meanwhile, could you tell me a bit more about how you ran into this issue? What does the line in your own code look like, where this exception was being triggered by min or max?

@dkempner

Copy link
Copy Markdown
Author

Thanks for disclosing that you used a genAI tool, I highly appreciate that.

The proposed change looks sane and correct to me, in fact it is currently a mystery to me why the conditions are in the wrong order. I will be diving in the commit history to figure that out.

In the meanwhile, could you tell me a bit more about how you ran into this issue? What does the line in your own code look like, where this exception was being triggered by min or max?

No production code to share. I was just using underscore as a way to test Fable's code spelunking capability.

Feel free to close if you think this isn't worth the merge.

@jgonggrijp

Copy link
Copy Markdown
Collaborator

I will not close it (at least not yet), but I will take more time to review this critically.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants