Skip to content

Commit 47917c9

Browse files
authoredOct 2, 2024··
Iterate whitespace for perf (#170)
1 parent 927d48a commit 47917c9

File tree

2 files changed

+56
-16
lines changed

2 files changed

+56
-16
lines changed
 

‎index.js

+40-15
Original file line numberDiff line numberDiff line change
@@ -95,40 +95,49 @@ function parse(str, options) {
9595
throw new TypeError('argument str must be a string');
9696
}
9797

98-
var obj = {}
98+
var obj = {};
9999
var opt = options || {};
100100
var dec = opt.decode || decode;
101101

102-
var index = 0
103-
while (index < str.length) {
104-
var eqIdx = str.indexOf('=', index)
102+
var index = 0;
103+
var eqIdx = 0;
104+
var endIdx = 0;
105+
var len = str.length;
106+
var max = len - 2;
107+
108+
while (index < max) {
109+
eqIdx = str.indexOf('=', index);
105110

106111
// no more cookie pairs
107112
if (eqIdx === -1) {
108-
break
113+
break;
109114
}
110115

111-
var endIdx = str.indexOf(';', index)
116+
endIdx = str.indexOf(';', index);
112117

113118
if (endIdx === -1) {
114-
endIdx = str.length
115-
} else if (endIdx < eqIdx) {
119+
endIdx = len;
120+
} else if (eqIdx > endIdx) {
116121
// backtrack on prior semicolon
117-
index = str.lastIndexOf(';', eqIdx - 1) + 1
118-
continue
122+
index = str.lastIndexOf(';', eqIdx - 1) + 1;
123+
continue;
119124
}
120125

121-
var key = str.slice(index, eqIdx).trim()
126+
var keyStartIdx = startIndex(str, index, eqIdx);
127+
var keyEndIdx = endIndex(str, eqIdx, keyStartIdx);
128+
var key = str.slice(keyStartIdx, keyEndIdx);
122129

123130
// only assign once
124131
if (undefined === obj[key]) {
125-
var val = str.slice(eqIdx + 1, endIdx).trim()
132+
var valStartIdx = startIndex(str, eqIdx + 1, endIdx);
133+
var valEndIdx = endIndex(str, endIdx, valStartIdx);
126134

127-
// quoted values
128-
if (val.charCodeAt(0) === 0x22) {
129-
val = val.slice(1, -1)
135+
if (str.charCodeAt(valStartIdx) === 0x22 /* " */ && str.charCodeAt(valEndIdx - 1) === 0x22 /* " */) {
136+
valStartIdx++;
137+
valEndIdx--;
130138
}
131139

140+
var val = str.slice(valStartIdx, valEndIdx);
132141
obj[key] = tryDecode(val, dec);
133142
}
134143

@@ -138,6 +147,22 @@ function parse(str, options) {
138147
return obj;
139148
}
140149

150+
function startIndex(str, index, max) {
151+
do {
152+
var code = str.charCodeAt(index);
153+
if (code !== 0x20 /* */ && code !== 0x09 /* \t */) return index;
154+
} while (++index < max);
155+
return max;
156+
}
157+
158+
function endIndex(str, index, min) {
159+
while (index > min) {
160+
var code = str.charCodeAt(--index);
161+
if (code !== 0x20 /* */ && code !== 0x09 /* \t */) return index + 1;
162+
}
163+
return min;
164+
}
165+
141166
/**
142167
* Serialize data into a cookie header.
143168
*

‎test/parse.js

+16-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ describe('cookie.parse(str)', function () {
2424
})
2525

2626
it('should parse cookie with empty value', function () {
27-
assert.deepEqual(cookie.parse('foo= ; bar='), { foo: '', bar: '' })
27+
assert.deepEqual(cookie.parse('foo=; bar='), { foo: '', bar: '' })
2828
})
2929

3030
it('should URL-decode values', function () {
@@ -34,6 +34,21 @@ describe('cookie.parse(str)', function () {
3434
assert.deepEqual(cookie.parse('email=%20%22%2c%3b%2f'), { email: ' ",;/' })
3535
})
3636

37+
it('should parse quoted values', function () {
38+
assert.deepEqual(cookie.parse('foo="bar"'), { foo: 'bar' })
39+
assert.deepEqual(cookie.parse('foo=" a b c "'), { foo: ' a b c ' })
40+
})
41+
42+
it('should trim whitespace around key and value', function () {
43+
assert.deepEqual(cookie.parse(' foo = "bar" '), { foo: 'bar' })
44+
assert.deepEqual(cookie.parse(' foo = bar ; fizz = buzz '), { foo: 'bar', fizz: 'buzz' })
45+
assert.deepEqual(cookie.parse(' foo = " a b c " '), { foo: ' a b c ' })
46+
assert.deepEqual(cookie.parse(' = bar '), { '': 'bar' })
47+
assert.deepEqual(cookie.parse(' foo = '), { foo: '' })
48+
assert.deepEqual(cookie.parse(' = '), { '': '' })
49+
assert.deepEqual(cookie.parse('\tfoo\t=\tbar\t'), { foo: 'bar' })
50+
})
51+
3752
it('should return original value on escape error', function () {
3853
assert.deepEqual(cookie.parse('foo=%1;bar=bar'), { foo: '%1', bar: 'bar' })
3954
})

0 commit comments

Comments
 (0)
Please sign in to comment.