From aa1b087e8baacd104e271f1db16a1bbcb3a644ea Mon Sep 17 00:00:00 2001 From: awais-ur-rehman Date: Sat, 31 Oct 2026 17:44:04 +0500 Subject: [PATCH] fix(parse): preserve empty parameter names --- index.js | 2 +- test.js | 28 ++++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/index.js b/index.js index 58c9808..193e7a3 100644 --- a/index.js +++ b/index.js @@ -41,7 +41,7 @@ function encode(input) { * @api public */ function querystring(query) { - var parser = /([^=?#&]+)=?([^&]*)/g + var parser = /([^=?#&]+|(?==))=?([^&]*)/g , result = {} , part; diff --git a/test.js b/test.js index f000b6c..ab88689 100644 --- a/test.js +++ b/test.js @@ -106,6 +106,34 @@ describe('querystringify', function () { assume(obj.shizzle).equals('mynizzle'); }); + it('round-trips an empty parameter name', function () { + var obj = { '': 'value with spaces', foo: 'bar' }; + + assume(qs.parse(qs.stringify(obj))).deep.equals(obj); + }); + + it('parses empty names before, between and after named parameters', function () { + ['=value&foo=bar', 'foo=bar&=value', 'foo=bar&=value&baz=qux'].forEach(function (query) { + assume(qs.parse(query)['']).equals('value'); + assume(qs.parse(query).foo).equals('bar'); + }); + }); + + it('handles prefixes and empty values for empty names', function () { + ['=', '?=', '#='].forEach(function (query) { + assume(qs.parse(query)).deep.equals({ '': '' }); + }); + }); + + it('keeps the first value for an empty name', function () { + assume(qs.parse('=first&=second')).deep.equals({ '': 'first' }); + }); + + it('ignores empty separators and invalid empty-name values', function () { + assume(qs.parse('?&&#')).deep.equals({}); + assume(qs.parse('=%&foo=bar')).deep.equals({ foo: 'bar' }); + }); + it('first value wins', function () { var obj = qs.parse('foo=1&foo=2');