|
23 | 23 |
|
24 | 24 | const {
|
25 | 25 | Array,
|
26 |
| - ArrayFrom, |
27 | 26 | ArrayIsArray,
|
28 | 27 | ArrayPrototypeForEach,
|
29 |
| - ArrayPrototypeIndexOf, |
30 | 28 | MathFloor,
|
31 | 29 | MathMin,
|
32 | 30 | MathTrunc,
|
@@ -70,6 +68,7 @@ const {
|
70 | 68 | swap64: _swap64,
|
71 | 69 | kMaxLength,
|
72 | 70 | kStringMaxLength,
|
| 71 | + atob: _atob, |
73 | 72 | } = internalBinding('buffer');
|
74 | 73 | const {
|
75 | 74 | constants: {
|
@@ -1259,85 +1258,26 @@ function btoa(input) {
|
1259 | 1258 | return buf.toString('base64');
|
1260 | 1259 | }
|
1261 | 1260 |
|
1262 |
| -// Refs: https://infra.spec.whatwg.org/#forgiving-base64-decode |
1263 |
| -const kForgivingBase64AllowedChars = [ |
1264 |
| - // ASCII whitespace |
1265 |
| - // Refs: https://infra.spec.whatwg.org/#ascii-whitespace |
1266 |
| - 0x09, 0x0A, 0x0C, 0x0D, 0x20, |
1267 |
| - |
1268 |
| - // Uppercase letters |
1269 |
| - ...ArrayFrom({ length: 26 }, (_, i) => StringPrototypeCharCodeAt('A') + i), |
1270 |
| - |
1271 |
| - // Lowercase letters |
1272 |
| - ...ArrayFrom({ length: 26 }, (_, i) => StringPrototypeCharCodeAt('a') + i), |
1273 |
| - |
1274 |
| - // Decimal digits |
1275 |
| - ...ArrayFrom({ length: 10 }, (_, i) => StringPrototypeCharCodeAt('0') + i), |
1276 |
| - |
1277 |
| - 0x2B, // + |
1278 |
| - 0x2F, // / |
1279 |
| - 0x3D, // = |
1280 |
| -]; |
1281 |
| -const kEqualSignIndex = ArrayPrototypeIndexOf(kForgivingBase64AllowedChars, |
1282 |
| - 0x3D); |
1283 |
| - |
1284 | 1261 | function atob(input) {
|
1285 |
| - // The implementation here has not been performance optimized in any way and |
1286 |
| - // should not be. |
1287 |
| - // Refs: https://github.com/nodejs/node/pull/38433#issuecomment-828426932 |
1288 | 1262 | if (arguments.length === 0) {
|
1289 | 1263 | throw new ERR_MISSING_ARGS('input');
|
1290 | 1264 | }
|
1291 | 1265 |
|
1292 |
| - input = `${input}`; |
1293 |
| - let nonAsciiWhitespaceCharCount = 0; |
1294 |
| - let equalCharCount = 0; |
| 1266 | + const result = _atob(`${input}`); |
1295 | 1267 |
|
1296 |
| - for (let n = 0; n < input.length; n++) { |
1297 |
| - const index = ArrayPrototypeIndexOf( |
1298 |
| - kForgivingBase64AllowedChars, |
1299 |
| - StringPrototypeCharCodeAt(input, n)); |
1300 |
| - |
1301 |
| - if (index > 4) { |
1302 |
| - // The first 5 elements of `kForgivingBase64AllowedChars` are |
1303 |
| - // ASCII whitespace char codes. |
1304 |
| - nonAsciiWhitespaceCharCount++; |
1305 |
| - |
1306 |
| - if (index === kEqualSignIndex) { |
1307 |
| - equalCharCount++; |
1308 |
| - } else if (equalCharCount) { |
1309 |
| - // The `=` char is only allowed at the end. |
1310 |
| - throw lazyDOMException('Invalid character', 'InvalidCharacterError'); |
1311 |
| - } |
1312 |
| - |
1313 |
| - if (equalCharCount > 2) { |
1314 |
| - // Only one more `=` is permitted after the first equal sign. |
1315 |
| - throw lazyDOMException('Invalid character', 'InvalidCharacterError'); |
1316 |
| - } |
1317 |
| - } else if (index === -1) { |
| 1268 | + switch (result) { |
| 1269 | + case -2: // Invalid character |
1318 | 1270 | throw lazyDOMException('Invalid character', 'InvalidCharacterError');
|
1319 |
| - } |
1320 |
| - } |
1321 |
| - |
1322 |
| - let reminder = nonAsciiWhitespaceCharCount % 4; |
1323 |
| - |
1324 |
| - // See #2, #3, #4 - https://infra.spec.whatwg.org/#forgiving-base64 |
1325 |
| - if (!reminder) { |
1326 |
| - // Remove all trailing `=` characters and get the new reminder. |
1327 |
| - reminder = (nonAsciiWhitespaceCharCount - equalCharCount) % 4; |
1328 |
| - } else if (equalCharCount) { |
1329 |
| - // `=` should not in the input if there's a reminder. |
1330 |
| - throw lazyDOMException('Invalid character', 'InvalidCharacterError'); |
1331 |
| - } |
1332 |
| - |
1333 |
| - // See #3 - https://infra.spec.whatwg.org/#forgiving-base64 |
1334 |
| - if (reminder === 1) { |
1335 |
| - throw lazyDOMException( |
1336 |
| - 'The string to be decoded is not correctly encoded.', |
1337 |
| - 'InvalidCharacterError'); |
| 1271 | + case -1: // Single character remained |
| 1272 | + throw lazyDOMException( |
| 1273 | + 'The string to be decoded is not correctly encoded.', |
| 1274 | + 'InvalidCharacterError'); |
| 1275 | + case -3: // Possible overflow |
| 1276 | + // TODO(@anonrig): Throw correct error in here. |
| 1277 | + throw lazyDOMException('The input causes overflow.', 'InvalidCharacterError'); |
| 1278 | + default: |
| 1279 | + return result; |
1338 | 1280 | }
|
1339 |
| - |
1340 |
| - return Buffer.from(input, 'base64').toString('latin1'); |
1341 | 1281 | }
|
1342 | 1282 |
|
1343 | 1283 | function isUtf8(input) {
|
|
0 commit comments