lighthouse
Version:
Automated auditing, performance metrics, and best practices for the web.
72 lines (64 loc) • 2.07 kB
JavaScript
/**
* @license
* Copyright 2021 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
const btoa_ = typeof btoa !== 'undefined' ?
btoa :
/** @param {string} str */
(str) => Buffer.from(str).toString('base64');
const atob_ = typeof atob !== 'undefined' ?
atob :
/** @param {string} str */
(str) => Buffer.from(str, 'base64').toString();
/**
* Takes an UTF-8 string and returns a base64 encoded string.
* If gzip is true, the UTF-8 bytes are gzipped before base64'd, using
* CompressionStream (currently only in Chrome), falling back to pako
* (which is only used to encode in our Node tests).
* @param {string} string
* @param {{gzip: boolean}} options
* @return {Promise<string>}
*/
async function toBase64(string, options) {
let bytes = new TextEncoder().encode(string);
if (options.gzip) {
if (typeof CompressionStream !== 'undefined') {
const cs = new CompressionStream('gzip');
const writer = cs.writable.getWriter();
writer.write(bytes);
writer.close();
const compAb = await new Response(cs.readable).arrayBuffer();
bytes = new Uint8Array(compAb);
} else {
/** @type {import('pako')=} */
const pako = window.pako;
bytes = pako.gzip(string);
}
}
let binaryString = '';
// This is ~25% faster than building the string one character at a time.
// https://jsbench.me/2gkoxazvjl
const chunkSize = 5000;
for (let i = 0; i < bytes.length; i += chunkSize) {
binaryString += String.fromCharCode(...bytes.subarray(i, i + chunkSize));
}
return btoa_(binaryString);
}
/**
* @param {string} encoded
* @param {{gzip: boolean}} options
* @return {string}
*/
function fromBase64(encoded, options) {
const binaryString = atob_(encoded);
const bytes = Uint8Array.from(binaryString, c => c.charCodeAt(0));
if (options.gzip) {
/** @type {import('pako')=} */
const pako = window.pako;
return pako.ungzip(bytes, {to: 'string'});
} else {
return new TextDecoder().decode(bytes);
}
}
export const TextEncoding = {toBase64, fromBase64};