diff --git a/src/index.ts b/src/index.ts index c87c955..dd7af6f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -58,6 +58,12 @@ const domainValueRegExp = */ const pathValueRegExp = /^[\u0020-\u003A\u003D-\u007E]*$/; +const __toString = Object.prototype.toString; +const __hasOwnProperty = Object.prototype.hasOwnProperty; + +const NullObject = function () {}; +NullObject.prototype = Object.create(null); + /** * Parse options. */ @@ -86,7 +92,7 @@ export function parse( str: string, options?: ParseOptions, ): Record { - const obj: Record = {}; + const obj: Record = new NullObject(); const len = str.length; // RFC 6265 sec 4.1.1, RFC 2616 2.2 defines a cookie name consists of one char minimum, plus '='. if (len < 2) return obj; @@ -112,7 +118,7 @@ export function parse( const key = str.slice(keyStartIdx, keyEndIdx); // only assign once - if (!obj.hasOwnProperty(key)) { + if (!__hasOwnProperty.call(obj, key)) { let valStartIdx = startIndex(str, eqIdx + 1, endIdx); let valEndIdx = endIndex(str, endIdx, valStartIdx); @@ -296,7 +302,10 @@ export function serialize( } if (options.expires) { - if (!Number.isFinite(options.expires.valueOf())) { + if ( + !isDate(options.expires) || + !Number.isFinite(options.expires.valueOf()) + ) { throw new TypeError("option expires is invalid"); } @@ -358,6 +367,13 @@ function decode(str: string): string { return str.indexOf("%") !== -1 ? decodeURIComponent(str) : str; } +/** + * Determine if value is a Date. + */ +function isDate(val: any): val is Date { + return __toString.call(val) === "[object Date]"; +} + /** * Try decoding a string using a decoding function. */