From ab084c199ebf83d6817a563905dfdea7b0f5106d Mon Sep 17 00:00:00 2001 From: Antoine du Hamel Date: Wed, 18 Nov 2020 22:09:33 +0100 Subject: [PATCH] querystring: refactor to use more primordials PR-URL: https://github.com/nodejs/node/pull/36315 Reviewed-By: Luigi Pinca Reviewed-By: Rich Trott --- lib/internal/querystring.js | 20 +++++++++++++------- lib/querystring.js | 32 +++++++++++++++++--------------- 2 files changed, 30 insertions(+), 22 deletions(-) diff --git a/lib/internal/querystring.js b/lib/internal/querystring.js index 5306c7f82bb14a..658faa93b6ad4d 100644 --- a/lib/internal/querystring.js +++ b/lib/internal/querystring.js @@ -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 @@ -41,13 +47,13 @@ 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]; } @@ -55,11 +61,11 @@ function encodeStr(str, noEscapeTable, hexTable) { 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) { @@ -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); @@ -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; } diff --git a/lib/querystring.js b/lib/querystring.js index 0aa798d462b25c..644cee4bde5f4b 100644 --- a/lib/querystring.js +++ b/lib/querystring.js @@ -32,6 +32,8 @@ const { ObjectCreate, ObjectKeys, String, + StringPrototypeCharCodeAt, + StringPrototypeSlice, } = primordials; const { Buffer } = require('buffer'); @@ -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; // '%' @@ -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]; // & @@ -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; @@ -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]) { @@ -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) @@ -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); @@ -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; } @@ -369,7 +371,7 @@ 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; @@ -377,7 +379,7 @@ function parse(qs, sep, eq, options) { } if (code === 43/* + */) { if (lastPos < i) - value += qs.slice(lastPos, i); + value += StringPrototypeSlice(qs, lastPos, i); value += plusChar; lastPos = i + 1; } else if (!valEncoded) { @@ -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;