Skip to content

Commit cfefdd7

Browse files
committed
fix: compare Date timestamps instead of object references in cookie expires setter
1 parent f6fb731 commit cfefdd7

File tree

2 files changed

+49
-5
lines changed

2 files changed

+49
-5
lines changed

src/cookies.ts

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -158,10 +158,10 @@ export class Cookie<T> implements ElysiaCookie {
158158
set value(value: T) {
159159
// Check if value actually changed before creating entry in jar
160160
const current = this.cookie.value
161-
161+
162162
// Simple equality check
163163
if (current === value) return
164-
164+
165165
// For objects, do a deep equality check
166166
if (
167167
typeof current === 'object' &&
@@ -175,7 +175,7 @@ export class Cookie<T> implements ElysiaCookie {
175175
// If stringify fails, proceed with setting the value
176176
}
177177
}
178-
178+
179179
// Only create entry in jar if value actually changed
180180
if (!(this.name in this.jar)) this.jar[this.name] = { ...this.initial }
181181
this.jar[this.name].value = value
@@ -186,7 +186,11 @@ export class Cookie<T> implements ElysiaCookie {
186186
}
187187

188188
set expires(expires: Date | undefined) {
189-
if (this.cookie.expires === expires) return
189+
// Handle undefined values and compare timestamps instead of Date objects
190+
const currentExpires = this.cookie.expires
191+
if (currentExpires === undefined && expires === undefined) return
192+
if (currentExpires?.getTime() === expires?.getTime()) return
193+
190194
if (!(this.name in this.jar)) this.jar[this.name] = { ...this.initial }
191195
this.jar[this.name].expires = expires
192196
}
@@ -245,7 +249,9 @@ export class Cookie<T> implements ElysiaCookie {
245249
return this.cookie.sameSite
246250
}
247251

248-
set sameSite(sameSite: true | false | 'lax' | 'strict' | 'none' | undefined) {
252+
set sameSite(
253+
sameSite: true | false | 'lax' | 'strict' | 'none' | undefined
254+
) {
249255
if (this.cookie.sameSite === sameSite) return
250256
if (!(this.name in this.jar)) this.jar[this.name] = { ...this.initial }
251257
this.jar[this.name].sameSite = sameSite

test/validator/cookie.test.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -462,3 +462,41 @@ describe('Cookie Validation', () => {
462462
expect(await response.text()).toBe('empty')
463463
})
464464
})
465+
466+
it('expires setter compares timestamps not Date objects', async () => {
467+
const app = new Elysia().get('/', ({ cookie: { session }, set }) => {
468+
// Test 1: Setting expires with same timestamp should not update
469+
const date1 = new Date('2025-12-31T23:59:59.000Z')
470+
const date2 = new Date('2025-12-31T23:59:59.000Z')
471+
472+
session.value = 'test'
473+
session.expires = date1
474+
475+
// Get reference to jar before setting with same timestamp
476+
const jarBefore = set.cookie
477+
session.expires = date2 // Same timestamp, should not update
478+
const jarAfter = set.cookie
479+
480+
// Verify jar wasn't recreated (same reference)
481+
expect(jarBefore).toBe(jarAfter)
482+
expect(session.expires?.getTime()).toBe(date1.getTime())
483+
484+
// Test 2: Setting expires with different timestamp should update
485+
const date3 = new Date('2026-01-01T00:00:00.000Z')
486+
session.expires = date3
487+
expect(session.expires?.getTime()).toBe(date3.getTime())
488+
489+
// Test 3: Both undefined should not update
490+
session.expires = undefined
491+
const jarBeforeUndefined = set.cookie
492+
session.expires = undefined
493+
const jarAfterUndefined = set.cookie
494+
expect(jarBeforeUndefined).toBe(jarAfterUndefined)
495+
496+
return 'ok'
497+
})
498+
499+
const response = await app.handle(req('/'))
500+
expect(response.status).toBe(200)
501+
expect(await response.text()).toBe('ok')
502+
})

0 commit comments

Comments
 (0)