summaryrefslogtreecommitdiff
path: root/ext/node/polyfills/internal_binding/_utils.ts
diff options
context:
space:
mode:
Diffstat (limited to 'ext/node/polyfills/internal_binding/_utils.ts')
-rw-r--r--ext/node/polyfills/internal_binding/_utils.ts86
1 files changed, 51 insertions, 35 deletions
diff --git a/ext/node/polyfills/internal_binding/_utils.ts b/ext/node/polyfills/internal_binding/_utils.ts
index d543fd372..ab174608b 100644
--- a/ext/node/polyfills/internal_binding/_utils.ts
+++ b/ext/node/polyfills/internal_binding/_utils.ts
@@ -9,11 +9,12 @@ import {
} from "ext:deno_web/00_infra.js";
export function asciiToBytes(str: string) {
- const byteArray = [];
- for (let i = 0; i < str.length; ++i) {
- byteArray.push(str.charCodeAt(i) & 255);
+ const length = str.length;
+ const byteArray = new Uint8Array(length);
+ for (let i = 0; i < length; ++i) {
+ byteArray[i] = str.charCodeAt(i) & 255;
}
- return new Uint8Array(byteArray);
+ return byteArray;
}
export function base64ToBytes(str: string) {
@@ -25,16 +26,26 @@ export function base64ToBytes(str: string) {
const INVALID_BASE64_RE = /[^+/0-9A-Za-z-_]/g;
function base64clean(str: string) {
// Node takes equal signs as end of the Base64 encoding
- str = str.split("=")[0];
+ const eqIndex = str.indexOf("=");
+ str = eqIndex !== -1 ? str.substring(0, eqIndex).trimStart() : str.trim();
// Node strips out invalid characters like \n and \t from the string, std/base64 does not
- str = str.trim().replace(INVALID_BASE64_RE, "");
+ str = str.replace(INVALID_BASE64_RE, "");
// Node converts strings with length < 2 to ''
- if (str.length < 2) return "";
+ const length = str.length;
+ if (length < 2) return "";
// Node allows for non-padded base64 strings (missing trailing ===), std/base64 does not
- while (str.length % 4 !== 0) {
- str = str + "=";
+ switch (length % 4) {
+ case 0:
+ return str;
+ case 1:
+ return `${str}===`;
+ case 2:
+ return `${str}==`;
+ case 3:
+ return `${str}=`;
+ default:
+ throw new Error("Unexpected NaN value for string length");
}
- return str;
}
export function base64UrlToBytes(str: string) {
@@ -44,9 +55,10 @@ export function base64UrlToBytes(str: string) {
}
export function hexToBytes(str: string) {
- const byteArray = new Uint8Array(Math.floor((str || "").length / 2));
- let i;
- for (i = 0; i < byteArray.length; i++) {
+ const length = str.length >>> 1;
+ const byteArray = new Uint8Array(length);
+ let i: number;
+ for (i = 0; i < length; i++) {
const a = Number.parseInt(str[i * 2], 16);
const b = Number.parseInt(str[i * 2 + 1], 16);
if (Number.isNaN(a) && Number.isNaN(b)) {
@@ -54,39 +66,43 @@ export function hexToBytes(str: string) {
}
byteArray[i] = (a << 4) | b;
}
- return new Uint8Array(
- i === byteArray.length ? byteArray : byteArray.slice(0, i),
- );
+ // Returning a buffer subarray is okay: This API's return value
+ // is never exposed to users and is only ever used for its length
+ // and the data within the subarray.
+ return i === length ? byteArray : byteArray.subarray(0, i);
}
-export function utf16leToBytes(str: string, units: number) {
- let c, hi, lo;
- const byteArray = [];
- for (let i = 0; i < str.length; ++i) {
- if ((units -= 2) < 0) {
- break;
- }
- c = str.charCodeAt(i);
- hi = c >> 8;
- lo = c % 256;
- byteArray.push(lo);
- byteArray.push(hi);
+export function utf16leToBytes(str: string, units?: number) {
+ // If units is defined, round it to even values for 16 byte "steps"
+ // and use it as an upper bound value for our string byte array's length.
+ const length = Math.min(str.length * 2, units ? (units >>> 1) * 2 : Infinity);
+ const byteArray = new Uint8Array(length);
+ const view = new DataView(byteArray.buffer);
+ let i: number;
+ for (i = 0; i * 2 < length; i++) {
+ view.setUint16(i * 2, str.charCodeAt(i), true);
}
- return new Uint8Array(byteArray);
+ // Returning a buffer subarray is okay: This API's return value
+ // is never exposed to users and is only ever used for its length
+ // and the data within the subarray.
+ return i * 2 === length ? byteArray : byteArray.subarray(0, i * 2);
}
export function bytesToAscii(bytes: Uint8Array) {
- let ret = "";
- for (let i = 0; i < bytes.length; ++i) {
- ret += String.fromCharCode(bytes[i] & 127);
+ let res = "";
+ const length = bytes.byteLength;
+ for (let i = 0; i < length; ++i) {
+ res = `${res}${String.fromCharCode(bytes[i] & 127)}`;
}
- return ret;
+ return res;
}
export function bytesToUtf16le(bytes: Uint8Array) {
let res = "";
- for (let i = 0; i < bytes.length - 1; i += 2) {
- res += String.fromCharCode(bytes[i] + bytes[i + 1] * 256);
+ const length = bytes.byteLength;
+ const view = new DataView(bytes.buffer, bytes.byteOffset, length);
+ for (let i = 0; i < length - 1; i += 2) {
+ res = `${res}${String.fromCharCode(view.getUint16(i, true))}`;
}
return res;
}