[Fix] parse: throw on unbalanced bracket groups#560
Conversation
…bracket keys (#558) Pin the current (lenient) parse output for every malformed/unbalanced bracket-key shape, so any future change to that behavior (e.g. the proposed "throw on unbalanced brackets" in #560) is explicit in the test diff rather than silent. Each case asserts both that parsing does not throw and the exact output, via a small `characterizeParse` helper, so a change that introduces a throw fails cleanly per case instead of aborting the run. Covers the cases #560 would make throw (`a[bc`, `a[`, `a[b][c`, `a[b]c[d`, the issue reproduction, stray-close variants), the ones it would leave as literals (inner-bracket and bracket-prefixed keys), the depth- and allowDots-dependent shapes, and the unaffected stray-close/trailing-text keys.
2518024 to
4f2c349
Compare
|
I've added some tests to |
parse: throw on unbalanced bracket groups
4f2c349 to
8490add
Compare
|
Updated the branch after the new characterization tests were added on main.\n\nThe PR now keeps the new throwing behavior for unbalanced bracket groups after a parent key, including the #558 reproduction, while preserving the existing lenient behavior for bracket-prefixed keys, inner-bracket cases, and depth-limited literal remainders.\n\nVerification:\n- |
8490add to
8105b0c
Compare
|
The |
| } | ||
|
|
||
| if (close < 0) { | ||
| if (parent && key.indexOf('[', open + 1) < 0) { |
There was a problem hiding this comment.
If we're going to throw on unbalanced brackets, I think we should throw on all of them rather than this narrow subset. As written, the guard only fires when there's a parent and no later [, which leaves three inconsistent escape hatches:
- Depth-dependent.
a[b]c[d]e[f=vthrows atdepth: 5but silently falls through to the lenient literal path (below, ~line 312) atdepth: 1. Whether malformed input throws shouldn't depend on thedepthoption - Later-
[escape.key.indexOf('[', open + 1) < 0meansa[bc[=vstays lenient even though it's just as unbalanced - only a trailing unclosed bracket throws - Bracket-prefixed keys never throw (the
parent &&guard), so[a[b=vstays lenient too
So the effective rule is hard to describe: "unbalanced brackets throw, unless the key starts with [, or has another [ after the unclosed one, or the unclosed group is past the depth budget." If the intent is "malformed key → throw," I'd rather detect an unbalanced bracket count for the whole key up front and throw unconditionally, so the behavior is consistent regardless of parent, later brackets, or depth.
Yes, I am a human contributor and I substantially reviewed and contributed to this change. I used coding assistance while working on it, but I read the issue, reviewed the implementation and tests, made the final decisions, and take responsibility for the contribution. |
Closes #558.
This changes parser behavior for malformed nested keys that start a bracket group after a parent key but never close it. Instead of treating the rest of the key as a literal segment,
qs.parsenow throws aRangeError, which matches the maintainer direction in the issue discussion.Existing behavior is preserved for bracket-prefixed keys and for keys with unterminated inner bracket groups that are already handled as literal segments.
Verification:
npx tape test/parse.jsnpm run tests-onlynpm run lintnpm test