diff options
author | Bartek Iwańczuk <biwanczuk@gmail.com> | 2020-03-05 13:05:41 +0100 |
---|---|---|
committer | Bartek Iwańczuk <biwanczuk@gmail.com> | 2020-03-05 18:48:55 +0100 |
commit | 2e590072148c85bbc479ab49aa9556b0a2cfaff2 (patch) | |
tree | 89747e7b6762158e35f9120ca0ef0fa14991ae34 /cli/js/compiler_util.ts | |
parent | 9b59ed7c7907c5f365e72b5c5a74114eb8ff1488 (diff) |
move Web APIs to cli/js/web/
Diffstat (limited to 'cli/js/compiler_util.ts')
-rw-r--r-- | cli/js/compiler_util.ts | 133 |
1 files changed, 131 insertions, 2 deletions
diff --git a/cli/js/compiler_util.ts b/cli/js/compiler_util.ts index 379099f79..57ba9589b 100644 --- a/cli/js/compiler_util.ts +++ b/cli/js/compiler_util.ts @@ -6,7 +6,7 @@ import { buildBundle } from "./compiler_bundler.ts"; import { ConfigureResponse, Host } from "./compiler_host.ts"; import { SourceFile } from "./compiler_sourcefile.ts"; import { sendSync } from "./dispatch_json.ts"; -import { TextDecoder, TextEncoder } from "./text_encoding.ts"; +import { atob, TextDecoder, TextEncoder } from "./web/text_encoding.ts"; import { core } from "./core.ts"; import * as util from "./util.ts"; import { assert } from "./util.ts"; @@ -145,7 +145,7 @@ export function createWriteFile(state: WriteFileState): WriteFileCallback { const encodedData = encoder.encode(content); console.warn(`Emitting bundle to "${state.outFile}"`); writeFileSync(state.outFile, encodedData); - console.warn(`${util.humanFileSize(encodedData.length)} emitted.`); + console.warn(`${humanFileSize(encodedData.length)} emitted.`); } else { console.log(content); } @@ -333,3 +333,132 @@ export function processConfigureResponse( } return diagnostics; } + +// Constants used by `normalizeString` and `resolvePath` +export const CHAR_DOT = 46; /* . */ +export const CHAR_FORWARD_SLASH = 47; /* / */ + +/** Resolves `.` and `..` elements in a path with directory names */ +export function normalizeString( + path: string, + allowAboveRoot: boolean, + separator: string, + isPathSeparator: (code: number) => boolean +): string { + let res = ""; + let lastSegmentLength = 0; + let lastSlash = -1; + let dots = 0; + let code: number; + for (let i = 0, len = path.length; i <= len; ++i) { + if (i < len) code = path.charCodeAt(i); + else if (isPathSeparator(code!)) break; + else code = CHAR_FORWARD_SLASH; + + if (isPathSeparator(code)) { + if (lastSlash === i - 1 || dots === 1) { + // NOOP + } else if (lastSlash !== i - 1 && dots === 2) { + if ( + res.length < 2 || + lastSegmentLength !== 2 || + res.charCodeAt(res.length - 1) !== CHAR_DOT || + res.charCodeAt(res.length - 2) !== CHAR_DOT + ) { + if (res.length > 2) { + const lastSlashIndex = res.lastIndexOf(separator); + if (lastSlashIndex === -1) { + res = ""; + lastSegmentLength = 0; + } else { + res = res.slice(0, lastSlashIndex); + lastSegmentLength = res.length - 1 - res.lastIndexOf(separator); + } + lastSlash = i; + dots = 0; + continue; + } else if (res.length === 2 || res.length === 1) { + res = ""; + lastSegmentLength = 0; + lastSlash = i; + dots = 0; + continue; + } + } + if (allowAboveRoot) { + if (res.length > 0) res += `${separator}..`; + else res = ".."; + lastSegmentLength = 2; + } + } else { + if (res.length > 0) res += separator + path.slice(lastSlash + 1, i); + else res = path.slice(lastSlash + 1, i); + lastSegmentLength = i - lastSlash - 1; + } + lastSlash = i; + dots = 0; + } else if (code === CHAR_DOT && dots !== -1) { + ++dots; + } else { + dots = -1; + } + } + return res; +} + +/** Return the common path shared by the `paths`. + * + * @param paths The set of paths to compare. + * @param sep An optional separator to use. Defaults to `/`. + * @internal + */ +export function commonPath(paths: string[], sep = "/"): string { + const [first = "", ...remaining] = paths; + if (first === "" || remaining.length === 0) { + return first.substring(0, first.lastIndexOf(sep) + 1); + } + const parts = first.split(sep); + + let endOfPrefix = parts.length; + for (const path of remaining) { + const compare = path.split(sep); + for (let i = 0; i < endOfPrefix; i++) { + if (compare[i] !== parts[i]) { + endOfPrefix = i; + } + } + + if (endOfPrefix === 0) { + return ""; + } + } + const prefix = parts.slice(0, endOfPrefix).join(sep); + return prefix.endsWith(sep) ? prefix : `${prefix}${sep}`; +} + +/** Utility function to turn the number of bytes into a human readable + * unit */ +function humanFileSize(bytes: number): string { + const thresh = 1000; + if (Math.abs(bytes) < thresh) { + return bytes + " B"; + } + const units = ["kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"]; + let u = -1; + do { + bytes /= thresh; + ++u; + } while (Math.abs(bytes) >= thresh && u < units.length - 1); + return `${bytes.toFixed(1)} ${units[u]}`; +} + +// @internal +export function base64ToUint8Array(data: string): Uint8Array { + const binString = atob(data); + const size = binString.length; + const bytes = new Uint8Array(size); + for (let i = 0; i < size; i++) { + bytes[i] = binString.charCodeAt(i); + } + return bytes; +} |