fix(formDataToJSON): only split keys on bracket and dot notation#11006
Conversation
parsePropPath tokenized field names with /\w+|\[(\w*)]/g, which silently
dropped any non-word separator. A key like `user-name` was split into
`{user:{name}}` instead of staying a literal key; the same happened for
spaces, `+`, `*` and `&`. Match each segment as any run of characters
except `.`, `[` and `]` so only bracket and dot notation split.
Address review feedback on the property-path tokenizer: - Exclude `[` and `.` from the bracket capture (`\[([^.[\]]*)]`) so the match fails fast at the next `[` instead of being able to rescan to the end of the string from every unmatched `[`. Parsing is now linear in the name length (the previous pattern was quadratic on long malformed bracket input). - Bracket contents now use the same character class as dot-notation segments (excluding `.`, `[` and `]`), so the grammar matches the documented comment. `.`, `[` and `]` keep their existing meaning, e.g. `foo[bar.baz]` still nests as `['foo','bar','baz']`; only previously-dropped separators stay literal. Add regression tests for a long malformed bracket name (linear-time parse) and for `.`/`[` appearing inside bracket groups.
…literal-keys # Conflicts: # PRE_RELEASE_CHANGELOG.md
|
Thanks for the review and the assign, @jasonsaayman — both points addressed. Linearity: the bracket group now excludes
(old ~4× per doubling = O(n²); new flat). Added a regression test that parses Grammar: bracket contents now use the same character class as dot-notation segments (excluding Also merged the latest |
…teral-keys # Conflicts: # PRE_RELEASE_DOCS.md
Closes #5402.
formDataToJSON/formToJSONsplit a field name likeuser-nameinto{ user: { name: ... } }instead of keeping the literal key. The same happened for spaces,+,*,&, etc.The cause is the tokenizer in
parsePropPath:It matches runs of word characters and bracket groups, silently dropping any non-word separator. So
user-namematchesuserandnameand the-is discarded, producing nested objects.Fix
Match each path segment as any run of characters except
.,[and]:Bracket notation (
foo[bar][baz],foo[],foo[0]) and dot notation (foo.bar) still split exactly as before — only previously-dropped separators (-, space,+,*,&) are now kept as literal key characters. The existing[]-empty handling and the depth guard are unchanged, and the prototype-pollution protection (which relies on dot-splitting of__proto__.x/constructor.prototype.y) is preserved.Tests
Added two cases to
tests/unit/helpers/formDataToJSON.test.js: one assertinguser-name,first name,a+bstay literal keys, and one asserting bracket/dot notation still nests (foo[bar-baz]→{ foo: { 'bar-baz': ... } }). Verified both fail on the old regex and pass with the fix; the fullformDataToJSONunit suite (13 tests) is green and ESLint is clean.🏄
Summary by cubic
Fixes
formDataToJSON/formToJSONso only dot and bracket notation split keys; hyphens, spaces, and symbols stay literal. Also makes path parsing linear and treats.and[inside brackets as separators. Closes #5402.Description
/[^.[\]]+|\[([^.[\]]*)]/g..and[]split keys;-, spaces,+,*,&, etc., stay literal..and[separate segments (e.g.,foo[bar.baz]→{ foo: { bar: { baz } } }).[for linear-time parsing on malformed input.Docs
/docs/to state that only.and[]split, with examples for literal keys (e.g.,user-name) and nested cases (user.name,user[name]).Testing
user-name,first name,a+b), dot/bracket nesting with literals, separators inside brackets, and linear-time parsing on long malformed input.Semantic version impact
Written for commit c3b3461. Summary will update on new commits.