• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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