1'use strict'; 2 3const { 4 Array, 5 Int8Array, 6 NumberPrototypeToString, 7 StringPrototypeCharCodeAt, 8 StringPrototypeSlice, 9 StringPrototypeToUpperCase, 10} = primordials; 11 12const { ERR_INVALID_URI } = require('internal/errors').codes; 13 14const hexTable = new Array(256); 15for (let i = 0; i < 256; ++i) 16 hexTable[i] = '%' + 17 StringPrototypeToUpperCase((i < 16 ? '0' : '') + 18 NumberPrototypeToString(i, 16)); 19 20const isHexTable = new Int8Array([ 21 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0 - 15 22 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16 - 31 23 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 32 - 47 24 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, // 48 - 63 25 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 64 - 79 26 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 80 - 95 27 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 96 - 111 28 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 112 - 127 29 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 128 ... 30 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // ... 256 37]); 38 39/** 40 * @param {string} str 41 * @param {Int8Array} noEscapeTable 42 * @param {string[]} hexTable 43 * @returns {string} 44 */ 45function encodeStr(str, noEscapeTable, hexTable) { 46 const len = str.length; 47 if (len === 0) 48 return ''; 49 50 let out = ''; 51 let lastPos = 0; 52 let i = 0; 53 54 outer: 55 for (; i < len; i++) { 56 let c = StringPrototypeCharCodeAt(str, i); 57 58 // ASCII 59 while (c < 0x80) { 60 if (noEscapeTable[c] !== 1) { 61 if (lastPos < i) 62 out += StringPrototypeSlice(str, lastPos, i); 63 lastPos = i + 1; 64 out += hexTable[c]; 65 } 66 67 if (++i === len) 68 break outer; 69 70 c = StringPrototypeCharCodeAt(str, i); 71 } 72 73 if (lastPos < i) 74 out += StringPrototypeSlice(str, lastPos, i); 75 76 // Multi-byte characters ... 77 if (c < 0x800) { 78 lastPos = i + 1; 79 out += hexTable[0xC0 | (c >> 6)] + 80 hexTable[0x80 | (c & 0x3F)]; 81 continue; 82 } 83 if (c < 0xD800 || c >= 0xE000) { 84 lastPos = i + 1; 85 out += hexTable[0xE0 | (c >> 12)] + 86 hexTable[0x80 | ((c >> 6) & 0x3F)] + 87 hexTable[0x80 | (c & 0x3F)]; 88 continue; 89 } 90 // Surrogate pair 91 ++i; 92 93 // This branch should never happen because all URLSearchParams entries 94 // should already be converted to USVString. But, included for 95 // completion's sake anyway. 96 if (i >= len) 97 throw new ERR_INVALID_URI(); 98 99 const c2 = StringPrototypeCharCodeAt(str, i) & 0x3FF; 100 101 lastPos = i + 1; 102 c = 0x10000 + (((c & 0x3FF) << 10) | c2); 103 out += hexTable[0xF0 | (c >> 18)] + 104 hexTable[0x80 | ((c >> 12) & 0x3F)] + 105 hexTable[0x80 | ((c >> 6) & 0x3F)] + 106 hexTable[0x80 | (c & 0x3F)]; 107 } 108 if (lastPos === 0) 109 return str; 110 if (lastPos < len) 111 return out + StringPrototypeSlice(str, lastPos); 112 return out; 113} 114 115module.exports = { 116 encodeStr, 117 hexTable, 118 isHexTable, 119}; 120