Skip to content

Commit f4796d5

Browse files
mscdexitaloacasas
authored andcommitted
querystring: improve stringify() performance
PR-URL: #10852 Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Claudio Rodriguez <[email protected]>
1 parent 53421b1 commit f4796d5

File tree

2 files changed

+32
-21
lines changed

2 files changed

+32
-21
lines changed

lib/querystring.js

+28-21
Original file line numberDiff line numberDiff line change
@@ -100,12 +100,29 @@ function qsUnescape(s, decodeSpaces) {
100100
}
101101

102102

103-
var hexTable = new Array(256);
103+
const hexTable = [];
104104
for (var i = 0; i < 256; ++i)
105105
hexTable[i] = '%' + ((i < 16 ? '0' : '') + i.toString(16)).toUpperCase();
106+
107+
// These characters do not need escaping when generating query strings:
108+
// ! - . _ ~
109+
// ' ( ) *
110+
// digits
111+
// alpha (uppercase)
112+
// alpha (lowercase)
113+
const noEscape = [
114+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0 - 15
115+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16 - 31
116+
0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, // 32 - 47
117+
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, // 48 - 63
118+
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 64 - 79
119+
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, // 80 - 95
120+
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 96 - 111
121+
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0 // 112 - 127
122+
];
123+
// QueryString.escape() replaces encodeURIComponent()
124+
// http://www.ecma-international.org/ecma-262/5.1/#sec-15.1.3.4
106125
function qsEscape(str) {
107-
// replaces encodeURIComponent
108-
// http://www.ecma-international.org/ecma-262/5.1/#sec-15.1.3.4
109126
if (typeof str !== 'string') {
110127
if (typeof str === 'object')
111128
str = String(str);
@@ -118,30 +135,20 @@ function qsEscape(str) {
118135
for (var i = 0; i < str.length; ++i) {
119136
var c = str.charCodeAt(i);
120137

121-
// These characters do not need escaping (in order):
122-
// ! - . _ ~
123-
// ' ( ) *
124-
// digits
125-
// alpha (uppercase)
126-
// alpha (lowercase)
127-
if (c === 0x21 || c === 0x2D || c === 0x2E || c === 0x5F || c === 0x7E ||
128-
(c >= 0x27 && c <= 0x2A) ||
129-
(c >= 0x30 && c <= 0x39) ||
130-
(c >= 0x41 && c <= 0x5A) ||
131-
(c >= 0x61 && c <= 0x7A)) {
132-
continue;
133-
}
134-
135-
if (i - lastPos > 0)
136-
out += str.slice(lastPos, i);
137-
138-
// Other ASCII characters
138+
// ASCII
139139
if (c < 0x80) {
140+
if (noEscape[c] === 1)
141+
continue;
142+
if (lastPos < i)
143+
out += str.slice(lastPos, i);
140144
lastPos = i + 1;
141145
out += hexTable[c];
142146
continue;
143147
}
144148

149+
if (lastPos < i)
150+
out += str.slice(lastPos, i);
151+
145152
// Multi-byte characters ...
146153
if (c < 0x800) {
147154
lastPos = i + 1;

test/parallel/test-querystring.js

+4
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,10 @@ const qsNoMungeTestCases = [
9595
['foo=bar&foo=baz', {'foo': ['bar', 'baz']}],
9696
['foo=bar&foo=baz', foreignObject],
9797
['blah=burp', {'blah': 'burp'}],
98+
['a=!-._~\'()*', {'a': '!-._~\'()*'}],
99+
['a=abcdefghijklmnopqrstuvwxyz', {'a': 'abcdefghijklmnopqrstuvwxyz'}],
100+
['a=ABCDEFGHIJKLMNOPQRSTUVWXYZ', {'a': 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'}],
101+
['a=0123456789', {'a': '0123456789'}],
98102
['gragh=1&gragh=3&goo=2', {'gragh': ['1', '3'], 'goo': '2'}],
99103
['frappucino=muffin&goat%5B%5D=scone&pond=moose',
100104
{'frappucino': 'muffin', 'goat[]': 'scone', 'pond': 'moose'}],

0 commit comments

Comments
 (0)