From d3bff5cdd93a4c2355305ccf1f4172ad07603ba6 Mon Sep 17 00:00:00 2001 From: Blake Embrey Date: Mon, 29 Jun 2026 15:52:37 -0700 Subject: [PATCH 1/4] Increment `=` index when parsing `set-cookie` --- src/index.ts | 25 +++++++++++++------------ src/parse-cookie.bench.ts | 5 +++++ src/parse-set-cookie.bench.ts | 5 +++++ 3 files changed, 23 insertions(+), 12 deletions(-) diff --git a/src/index.ts b/src/index.ts index 316dd09..a30133a 100644 --- a/src/index.ts +++ b/src/index.ts @@ -120,7 +120,7 @@ export function parseCookie(str: string, options?: ParseOptions): Cookies { do { const eqIdx = eqIndex(str, index, len); - if (eqIdx === -1) break; // No more cookie pairs. + if (eqIdx === len) break; // No more cookie pairs. const endIdx = endIndex(str, index, len); @@ -398,9 +398,9 @@ export function parseSetCookie(str: string, options?: ParseOptions): SetCookie { const dec = options?.decode || decode; const len = str.length; const endIdx = endIndex(str, 0, len); - const eqIdx = eqIndex(str, 0, endIdx); + let eqIdx = eqIndex(str, 0, len); const setCookie: SetCookie = - eqIdx === -1 + eqIdx >= endIdx ? { name: "", value: dec(valueSlice(str, 0, endIdx)) } : { name: valueSlice(str, 0, eqIdx), @@ -410,12 +410,13 @@ export function parseSetCookie(str: string, options?: ParseOptions): SetCookie { let index = endIdx + 1; while (index < len) { const endIdx = endIndex(str, index, len); - const eqIdx = eqIndex(str, index, endIdx); + if (eqIdx < index) eqIdx = eqIndex(str, index, len); + const attr = - eqIdx === -1 - ? valueSlice(str, index, endIdx) - : valueSlice(str, index, eqIdx); - const val = eqIdx === -1 ? undefined : valueSlice(str, eqIdx + 1, endIdx); + eqIdx < endIdx + ? valueSlice(str, index, eqIdx) + : valueSlice(str, index, endIdx); + const val = eqIdx < endIdx ? valueSlice(str, eqIdx + 1, endIdx) : undefined; switch (attr.toLowerCase()) { case "httponly": @@ -472,7 +473,7 @@ export function parseSetCookie(str: string, options?: ParseOptions): SetCookie { } /** - * Find the `;` character between `min` and `len` in str. + * Find the next `;` character, or return `len`. */ function endIndex(str: string, min: number, len: number) { const index = str.indexOf(";", min); @@ -480,11 +481,11 @@ function endIndex(str: string, min: number, len: number) { } /** - * Find the `=` character between `min` and `max` in str. + * Find the next `=` character, or return `len`. */ -function eqIndex(str: string, min: number, max: number) { +function eqIndex(str: string, min: number, len: number) { const index = str.indexOf("=", min); - return index < max ? index : -1; + return index === -1 ? len : index; } /** diff --git a/src/parse-cookie.bench.ts b/src/parse-cookie.bench.ts index 738b7a6..b31c587 100644 --- a/src/parse-cookie.bench.ts +++ b/src/parse-cookie.bench.ts @@ -33,6 +33,11 @@ describe("cookie.parseCookie", () => { bench("100 cookies", () => { cookie.parseCookie(cookies100); }); + + const semicolons = ";".repeat(100_000); + bench("100k semicolons", () => { + cookie.parseCookie(semicolons); + }); }); describe("parse top-sites", () => { diff --git a/src/parse-set-cookie.bench.ts b/src/parse-set-cookie.bench.ts index 51a6ee9..637d959 100644 --- a/src/parse-set-cookie.bench.ts +++ b/src/parse-set-cookie.bench.ts @@ -10,4 +10,9 @@ describe("parse top-sites", () => { } }); }); + + const semicolons = "a;".repeat(100_000); + bench("100k semicolons", () => { + cookie.parseSetCookie(semicolons); + }); }); From 231735ee0e3920f14f1e59a619da971d8aed8452 Mon Sep 17 00:00:00 2001 From: Blake Embrey Date: Mon, 29 Jun 2026 15:58:06 -0700 Subject: [PATCH 2/4] Shave 4 bytes --- package.json | 2 +- src/index.ts | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index ee81553..9d935bc 100644 --- a/package.json +++ b/package.json @@ -48,7 +48,7 @@ "size-limit": [ { "path": "dist/index.js", - "limit": "1.4 KB" + "limit": "1.2 KB" } ], "ts-scripts": { diff --git a/src/index.ts b/src/index.ts index a30133a..23fe8ea 100644 --- a/src/index.ts +++ b/src/index.ts @@ -400,12 +400,12 @@ export function parseSetCookie(str: string, options?: ParseOptions): SetCookie { const endIdx = endIndex(str, 0, len); let eqIdx = eqIndex(str, 0, len); const setCookie: SetCookie = - eqIdx >= endIdx - ? { name: "", value: dec(valueSlice(str, 0, endIdx)) } - : { + eqIdx < endIdx + ? { name: valueSlice(str, 0, eqIdx), value: dec(valueSlice(str, eqIdx + 1, endIdx)), - }; + } + : { name: "", value: dec(valueSlice(str, 0, endIdx)) }; let index = endIdx + 1; while (index < len) { From f77fde38453a1ad8ebc452e024e10bd3a715b2ed Mon Sep 17 00:00:00 2001 From: Blake Embrey Date: Mon, 29 Jun 2026 15:59:38 -0700 Subject: [PATCH 3/4] Undo package limit --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 9d935bc..ee81553 100644 --- a/package.json +++ b/package.json @@ -48,7 +48,7 @@ "size-limit": [ { "path": "dist/index.js", - "limit": "1.2 KB" + "limit": "1.4 KB" } ], "ts-scripts": { From 571a3031aeaa2f45aa90d56dda2f75bad12d8133 Mon Sep 17 00:00:00 2001 From: Blake Embrey Date: Mon, 29 Jun 2026 16:18:59 -0700 Subject: [PATCH 4/4] Benchmark empty params --- src/parse-set-cookie.bench.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/parse-set-cookie.bench.ts b/src/parse-set-cookie.bench.ts index 637d959..8d0b595 100644 --- a/src/parse-set-cookie.bench.ts +++ b/src/parse-set-cookie.bench.ts @@ -11,7 +11,7 @@ describe("parse top-sites", () => { }); }); - const semicolons = "a;".repeat(100_000); + const semicolons = ";".repeat(100_000); bench("100k semicolons", () => { cookie.parseSetCookie(semicolons); });