Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

querystring: refactor to use more primordials #36315

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
20 changes: 13 additions & 7 deletions lib/internal/querystring.js
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
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