Skip to content

Commit

Permalink
querystring: refactor to use more primordials
Browse files Browse the repository at this point in the history
PR-URL: nodejs#36315
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Rich Trott <rtrott@gmail.com>
  • Loading branch information
aduh95 authored and cjihrig committed Dec 8, 2020
1 parent 2eddea3 commit 8594b30
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 22 deletions.
20 changes: 13 additions & 7 deletions lib/internal/querystring.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,19 @@
const {
Array,
Int8Array,
NumberPrototypeToString,
StringPrototypeCharCodeAt,
StringPrototypeSlice,
StringPrototypeToUpperCase,
} = primordials;

const { ERR_INVALID_URI } = require('internal/errors').codes;

const hexTable = new Array(256);
for (let i = 0; i < 256; ++i)
hexTable[i] = '%' + ((i < 16 ? '0' : '') + i.toString(16)).toUpperCase();
hexTable[i] = '%' +
StringPrototypeToUpperCase((i < 16 ? '0' : '') +
NumberPrototypeToString(i, 16));

const isHexTable = new Int8Array([
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0 - 15
Expand Down Expand Up @@ -41,25 +47,25 @@ function encodeStr(str, noEscapeTable, hexTable) {

outer:
for (; i < len; i++) {
let c = str.charCodeAt(i);
let c = StringPrototypeCharCodeAt(str, i);

// ASCII
while (c < 0x80) {
if (noEscapeTable[c] !== 1) {
if (lastPos < i)
out += str.slice(lastPos, i);
out += StringPrototypeSlice(str, lastPos, i);
lastPos = i + 1;
out += hexTable[c];
}

if (++i === len)
break outer;

c = str.charCodeAt(i);
c = StringPrototypeCharCodeAt(str, i);
}

if (lastPos < i)
out += str.slice(lastPos, i);
out += StringPrototypeSlice(str, lastPos, i);

// Multi-byte characters ...
if (c < 0x800) {
Expand All @@ -84,7 +90,7 @@ function encodeStr(str, noEscapeTable, hexTable) {
if (i >= len)
throw new ERR_INVALID_URI();

const c2 = str.charCodeAt(i) & 0x3FF;
const c2 = StringPrototypeCharCodeAt(str, i) & 0x3FF;

lastPos = i + 1;
c = 0x10000 + (((c & 0x3FF) << 10) | c2);
Expand All @@ -96,7 +102,7 @@ function encodeStr(str, noEscapeTable, hexTable) {
if (lastPos === 0)
return str;
if (lastPos < len)
return out + str.slice(lastPos);
return out + StringPrototypeSlice(str, lastPos);
return out;
}

Expand Down
32 changes: 17 additions & 15 deletions lib/querystring.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ const {
ObjectCreate,
ObjectKeys,
String,
StringPrototypeCharCodeAt,
StringPrototypeSlice,
} = primordials;

const { Buffer } = require('buffer');
Expand Down Expand Up @@ -86,20 +88,20 @@ function unescapeBuffer(s, decodeSpaces) {
// Flag to know if some hex chars have been decoded
let hasHex = false;
while (index < s.length) {
currentChar = s.charCodeAt(index);
currentChar = StringPrototypeCharCodeAt(s, index);
if (currentChar === 43 /* '+' */ && decodeSpaces) {
out[outIndex++] = 32; // ' '
index++;
continue;
}
if (currentChar === 37 /* '%' */ && index < maxLength) {
currentChar = s.charCodeAt(++index);
currentChar = StringPrototypeCharCodeAt(s, ++index);
hexHigh = unhexTable[currentChar];
if (!(hexHigh >= 0)) {
out[outIndex++] = 37; // '%'
continue;
} else {
nextChar = s.charCodeAt(++index);
nextChar = StringPrototypeCharCodeAt(s, ++index);
hexLow = unhexTable[nextChar];
if (!(hexLow >= 0)) {
out[outIndex++] = 37; // '%'
Expand Down Expand Up @@ -231,10 +233,10 @@ function stringify(obj, sep, eq, options) {

function charCodes(str) {
if (str.length === 0) return [];
if (str.length === 1) return [str.charCodeAt(0)];
if (str.length === 1) return [StringPrototypeCharCodeAt(str, 0)];
const ret = new Array(str.length);
for (let i = 0; i < str.length; ++i)
ret[i] = str.charCodeAt(i);
ret[i] = StringPrototypeCharCodeAt(str, i);
return ret;
}
const defSepCodes = [38]; // &
Expand Down Expand Up @@ -268,8 +270,8 @@ function parse(qs, sep, eq, options) {
return obj;
}

const sepCodes = (!sep ? defSepCodes : charCodes(sep + ''));
const eqCodes = (!eq ? defEqCodes : charCodes(eq + ''));
const sepCodes = (!sep ? defSepCodes : charCodes(String(sep)));
const eqCodes = (!eq ? defEqCodes : charCodes(String(eq)));
const sepLen = sepCodes.length;
const eqLen = eqCodes.length;

Expand Down Expand Up @@ -300,7 +302,7 @@ function parse(qs, sep, eq, options) {
const plusChar = (customDecode ? '%20' : ' ');
let encodeCheck = 0;
for (let i = 0; i < qs.length; ++i) {
const code = qs.charCodeAt(i);
const code = StringPrototypeCharCodeAt(qs, i);

// Try matching key/value pair separator (e.g. '&')
if (code === sepCodes[sepIdx]) {
Expand All @@ -311,7 +313,7 @@ function parse(qs, sep, eq, options) {
// We didn't find the (entire) key/value separator
if (lastPos < end) {
// Treat the substring as part of the key instead of the value
key += qs.slice(lastPos, end);
key += StringPrototypeSlice(qs, lastPos, end);
} else if (key.length === 0) {
// We saw an empty substring between separators
if (--pairs === 0)
Expand All @@ -321,7 +323,7 @@ function parse(qs, sep, eq, options) {
continue;
}
} else if (lastPos < end) {
value += qs.slice(lastPos, end);
value += StringPrototypeSlice(qs, lastPos, end);
}

addKeyVal(obj, key, value, keyEncoded, valEncoded, decode);
Expand All @@ -343,7 +345,7 @@ function parse(qs, sep, eq, options) {
// Key/value separator match!
const end = i - eqIdx + 1;
if (lastPos < end)
key += qs.slice(lastPos, end);
key += StringPrototypeSlice(qs, lastPos, end);
encodeCheck = 0;
lastPos = i + 1;
}
Expand All @@ -369,15 +371,15 @@ function parse(qs, sep, eq, options) {
}
if (code === 43/* + */) {
if (lastPos < i)
key += qs.slice(lastPos, i);
key += StringPrototypeSlice(qs, lastPos, i);
key += plusChar;
lastPos = i + 1;
continue;
}
}
if (code === 43/* + */) {
if (lastPos < i)
value += qs.slice(lastPos, i);
value += StringPrototypeSlice(qs, lastPos, i);
value += plusChar;
lastPos = i + 1;
} else if (!valEncoded) {
Expand All @@ -400,9 +402,9 @@ function parse(qs, sep, eq, options) {
// Deal with any leftover key or value data
if (lastPos < qs.length) {
if (eqIdx < eqLen)
key += qs.slice(lastPos);
key += StringPrototypeSlice(qs, lastPos);
else if (sepIdx < sepLen)
value += qs.slice(lastPos);
value += StringPrototypeSlice(qs, lastPos);
} else if (eqIdx === 0 && key.length === 0) {
// We ended on an empty substring
return obj;
Expand Down

0 comments on commit 8594b30

Please sign in to comment.