From 1e6cc59ed40638b1cb60e892f8c88877b523370c Mon Sep 17 00:00:00 2001 From: Kohei Watanabe Date: Fri, 12 Jun 2020 16:38:34 +0900 Subject: [PATCH 1/2] init From eb9915af3e4118edd5408e5a17eebd0fcd07ae9f Mon Sep 17 00:00:00 2001 From: Kohei Watanabe Date: Fri, 12 Jun 2020 16:38:57 +0900 Subject: [PATCH 2/2] first commit --- server.bundle.js | 5640 ++++++++++++++++++++++++++++++++++++++++++++++ server.ts | 10 + 2 files changed, 5650 insertions(+) create mode 100644 server.bundle.js create mode 100644 server.ts diff --git a/server.bundle.js b/server.bundle.js new file mode 100644 index 0000000..96293eb --- /dev/null +++ b/server.bundle.js @@ -0,0 +1,5640 @@ +// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. + +// This is a specialised implementation of a System module loader. + +"use strict"; + +// @ts-nocheck +/* eslint-disable */ +let System, __instantiateAsync, __instantiate; + +(() => { + const r = new Map(); + + System = { + register(id, d, f) { + r.set(id, { d, f, exp: {} }); + }, + }; + + async function dI(mid, src) { + let id = mid.replace(/\.\w+$/i, ""); + if (id.includes("./")) { + const [o, ...ia] = id.split("/").reverse(), + [, ...sa] = src.split("/").reverse(), + oa = [o]; + let s = 0, + i; + while ((i = ia.shift())) { + if (i === "..") s++; + else if (i === ".") break; + else oa.push(i); + } + if (s < sa.length) oa.push(...sa.slice(s)); + id = oa.reverse().join("/"); + } + return r.has(id) ? gExpA(id) : import(mid); + } + + function gC(id, main) { + return { + id, + import: (m) => dI(m, id), + meta: { url: id, main }, + }; + } + + function gE(exp) { + return (id, v) => { + v = typeof id === "string" ? { [id]: v } : id; + for (const [id, value] of Object.entries(v)) { + Object.defineProperty(exp, id, { + value, + writable: true, + enumerable: true, + }); + } + }; + } + + function rF(main) { + for (const [id, m] of r.entries()) { + const { f, exp } = m; + const { execute: e, setters: s } = f(gE(exp), gC(id, id === main)); + delete m.f; + m.e = e; + m.s = s; + } + } + + async function gExpA(id) { + if (!r.has(id)) return; + const m = r.get(id); + if (m.s) { + const { d, e, s } = m; + delete m.s; + delete m.e; + for (let i = 0; i < s.length; i++) s[i](await gExpA(d[i])); + const r = e(); + if (r) await r; + } + return m.exp; + } + + function gExp(id) { + if (!r.has(id)) return; + const m = r.get(id); + if (m.s) { + const { d, e, s } = m; + delete m.s; + delete m.e; + for (let i = 0; i < s.length; i++) s[i](gExp(d[i])); + e(); + } + return m.exp; + } + + __instantiateAsync = async (m) => { + System = __instantiateAsync = __instantiate = undefined; + rF(m); + return gExpA(m); + }; + + __instantiate = (m) => { + System = __instantiateAsync = __instantiate = undefined; + rF(m); + return gExp(m); + }; +})(); + +System.register( + "https://deno.land/std@0.56.0/encoding/utf8", + [], + function (exports_1, context_1) { + "use strict"; + var encoder, decoder; + var __moduleName = context_1 && context_1.id; + /** Shorthand for new TextEncoder().encode() */ + function encode(input) { + return encoder.encode(input); + } + exports_1("encode", encode); + /** Shorthand for new TextDecoder().decode() */ + function decode(input) { + return decoder.decode(input); + } + exports_1("decode", decode); + return { + setters: [], + execute: function () { + /** A default TextEncoder instance */ + exports_1("encoder", encoder = new TextEncoder()); + /** A default TextDecoder instance */ + exports_1("decoder", decoder = new TextDecoder()); + }, + }; + }, +); +// Copyright the Browserify authors. MIT License. +// Ported from https://github.com/browserify/path-browserify/ +/** This module is browser compatible. */ +System.register( + "https://deno.land/std@0.56.0/path/_constants", + [], + function (exports_2, context_2) { + "use strict"; + var CHAR_UPPERCASE_A, + CHAR_LOWERCASE_A, + CHAR_UPPERCASE_Z, + CHAR_LOWERCASE_Z, + CHAR_DOT, + CHAR_FORWARD_SLASH, + CHAR_BACKWARD_SLASH, + CHAR_VERTICAL_LINE, + CHAR_COLON, + CHAR_QUESTION_MARK, + CHAR_UNDERSCORE, + CHAR_LINE_FEED, + CHAR_CARRIAGE_RETURN, + CHAR_TAB, + CHAR_FORM_FEED, + CHAR_EXCLAMATION_MARK, + CHAR_HASH, + CHAR_SPACE, + CHAR_NO_BREAK_SPACE, + CHAR_ZERO_WIDTH_NOBREAK_SPACE, + CHAR_LEFT_SQUARE_BRACKET, + CHAR_RIGHT_SQUARE_BRACKET, + CHAR_LEFT_ANGLE_BRACKET, + CHAR_RIGHT_ANGLE_BRACKET, + CHAR_LEFT_CURLY_BRACKET, + CHAR_RIGHT_CURLY_BRACKET, + CHAR_HYPHEN_MINUS, + CHAR_PLUS, + CHAR_DOUBLE_QUOTE, + CHAR_SINGLE_QUOTE, + CHAR_PERCENT, + CHAR_SEMICOLON, + CHAR_CIRCUMFLEX_ACCENT, + CHAR_GRAVE_ACCENT, + CHAR_AT, + CHAR_AMPERSAND, + CHAR_EQUAL, + CHAR_0, + CHAR_9, + navigator, + isWindows; + var __moduleName = context_2 && context_2.id; + return { + setters: [], + execute: function () { + // Alphabet chars. + exports_2("CHAR_UPPERCASE_A", CHAR_UPPERCASE_A = 65); /* A */ + exports_2("CHAR_LOWERCASE_A", CHAR_LOWERCASE_A = 97); /* a */ + exports_2("CHAR_UPPERCASE_Z", CHAR_UPPERCASE_Z = 90); /* Z */ + exports_2("CHAR_LOWERCASE_Z", CHAR_LOWERCASE_Z = 122); /* z */ + // Non-alphabetic chars. + exports_2("CHAR_DOT", CHAR_DOT = 46); /* . */ + exports_2("CHAR_FORWARD_SLASH", CHAR_FORWARD_SLASH = 47); /* / */ + exports_2("CHAR_BACKWARD_SLASH", CHAR_BACKWARD_SLASH = 92); /* \ */ + exports_2("CHAR_VERTICAL_LINE", CHAR_VERTICAL_LINE = 124); /* | */ + exports_2("CHAR_COLON", CHAR_COLON = 58); /* : */ + exports_2("CHAR_QUESTION_MARK", CHAR_QUESTION_MARK = 63); /* ? */ + exports_2("CHAR_UNDERSCORE", CHAR_UNDERSCORE = 95); /* _ */ + exports_2("CHAR_LINE_FEED", CHAR_LINE_FEED = 10); /* \n */ + exports_2("CHAR_CARRIAGE_RETURN", CHAR_CARRIAGE_RETURN = 13); /* \r */ + exports_2("CHAR_TAB", CHAR_TAB = 9); /* \t */ + exports_2("CHAR_FORM_FEED", CHAR_FORM_FEED = 12); /* \f */ + exports_2("CHAR_EXCLAMATION_MARK", CHAR_EXCLAMATION_MARK = 33); /* ! */ + exports_2("CHAR_HASH", CHAR_HASH = 35); /* # */ + exports_2("CHAR_SPACE", CHAR_SPACE = 32); /* */ + exports_2( + "CHAR_NO_BREAK_SPACE", + CHAR_NO_BREAK_SPACE = 160, + ); /* \u00A0 */ + exports_2( + "CHAR_ZERO_WIDTH_NOBREAK_SPACE", + CHAR_ZERO_WIDTH_NOBREAK_SPACE = 65279, + ); /* \uFEFF */ + exports_2( + "CHAR_LEFT_SQUARE_BRACKET", + CHAR_LEFT_SQUARE_BRACKET = 91, + ); /* [ */ + exports_2( + "CHAR_RIGHT_SQUARE_BRACKET", + CHAR_RIGHT_SQUARE_BRACKET = 93, + ); /* ] */ + exports_2( + "CHAR_LEFT_ANGLE_BRACKET", + CHAR_LEFT_ANGLE_BRACKET = 60, + ); /* < */ + exports_2( + "CHAR_RIGHT_ANGLE_BRACKET", + CHAR_RIGHT_ANGLE_BRACKET = 62, + ); /* > */ + exports_2( + "CHAR_LEFT_CURLY_BRACKET", + CHAR_LEFT_CURLY_BRACKET = 123, + ); /* { */ + exports_2( + "CHAR_RIGHT_CURLY_BRACKET", + CHAR_RIGHT_CURLY_BRACKET = 125, + ); /* } */ + exports_2("CHAR_HYPHEN_MINUS", CHAR_HYPHEN_MINUS = 45); /* - */ + exports_2("CHAR_PLUS", CHAR_PLUS = 43); /* + */ + exports_2("CHAR_DOUBLE_QUOTE", CHAR_DOUBLE_QUOTE = 34); /* " */ + exports_2("CHAR_SINGLE_QUOTE", CHAR_SINGLE_QUOTE = 39); /* ' */ + exports_2("CHAR_PERCENT", CHAR_PERCENT = 37); /* % */ + exports_2("CHAR_SEMICOLON", CHAR_SEMICOLON = 59); /* ; */ + exports_2( + "CHAR_CIRCUMFLEX_ACCENT", + CHAR_CIRCUMFLEX_ACCENT = 94, + ); /* ^ */ + exports_2("CHAR_GRAVE_ACCENT", CHAR_GRAVE_ACCENT = 96); /* ` */ + exports_2("CHAR_AT", CHAR_AT = 64); /* @ */ + exports_2("CHAR_AMPERSAND", CHAR_AMPERSAND = 38); /* & */ + exports_2("CHAR_EQUAL", CHAR_EQUAL = 61); /* = */ + // Digits + exports_2("CHAR_0", CHAR_0 = 48); /* 0 */ + exports_2("CHAR_9", CHAR_9 = 57); /* 9 */ + // eslint-disable-next-line @typescript-eslint/no-explicit-any + navigator = globalThis.navigator; + isWindows = false; + exports_2("isWindows", isWindows); + if (globalThis.Deno != null) { + exports_2("isWindows", isWindows = Deno.build.os == "windows"); + } else if (navigator?.appVersion != null) { + exports_2( + "isWindows", + isWindows = navigator.appVersion.includes("Win"), + ); + } + }, + }; + }, +); +/** This module is browser compatible. */ +System.register( + "https://deno.land/std@0.56.0/path/_interface", + [], + function (exports_3, context_3) { + "use strict"; + var __moduleName = context_3 && context_3.id; + return { + setters: [], + execute: function () { + }, + }; + }, +); +// Copyright the Browserify authors. MIT License. +// Ported from https://github.com/browserify/path-browserify/ +/** This module is browser compatible. */ +System.register( + "https://deno.land/std@0.56.0/path/_util", + ["https://deno.land/std@0.56.0/path/_constants"], + function (exports_4, context_4) { + "use strict"; + var _constants_ts_1; + var __moduleName = context_4 && context_4.id; + function assertPath(path) { + if (typeof path !== "string") { + throw new TypeError( + `Path must be a string. Received ${JSON.stringify(path)}`, + ); + } + } + exports_4("assertPath", assertPath); + function isPosixPathSeparator(code) { + return code === _constants_ts_1.CHAR_FORWARD_SLASH; + } + exports_4("isPosixPathSeparator", isPosixPathSeparator); + function isPathSeparator(code) { + return isPosixPathSeparator(code) || + code === _constants_ts_1.CHAR_BACKWARD_SLASH; + } + exports_4("isPathSeparator", isPathSeparator); + function isWindowsDeviceRoot(code) { + return ((code >= _constants_ts_1.CHAR_LOWERCASE_A && + code <= _constants_ts_1.CHAR_LOWERCASE_Z) || + (code >= _constants_ts_1.CHAR_UPPERCASE_A && + code <= _constants_ts_1.CHAR_UPPERCASE_Z)); + } + exports_4("isWindowsDeviceRoot", isWindowsDeviceRoot); + // Resolves . and .. elements in a path with directory names + function normalizeString(path, allowAboveRoot, separator, isPathSeparator) { + let res = ""; + let lastSegmentLength = 0; + let lastSlash = -1; + let dots = 0; + let code; + for (let i = 0, len = path.length; i <= len; ++i) { + if (i < len) { + code = path.charCodeAt(i); + } else if (isPathSeparator(code)) { + break; + } else { + code = _constants_ts_1.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) !== _constants_ts_1.CHAR_DOT || + res.charCodeAt(res.length - 2) !== _constants_ts_1.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 === _constants_ts_1.CHAR_DOT && dots !== -1) { + ++dots; + } else { + dots = -1; + } + } + return res; + } + exports_4("normalizeString", normalizeString); + function _format(sep, pathObject) { + const dir = pathObject.dir || pathObject.root; + const base = pathObject.base || + (pathObject.name || "") + (pathObject.ext || ""); + if (!dir) { + return base; + } + if (dir === pathObject.root) { + return dir + base; + } + return dir + sep + base; + } + exports_4("_format", _format); + return { + setters: [ + function (_constants_ts_1_1) { + _constants_ts_1 = _constants_ts_1_1; + }, + ], + execute: function () { + }, + }; + }, +); +// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. +/** A module to print ANSI terminal colors. Inspired by chalk, kleur, and colors + * on npm. + * + * ``` + * import { bgBlue, red, bold } from "https://deno.land/std/fmt/colors.ts"; + * console.log(bgBlue(red(bold("Hello world!")))); + * ``` + * + * This module supports `NO_COLOR` environmental variable disabling any coloring + * if `NO_COLOR` is set. + * + * This module is browser compatible. */ +System.register( + "https://deno.land/std@0.56.0/fmt/colors", + [], + function (exports_5, context_5) { + "use strict"; + var noColor, enabled, ANSI_PATTERN; + var __moduleName = context_5 && context_5.id; + function setColorEnabled(value) { + if (noColor) { + return; + } + enabled = value; + } + exports_5("setColorEnabled", setColorEnabled); + function getColorEnabled() { + return enabled; + } + exports_5("getColorEnabled", getColorEnabled); + function code(open, close) { + return { + open: `\x1b[${open.join(";")}m`, + close: `\x1b[${close}m`, + regexp: new RegExp(`\\x1b\\[${close}m`, "g"), + }; + } + function run(str, code) { + return enabled + ? `${code.open}${str.replace(code.regexp, code.open)}${code.close}` + : str; + } + function reset(str) { + return run(str, code([0], 0)); + } + exports_5("reset", reset); + function bold(str) { + return run(str, code([1], 22)); + } + exports_5("bold", bold); + function dim(str) { + return run(str, code([2], 22)); + } + exports_5("dim", dim); + function italic(str) { + return run(str, code([3], 23)); + } + exports_5("italic", italic); + function underline(str) { + return run(str, code([4], 24)); + } + exports_5("underline", underline); + function inverse(str) { + return run(str, code([7], 27)); + } + exports_5("inverse", inverse); + function hidden(str) { + return run(str, code([8], 28)); + } + exports_5("hidden", hidden); + function strikethrough(str) { + return run(str, code([9], 29)); + } + exports_5("strikethrough", strikethrough); + function black(str) { + return run(str, code([30], 39)); + } + exports_5("black", black); + function red(str) { + return run(str, code([31], 39)); + } + exports_5("red", red); + function green(str) { + return run(str, code([32], 39)); + } + exports_5("green", green); + function yellow(str) { + return run(str, code([33], 39)); + } + exports_5("yellow", yellow); + function blue(str) { + return run(str, code([34], 39)); + } + exports_5("blue", blue); + function magenta(str) { + return run(str, code([35], 39)); + } + exports_5("magenta", magenta); + function cyan(str) { + return run(str, code([36], 39)); + } + exports_5("cyan", cyan); + function white(str) { + return run(str, code([37], 39)); + } + exports_5("white", white); + function gray(str) { + return run(str, code([90], 39)); + } + exports_5("gray", gray); + function bgBlack(str) { + return run(str, code([40], 49)); + } + exports_5("bgBlack", bgBlack); + function bgRed(str) { + return run(str, code([41], 49)); + } + exports_5("bgRed", bgRed); + function bgGreen(str) { + return run(str, code([42], 49)); + } + exports_5("bgGreen", bgGreen); + function bgYellow(str) { + return run(str, code([43], 49)); + } + exports_5("bgYellow", bgYellow); + function bgBlue(str) { + return run(str, code([44], 49)); + } + exports_5("bgBlue", bgBlue); + function bgMagenta(str) { + return run(str, code([45], 49)); + } + exports_5("bgMagenta", bgMagenta); + function bgCyan(str) { + return run(str, code([46], 49)); + } + exports_5("bgCyan", bgCyan); + function bgWhite(str) { + return run(str, code([47], 49)); + } + exports_5("bgWhite", bgWhite); + /* Special Color Sequences */ + function clampAndTruncate(n, max = 255, min = 0) { + return Math.trunc(Math.max(Math.min(n, max), min)); + } + /** Set text color using paletted 8bit colors. + * https://en.wikipedia.org/wiki/ANSI_escape_code#8-bit */ + function rgb8(str, color) { + return run(str, code([38, 5, clampAndTruncate(color)], 39)); + } + exports_5("rgb8", rgb8); + /** Set background color using paletted 8bit colors. + * https://en.wikipedia.org/wiki/ANSI_escape_code#8-bit */ + function bgRgb8(str, color) { + return run(str, code([48, 5, clampAndTruncate(color)], 49)); + } + exports_5("bgRgb8", bgRgb8); + /** Set text color using 24bit rgb. + * `color` can be a number in range `0x000000` to `0xffffff` or + * an `Rgb`. + * + * To produce the color magenta: + * + * rgba24("foo", 0xff00ff); + * rgba24("foo", {r: 255, g: 0, b: 255}); + */ + function rgb24(str, color) { + if (typeof color === "number") { + return run( + str, + code( + [38, 2, (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff], + 39, + ), + ); + } + return run( + str, + code([ + 38, + 2, + clampAndTruncate(color.r), + clampAndTruncate(color.g), + clampAndTruncate(color.b), + ], 39), + ); + } + exports_5("rgb24", rgb24); + /** Set background color using 24bit rgb. + * `color` can be a number in range `0x000000` to `0xffffff` or + * an `Rgb`. + * + * To produce the color magenta: + * + * bgRgba24("foo", 0xff00ff); + * bgRgba24("foo", {r: 255, g: 0, b: 255}); + */ + function bgRgb24(str, color) { + if (typeof color === "number") { + return run( + str, + code( + [48, 2, (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff], + 49, + ), + ); + } + return run( + str, + code([ + 48, + 2, + clampAndTruncate(color.r), + clampAndTruncate(color.g), + clampAndTruncate(color.b), + ], 49), + ); + } + exports_5("bgRgb24", bgRgb24); + function stripColor(string) { + return string.replace(ANSI_PATTERN, ""); + } + exports_5("stripColor", stripColor); + return { + setters: [], + execute: function () { + noColor = globalThis.Deno?.noColor ?? true; + enabled = !noColor; + // https://github.com/chalk/ansi-regex/blob/2b56fb0c7a07108e5b54241e8faec160d393aedb/index.js + ANSI_PATTERN = new RegExp( + [ + "[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:[a-zA-Z\\d]*(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)", + "(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-ntqry=><~]))", + ].join("|"), + "g", + ); + }, + }; + }, +); +// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. +/** This module is browser compatible. */ +System.register( + "https://deno.land/std@0.56.0/testing/diff", + [], + function (exports_6, context_6) { + "use strict"; + var DiffType, REMOVED, COMMON, ADDED; + var __moduleName = context_6 && context_6.id; + function createCommon(A, B, reverse) { + const common = []; + if (A.length === 0 || B.length === 0) { + return []; + } + for (let i = 0; i < Math.min(A.length, B.length); i += 1) { + if ( + A[reverse ? A.length - i - 1 : i] === + B[reverse ? B.length - i - 1 : i] + ) { + common.push(A[reverse ? A.length - i - 1 : i]); + } else { + return common; + } + } + return common; + } + function diff(A, B) { + const prefixCommon = createCommon(A, B); + const suffixCommon = createCommon( + A.slice(prefixCommon.length), + B.slice(prefixCommon.length), + true, + ).reverse(); + A = suffixCommon.length + ? A.slice(prefixCommon.length, -suffixCommon.length) + : A.slice(prefixCommon.length); + B = suffixCommon.length + ? B.slice(prefixCommon.length, -suffixCommon.length) + : B.slice(prefixCommon.length); + const swapped = B.length > A.length; + [A, B] = swapped ? [B, A] : [A, B]; + const M = A.length; + const N = B.length; + if (!M && !N && !suffixCommon.length && !prefixCommon.length) { + return []; + } + if (!N) { + return [ + ...prefixCommon.map((c) => ({ type: DiffType.common, value: c })), + ...A.map((a) => ({ + type: swapped ? DiffType.added : DiffType.removed, + value: a, + })), + ...suffixCommon.map((c) => ({ type: DiffType.common, value: c })), + ]; + } + const offset = N; + const delta = M - N; + const size = M + N + 1; + const fp = new Array(size).fill({ y: -1 }); + /** + * INFO: + * This buffer is used to save memory and improve performance. + * The first half is used to save route and last half is used to save diff + * type. + * This is because, when I kept new uint8array area to save type,performance + * worsened. + */ + const routes = new Uint32Array((M * N + size + 1) * 2); + const diffTypesPtrOffset = routes.length / 2; + let ptr = 0; + let p = -1; + function backTrace(A, B, current, swapped) { + const M = A.length; + const N = B.length; + const result = []; + let a = M - 1; + let b = N - 1; + let j = routes[current.id]; + let type = routes[current.id + diffTypesPtrOffset]; + while (true) { + if (!j && !type) { + break; + } + const prev = j; + if (type === REMOVED) { + result.unshift({ + type: swapped ? DiffType.removed : DiffType.added, + value: B[b], + }); + b -= 1; + } else if (type === ADDED) { + result.unshift({ + type: swapped ? DiffType.added : DiffType.removed, + value: A[a], + }); + a -= 1; + } else { + result.unshift({ type: DiffType.common, value: A[a] }); + a -= 1; + b -= 1; + } + j = routes[prev]; + type = routes[prev + diffTypesPtrOffset]; + } + return result; + } + function createFP(slide, down, k, M) { + if (slide && slide.y === -1 && down && down.y === -1) { + return { y: 0, id: 0 }; + } + if ( + (down && down.y === -1) || + k === M || + (slide && slide.y) > (down && down.y) + 1 + ) { + const prev = slide.id; + ptr++; + routes[ptr] = prev; + routes[ptr + diffTypesPtrOffset] = ADDED; + return { y: slide.y, id: ptr }; + } else { + const prev = down.id; + ptr++; + routes[ptr] = prev; + routes[ptr + diffTypesPtrOffset] = REMOVED; + return { y: down.y + 1, id: ptr }; + } + } + function snake(k, slide, down, _offset, A, B) { + const M = A.length; + const N = B.length; + if (k < -N || M < k) { + return { y: -1, id: -1 }; + } + const fp = createFP(slide, down, k, M); + while (fp.y + k < M && fp.y < N && A[fp.y + k] === B[fp.y]) { + const prev = fp.id; + ptr++; + fp.id = ptr; + fp.y += 1; + routes[ptr] = prev; + routes[ptr + diffTypesPtrOffset] = COMMON; + } + return fp; + } + while (fp[delta + offset].y < N) { + p = p + 1; + for (let k = -p; k < delta; ++k) { + fp[k + offset] = snake( + k, + fp[k - 1 + offset], + fp[k + 1 + offset], + offset, + A, + B, + ); + } + for (let k = delta + p; k > delta; --k) { + fp[k + offset] = snake( + k, + fp[k - 1 + offset], + fp[k + 1 + offset], + offset, + A, + B, + ); + } + fp[delta + offset] = snake( + delta, + fp[delta - 1 + offset], + fp[delta + 1 + offset], + offset, + A, + B, + ); + } + return [ + ...prefixCommon.map((c) => ({ type: DiffType.common, value: c })), + ...backTrace(A, B, fp[delta + offset], swapped), + ...suffixCommon.map((c) => ({ type: DiffType.common, value: c })), + ]; + } + exports_6("default", diff); + return { + setters: [], + execute: function () { + (function (DiffType) { + DiffType["removed"] = "removed"; + DiffType["common"] = "common"; + DiffType["added"] = "added"; + })(DiffType || (DiffType = {})); + exports_6("DiffType", DiffType); + REMOVED = 1; + COMMON = 2; + ADDED = 3; + }, + }; + }, +); +// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. +/** This module is browser compatible. Do not rely on good formatting of values + * for AssertionError messages in browsers. */ +System.register( + "https://deno.land/std@0.56.0/testing/asserts", + [ + "https://deno.land/std@0.56.0/fmt/colors", + "https://deno.land/std@0.56.0/testing/diff", + ], + function (exports_7, context_7) { + "use strict"; + var colors_ts_1, diff_ts_1, CAN_NOT_DISPLAY, AssertionError; + var __moduleName = context_7 && context_7.id; + function format(v) { + let string = globalThis.Deno ? Deno.inspect(v) : String(v); + if (typeof v == "string") { + string = `"${string.replace(/(?=["\\])/g, "\\")}"`; + } + return string; + } + function createColor(diffType) { + switch (diffType) { + case diff_ts_1.DiffType.added: + return (s) => colors_ts_1.green(colors_ts_1.bold(s)); + case diff_ts_1.DiffType.removed: + return (s) => colors_ts_1.red(colors_ts_1.bold(s)); + default: + return colors_ts_1.white; + } + } + function createSign(diffType) { + switch (diffType) { + case diff_ts_1.DiffType.added: + return "+ "; + case diff_ts_1.DiffType.removed: + return "- "; + default: + return " "; + } + } + function buildMessage(diffResult) { + const messages = []; + messages.push(""); + messages.push(""); + messages.push( + ` ${colors_ts_1.gray(colors_ts_1.bold("[Diff]"))} ${ + colors_ts_1.red(colors_ts_1.bold("Actual")) + } / ${colors_ts_1.green(colors_ts_1.bold("Expected"))}`, + ); + messages.push(""); + messages.push(""); + diffResult.forEach((result) => { + const c = createColor(result.type); + messages.push(c(`${createSign(result.type)}${result.value}`)); + }); + messages.push(""); + return messages; + } + function isKeyedCollection(x) { + return [Symbol.iterator, "size"].every((k) => k in x); + } + function equal(c, d) { + const seen = new Map(); + return (function compare(a, b) { + // Have to render RegExp & Date for string comparison + // unless it's mistreated as object + if ( + a && + b && + ((a instanceof RegExp && b instanceof RegExp) || + (a instanceof Date && b instanceof Date)) + ) { + return String(a) === String(b); + } + if (Object.is(a, b)) { + return true; + } + if (a && typeof a === "object" && b && typeof b === "object") { + if (seen.get(a) === b) { + return true; + } + if (Object.keys(a || {}).length !== Object.keys(b || {}).length) { + return false; + } + if (isKeyedCollection(a) && isKeyedCollection(b)) { + if (a.size !== b.size) { + return false; + } + let unmatchedEntries = a.size; + for (const [aKey, aValue] of a.entries()) { + for (const [bKey, bValue] of b.entries()) { + /* Given that Map keys can be references, we need + * to ensure that they are also deeply equal */ + if ( + (aKey === aValue && bKey === bValue && compare(aKey, bKey)) || + (compare(aKey, bKey) && compare(aValue, bValue)) + ) { + unmatchedEntries--; + } + } + } + return unmatchedEntries === 0; + } + const merged = { ...a, ...b }; + for (const key in merged) { + if (!compare(a && a[key], b && b[key])) { + return false; + } + } + seen.set(a, b); + return true; + } + return false; + })(c, d); + } + exports_7("equal", equal); + /** Make an assertion, if not `true`, then throw. */ + function assert(expr, msg = "") { + if (!expr) { + throw new AssertionError(msg); + } + } + exports_7("assert", assert); + /** + * Make an assertion that `actual` and `expected` are equal, deeply. If not + * deeply equal, then throw. + */ + function assertEquals(actual, expected, msg) { + if (equal(actual, expected)) { + return; + } + let message = ""; + const actualString = format(actual); + const expectedString = format(expected); + try { + const diffResult = diff_ts_1.default( + actualString.split("\n"), + expectedString.split("\n"), + ); + const diffMsg = buildMessage(diffResult).join("\n"); + message = `Values are not equal:\n${diffMsg}`; + } catch (e) { + message = `\n${colors_ts_1.red(CAN_NOT_DISPLAY)} + \n\n`; + } + if (msg) { + message = msg; + } + throw new AssertionError(message); + } + exports_7("assertEquals", assertEquals); + /** + * Make an assertion that `actual` and `expected` are not equal, deeply. + * If not then throw. + */ + function assertNotEquals(actual, expected, msg) { + if (!equal(actual, expected)) { + return; + } + let actualString; + let expectedString; + try { + actualString = String(actual); + } catch (e) { + actualString = "[Cannot display]"; + } + try { + expectedString = String(expected); + } catch (e) { + expectedString = "[Cannot display]"; + } + if (!msg) { + msg = `actual: ${actualString} expected: ${expectedString}`; + } + throw new AssertionError(msg); + } + exports_7("assertNotEquals", assertNotEquals); + /** + * Make an assertion that `actual` and `expected` are strictly equal. If + * not then throw. + */ + function assertStrictEq(actual, expected, msg) { + if (actual === expected) { + return; + } + let message; + if (msg) { + message = msg; + } else { + const actualString = format(actual); + const expectedString = format(expected); + if (actualString === expectedString) { + const withOffset = actualString + .split("\n") + .map((l) => ` ${l}`) + .join("\n"); + message = + `Values have the same structure but are not reference-equal:\n\n${ + colors_ts_1.red(withOffset) + }\n`; + } else { + try { + const diffResult = diff_ts_1.default( + actualString.split("\n"), + expectedString.split("\n"), + ); + const diffMsg = buildMessage(diffResult).join("\n"); + message = `Values are not strictly equal:\n${diffMsg}`; + } catch (e) { + message = `\n${colors_ts_1.red(CAN_NOT_DISPLAY)} + \n\n`; + } + } + } + throw new AssertionError(message); + } + exports_7("assertStrictEq", assertStrictEq); + /** + * Make an assertion that actual contains expected. If not + * then thrown. + */ + function assertStrContains(actual, expected, msg) { + if (!actual.includes(expected)) { + if (!msg) { + msg = `actual: "${actual}" expected to contain: "${expected}"`; + } + throw new AssertionError(msg); + } + } + exports_7("assertStrContains", assertStrContains); + /** + * Make an assertion that `actual` contains the `expected` values + * If not then thrown. + */ + function assertArrayContains(actual, expected, msg) { + const missing = []; + for (let i = 0; i < expected.length; i++) { + let found = false; + for (let j = 0; j < actual.length; j++) { + if (equal(expected[i], actual[j])) { + found = true; + break; + } + } + if (!found) { + missing.push(expected[i]); + } + } + if (missing.length === 0) { + return; + } + if (!msg) { + msg = `actual: "${format(actual)}" expected to contain: "${ + format(expected) + }"\nmissing: ${format(missing)}`; + } + throw new AssertionError(msg); + } + exports_7("assertArrayContains", assertArrayContains); + /** + * Make an assertion that `actual` match RegExp `expected`. If not + * then thrown + */ + function assertMatch(actual, expected, msg) { + if (!expected.test(actual)) { + if (!msg) { + msg = `actual: "${actual}" expected to match: "${expected}"`; + } + throw new AssertionError(msg); + } + } + exports_7("assertMatch", assertMatch); + /** + * Forcefully throws a failed assertion + */ + function fail(msg) { + // eslint-disable-next-line @typescript-eslint/no-use-before-define + assert(false, `Failed assertion${msg ? `: ${msg}` : "."}`); + } + exports_7("fail", fail); + /** Executes a function, expecting it to throw. If it does not, then it + * throws. An error class and a string that should be included in the + * error message can also be asserted. + */ + function assertThrows(fn, ErrorClass, msgIncludes = "", msg) { + let doesThrow = false; + let error = null; + try { + fn(); + } catch (e) { + if ( + ErrorClass && !(Object.getPrototypeOf(e) === ErrorClass.prototype) + ) { + msg = + `Expected error to be instance of "${ErrorClass.name}", but was "${e.constructor.name}"${ + msg ? `: ${msg}` : "." + }`; + throw new AssertionError(msg); + } + if ( + msgIncludes && + !colors_ts_1.stripColor(e.message).includes( + colors_ts_1.stripColor(msgIncludes), + ) + ) { + msg = + `Expected error message to include "${msgIncludes}", but got "${e.message}"${ + msg ? `: ${msg}` : "." + }`; + throw new AssertionError(msg); + } + doesThrow = true; + error = e; + } + if (!doesThrow) { + msg = `Expected function to throw${msg ? `: ${msg}` : "."}`; + throw new AssertionError(msg); + } + return error; + } + exports_7("assertThrows", assertThrows); + async function assertThrowsAsync(fn, ErrorClass, msgIncludes = "", msg) { + let doesThrow = false; + let error = null; + try { + await fn(); + } catch (e) { + if ( + ErrorClass && !(Object.getPrototypeOf(e) === ErrorClass.prototype) + ) { + msg = + `Expected error to be instance of "${ErrorClass.name}", but got "${e.name}"${ + msg ? `: ${msg}` : "." + }`; + throw new AssertionError(msg); + } + if ( + msgIncludes && + !colors_ts_1.stripColor(e.message).includes( + colors_ts_1.stripColor(msgIncludes), + ) + ) { + msg = + `Expected error message to include "${msgIncludes}", but got "${e.message}"${ + msg ? `: ${msg}` : "." + }`; + throw new AssertionError(msg); + } + doesThrow = true; + error = e; + } + if (!doesThrow) { + msg = `Expected function to throw${msg ? `: ${msg}` : "."}`; + throw new AssertionError(msg); + } + return error; + } + exports_7("assertThrowsAsync", assertThrowsAsync); + /** Use this to stub out methods that will throw when invoked. */ + function unimplemented(msg) { + throw new AssertionError(msg || "unimplemented"); + } + exports_7("unimplemented", unimplemented); + /** Use this to assert unreachable code. */ + function unreachable() { + throw new AssertionError("unreachable"); + } + exports_7("unreachable", unreachable); + return { + setters: [ + function (colors_ts_1_1) { + colors_ts_1 = colors_ts_1_1; + }, + function (diff_ts_1_1) { + diff_ts_1 = diff_ts_1_1; + }, + ], + execute: function () { + CAN_NOT_DISPLAY = "[Cannot display]"; + AssertionError = class AssertionError extends Error { + constructor(message) { + super(message); + this.name = "AssertionError"; + } + }; + exports_7("AssertionError", AssertionError); + }, + }; + }, +); +// Copyright the Browserify authors. MIT License. +// Ported from https://github.com/browserify/path-browserify/ +/** This module is browser compatible. */ +System.register( + "https://deno.land/std@0.56.0/path/win32", + [ + "https://deno.land/std@0.56.0/path/_constants", + "https://deno.land/std@0.56.0/path/_util", + "https://deno.land/std@0.56.0/testing/asserts", + ], + function (exports_8, context_8) { + "use strict"; + var _constants_ts_2, _util_ts_1, asserts_ts_1, sep, delimiter; + var __moduleName = context_8 && context_8.id; + function resolve(...pathSegments) { + let resolvedDevice = ""; + let resolvedTail = ""; + let resolvedAbsolute = false; + for (let i = pathSegments.length - 1; i >= -1; i--) { + let path; + if (i >= 0) { + path = pathSegments[i]; + } else if (!resolvedDevice) { + if (globalThis.Deno == null) { + throw new TypeError( + "Resolved a drive-letter-less path without a CWD.", + ); + } + path = Deno.cwd(); + } else { + if (globalThis.Deno == null) { + throw new TypeError("Resolved a relative path without a CWD."); + } + // Windows has the concept of drive-specific current working + // directories. If we've resolved a drive letter but not yet an + // absolute path, get cwd for that drive, or the process cwd if + // the drive cwd is not available. We're sure the device is not + // a UNC path at this points, because UNC paths are always absolute. + path = Deno.env.get(`=${resolvedDevice}`) || Deno.cwd(); + // Verify that a cwd was found and that it actually points + // to our drive. If not, default to the drive's root. + if ( + path === undefined || + path.slice(0, 3).toLowerCase() !== + `${resolvedDevice.toLowerCase()}\\` + ) { + path = `${resolvedDevice}\\`; + } + } + _util_ts_1.assertPath(path); + const len = path.length; + // Skip empty entries + if (len === 0) { + continue; + } + let rootEnd = 0; + let device = ""; + let isAbsolute = false; + const code = path.charCodeAt(0); + // Try to match a root + if (len > 1) { + if (_util_ts_1.isPathSeparator(code)) { + // Possible UNC root + // If we started with a separator, we know we at least have an + // absolute path of some kind (UNC or otherwise) + isAbsolute = true; + if (_util_ts_1.isPathSeparator(path.charCodeAt(1))) { + // Matched double path separator at beginning + let j = 2; + let last = j; + // Match 1 or more non-path separators + for (; j < len; ++j) { + if (_util_ts_1.isPathSeparator(path.charCodeAt(j))) { + break; + } + } + if (j < len && j !== last) { + const firstPart = path.slice(last, j); + // Matched! + last = j; + // Match 1 or more path separators + for (; j < len; ++j) { + if (!_util_ts_1.isPathSeparator(path.charCodeAt(j))) { + break; + } + } + if (j < len && j !== last) { + // Matched! + last = j; + // Match 1 or more non-path separators + for (; j < len; ++j) { + if (_util_ts_1.isPathSeparator(path.charCodeAt(j))) { + break; + } + } + if (j === len) { + // We matched a UNC root only + device = `\\\\${firstPart}\\${path.slice(last)}`; + rootEnd = j; + } else if (j !== last) { + // We matched a UNC root with leftovers + device = `\\\\${firstPart}\\${path.slice(last, j)}`; + rootEnd = j; + } + } + } + } else { + rootEnd = 1; + } + } else if (_util_ts_1.isWindowsDeviceRoot(code)) { + // Possible device root + if (path.charCodeAt(1) === _constants_ts_2.CHAR_COLON) { + device = path.slice(0, 2); + rootEnd = 2; + if (len > 2) { + if (_util_ts_1.isPathSeparator(path.charCodeAt(2))) { + // Treat separator following drive name as an absolute path + // indicator + isAbsolute = true; + rootEnd = 3; + } + } + } + } + } else if (_util_ts_1.isPathSeparator(code)) { + // `path` contains just a path separator + rootEnd = 1; + isAbsolute = true; + } + if ( + device.length > 0 && + resolvedDevice.length > 0 && + device.toLowerCase() !== resolvedDevice.toLowerCase() + ) { + // This path points to another device so it is not applicable + continue; + } + if (resolvedDevice.length === 0 && device.length > 0) { + resolvedDevice = device; + } + if (!resolvedAbsolute) { + resolvedTail = `${path.slice(rootEnd)}\\${resolvedTail}`; + resolvedAbsolute = isAbsolute; + } + if (resolvedAbsolute && resolvedDevice.length > 0) { + break; + } + } + // At this point the path should be resolved to a full absolute path, + // but handle relative paths to be safe (might happen when process.cwd() + // fails) + // Normalize the tail path + resolvedTail = _util_ts_1.normalizeString( + resolvedTail, + !resolvedAbsolute, + "\\", + _util_ts_1.isPathSeparator, + ); + return resolvedDevice + (resolvedAbsolute ? "\\" : "") + resolvedTail || + "."; + } + exports_8("resolve", resolve); + function normalize(path) { + _util_ts_1.assertPath(path); + const len = path.length; + if (len === 0) { + return "."; + } + let rootEnd = 0; + let device; + let isAbsolute = false; + const code = path.charCodeAt(0); + // Try to match a root + if (len > 1) { + if (_util_ts_1.isPathSeparator(code)) { + // Possible UNC root + // If we started with a separator, we know we at least have an absolute + // path of some kind (UNC or otherwise) + isAbsolute = true; + if (_util_ts_1.isPathSeparator(path.charCodeAt(1))) { + // Matched double path separator at beginning + let j = 2; + let last = j; + // Match 1 or more non-path separators + for (; j < len; ++j) { + if (_util_ts_1.isPathSeparator(path.charCodeAt(j))) { + break; + } + } + if (j < len && j !== last) { + const firstPart = path.slice(last, j); + // Matched! + last = j; + // Match 1 or more path separators + for (; j < len; ++j) { + if (!_util_ts_1.isPathSeparator(path.charCodeAt(j))) { + break; + } + } + if (j < len && j !== last) { + // Matched! + last = j; + // Match 1 or more non-path separators + for (; j < len; ++j) { + if (_util_ts_1.isPathSeparator(path.charCodeAt(j))) { + break; + } + } + if (j === len) { + // We matched a UNC root only + // Return the normalized version of the UNC root since there + // is nothing left to process + return `\\\\${firstPart}\\${path.slice(last)}\\`; + } else if (j !== last) { + // We matched a UNC root with leftovers + device = `\\\\${firstPart}\\${path.slice(last, j)}`; + rootEnd = j; + } + } + } + } else { + rootEnd = 1; + } + } else if (_util_ts_1.isWindowsDeviceRoot(code)) { + // Possible device root + if (path.charCodeAt(1) === _constants_ts_2.CHAR_COLON) { + device = path.slice(0, 2); + rootEnd = 2; + if (len > 2) { + if (_util_ts_1.isPathSeparator(path.charCodeAt(2))) { + // Treat separator following drive name as an absolute path + // indicator + isAbsolute = true; + rootEnd = 3; + } + } + } + } + } else if (_util_ts_1.isPathSeparator(code)) { + // `path` contains just a path separator, exit early to avoid unnecessary + // work + return "\\"; + } + let tail; + if (rootEnd < len) { + tail = _util_ts_1.normalizeString( + path.slice(rootEnd), + !isAbsolute, + "\\", + _util_ts_1.isPathSeparator, + ); + } else { + tail = ""; + } + if (tail.length === 0 && !isAbsolute) { + tail = "."; + } + if ( + tail.length > 0 && + _util_ts_1.isPathSeparator(path.charCodeAt(len - 1)) + ) { + tail += "\\"; + } + if (device === undefined) { + if (isAbsolute) { + if (tail.length > 0) { + return `\\${tail}`; + } else { + return "\\"; + } + } else if (tail.length > 0) { + return tail; + } else { + return ""; + } + } else if (isAbsolute) { + if (tail.length > 0) { + return `${device}\\${tail}`; + } else { + return `${device}\\`; + } + } else if (tail.length > 0) { + return device + tail; + } else { + return device; + } + } + exports_8("normalize", normalize); + function isAbsolute(path) { + _util_ts_1.assertPath(path); + const len = path.length; + if (len === 0) { + return false; + } + const code = path.charCodeAt(0); + if (_util_ts_1.isPathSeparator(code)) { + return true; + } else if (_util_ts_1.isWindowsDeviceRoot(code)) { + // Possible device root + if (len > 2 && path.charCodeAt(1) === _constants_ts_2.CHAR_COLON) { + if (_util_ts_1.isPathSeparator(path.charCodeAt(2))) { + return true; + } + } + } + return false; + } + exports_8("isAbsolute", isAbsolute); + function join(...paths) { + const pathsCount = paths.length; + if (pathsCount === 0) { + return "."; + } + let joined; + let firstPart = null; + for (let i = 0; i < pathsCount; ++i) { + const path = paths[i]; + _util_ts_1.assertPath(path); + if (path.length > 0) { + if (joined === undefined) { + joined = firstPart = path; + } else { + joined += `\\${path}`; + } + } + } + if (joined === undefined) { + return "."; + } + // Make sure that the joined path doesn't start with two slashes, because + // normalize() will mistake it for an UNC path then. + // + // This step is skipped when it is very clear that the user actually + // intended to point at an UNC path. This is assumed when the first + // non-empty string arguments starts with exactly two slashes followed by + // at least one more non-slash character. + // + // Note that for normalize() to treat a path as an UNC path it needs to + // have at least 2 components, so we don't filter for that here. + // This means that the user can use join to construct UNC paths from + // a server name and a share name; for example: + // path.join('//server', 'share') -> '\\\\server\\share\\') + let needsReplace = true; + let slashCount = 0; + asserts_ts_1.assert(firstPart != null); + if (_util_ts_1.isPathSeparator(firstPart.charCodeAt(0))) { + ++slashCount; + const firstLen = firstPart.length; + if (firstLen > 1) { + if (_util_ts_1.isPathSeparator(firstPart.charCodeAt(1))) { + ++slashCount; + if (firstLen > 2) { + if (_util_ts_1.isPathSeparator(firstPart.charCodeAt(2))) { + ++slashCount; + } else { + // We matched a UNC path in the first part + needsReplace = false; + } + } + } + } + } + if (needsReplace) { + // Find any more consecutive slashes we need to replace + for (; slashCount < joined.length; ++slashCount) { + if (!_util_ts_1.isPathSeparator(joined.charCodeAt(slashCount))) { + break; + } + } + // Replace the slashes if needed + if (slashCount >= 2) { + joined = `\\${joined.slice(slashCount)}`; + } + } + return normalize(joined); + } + exports_8("join", join); + // It will solve the relative path from `from` to `to`, for instance: + // from = 'C:\\orandea\\test\\aaa' + // to = 'C:\\orandea\\impl\\bbb' + // The output of the function should be: '..\\..\\impl\\bbb' + function relative(from, to) { + _util_ts_1.assertPath(from); + _util_ts_1.assertPath(to); + if (from === to) { + return ""; + } + const fromOrig = resolve(from); + const toOrig = resolve(to); + if (fromOrig === toOrig) { + return ""; + } + from = fromOrig.toLowerCase(); + to = toOrig.toLowerCase(); + if (from === to) { + return ""; + } + // Trim any leading backslashes + let fromStart = 0; + let fromEnd = from.length; + for (; fromStart < fromEnd; ++fromStart) { + if ( + from.charCodeAt(fromStart) !== _constants_ts_2.CHAR_BACKWARD_SLASH + ) { + break; + } + } + // Trim trailing backslashes (applicable to UNC paths only) + for (; fromEnd - 1 > fromStart; --fromEnd) { + if ( + from.charCodeAt(fromEnd - 1) !== _constants_ts_2.CHAR_BACKWARD_SLASH + ) { + break; + } + } + const fromLen = fromEnd - fromStart; + // Trim any leading backslashes + let toStart = 0; + let toEnd = to.length; + for (; toStart < toEnd; ++toStart) { + if (to.charCodeAt(toStart) !== _constants_ts_2.CHAR_BACKWARD_SLASH) { + break; + } + } + // Trim trailing backslashes (applicable to UNC paths only) + for (; toEnd - 1 > toStart; --toEnd) { + if (to.charCodeAt(toEnd - 1) !== _constants_ts_2.CHAR_BACKWARD_SLASH) { + break; + } + } + const toLen = toEnd - toStart; + // Compare paths to find the longest common path from root + const length = fromLen < toLen ? fromLen : toLen; + let lastCommonSep = -1; + let i = 0; + for (; i <= length; ++i) { + if (i === length) { + if (toLen > length) { + if ( + to.charCodeAt(toStart + i) === _constants_ts_2.CHAR_BACKWARD_SLASH + ) { + // We get here if `from` is the exact base path for `to`. + // For example: from='C:\\foo\\bar'; to='C:\\foo\\bar\\baz' + return toOrig.slice(toStart + i + 1); + } else if (i === 2) { + // We get here if `from` is the device root. + // For example: from='C:\\'; to='C:\\foo' + return toOrig.slice(toStart + i); + } + } + if (fromLen > length) { + if ( + from.charCodeAt(fromStart + i) === + _constants_ts_2.CHAR_BACKWARD_SLASH + ) { + // We get here if `to` is the exact base path for `from`. + // For example: from='C:\\foo\\bar'; to='C:\\foo' + lastCommonSep = i; + } else if (i === 2) { + // We get here if `to` is the device root. + // For example: from='C:\\foo\\bar'; to='C:\\' + lastCommonSep = 3; + } + } + break; + } + const fromCode = from.charCodeAt(fromStart + i); + const toCode = to.charCodeAt(toStart + i); + if (fromCode !== toCode) { + break; + } else if (fromCode === _constants_ts_2.CHAR_BACKWARD_SLASH) { + lastCommonSep = i; + } + } + // We found a mismatch before the first common path separator was seen, so + // return the original `to`. + if (i !== length && lastCommonSep === -1) { + return toOrig; + } + let out = ""; + if (lastCommonSep === -1) { + lastCommonSep = 0; + } + // Generate the relative path based on the path difference between `to` and + // `from` + for (i = fromStart + lastCommonSep + 1; i <= fromEnd; ++i) { + if ( + i === fromEnd || + from.charCodeAt(i) === _constants_ts_2.CHAR_BACKWARD_SLASH + ) { + if (out.length === 0) { + out += ".."; + } else { + out += "\\.."; + } + } + } + // Lastly, append the rest of the destination (`to`) path that comes after + // the common path parts + if (out.length > 0) { + return out + toOrig.slice(toStart + lastCommonSep, toEnd); + } else { + toStart += lastCommonSep; + if ( + toOrig.charCodeAt(toStart) === _constants_ts_2.CHAR_BACKWARD_SLASH + ) { + ++toStart; + } + return toOrig.slice(toStart, toEnd); + } + } + exports_8("relative", relative); + function toNamespacedPath(path) { + // Note: this will *probably* throw somewhere. + if (typeof path !== "string") { + return path; + } + if (path.length === 0) { + return ""; + } + const resolvedPath = resolve(path); + if (resolvedPath.length >= 3) { + if ( + resolvedPath.charCodeAt(0) === _constants_ts_2.CHAR_BACKWARD_SLASH + ) { + // Possible UNC root + if ( + resolvedPath.charCodeAt(1) === _constants_ts_2.CHAR_BACKWARD_SLASH + ) { + const code = resolvedPath.charCodeAt(2); + if ( + code !== _constants_ts_2.CHAR_QUESTION_MARK && + code !== _constants_ts_2.CHAR_DOT + ) { + // Matched non-long UNC root, convert the path to a long UNC path + return `\\\\?\\UNC\\${resolvedPath.slice(2)}`; + } + } + } else if (_util_ts_1.isWindowsDeviceRoot(resolvedPath.charCodeAt(0))) { + // Possible device root + if ( + resolvedPath.charCodeAt(1) === _constants_ts_2.CHAR_COLON && + resolvedPath.charCodeAt(2) === _constants_ts_2.CHAR_BACKWARD_SLASH + ) { + // Matched device root, convert the path to a long UNC path + return `\\\\?\\${resolvedPath}`; + } + } + } + return path; + } + exports_8("toNamespacedPath", toNamespacedPath); + function dirname(path) { + _util_ts_1.assertPath(path); + const len = path.length; + if (len === 0) { + return "."; + } + let rootEnd = -1; + let end = -1; + let matchedSlash = true; + let offset = 0; + const code = path.charCodeAt(0); + // Try to match a root + if (len > 1) { + if (_util_ts_1.isPathSeparator(code)) { + // Possible UNC root + rootEnd = offset = 1; + if (_util_ts_1.isPathSeparator(path.charCodeAt(1))) { + // Matched double path separator at beginning + let j = 2; + let last = j; + // Match 1 or more non-path separators + for (; j < len; ++j) { + if (_util_ts_1.isPathSeparator(path.charCodeAt(j))) { + break; + } + } + if (j < len && j !== last) { + // Matched! + last = j; + // Match 1 or more path separators + for (; j < len; ++j) { + if (!_util_ts_1.isPathSeparator(path.charCodeAt(j))) { + break; + } + } + if (j < len && j !== last) { + // Matched! + last = j; + // Match 1 or more non-path separators + for (; j < len; ++j) { + if (_util_ts_1.isPathSeparator(path.charCodeAt(j))) { + break; + } + } + if (j === len) { + // We matched a UNC root only + return path; + } + if (j !== last) { + // We matched a UNC root with leftovers + // Offset by 1 to include the separator after the UNC root to + // treat it as a "normal root" on top of a (UNC) root + rootEnd = offset = j + 1; + } + } + } + } + } else if (_util_ts_1.isWindowsDeviceRoot(code)) { + // Possible device root + if (path.charCodeAt(1) === _constants_ts_2.CHAR_COLON) { + rootEnd = offset = 2; + if (len > 2) { + if (_util_ts_1.isPathSeparator(path.charCodeAt(2))) { + rootEnd = offset = 3; + } + } + } + } + } else if (_util_ts_1.isPathSeparator(code)) { + // `path` contains just a path separator, exit early to avoid + // unnecessary work + return path; + } + for (let i = len - 1; i >= offset; --i) { + if (_util_ts_1.isPathSeparator(path.charCodeAt(i))) { + if (!matchedSlash) { + end = i; + break; + } + } else { + // We saw the first non-path separator + matchedSlash = false; + } + } + if (end === -1) { + if (rootEnd === -1) { + return "."; + } else { + end = rootEnd; + } + } + return path.slice(0, end); + } + exports_8("dirname", dirname); + function basename(path, ext = "") { + if (ext !== undefined && typeof ext !== "string") { + throw new TypeError('"ext" argument must be a string'); + } + _util_ts_1.assertPath(path); + let start = 0; + let end = -1; + let matchedSlash = true; + let i; + // Check for a drive letter prefix so as not to mistake the following + // path separator as an extra separator at the end of the path that can be + // disregarded + if (path.length >= 2) { + const drive = path.charCodeAt(0); + if (_util_ts_1.isWindowsDeviceRoot(drive)) { + if (path.charCodeAt(1) === _constants_ts_2.CHAR_COLON) { + start = 2; + } + } + } + if (ext !== undefined && ext.length > 0 && ext.length <= path.length) { + if (ext.length === path.length && ext === path) { + return ""; + } + let extIdx = ext.length - 1; + let firstNonSlashEnd = -1; + for (i = path.length - 1; i >= start; --i) { + const code = path.charCodeAt(i); + if (_util_ts_1.isPathSeparator(code)) { + // If we reached a path separator that was not part of a set of path + // separators at the end of the string, stop now + if (!matchedSlash) { + start = i + 1; + break; + } + } else { + if (firstNonSlashEnd === -1) { + // We saw the first non-path separator, remember this index in case + // we need it if the extension ends up not matching + matchedSlash = false; + firstNonSlashEnd = i + 1; + } + if (extIdx >= 0) { + // Try to match the explicit extension + if (code === ext.charCodeAt(extIdx)) { + if (--extIdx === -1) { + // We matched the extension, so mark this as the end of our path + // component + end = i; + } + } else { + // Extension does not match, so our result is the entire path + // component + extIdx = -1; + end = firstNonSlashEnd; + } + } + } + } + if (start === end) { + end = firstNonSlashEnd; + } else if (end === -1) { + end = path.length; + } + return path.slice(start, end); + } else { + for (i = path.length - 1; i >= start; --i) { + if (_util_ts_1.isPathSeparator(path.charCodeAt(i))) { + // If we reached a path separator that was not part of a set of path + // separators at the end of the string, stop now + if (!matchedSlash) { + start = i + 1; + break; + } + } else if (end === -1) { + // We saw the first non-path separator, mark this as the end of our + // path component + matchedSlash = false; + end = i + 1; + } + } + if (end === -1) { + return ""; + } + return path.slice(start, end); + } + } + exports_8("basename", basename); + function extname(path) { + _util_ts_1.assertPath(path); + let start = 0; + let startDot = -1; + let startPart = 0; + let end = -1; + let matchedSlash = true; + // Track the state of characters (if any) we see before our first dot and + // after any path separator we find + let preDotState = 0; + // Check for a drive letter prefix so as not to mistake the following + // path separator as an extra separator at the end of the path that can be + // disregarded + if ( + path.length >= 2 && + path.charCodeAt(1) === _constants_ts_2.CHAR_COLON && + _util_ts_1.isWindowsDeviceRoot(path.charCodeAt(0)) + ) { + start = startPart = 2; + } + for (let i = path.length - 1; i >= start; --i) { + const code = path.charCodeAt(i); + if (_util_ts_1.isPathSeparator(code)) { + // If we reached a path separator that was not part of a set of path + // separators at the end of the string, stop now + if (!matchedSlash) { + startPart = i + 1; + break; + } + continue; + } + if (end === -1) { + // We saw the first non-path separator, mark this as the end of our + // extension + matchedSlash = false; + end = i + 1; + } + if (code === _constants_ts_2.CHAR_DOT) { + // If this is our first dot, mark it as the start of our extension + if (startDot === -1) { + startDot = i; + } else if (preDotState !== 1) { + preDotState = 1; + } + } else if (startDot !== -1) { + // We saw a non-dot and non-path separator before our dot, so we should + // have a good chance at having a non-empty extension + preDotState = -1; + } + } + if ( + startDot === -1 || + end === -1 || + // We saw a non-dot character immediately before the dot + preDotState === 0 || + // The (right-most) trimmed path component is exactly '..' + (preDotState === 1 && startDot === end - 1 && + startDot === startPart + 1) + ) { + return ""; + } + return path.slice(startDot, end); + } + exports_8("extname", extname); + function format(pathObject) { + /* eslint-disable max-len */ + if (pathObject === null || typeof pathObject !== "object") { + throw new TypeError( + `The "pathObject" argument must be of type Object. Received type ${typeof pathObject}`, + ); + } + return _util_ts_1._format("\\", pathObject); + } + exports_8("format", format); + function parse(path) { + _util_ts_1.assertPath(path); + const ret = { root: "", dir: "", base: "", ext: "", name: "" }; + const len = path.length; + if (len === 0) { + return ret; + } + let rootEnd = 0; + let code = path.charCodeAt(0); + // Try to match a root + if (len > 1) { + if (_util_ts_1.isPathSeparator(code)) { + // Possible UNC root + rootEnd = 1; + if (_util_ts_1.isPathSeparator(path.charCodeAt(1))) { + // Matched double path separator at beginning + let j = 2; + let last = j; + // Match 1 or more non-path separators + for (; j < len; ++j) { + if (_util_ts_1.isPathSeparator(path.charCodeAt(j))) { + break; + } + } + if (j < len && j !== last) { + // Matched! + last = j; + // Match 1 or more path separators + for (; j < len; ++j) { + if (!_util_ts_1.isPathSeparator(path.charCodeAt(j))) { + break; + } + } + if (j < len && j !== last) { + // Matched! + last = j; + // Match 1 or more non-path separators + for (; j < len; ++j) { + if (_util_ts_1.isPathSeparator(path.charCodeAt(j))) { + break; + } + } + if (j === len) { + // We matched a UNC root only + rootEnd = j; + } else if (j !== last) { + // We matched a UNC root with leftovers + rootEnd = j + 1; + } + } + } + } + } else if (_util_ts_1.isWindowsDeviceRoot(code)) { + // Possible device root + if (path.charCodeAt(1) === _constants_ts_2.CHAR_COLON) { + rootEnd = 2; + if (len > 2) { + if (_util_ts_1.isPathSeparator(path.charCodeAt(2))) { + if (len === 3) { + // `path` contains just a drive root, exit early to avoid + // unnecessary work + ret.root = ret.dir = path; + return ret; + } + rootEnd = 3; + } + } else { + // `path` contains just a drive root, exit early to avoid + // unnecessary work + ret.root = ret.dir = path; + return ret; + } + } + } + } else if (_util_ts_1.isPathSeparator(code)) { + // `path` contains just a path separator, exit early to avoid + // unnecessary work + ret.root = ret.dir = path; + return ret; + } + if (rootEnd > 0) { + ret.root = path.slice(0, rootEnd); + } + let startDot = -1; + let startPart = rootEnd; + let end = -1; + let matchedSlash = true; + let i = path.length - 1; + // Track the state of characters (if any) we see before our first dot and + // after any path separator we find + let preDotState = 0; + // Get non-dir info + for (; i >= rootEnd; --i) { + code = path.charCodeAt(i); + if (_util_ts_1.isPathSeparator(code)) { + // If we reached a path separator that was not part of a set of path + // separators at the end of the string, stop now + if (!matchedSlash) { + startPart = i + 1; + break; + } + continue; + } + if (end === -1) { + // We saw the first non-path separator, mark this as the end of our + // extension + matchedSlash = false; + end = i + 1; + } + if (code === _constants_ts_2.CHAR_DOT) { + // If this is our first dot, mark it as the start of our extension + if (startDot === -1) { + startDot = i; + } else if (preDotState !== 1) { + preDotState = 1; + } + } else if (startDot !== -1) { + // We saw a non-dot and non-path separator before our dot, so we should + // have a good chance at having a non-empty extension + preDotState = -1; + } + } + if ( + startDot === -1 || + end === -1 || + // We saw a non-dot character immediately before the dot + preDotState === 0 || + // The (right-most) trimmed path component is exactly '..' + (preDotState === 1 && startDot === end - 1 && + startDot === startPart + 1) + ) { + if (end !== -1) { + ret.base = ret.name = path.slice(startPart, end); + } + } else { + ret.name = path.slice(startPart, startDot); + ret.base = path.slice(startPart, end); + ret.ext = path.slice(startDot, end); + } + // If the directory is the root, use the entire root as the `dir` including + // the trailing slash if any (`C:\abc` -> `C:\`). Otherwise, strip out the + // trailing slash (`C:\abc\def` -> `C:\abc`). + if (startPart > 0 && startPart !== rootEnd) { + ret.dir = path.slice(0, startPart - 1); + } else { + ret.dir = ret.root; + } + return ret; + } + exports_8("parse", parse); + /** Converts a file URL to a path string. + * + * fromFileUrl("file:///C:/Users/foo"); // "C:\\Users\\foo" + * fromFileUrl("file:///home/foo"); // "\\home\\foo" + * + * Note that non-file URLs are treated as file URLs and irrelevant components + * are ignored. + */ + function fromFileUrl(url) { + return new URL(url).pathname + .replace(/^\/*([A-Za-z]:)(\/|$)/, "$1/") + .replace(/\//g, "\\"); + } + exports_8("fromFileUrl", fromFileUrl); + return { + setters: [ + function (_constants_ts_2_1) { + _constants_ts_2 = _constants_ts_2_1; + }, + function (_util_ts_1_1) { + _util_ts_1 = _util_ts_1_1; + }, + function (asserts_ts_1_1) { + asserts_ts_1 = asserts_ts_1_1; + }, + ], + execute: function () { + exports_8("sep", sep = "\\"); + exports_8("delimiter", delimiter = ";"); + }, + }; + }, +); +// Copyright the Browserify authors. MIT License. +// Ported from https://github.com/browserify/path-browserify/ +/** This module is browser compatible. */ +System.register( + "https://deno.land/std@0.56.0/path/posix", + [ + "https://deno.land/std@0.56.0/path/_constants", + "https://deno.land/std@0.56.0/path/_util", + ], + function (exports_9, context_9) { + "use strict"; + var _constants_ts_3, _util_ts_2, sep, delimiter; + var __moduleName = context_9 && context_9.id; + // path.resolve([from ...], to) + function resolve(...pathSegments) { + let resolvedPath = ""; + let resolvedAbsolute = false; + for (let i = pathSegments.length - 1; i >= -1 && !resolvedAbsolute; i--) { + let path; + if (i >= 0) { + path = pathSegments[i]; + } else { + if (globalThis.Deno == null) { + throw new TypeError("Resolved a relative path without a CWD."); + } + path = Deno.cwd(); + } + _util_ts_2.assertPath(path); + // Skip empty entries + if (path.length === 0) { + continue; + } + resolvedPath = `${path}/${resolvedPath}`; + resolvedAbsolute = + path.charCodeAt(0) === _constants_ts_3.CHAR_FORWARD_SLASH; + } + // At this point the path should be resolved to a full absolute path, but + // handle relative paths to be safe (might happen when process.cwd() fails) + // Normalize the path + resolvedPath = _util_ts_2.normalizeString( + resolvedPath, + !resolvedAbsolute, + "/", + _util_ts_2.isPosixPathSeparator, + ); + if (resolvedAbsolute) { + if (resolvedPath.length > 0) { + return `/${resolvedPath}`; + } else { + return "/"; + } + } else if (resolvedPath.length > 0) { + return resolvedPath; + } else { + return "."; + } + } + exports_9("resolve", resolve); + function normalize(path) { + _util_ts_2.assertPath(path); + if (path.length === 0) { + return "."; + } + const isAbsolute = + path.charCodeAt(0) === _constants_ts_3.CHAR_FORWARD_SLASH; + const trailingSeparator = + path.charCodeAt(path.length - 1) === _constants_ts_3.CHAR_FORWARD_SLASH; + // Normalize the path + path = _util_ts_2.normalizeString( + path, + !isAbsolute, + "/", + _util_ts_2.isPosixPathSeparator, + ); + if (path.length === 0 && !isAbsolute) { + path = "."; + } + if (path.length > 0 && trailingSeparator) { + path += "/"; + } + if (isAbsolute) { + return `/${path}`; + } + return path; + } + exports_9("normalize", normalize); + function isAbsolute(path) { + _util_ts_2.assertPath(path); + return path.length > 0 && + path.charCodeAt(0) === _constants_ts_3.CHAR_FORWARD_SLASH; + } + exports_9("isAbsolute", isAbsolute); + function join(...paths) { + if (paths.length === 0) { + return "."; + } + let joined; + for (let i = 0, len = paths.length; i < len; ++i) { + const path = paths[i]; + _util_ts_2.assertPath(path); + if (path.length > 0) { + if (!joined) { + joined = path; + } else { + joined += `/${path}`; + } + } + } + if (!joined) { + return "."; + } + return normalize(joined); + } + exports_9("join", join); + function relative(from, to) { + _util_ts_2.assertPath(from); + _util_ts_2.assertPath(to); + if (from === to) { + return ""; + } + from = resolve(from); + to = resolve(to); + if (from === to) { + return ""; + } + // Trim any leading backslashes + let fromStart = 1; + const fromEnd = from.length; + for (; fromStart < fromEnd; ++fromStart) { + if (from.charCodeAt(fromStart) !== _constants_ts_3.CHAR_FORWARD_SLASH) { + break; + } + } + const fromLen = fromEnd - fromStart; + // Trim any leading backslashes + let toStart = 1; + const toEnd = to.length; + for (; toStart < toEnd; ++toStart) { + if (to.charCodeAt(toStart) !== _constants_ts_3.CHAR_FORWARD_SLASH) { + break; + } + } + const toLen = toEnd - toStart; + // Compare paths to find the longest common path from root + const length = fromLen < toLen ? fromLen : toLen; + let lastCommonSep = -1; + let i = 0; + for (; i <= length; ++i) { + if (i === length) { + if (toLen > length) { + if ( + to.charCodeAt(toStart + i) === _constants_ts_3.CHAR_FORWARD_SLASH + ) { + // We get here if `from` is the exact base path for `to`. + // For example: from='/foo/bar'; to='/foo/bar/baz' + return to.slice(toStart + i + 1); + } else if (i === 0) { + // We get here if `from` is the root + // For example: from='/'; to='/foo' + return to.slice(toStart + i); + } + } else if (fromLen > length) { + if ( + from.charCodeAt(fromStart + i) === + _constants_ts_3.CHAR_FORWARD_SLASH + ) { + // We get here if `to` is the exact base path for `from`. + // For example: from='/foo/bar/baz'; to='/foo/bar' + lastCommonSep = i; + } else if (i === 0) { + // We get here if `to` is the root. + // For example: from='/foo'; to='/' + lastCommonSep = 0; + } + } + break; + } + const fromCode = from.charCodeAt(fromStart + i); + const toCode = to.charCodeAt(toStart + i); + if (fromCode !== toCode) { + break; + } else if (fromCode === _constants_ts_3.CHAR_FORWARD_SLASH) { + lastCommonSep = i; + } + } + let out = ""; + // Generate the relative path based on the path difference between `to` + // and `from` + for (i = fromStart + lastCommonSep + 1; i <= fromEnd; ++i) { + if ( + i === fromEnd || + from.charCodeAt(i) === _constants_ts_3.CHAR_FORWARD_SLASH + ) { + if (out.length === 0) { + out += ".."; + } else { + out += "/.."; + } + } + } + // Lastly, append the rest of the destination (`to`) path that comes after + // the common path parts + if (out.length > 0) { + return out + to.slice(toStart + lastCommonSep); + } else { + toStart += lastCommonSep; + if (to.charCodeAt(toStart) === _constants_ts_3.CHAR_FORWARD_SLASH) { + ++toStart; + } + return to.slice(toStart); + } + } + exports_9("relative", relative); + function toNamespacedPath(path) { + // Non-op on posix systems + return path; + } + exports_9("toNamespacedPath", toNamespacedPath); + function dirname(path) { + _util_ts_2.assertPath(path); + if (path.length === 0) { + return "."; + } + const hasRoot = path.charCodeAt(0) === _constants_ts_3.CHAR_FORWARD_SLASH; + let end = -1; + let matchedSlash = true; + for (let i = path.length - 1; i >= 1; --i) { + if (path.charCodeAt(i) === _constants_ts_3.CHAR_FORWARD_SLASH) { + if (!matchedSlash) { + end = i; + break; + } + } else { + // We saw the first non-path separator + matchedSlash = false; + } + } + if (end === -1) { + return hasRoot ? "/" : "."; + } + if (hasRoot && end === 1) { + return "//"; + } + return path.slice(0, end); + } + exports_9("dirname", dirname); + function basename(path, ext = "") { + if (ext !== undefined && typeof ext !== "string") { + throw new TypeError('"ext" argument must be a string'); + } + _util_ts_2.assertPath(path); + let start = 0; + let end = -1; + let matchedSlash = true; + let i; + if (ext !== undefined && ext.length > 0 && ext.length <= path.length) { + if (ext.length === path.length && ext === path) { + return ""; + } + let extIdx = ext.length - 1; + let firstNonSlashEnd = -1; + for (i = path.length - 1; i >= 0; --i) { + const code = path.charCodeAt(i); + if (code === _constants_ts_3.CHAR_FORWARD_SLASH) { + // If we reached a path separator that was not part of a set of path + // separators at the end of the string, stop now + if (!matchedSlash) { + start = i + 1; + break; + } + } else { + if (firstNonSlashEnd === -1) { + // We saw the first non-path separator, remember this index in case + // we need it if the extension ends up not matching + matchedSlash = false; + firstNonSlashEnd = i + 1; + } + if (extIdx >= 0) { + // Try to match the explicit extension + if (code === ext.charCodeAt(extIdx)) { + if (--extIdx === -1) { + // We matched the extension, so mark this as the end of our path + // component + end = i; + } + } else { + // Extension does not match, so our result is the entire path + // component + extIdx = -1; + end = firstNonSlashEnd; + } + } + } + } + if (start === end) { + end = firstNonSlashEnd; + } else if (end === -1) { + end = path.length; + } + return path.slice(start, end); + } else { + for (i = path.length - 1; i >= 0; --i) { + if (path.charCodeAt(i) === _constants_ts_3.CHAR_FORWARD_SLASH) { + // If we reached a path separator that was not part of a set of path + // separators at the end of the string, stop now + if (!matchedSlash) { + start = i + 1; + break; + } + } else if (end === -1) { + // We saw the first non-path separator, mark this as the end of our + // path component + matchedSlash = false; + end = i + 1; + } + } + if (end === -1) { + return ""; + } + return path.slice(start, end); + } + } + exports_9("basename", basename); + function extname(path) { + _util_ts_2.assertPath(path); + let startDot = -1; + let startPart = 0; + let end = -1; + let matchedSlash = true; + // Track the state of characters (if any) we see before our first dot and + // after any path separator we find + let preDotState = 0; + for (let i = path.length - 1; i >= 0; --i) { + const code = path.charCodeAt(i); + if (code === _constants_ts_3.CHAR_FORWARD_SLASH) { + // If we reached a path separator that was not part of a set of path + // separators at the end of the string, stop now + if (!matchedSlash) { + startPart = i + 1; + break; + } + continue; + } + if (end === -1) { + // We saw the first non-path separator, mark this as the end of our + // extension + matchedSlash = false; + end = i + 1; + } + if (code === _constants_ts_3.CHAR_DOT) { + // If this is our first dot, mark it as the start of our extension + if (startDot === -1) { + startDot = i; + } else if (preDotState !== 1) { + preDotState = 1; + } + } else if (startDot !== -1) { + // We saw a non-dot and non-path separator before our dot, so we should + // have a good chance at having a non-empty extension + preDotState = -1; + } + } + if ( + startDot === -1 || + end === -1 || + // We saw a non-dot character immediately before the dot + preDotState === 0 || + // The (right-most) trimmed path component is exactly '..' + (preDotState === 1 && startDot === end - 1 && + startDot === startPart + 1) + ) { + return ""; + } + return path.slice(startDot, end); + } + exports_9("extname", extname); + function format(pathObject) { + /* eslint-disable max-len */ + if (pathObject === null || typeof pathObject !== "object") { + throw new TypeError( + `The "pathObject" argument must be of type Object. Received type ${typeof pathObject}`, + ); + } + return _util_ts_2._format("/", pathObject); + } + exports_9("format", format); + function parse(path) { + _util_ts_2.assertPath(path); + const ret = { root: "", dir: "", base: "", ext: "", name: "" }; + if (path.length === 0) { + return ret; + } + const isAbsolute = + path.charCodeAt(0) === _constants_ts_3.CHAR_FORWARD_SLASH; + let start; + if (isAbsolute) { + ret.root = "/"; + start = 1; + } else { + start = 0; + } + let startDot = -1; + let startPart = 0; + let end = -1; + let matchedSlash = true; + let i = path.length - 1; + // Track the state of characters (if any) we see before our first dot and + // after any path separator we find + let preDotState = 0; + // Get non-dir info + for (; i >= start; --i) { + const code = path.charCodeAt(i); + if (code === _constants_ts_3.CHAR_FORWARD_SLASH) { + // If we reached a path separator that was not part of a set of path + // separators at the end of the string, stop now + if (!matchedSlash) { + startPart = i + 1; + break; + } + continue; + } + if (end === -1) { + // We saw the first non-path separator, mark this as the end of our + // extension + matchedSlash = false; + end = i + 1; + } + if (code === _constants_ts_3.CHAR_DOT) { + // If this is our first dot, mark it as the start of our extension + if (startDot === -1) { + startDot = i; + } else if (preDotState !== 1) { + preDotState = 1; + } + } else if (startDot !== -1) { + // We saw a non-dot and non-path separator before our dot, so we should + // have a good chance at having a non-empty extension + preDotState = -1; + } + } + if ( + startDot === -1 || + end === -1 || + // We saw a non-dot character immediately before the dot + preDotState === 0 || + // The (right-most) trimmed path component is exactly '..' + (preDotState === 1 && startDot === end - 1 && + startDot === startPart + 1) + ) { + if (end !== -1) { + if (startPart === 0 && isAbsolute) { + ret.base = ret.name = path.slice(1, end); + } else { + ret.base = ret.name = path.slice(startPart, end); + } + } + } else { + if (startPart === 0 && isAbsolute) { + ret.name = path.slice(1, startDot); + ret.base = path.slice(1, end); + } else { + ret.name = path.slice(startPart, startDot); + ret.base = path.slice(startPart, end); + } + ret.ext = path.slice(startDot, end); + } + if (startPart > 0) { + ret.dir = path.slice(0, startPart - 1); + } else if (isAbsolute) { + ret.dir = "/"; + } + return ret; + } + exports_9("parse", parse); + /** Converts a file URL to a path string. + * + * fromFileUrl("file:///home/foo"); // "/home/foo" + * + * Note that non-file URLs are treated as file URLs and irrelevant components + * are ignored. + */ + function fromFileUrl(url) { + return new URL(url).pathname; + } + exports_9("fromFileUrl", fromFileUrl); + return { + setters: [ + function (_constants_ts_3_1) { + _constants_ts_3 = _constants_ts_3_1; + }, + function (_util_ts_2_1) { + _util_ts_2 = _util_ts_2_1; + }, + ], + execute: function () { + exports_9("sep", sep = "/"); + exports_9("delimiter", delimiter = ":"); + }, + }; + }, +); +// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. +/** This module is browser compatible. */ +System.register( + "https://deno.land/std@0.56.0/path/separator", + ["https://deno.land/std@0.56.0/path/_constants"], + function (exports_10, context_10) { + "use strict"; + var _constants_ts_4, SEP, SEP_PATTERN; + var __moduleName = context_10 && context_10.id; + return { + setters: [ + function (_constants_ts_4_1) { + _constants_ts_4 = _constants_ts_4_1; + }, + ], + execute: function () { + exports_10("SEP", SEP = _constants_ts_4.isWindows ? "\\" : "/"); + exports_10( + "SEP_PATTERN", + SEP_PATTERN = _constants_ts_4.isWindows ? /[\\/]+/ : /\/+/, + ); + }, + }; + }, +); +// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. +/** This module is browser compatible. */ +System.register( + "https://deno.land/std@0.56.0/path/common", + ["https://deno.land/std@0.56.0/path/separator"], + function (exports_11, context_11) { + "use strict"; + var separator_ts_1; + var __moduleName = context_11 && context_11.id; + /** Determines the common path from a set of paths, using an optional separator, + * which defaults to the OS default separator. + * + * import { common } from "https://deno.land/std/path/mod.ts"; + * const p = common([ + * "./deno/std/path/mod.ts", + * "./deno/std/fs/mod.ts", + * ]); + * console.log(p); // "./deno/std/" + * + */ + function common(paths, sep = separator_ts_1.SEP) { + 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}`; + } + exports_11("common", common); + return { + setters: [ + function (separator_ts_1_1) { + separator_ts_1 = separator_ts_1_1; + }, + ], + execute: function () { + }, + }; + }, +); +// This file is ported from globrex@0.1.2 +// MIT License +// Copyright (c) 2018 Terkel Gjervig Nielsen +/** This module is browser compatible. */ +System.register( + "https://deno.land/std@0.56.0/path/_globrex", + ["https://deno.land/std@0.56.0/path/_constants"], + function (exports_12, context_12) { + "use strict"; + var _constants_ts_5, + SEP, + SEP_ESC, + SEP_RAW, + GLOBSTAR, + WILDCARD, + GLOBSTAR_SEGMENT, + WILDCARD_SEGMENT; + var __moduleName = context_12 && context_12.id; + /** + * Convert any glob pattern to a JavaScript Regexp object + * @param glob Glob pattern to convert + * @param opts Configuration object + * @returns Converted object with string, segments and RegExp object + */ + function globrex( + glob, + { + extended = false, + globstar = false, + strict = false, + filepath = false, + flags = "", + } = {}, + ) { + const sepPattern = new RegExp(`^${SEP}${strict ? "" : "+"}$`); + let regex = ""; + let segment = ""; + let pathRegexStr = ""; + const pathSegments = []; + // If we are doing extended matching, this boolean is true when we are inside + // a group (eg {*.html,*.js}), and false otherwise. + let inGroup = false; + let inRange = false; + // extglob stack. Keep track of scope + const ext = []; + // Helper function to build string and segments + function add(str, options = { split: false, last: false, only: "" }) { + const { split, last, only } = options; + if (only !== "path") { + regex += str; + } + if (filepath && only !== "regex") { + pathRegexStr += str.match(sepPattern) ? SEP : str; + if (split) { + if (last) { + segment += str; + } + if (segment !== "") { + // change it 'includes' + if (!flags.includes("g")) { + segment = `^${segment}$`; + } + pathSegments.push(new RegExp(segment, flags)); + } + segment = ""; + } else { + segment += str; + } + } + } + let c, n; + for (let i = 0; i < glob.length; i++) { + c = glob[i]; + n = glob[i + 1]; + if (["\\", "$", "^", ".", "="].includes(c)) { + add(`\\${c}`); + continue; + } + if (c.match(sepPattern)) { + add(SEP, { split: true }); + if (n != null && n.match(sepPattern) && !strict) { + regex += "?"; + } + continue; + } + if (c === "(") { + if (ext.length) { + add(`${c}?:`); + continue; + } + add(`\\${c}`); + continue; + } + if (c === ")") { + if (ext.length) { + add(c); + const type = ext.pop(); + if (type === "@") { + add("{1}"); + } else if (type === "!") { + add(WILDCARD); + } else { + add(type); + } + continue; + } + add(`\\${c}`); + continue; + } + if (c === "|") { + if (ext.length) { + add(c); + continue; + } + add(`\\${c}`); + continue; + } + if (c === "+") { + if (n === "(" && extended) { + ext.push(c); + continue; + } + add(`\\${c}`); + continue; + } + if (c === "@" && extended) { + if (n === "(") { + ext.push(c); + continue; + } + } + if (c === "!") { + if (extended) { + if (inRange) { + add("^"); + continue; + } + if (n === "(") { + ext.push(c); + add("(?!"); + i++; + continue; + } + add(`\\${c}`); + continue; + } + add(`\\${c}`); + continue; + } + if (c === "?") { + if (extended) { + if (n === "(") { + ext.push(c); + } else { + add("."); + } + continue; + } + add(`\\${c}`); + continue; + } + if (c === "[") { + if (inRange && n === ":") { + i++; // skip [ + let value = ""; + while (glob[++i] !== ":") { + value += glob[i]; + } + if (value === "alnum") { + add("(?:\\w|\\d)"); + } else if (value === "space") { + add("\\s"); + } else if (value === "digit") { + add("\\d"); + } + i++; // skip last ] + continue; + } + if (extended) { + inRange = true; + add(c); + continue; + } + add(`\\${c}`); + continue; + } + if (c === "]") { + if (extended) { + inRange = false; + add(c); + continue; + } + add(`\\${c}`); + continue; + } + if (c === "{") { + if (extended) { + inGroup = true; + add("(?:"); + continue; + } + add(`\\${c}`); + continue; + } + if (c === "}") { + if (extended) { + inGroup = false; + add(")"); + continue; + } + add(`\\${c}`); + continue; + } + if (c === ",") { + if (inGroup) { + add("|"); + continue; + } + add(`\\${c}`); + continue; + } + if (c === "*") { + if (n === "(" && extended) { + ext.push(c); + continue; + } + // Move over all consecutive "*"'s. + // Also store the previous and next characters + const prevChar = glob[i - 1]; + let starCount = 1; + while (glob[i + 1] === "*") { + starCount++; + i++; + } + const nextChar = glob[i + 1]; + if (!globstar) { + // globstar is disabled, so treat any number of "*" as one + add(".*"); + } else { + // globstar is enabled, so determine if this is a globstar segment + const isGlobstar = starCount > 1 && // multiple "*"'s + // from the start of the segment + [SEP_RAW, "/", undefined].includes(prevChar) && + // to the end of the segment + [SEP_RAW, "/", undefined].includes(nextChar); + if (isGlobstar) { + // it's a globstar, so match zero or more path segments + add(GLOBSTAR, { only: "regex" }); + add(GLOBSTAR_SEGMENT, { only: "path", last: true, split: true }); + i++; // move over the "/" + } else { + // it's not a globstar, so only match one path segment + add(WILDCARD, { only: "regex" }); + add(WILDCARD_SEGMENT, { only: "path" }); + } + } + continue; + } + add(c); + } + // When regexp 'g' flag is specified don't + // constrain the regular expression with ^ & $ + if (!flags.includes("g")) { + regex = `^${regex}$`; + segment = `^${segment}$`; + if (filepath) { + pathRegexStr = `^${pathRegexStr}$`; + } + } + const result = { regex: new RegExp(regex, flags) }; + // Push the last segment + if (filepath) { + pathSegments.push(new RegExp(segment, flags)); + result.path = { + regex: new RegExp(pathRegexStr, flags), + segments: pathSegments, + globstar: new RegExp( + !flags.includes("g") ? `^${GLOBSTAR_SEGMENT}$` : GLOBSTAR_SEGMENT, + flags, + ), + }; + } + return result; + } + exports_12("globrex", globrex); + return { + setters: [ + function (_constants_ts_5_1) { + _constants_ts_5 = _constants_ts_5_1; + }, + ], + execute: function () { + SEP = _constants_ts_5.isWindows ? `(?:\\\\|\\/)` : `\\/`; + SEP_ESC = _constants_ts_5.isWindows ? `\\\\` : `/`; + SEP_RAW = _constants_ts_5.isWindows ? `\\` : `/`; + GLOBSTAR = `(?:(?:[^${SEP_ESC}/]*(?:${SEP_ESC}|\/|$))*)`; + WILDCARD = `(?:[^${SEP_ESC}/]*)`; + GLOBSTAR_SEGMENT = `((?:[^${SEP_ESC}/]*(?:${SEP_ESC}|\/|$))*)`; + WILDCARD_SEGMENT = `(?:[^${SEP_ESC}/]*)`; + }, + }; + }, +); +// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. +/** This module is browser compatible. */ +System.register( + "https://deno.land/std@0.56.0/path/glob", + [ + "https://deno.land/std@0.56.0/path/separator", + "https://deno.land/std@0.56.0/path/_globrex", + "https://deno.land/std@0.56.0/path/mod", + "https://deno.land/std@0.56.0/testing/asserts", + ], + function (exports_13, context_13) { + "use strict"; + var separator_ts_2, _globrex_ts_1, mod_ts_1, asserts_ts_2; + var __moduleName = context_13 && context_13.id; + /** + * Generate a regex based on glob pattern and options + * This was meant to be using the the `fs.walk` function + * but can be used anywhere else. + * Examples: + * + * Looking for all the `ts` files: + * walkSync(".", { + * match: [globToRegExp("*.ts")] + * }) + * + * Looking for all the `.json` files in any subfolder: + * walkSync(".", { + * match: [globToRegExp(join("a", "**", "*.json"),{ + * flags: "g", + * extended: true, + * globstar: true + * })] + * }) + * + * @param glob - Glob pattern to be used + * @param options - Specific options for the glob pattern + * @returns A RegExp for the glob pattern + */ + function globToRegExp(glob, { extended = false, globstar = true } = {}) { + const result = _globrex_ts_1.globrex(glob, { + extended, + globstar, + strict: false, + filepath: true, + }); + asserts_ts_2.assert(result.path != null); + return result.path.regex; + } + exports_13("globToRegExp", globToRegExp); + /** Test whether the given string is a glob */ + function isGlob(str) { + const chars = { "{": "}", "(": ")", "[": "]" }; + /* eslint-disable-next-line max-len */ + const regex = + /\\(.)|(^!|\*|[\].+)]\?|\[[^\\\]]+\]|\{[^\\}]+\}|\(\?[:!=][^\\)]+\)|\([^|]+\|[^\\)]+\))/; + if (str === "") { + return false; + } + let match; + while ((match = regex.exec(str))) { + if (match[2]) { + return true; + } + let idx = match.index + match[0].length; + // if an open bracket/brace/paren is escaped, + // set the index to the next closing character + const open = match[1]; + const close = open ? chars[open] : null; + if (open && close) { + const n = str.indexOf(close, idx); + if (n !== -1) { + idx = n + 1; + } + } + str = str.slice(idx); + } + return false; + } + exports_13("isGlob", isGlob); + /** Like normalize(), but doesn't collapse "**\/.." when `globstar` is true. */ + function normalizeGlob(glob, { globstar = false } = {}) { + if (!!glob.match(/\0/g)) { + throw new Error(`Glob contains invalid characters: "${glob}"`); + } + if (!globstar) { + return mod_ts_1.normalize(glob); + } + const s = separator_ts_2.SEP_PATTERN.source; + const badParentPattern = new RegExp( + `(?<=(${s}|^)\\*\\*${s})\\.\\.(?=${s}|$)`, + "g", + ); + return mod_ts_1.normalize(glob.replace(badParentPattern, "\0")).replace( + /\0/g, + "..", + ); + } + exports_13("normalizeGlob", normalizeGlob); + /** Like join(), but doesn't collapse "**\/.." when `globstar` is true. */ + function joinGlobs(globs, { extended = false, globstar = false } = {}) { + if (!globstar || globs.length == 0) { + return mod_ts_1.join(...globs); + } + if (globs.length === 0) { + return "."; + } + let joined; + for (const glob of globs) { + const path = glob; + if (path.length > 0) { + if (!joined) { + joined = path; + } else { + joined += `${separator_ts_2.SEP}${path}`; + } + } + } + if (!joined) { + return "."; + } + return normalizeGlob(joined, { extended, globstar }); + } + exports_13("joinGlobs", joinGlobs); + return { + setters: [ + function (separator_ts_2_1) { + separator_ts_2 = separator_ts_2_1; + }, + function (_globrex_ts_1_1) { + _globrex_ts_1 = _globrex_ts_1_1; + }, + function (mod_ts_1_1) { + mod_ts_1 = mod_ts_1_1; + }, + function (asserts_ts_2_1) { + asserts_ts_2 = asserts_ts_2_1; + }, + ], + execute: function () { + }, + }; + }, +); +// Copyright the Browserify authors. MIT License. +// Ported mostly from https://github.com/browserify/path-browserify/ +/** This module is browser compatible. */ +System.register( + "https://deno.land/std@0.56.0/path/mod", + [ + "https://deno.land/std@0.56.0/path/_constants", + "https://deno.land/std@0.56.0/path/win32", + "https://deno.land/std@0.56.0/path/posix", + "https://deno.land/std@0.56.0/path/common", + "https://deno.land/std@0.56.0/path/separator", + "https://deno.land/std@0.56.0/path/_interface", + "https://deno.land/std@0.56.0/path/glob", + ], + function (exports_14, context_14) { + "use strict"; + var _constants_ts_6, + _win32, + _posix, + path, + win32, + posix, + basename, + delimiter, + dirname, + extname, + format, + fromFileUrl, + isAbsolute, + join, + normalize, + parse, + relative, + resolve, + sep, + toNamespacedPath; + var __moduleName = context_14 && context_14.id; + var exportedNames_1 = { + "win32": true, + "posix": true, + "basename": true, + "delimiter": true, + "dirname": true, + "extname": true, + "format": true, + "fromFileUrl": true, + "isAbsolute": true, + "join": true, + "normalize": true, + "parse": true, + "relative": true, + "resolve": true, + "sep": true, + "toNamespacedPath": true, + "SEP": true, + "SEP_PATTERN": true, + }; + function exportStar_1(m) { + var exports = {}; + for (var n in m) { + if (n !== "default" && !exportedNames_1.hasOwnProperty(n)) { + exports[n] = m[n]; + } + } + exports_14(exports); + } + return { + setters: [ + function (_constants_ts_6_1) { + _constants_ts_6 = _constants_ts_6_1; + }, + function (_win32_1) { + _win32 = _win32_1; + }, + function (_posix_1) { + _posix = _posix_1; + }, + function (common_ts_1_1) { + exportStar_1(common_ts_1_1); + }, + function (separator_ts_3_1) { + exports_14({ + "SEP": separator_ts_3_1["SEP"], + "SEP_PATTERN": separator_ts_3_1["SEP_PATTERN"], + }); + }, + function (_interface_ts_1_1) { + exportStar_1(_interface_ts_1_1); + }, + function (glob_ts_1_1) { + exportStar_1(glob_ts_1_1); + }, + ], + execute: function () { + path = _constants_ts_6.isWindows ? _win32 : _posix; + exports_14("win32", win32 = _win32); + exports_14("posix", posix = _posix); + exports_14("basename", basename = path.basename), + exports_14("delimiter", delimiter = path.delimiter), + exports_14("dirname", dirname = path.dirname), + exports_14("extname", extname = path.extname), + exports_14("format", format = path.format), + exports_14("fromFileUrl", fromFileUrl = path.fromFileUrl), + exports_14("isAbsolute", isAbsolute = path.isAbsolute), + exports_14("join", join = path.join), + exports_14("normalize", normalize = path.normalize), + exports_14("parse", parse = path.parse), + exports_14("relative", relative = path.relative), + exports_14("resolve", resolve = path.resolve), + exports_14("sep", sep = path.sep), + exports_14( + "toNamespacedPath", + toNamespacedPath = path.toNamespacedPath, + ); + }, + }; + }, +); +System.register( + "https://deno.land/std@0.56.0/io/util", + [ + "https://deno.land/std@0.56.0/path/mod", + "https://deno.land/std@0.56.0/encoding/utf8", + ], + function (exports_15, context_15) { + "use strict"; + var Buffer, mkdir, open, path, utf8_ts_1; + var __moduleName = context_15 && context_15.id; + /** + * Copy bytes from one Uint8Array to another. Bytes from `src` which don't fit + * into `dst` will not be copied. + * + * @param src Source byte array + * @param dst Destination byte array + * @param off Offset into `dst` at which to begin writing values from `src`. + * @return number of bytes copied + */ + function copyBytes(src, dst, off = 0) { + off = Math.max(0, Math.min(off, dst.byteLength)); + const dstBytesAvailable = dst.byteLength - off; + if (src.byteLength > dstBytesAvailable) { + src = src.subarray(0, dstBytesAvailable); + } + dst.set(src, off); + return src.byteLength; + } + exports_15("copyBytes", copyBytes); + function charCode(s) { + return s.charCodeAt(0); + } + exports_15("charCode", charCode); + function stringsReader(s) { + return new Buffer(utf8_ts_1.encode(s).buffer); + } + exports_15("stringsReader", stringsReader); + /** Create or open a temporal file at specified directory with prefix and + * postfix + * */ + async function tempFile(dir, opts = { prefix: "", postfix: "" }) { + const r = Math.floor(Math.random() * 1000000); + const filepath = path.resolve( + `${dir}/${opts.prefix || ""}${r}${opts.postfix || ""}`, + ); + await mkdir(path.dirname(filepath), { recursive: true }); + const file = await open(filepath, { + create: true, + read: true, + write: true, + append: true, + }); + return { file, filepath }; + } + exports_15("tempFile", tempFile); + return { + setters: [ + function (path_1) { + path = path_1; + }, + function (utf8_ts_1_1) { + utf8_ts_1 = utf8_ts_1_1; + }, + ], + execute: function () { + // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. + Buffer = Deno.Buffer, mkdir = Deno.mkdir, open = Deno.open; + }, + }; + }, +); +// Based on https://github.com/golang/go/blob/891682/src/bufio/bufio.go +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +System.register( + "https://deno.land/std@0.56.0/io/bufio", + [ + "https://deno.land/std@0.56.0/io/util", + "https://deno.land/std@0.56.0/testing/asserts", + ], + function (exports_16, context_16) { + "use strict"; + var util_ts_1, + asserts_ts_3, + DEFAULT_BUF_SIZE, + MIN_BUF_SIZE, + MAX_CONSECUTIVE_EMPTY_READS, + CR, + LF, + BufferFullError, + PartialReadError, + BufReader, + AbstractBufBase, + BufWriter, + BufWriterSync; + var __moduleName = context_16 && context_16.id; + /** Generate longest proper prefix which is also suffix array. */ + function createLPS(pat) { + const lps = new Uint8Array(pat.length); + lps[0] = 0; + let prefixEnd = 0; + let i = 1; + while (i < lps.length) { + if (pat[i] == pat[prefixEnd]) { + prefixEnd++; + lps[i] = prefixEnd; + i++; + } else if (prefixEnd === 0) { + lps[i] = 0; + i++; + } else { + prefixEnd = pat[prefixEnd - 1]; + } + } + return lps; + } + /** Read delimited bytes from a Reader. */ + async function* readDelim(reader, delim) { + // Avoid unicode problems + const delimLen = delim.length; + const delimLPS = createLPS(delim); + let inputBuffer = new Deno.Buffer(); + const inspectArr = new Uint8Array(Math.max(1024, delimLen + 1)); + // Modified KMP + let inspectIndex = 0; + let matchIndex = 0; + while (true) { + const result = await reader.read(inspectArr); + if (result === null) { + // Yield last chunk. + yield inputBuffer.bytes(); + return; + } + if (result < 0) { + // Discard all remaining and silently fail. + return; + } + const sliceRead = inspectArr.subarray(0, result); + await Deno.writeAll(inputBuffer, sliceRead); + let sliceToProcess = inputBuffer.bytes(); + while (inspectIndex < sliceToProcess.length) { + if (sliceToProcess[inspectIndex] === delim[matchIndex]) { + inspectIndex++; + matchIndex++; + if (matchIndex === delimLen) { + // Full match + const matchEnd = inspectIndex - delimLen; + const readyBytes = sliceToProcess.subarray(0, matchEnd); + // Copy + const pendingBytes = sliceToProcess.slice(inspectIndex); + yield readyBytes; + // Reset match, different from KMP. + sliceToProcess = pendingBytes; + inspectIndex = 0; + matchIndex = 0; + } + } else { + if (matchIndex === 0) { + inspectIndex++; + } else { + matchIndex = delimLPS[matchIndex - 1]; + } + } + } + // Keep inspectIndex and matchIndex. + inputBuffer = new Deno.Buffer(sliceToProcess); + } + } + exports_16("readDelim", readDelim); + /** Read delimited strings from a Reader. */ + async function* readStringDelim(reader, delim) { + const encoder = new TextEncoder(); + const decoder = new TextDecoder(); + for await (const chunk of readDelim(reader, encoder.encode(delim))) { + yield decoder.decode(chunk); + } + } + exports_16("readStringDelim", readStringDelim); + /** Read strings line-by-line from a Reader. */ + // eslint-disable-next-line require-await + async function* readLines(reader) { + yield* readStringDelim(reader, "\n"); + } + exports_16("readLines", readLines); + return { + setters: [ + function (util_ts_1_1) { + util_ts_1 = util_ts_1_1; + }, + function (asserts_ts_3_1) { + asserts_ts_3 = asserts_ts_3_1; + }, + ], + execute: function () { + DEFAULT_BUF_SIZE = 4096; + MIN_BUF_SIZE = 16; + MAX_CONSECUTIVE_EMPTY_READS = 100; + CR = util_ts_1.charCode("\r"); + LF = util_ts_1.charCode("\n"); + BufferFullError = class BufferFullError extends Error { + constructor(partial) { + super("Buffer full"); + this.partial = partial; + this.name = "BufferFullError"; + } + }; + exports_16("BufferFullError", BufferFullError); + PartialReadError = class PartialReadError + extends Deno.errors.UnexpectedEof { + constructor() { + super("Encountered UnexpectedEof, data only partially read"); + this.name = "PartialReadError"; + } + }; + exports_16("PartialReadError", PartialReadError); + /** BufReader implements buffering for a Reader object. */ + BufReader = class BufReader { + constructor(rd, size = DEFAULT_BUF_SIZE) { + this.r = 0; // buf read position. + this.w = 0; // buf write position. + this.eof = false; + if (size < MIN_BUF_SIZE) { + size = MIN_BUF_SIZE; + } + this._reset(new Uint8Array(size), rd); + } + // private lastByte: number; + // private lastCharSize: number; + /** return new BufReader unless r is BufReader */ + static create(r, size = DEFAULT_BUF_SIZE) { + return r instanceof BufReader ? r : new BufReader(r, size); + } + /** Returns the size of the underlying buffer in bytes. */ + size() { + return this.buf.byteLength; + } + buffered() { + return this.w - this.r; + } + // Reads a new chunk into the buffer. + async _fill() { + // Slide existing data to beginning. + if (this.r > 0) { + this.buf.copyWithin(0, this.r, this.w); + this.w -= this.r; + this.r = 0; + } + if (this.w >= this.buf.byteLength) { + throw Error("bufio: tried to fill full buffer"); + } + // Read new data: try a limited number of times. + for (let i = MAX_CONSECUTIVE_EMPTY_READS; i > 0; i--) { + const rr = await this.rd.read(this.buf.subarray(this.w)); + if (rr === null) { + this.eof = true; + return; + } + asserts_ts_3.assert(rr >= 0, "negative read"); + this.w += rr; + if (rr > 0) { + return; + } + } + throw new Error( + `No progress after ${MAX_CONSECUTIVE_EMPTY_READS} read() calls`, + ); + } + /** Discards any buffered data, resets all state, and switches + * the buffered reader to read from r. + */ + reset(r) { + this._reset(this.buf, r); + } + _reset(buf, rd) { + this.buf = buf; + this.rd = rd; + this.eof = false; + // this.lastByte = -1; + // this.lastCharSize = -1; + } + /** reads data into p. + * It returns the number of bytes read into p. + * The bytes are taken from at most one Read on the underlying Reader, + * hence n may be less than len(p). + * To read exactly len(p) bytes, use io.ReadFull(b, p). + */ + async read(p) { + let rr = p.byteLength; + if (p.byteLength === 0) { + return rr; + } + if (this.r === this.w) { + if (p.byteLength >= this.buf.byteLength) { + // Large read, empty buffer. + // Read directly into p to avoid copy. + const rr = await this.rd.read(p); + const nread = rr ?? 0; + asserts_ts_3.assert(nread >= 0, "negative read"); + // if (rr.nread > 0) { + // this.lastByte = p[rr.nread - 1]; + // this.lastCharSize = -1; + // } + return rr; + } + // One read. + // Do not use this.fill, which will loop. + this.r = 0; + this.w = 0; + rr = await this.rd.read(this.buf); + if (rr === 0 || rr === null) { + return rr; + } + asserts_ts_3.assert(rr >= 0, "negative read"); + this.w += rr; + } + // copy as much as we can + const copied = util_ts_1.copyBytes( + this.buf.subarray(this.r, this.w), + p, + 0, + ); + this.r += copied; + // this.lastByte = this.buf[this.r - 1]; + // this.lastCharSize = -1; + return copied; + } + /** reads exactly `p.length` bytes into `p`. + * + * If successful, `p` is returned. + * + * If the end of the underlying stream has been reached, and there are no more + * bytes available in the buffer, `readFull()` returns `null` instead. + * + * An error is thrown if some bytes could be read, but not enough to fill `p` + * entirely before the underlying stream reported an error or EOF. Any error + * thrown will have a `partial` property that indicates the slice of the + * buffer that has been successfully filled with data. + * + * Ported from https://golang.org/pkg/io/#ReadFull + */ + async readFull(p) { + let bytesRead = 0; + while (bytesRead < p.length) { + try { + const rr = await this.read(p.subarray(bytesRead)); + if (rr === null) { + if (bytesRead === 0) { + return null; + } else { + throw new PartialReadError(); + } + } + bytesRead += rr; + } catch (err) { + err.partial = p.subarray(0, bytesRead); + throw err; + } + } + return p; + } + /** Returns the next byte [0, 255] or `null`. */ + async readByte() { + while (this.r === this.w) { + if (this.eof) { + return null; + } + await this._fill(); // buffer is empty. + } + const c = this.buf[this.r]; + this.r++; + // this.lastByte = c; + return c; + } + /** readString() reads until the first occurrence of delim in the input, + * returning a string containing the data up to and including the delimiter. + * If ReadString encounters an error before finding a delimiter, + * it returns the data read before the error and the error itself + * (often `null`). + * ReadString returns err != nil if and only if the returned data does not end + * in delim. + * For simple uses, a Scanner may be more convenient. + */ + async readString(delim) { + if (delim.length !== 1) { + throw new Error("Delimiter should be a single character"); + } + const buffer = await this.readSlice(delim.charCodeAt(0)); + if (buffer === null) { + return null; + } + return new TextDecoder().decode(buffer); + } + /** `readLine()` is a low-level line-reading primitive. Most callers should + * use `readString('\n')` instead or use a Scanner. + * + * `readLine()` tries to return a single line, not including the end-of-line + * bytes. If the line was too long for the buffer then `more` is set and the + * beginning of the line is returned. The rest of the line will be returned + * from future calls. `more` will be false when returning the last fragment + * of the line. The returned buffer is only valid until the next call to + * `readLine()`. + * + * The text returned from ReadLine does not include the line end ("\r\n" or + * "\n"). + * + * When the end of the underlying stream is reached, the final bytes in the + * stream are returned. No indication or error is given if the input ends + * without a final line end. When there are no more trailing bytes to read, + * `readLine()` returns `null`. + * + * Calling `unreadByte()` after `readLine()` will always unread the last byte + * read (possibly a character belonging to the line end) even if that byte is + * not part of the line returned by `readLine()`. + */ + async readLine() { + let line; + try { + line = await this.readSlice(LF); + } catch (err) { + let { partial } = err; + asserts_ts_3.assert( + partial instanceof Uint8Array, + "bufio: caught error from `readSlice()` without `partial` property", + ); + // Don't throw if `readSlice()` failed with `BufferFullError`, instead we + // just return whatever is available and set the `more` flag. + if (!(err instanceof BufferFullError)) { + throw err; + } + // Handle the case where "\r\n" straddles the buffer. + if ( + !this.eof && + partial.byteLength > 0 && + partial[partial.byteLength - 1] === CR + ) { + // Put the '\r' back on buf and drop it from line. + // Let the next call to ReadLine check for "\r\n". + asserts_ts_3.assert( + this.r > 0, + "bufio: tried to rewind past start of buffer", + ); + this.r--; + partial = partial.subarray(0, partial.byteLength - 1); + } + return { line: partial, more: !this.eof }; + } + if (line === null) { + return null; + } + if (line.byteLength === 0) { + return { line, more: false }; + } + if (line[line.byteLength - 1] == LF) { + let drop = 1; + if (line.byteLength > 1 && line[line.byteLength - 2] === CR) { + drop = 2; + } + line = line.subarray(0, line.byteLength - drop); + } + return { line, more: false }; + } + /** `readSlice()` reads until the first occurrence of `delim` in the input, + * returning a slice pointing at the bytes in the buffer. The bytes stop + * being valid at the next read. + * + * If `readSlice()` encounters an error before finding a delimiter, or the + * buffer fills without finding a delimiter, it throws an error with a + * `partial` property that contains the entire buffer. + * + * If `readSlice()` encounters the end of the underlying stream and there are + * any bytes left in the buffer, the rest of the buffer is returned. In other + * words, EOF is always treated as a delimiter. Once the buffer is empty, + * it returns `null`. + * + * Because the data returned from `readSlice()` will be overwritten by the + * next I/O operation, most clients should use `readString()` instead. + */ + async readSlice(delim) { + let s = 0; // search start index + let slice; + while (true) { + // Search buffer. + let i = this.buf.subarray(this.r + s, this.w).indexOf(delim); + if (i >= 0) { + i += s; + slice = this.buf.subarray(this.r, this.r + i + 1); + this.r += i + 1; + break; + } + // EOF? + if (this.eof) { + if (this.r === this.w) { + return null; + } + slice = this.buf.subarray(this.r, this.w); + this.r = this.w; + break; + } + // Buffer full? + if (this.buffered() >= this.buf.byteLength) { + this.r = this.w; + // #4521 The internal buffer should not be reused across reads because it causes corruption of data. + const oldbuf = this.buf; + const newbuf = this.buf.slice(0); + this.buf = newbuf; + throw new BufferFullError(oldbuf); + } + s = this.w - this.r; // do not rescan area we scanned before + // Buffer is not full. + try { + await this._fill(); + } catch (err) { + err.partial = slice; + throw err; + } + } + // Handle last byte, if any. + // const i = slice.byteLength - 1; + // if (i >= 0) { + // this.lastByte = slice[i]; + // this.lastCharSize = -1 + // } + return slice; + } + /** `peek()` returns the next `n` bytes without advancing the reader. The + * bytes stop being valid at the next read call. + * + * When the end of the underlying stream is reached, but there are unread + * bytes left in the buffer, those bytes are returned. If there are no bytes + * left in the buffer, it returns `null`. + * + * If an error is encountered before `n` bytes are available, `peek()` throws + * an error with the `partial` property set to a slice of the buffer that + * contains the bytes that were available before the error occurred. + */ + async peek(n) { + if (n < 0) { + throw Error("negative count"); + } + let avail = this.w - this.r; + while (avail < n && avail < this.buf.byteLength && !this.eof) { + try { + await this._fill(); + } catch (err) { + err.partial = this.buf.subarray(this.r, this.w); + throw err; + } + avail = this.w - this.r; + } + if (avail === 0 && this.eof) { + return null; + } else if (avail < n && this.eof) { + return this.buf.subarray(this.r, this.r + avail); + } else if (avail < n) { + throw new BufferFullError(this.buf.subarray(this.r, this.w)); + } + return this.buf.subarray(this.r, this.r + n); + } + }; + exports_16("BufReader", BufReader); + AbstractBufBase = class AbstractBufBase { + constructor() { + this.usedBufferBytes = 0; + this.err = null; + } + /** Size returns the size of the underlying buffer in bytes. */ + size() { + return this.buf.byteLength; + } + /** Returns how many bytes are unused in the buffer. */ + available() { + return this.buf.byteLength - this.usedBufferBytes; + } + /** buffered returns the number of bytes that have been written into the + * current buffer. + */ + buffered() { + return this.usedBufferBytes; + } + checkBytesWritten(numBytesWritten) { + if (numBytesWritten < this.usedBufferBytes) { + if (numBytesWritten > 0) { + this.buf.copyWithin(0, numBytesWritten, this.usedBufferBytes); + this.usedBufferBytes -= numBytesWritten; + } + this.err = new Error("Short write"); + throw this.err; + } + } + }; + /** BufWriter implements buffering for an deno.Writer object. + * If an error occurs writing to a Writer, no more data will be + * accepted and all subsequent writes, and flush(), will return the error. + * After all data has been written, the client should call the + * flush() method to guarantee all data has been forwarded to + * the underlying deno.Writer. + */ + BufWriter = class BufWriter extends AbstractBufBase { + constructor(writer, size = DEFAULT_BUF_SIZE) { + super(); + this.writer = writer; + if (size <= 0) { + size = DEFAULT_BUF_SIZE; + } + this.buf = new Uint8Array(size); + } + /** return new BufWriter unless writer is BufWriter */ + static create(writer, size = DEFAULT_BUF_SIZE) { + return writer instanceof BufWriter ? writer + : new BufWriter(writer, size); + } + /** Discards any unflushed buffered data, clears any error, and + * resets buffer to write its output to w. + */ + reset(w) { + this.err = null; + this.usedBufferBytes = 0; + this.writer = w; + } + /** Flush writes any buffered data to the underlying io.Writer. */ + async flush() { + if (this.err !== null) { + throw this.err; + } + if (this.usedBufferBytes === 0) { + return; + } + let numBytesWritten = 0; + try { + numBytesWritten = await this.writer.write( + this.buf.subarray(0, this.usedBufferBytes), + ); + } catch (e) { + this.err = e; + throw e; + } + this.checkBytesWritten(numBytesWritten); + this.usedBufferBytes = 0; + } + /** Writes the contents of `data` into the buffer. If the contents won't fully + * fit into the buffer, those bytes that can are copied into the buffer, the + * buffer is the flushed to the writer and the remaining bytes are copied into + * the now empty buffer. + * + * @return the number of bytes written to the buffer. + */ + async write(data) { + if (this.err !== null) { + throw this.err; + } + if (data.length === 0) { + return 0; + } + let totalBytesWritten = 0; + let numBytesWritten = 0; + while (data.byteLength > this.available()) { + if (this.buffered() === 0) { + // Large write, empty buffer. + // Write directly from data to avoid copy. + try { + numBytesWritten = await this.writer.write(data); + } catch (e) { + this.err = e; + throw e; + } + } else { + numBytesWritten = util_ts_1.copyBytes( + data, + this.buf, + this.usedBufferBytes, + ); + this.usedBufferBytes += numBytesWritten; + await this.flush(); + } + totalBytesWritten += numBytesWritten; + data = data.subarray(numBytesWritten); + } + numBytesWritten = util_ts_1.copyBytes( + data, + this.buf, + this.usedBufferBytes, + ); + this.usedBufferBytes += numBytesWritten; + totalBytesWritten += numBytesWritten; + return totalBytesWritten; + } + }; + exports_16("BufWriter", BufWriter); + /** BufWriterSync implements buffering for a deno.WriterSync object. + * If an error occurs writing to a WriterSync, no more data will be + * accepted and all subsequent writes, and flush(), will return the error. + * After all data has been written, the client should call the + * flush() method to guarantee all data has been forwarded to + * the underlying deno.WriterSync. + */ + BufWriterSync = class BufWriterSync extends AbstractBufBase { + constructor(writer, size = DEFAULT_BUF_SIZE) { + super(); + this.writer = writer; + if (size <= 0) { + size = DEFAULT_BUF_SIZE; + } + this.buf = new Uint8Array(size); + } + /** return new BufWriterSync unless writer is BufWriterSync */ + static create(writer, size = DEFAULT_BUF_SIZE) { + return writer instanceof BufWriterSync + ? writer + : new BufWriterSync(writer, size); + } + /** Discards any unflushed buffered data, clears any error, and + * resets buffer to write its output to w. + */ + reset(w) { + this.err = null; + this.usedBufferBytes = 0; + this.writer = w; + } + /** Flush writes any buffered data to the underlying io.WriterSync. */ + flush() { + if (this.err !== null) { + throw this.err; + } + if (this.usedBufferBytes === 0) { + return; + } + let numBytesWritten = 0; + try { + numBytesWritten = this.writer.writeSync( + this.buf.subarray(0, this.usedBufferBytes), + ); + } catch (e) { + this.err = e; + throw e; + } + this.checkBytesWritten(numBytesWritten); + this.usedBufferBytes = 0; + } + /** Writes the contents of `data` into the buffer. If the contents won't fully + * fit into the buffer, those bytes that can are copied into the buffer, the + * buffer is the flushed to the writer and the remaining bytes are copied into + * the now empty buffer. + * + * @return the number of bytes written to the buffer. + */ + writeSync(data) { + if (this.err !== null) { + throw this.err; + } + if (data.length === 0) { + return 0; + } + let totalBytesWritten = 0; + let numBytesWritten = 0; + while (data.byteLength > this.available()) { + if (this.buffered() === 0) { + // Large write, empty buffer. + // Write directly from data to avoid copy. + try { + numBytesWritten = this.writer.writeSync(data); + } catch (e) { + this.err = e; + throw e; + } + } else { + numBytesWritten = util_ts_1.copyBytes( + data, + this.buf, + this.usedBufferBytes, + ); + this.usedBufferBytes += numBytesWritten; + this.flush(); + } + totalBytesWritten += numBytesWritten; + data = data.subarray(numBytesWritten); + } + numBytesWritten = util_ts_1.copyBytes( + data, + this.buf, + this.usedBufferBytes, + ); + this.usedBufferBytes += numBytesWritten; + totalBytesWritten += numBytesWritten; + return totalBytesWritten; + } + }; + exports_16("BufWriterSync", BufWriterSync); + }, + }; + }, +); +System.register( + "https://deno.land/std@0.56.0/async/deferred", + [], + function (exports_17, context_17) { + "use strict"; + var __moduleName = context_17 && context_17.id; + /** Creates a Promise with the `reject` and `resolve` functions + * placed as methods on the promise object itself. It allows you to do: + * + * const p = deferred(); + * // ... + * p.resolve(42); + */ + function deferred() { + let methods; + const promise = new Promise((resolve, reject) => { + methods = { resolve, reject }; + }); + return Object.assign(promise, methods); + } + exports_17("deferred", deferred); + return { + setters: [], + execute: function () { + }, + }; + }, +); +System.register( + "https://deno.land/std@0.56.0/async/delay", + [], + function (exports_18, context_18) { + "use strict"; + var __moduleName = context_18 && context_18.id; + // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. + /* Resolves after the given number of milliseconds. */ + function delay(ms) { + return new Promise((res) => + setTimeout(() => { + res(); + }, ms) + ); + } + exports_18("delay", delay); + return { + setters: [], + execute: function () { + }, + }; + }, +); +System.register( + "https://deno.land/std@0.56.0/async/mux_async_iterator", + ["https://deno.land/std@0.56.0/async/deferred"], + function (exports_19, context_19) { + "use strict"; + var deferred_ts_1, MuxAsyncIterator; + var __moduleName = context_19 && context_19.id; + return { + setters: [ + function (deferred_ts_1_1) { + deferred_ts_1 = deferred_ts_1_1; + }, + ], + execute: function () { + /** The MuxAsyncIterator class multiplexes multiple async iterators into a + * single stream. It currently makes a few assumptions: + * - The iterators do not throw. + * - The final result (the value returned and not yielded from the iterator) + * does not matter; if there is any, it is discarded. + */ + MuxAsyncIterator = class MuxAsyncIterator { + constructor() { + this.iteratorCount = 0; + this.yields = []; + this.signal = deferred_ts_1.deferred(); + } + add(iterator) { + ++this.iteratorCount; + this.callIteratorNext(iterator); + } + async callIteratorNext(iterator) { + const { value, done } = await iterator.next(); + if (done) { + --this.iteratorCount; + } else { + this.yields.push({ iterator, value }); + } + this.signal.resolve(); + } + async *iterate() { + while (this.iteratorCount > 0) { + // Sleep until any of the wrapped iterators yields. + await this.signal; + // Note that while we're looping over `yields`, new items may be added. + for (let i = 0; i < this.yields.length; i++) { + const { iterator, value } = this.yields[i]; + yield value; + this.callIteratorNext(iterator); + } + // Clear the `yields` list and reset the `signal` promise. + this.yields.length = 0; + this.signal = deferred_ts_1.deferred(); + } + } + [Symbol.asyncIterator]() { + return this.iterate(); + } + }; + exports_19("MuxAsyncIterator", MuxAsyncIterator); + }, + }; + }, +); +System.register( + "https://deno.land/std@0.56.0/async/mod", + [ + "https://deno.land/std@0.56.0/async/deferred", + "https://deno.land/std@0.56.0/async/delay", + "https://deno.land/std@0.56.0/async/mux_async_iterator", + ], + function (exports_20, context_20) { + "use strict"; + var __moduleName = context_20 && context_20.id; + function exportStar_2(m) { + var exports = {}; + for (var n in m) { + if (n !== "default") exports[n] = m[n]; + } + exports_20(exports); + } + return { + setters: [ + function (deferred_ts_2_1) { + exportStar_2(deferred_ts_2_1); + }, + function (delay_ts_1_1) { + exportStar_2(delay_ts_1_1); + }, + function (mux_async_iterator_ts_1_1) { + exportStar_2(mux_async_iterator_ts_1_1); + }, + ], + execute: function () { + }, + }; + }, +); +System.register( + "https://deno.land/std@0.56.0/bytes/mod", + ["https://deno.land/std@0.56.0/io/util"], + function (exports_21, context_21) { + "use strict"; + var util_ts_2; + var __moduleName = context_21 && context_21.id; + /** Find first index of binary pattern from a. If not found, then return -1 + * @param source soruce array + * @param pat pattern to find in source array + */ + function findIndex(source, pat) { + const s = pat[0]; + for (let i = 0; i < source.length; i++) { + if (source[i] !== s) { + continue; + } + const pin = i; + let matched = 1; + let j = i; + while (matched < pat.length) { + j++; + if (source[j] !== pat[j - pin]) { + break; + } + matched++; + } + if (matched === pat.length) { + return pin; + } + } + return -1; + } + exports_21("findIndex", findIndex); + /** Find last index of binary pattern from a. If not found, then return -1. + * @param source soruce array + * @param pat pattern to find in source array + */ + function findLastIndex(source, pat) { + const e = pat[pat.length - 1]; + for (let i = source.length - 1; i >= 0; i--) { + if (source[i] !== e) { + continue; + } + const pin = i; + let matched = 1; + let j = i; + while (matched < pat.length) { + j--; + if (source[j] !== pat[pat.length - 1 - (pin - j)]) { + break; + } + matched++; + } + if (matched === pat.length) { + return pin - pat.length + 1; + } + } + return -1; + } + exports_21("findLastIndex", findLastIndex); + /** Check whether binary arrays are equal to each other. + * @param source first array to check equality + * @param match second array to check equality + */ + function equal(source, match) { + if (source.length !== match.length) { + return false; + } + for (let i = 0; i < match.length; i++) { + if (source[i] !== match[i]) { + return false; + } + } + return true; + } + exports_21("equal", equal); + /** Check whether binary array starts with prefix. + * @param source srouce array + * @param prefix prefix array to check in source + */ + function hasPrefix(source, prefix) { + for (let i = 0, max = prefix.length; i < max; i++) { + if (source[i] !== prefix[i]) { + return false; + } + } + return true; + } + exports_21("hasPrefix", hasPrefix); + /** Check whether binary array ends with suffix. + * @param source srouce array + * @param suffix suffix array to check in source + */ + function hasSuffix(source, suffix) { + for ( + let srci = source.length - 1, sfxi = suffix.length - 1; + sfxi >= 0; + srci--, sfxi-- + ) { + if (source[srci] !== suffix[sfxi]) { + return false; + } + } + return true; + } + exports_21("hasSuffix", hasSuffix); + /** Repeat bytes. returns a new byte slice consisting of `count` copies of `b`. + * @param origin The origin bytes + * @param count The count you want to repeat. + */ + function repeat(origin, count) { + if (count === 0) { + return new Uint8Array(); + } + if (count < 0) { + throw new Error("bytes: negative repeat count"); + } else if ((origin.length * count) / count !== origin.length) { + throw new Error("bytes: repeat count causes overflow"); + } + const int = Math.floor(count); + if (int !== count) { + throw new Error("bytes: repeat count must be an integer"); + } + const nb = new Uint8Array(origin.length * count); + let bp = util_ts_2.copyBytes(origin, nb); + for (; bp < nb.length; bp *= 2) { + util_ts_2.copyBytes(nb.slice(0, bp), nb, bp); + } + return nb; + } + exports_21("repeat", repeat); + /** Concatenate two binary arrays and return new one. + * @param origin origin array to concatenate + * @param b array to concatenate with origin + */ + function concat(origin, b) { + const output = new Uint8Array(origin.length + b.length); + output.set(origin, 0); + output.set(b, origin.length); + return output; + } + exports_21("concat", concat); + /** Check srouce array contains pattern array. + * @param source srouce array + * @param pat patter array + */ + function contains(source, pat) { + return findIndex(source, pat) != -1; + } + exports_21("contains", contains); + return { + setters: [ + function (util_ts_2_1) { + util_ts_2 = util_ts_2_1; + }, + ], + execute: function () { + }, + }; + }, +); +// Based on https://github.com/golang/go/tree/master/src/net/textproto +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +System.register( + "https://deno.land/std@0.56.0/textproto/mod", + [ + "https://deno.land/std@0.56.0/io/util", + "https://deno.land/std@0.56.0/bytes/mod", + "https://deno.land/std@0.56.0/encoding/utf8", + ], + function (exports_22, context_22) { + "use strict"; + var util_ts_3, mod_ts_2, utf8_ts_2, invalidHeaderCharRegex, TextProtoReader; + var __moduleName = context_22 && context_22.id; + function str(buf) { + if (buf == null) { + return ""; + } else { + return utf8_ts_2.decode(buf); + } + } + return { + setters: [ + function (util_ts_3_1) { + util_ts_3 = util_ts_3_1; + }, + function (mod_ts_2_1) { + mod_ts_2 = mod_ts_2_1; + }, + function (utf8_ts_2_1) { + utf8_ts_2 = utf8_ts_2_1; + }, + ], + execute: function () { + // FROM https://github.com/denoland/deno/blob/b34628a26ab0187a827aa4ebe256e23178e25d39/cli/js/web/headers.ts#L9 + invalidHeaderCharRegex = /[^\t\x20-\x7e\x80-\xff]/g; + TextProtoReader = class TextProtoReader { + constructor(r) { + this.r = r; + } + /** readLine() reads a single line from the TextProtoReader, + * eliding the final \n or \r\n from the returned string. + */ + async readLine() { + const s = await this.readLineSlice(); + if (s === null) { + return null; + } + return str(s); + } + /** ReadMIMEHeader reads a MIME-style header from r. + * The header is a sequence of possibly continued Key: Value lines + * ending in a blank line. + * The returned map m maps CanonicalMIMEHeaderKey(key) to a + * sequence of values in the same order encountered in the input. + * + * For example, consider this input: + * + * My-Key: Value 1 + * Long-Key: Even + * Longer Value + * My-Key: Value 2 + * + * Given that input, ReadMIMEHeader returns the map: + * + * map[string][]string{ + * "My-Key": {"Value 1", "Value 2"}, + * "Long-Key": {"Even Longer Value"}, + * } + */ + async readMIMEHeader() { + const m = new Headers(); + let line; + // The first line cannot start with a leading space. + let buf = await this.r.peek(1); + if (buf === null) { + return null; + } else if ( + buf[0] == util_ts_3.charCode(" ") || + buf[0] == util_ts_3.charCode("\t") + ) { + line = (await this.readLineSlice()); + } + buf = await this.r.peek(1); + if (buf === null) { + throw new Deno.errors.UnexpectedEof(); + } else if ( + buf[0] == util_ts_3.charCode(" ") || + buf[0] == util_ts_3.charCode("\t") + ) { + throw new Deno.errors.InvalidData( + `malformed MIME header initial line: ${str(line)}`, + ); + } + while (true) { + const kv = await this.readLineSlice(); // readContinuedLineSlice + if (kv === null) { + throw new Deno.errors.UnexpectedEof(); + } + if (kv.byteLength === 0) { + return m; + } + // Key ends at first colon + let i = kv.indexOf(util_ts_3.charCode(":")); + if (i < 0) { + throw new Deno.errors.InvalidData( + `malformed MIME header line: ${str(kv)}`, + ); + } + //let key = canonicalMIMEHeaderKey(kv.subarray(0, endKey)); + const key = str(kv.subarray(0, i)); + // As per RFC 7230 field-name is a token, + // tokens consist of one or more chars. + // We could throw `Deno.errors.InvalidData` here, + // but better to be liberal in what we + // accept, so if we get an empty key, skip it. + if (key == "") { + continue; + } + // Skip initial spaces in value. + i++; // skip colon + while ( + i < kv.byteLength && + (kv[i] == util_ts_3.charCode(" ") || + kv[i] == util_ts_3.charCode("\t")) + ) { + i++; + } + const value = str(kv.subarray(i)).replace( + invalidHeaderCharRegex, + encodeURI, + ); + // In case of invalid header we swallow the error + // example: "Audio Mode" => invalid due to space in the key + try { + m.append(key, value); + } catch {} + } + } + async readLineSlice() { + // this.closeDot(); + let line; + while (true) { + const r = await this.r.readLine(); + if (r === null) { + return null; + } + const { line: l, more } = r; + // Avoid the copy if the first call produced a full line. + if (!line && !more) { + // TODO(ry): + // This skipSpace() is definitely misplaced, but I don't know where it + // comes from nor how to fix it. + if (this.skipSpace(l) === 0) { + return new Uint8Array(0); + } + return l; + } + line = line ? mod_ts_2.concat(line, l) : l; + if (!more) { + break; + } + } + return line; + } + skipSpace(l) { + let n = 0; + for (let i = 0; i < l.length; i++) { + if ( + l[i] === util_ts_3.charCode(" ") || + l[i] === util_ts_3.charCode("\t") + ) { + continue; + } + n++; + } + return n; + } + }; + exports_22("TextProtoReader", TextProtoReader); + }, + }; + }, +); +// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. +System.register( + "https://deno.land/std@0.56.0/http/http_status", + [], + function (exports_23, context_23) { + "use strict"; + var Status, STATUS_TEXT; + var __moduleName = context_23 && context_23.id; + return { + setters: [], + execute: function () { + /** HTTP status codes */ + (function (Status) { + /** RFC 7231, 6.2.1 */ + Status[Status["Continue"] = 100] = "Continue"; + /** RFC 7231, 6.2.2 */ + Status[Status["SwitchingProtocols"] = 101] = "SwitchingProtocols"; + /** RFC 2518, 10.1 */ + Status[Status["Processing"] = 102] = "Processing"; + /** RFC 8297 **/ + Status[Status["EarlyHints"] = 103] = "EarlyHints"; + /** RFC 7231, 6.3.1 */ + Status[Status["OK"] = 200] = "OK"; + /** RFC 7231, 6.3.2 */ + Status[Status["Created"] = 201] = "Created"; + /** RFC 7231, 6.3.3 */ + Status[Status["Accepted"] = 202] = "Accepted"; + /** RFC 7231, 6.3.4 */ + Status[Status["NonAuthoritativeInfo"] = 203] = "NonAuthoritativeInfo"; + /** RFC 7231, 6.3.5 */ + Status[Status["NoContent"] = 204] = "NoContent"; + /** RFC 7231, 6.3.6 */ + Status[Status["ResetContent"] = 205] = "ResetContent"; + /** RFC 7233, 4.1 */ + Status[Status["PartialContent"] = 206] = "PartialContent"; + /** RFC 4918, 11.1 */ + Status[Status["MultiStatus"] = 207] = "MultiStatus"; + /** RFC 5842, 7.1 */ + Status[Status["AlreadyReported"] = 208] = "AlreadyReported"; + /** RFC 3229, 10.4.1 */ + Status[Status["IMUsed"] = 226] = "IMUsed"; + /** RFC 7231, 6.4.1 */ + Status[Status["MultipleChoices"] = 300] = "MultipleChoices"; + /** RFC 7231, 6.4.2 */ + Status[Status["MovedPermanently"] = 301] = "MovedPermanently"; + /** RFC 7231, 6.4.3 */ + Status[Status["Found"] = 302] = "Found"; + /** RFC 7231, 6.4.4 */ + Status[Status["SeeOther"] = 303] = "SeeOther"; + /** RFC 7232, 4.1 */ + Status[Status["NotModified"] = 304] = "NotModified"; + /** RFC 7231, 6.4.5 */ + Status[Status["UseProxy"] = 305] = "UseProxy"; + /** RFC 7231, 6.4.7 */ + Status[Status["TemporaryRedirect"] = 307] = "TemporaryRedirect"; + /** RFC 7538, 3 */ + Status[Status["PermanentRedirect"] = 308] = "PermanentRedirect"; + /** RFC 7231, 6.5.1 */ + Status[Status["BadRequest"] = 400] = "BadRequest"; + /** RFC 7235, 3.1 */ + Status[Status["Unauthorized"] = 401] = "Unauthorized"; + /** RFC 7231, 6.5.2 */ + Status[Status["PaymentRequired"] = 402] = "PaymentRequired"; + /** RFC 7231, 6.5.3 */ + Status[Status["Forbidden"] = 403] = "Forbidden"; + /** RFC 7231, 6.5.4 */ + Status[Status["NotFound"] = 404] = "NotFound"; + /** RFC 7231, 6.5.5 */ + Status[Status["MethodNotAllowed"] = 405] = "MethodNotAllowed"; + /** RFC 7231, 6.5.6 */ + Status[Status["NotAcceptable"] = 406] = "NotAcceptable"; + /** RFC 7235, 3.2 */ + Status[Status["ProxyAuthRequired"] = 407] = "ProxyAuthRequired"; + /** RFC 7231, 6.5.7 */ + Status[Status["RequestTimeout"] = 408] = "RequestTimeout"; + /** RFC 7231, 6.5.8 */ + Status[Status["Conflict"] = 409] = "Conflict"; + /** RFC 7231, 6.5.9 */ + Status[Status["Gone"] = 410] = "Gone"; + /** RFC 7231, 6.5.10 */ + Status[Status["LengthRequired"] = 411] = "LengthRequired"; + /** RFC 7232, 4.2 */ + Status[Status["PreconditionFailed"] = 412] = "PreconditionFailed"; + /** RFC 7231, 6.5.11 */ + Status[Status["RequestEntityTooLarge"] = 413] = + "RequestEntityTooLarge"; + /** RFC 7231, 6.5.12 */ + Status[Status["RequestURITooLong"] = 414] = "RequestURITooLong"; + /** RFC 7231, 6.5.13 */ + Status[Status["UnsupportedMediaType"] = 415] = "UnsupportedMediaType"; + /** RFC 7233, 4.4 */ + Status[Status["RequestedRangeNotSatisfiable"] = 416] = + "RequestedRangeNotSatisfiable"; + /** RFC 7231, 6.5.14 */ + Status[Status["ExpectationFailed"] = 417] = "ExpectationFailed"; + /** RFC 7168, 2.3.3 */ + Status[Status["Teapot"] = 418] = "Teapot"; + /** RFC 7540, 9.1.2 */ + Status[Status["MisdirectedRequest"] = 421] = "MisdirectedRequest"; + /** RFC 4918, 11.2 */ + Status[Status["UnprocessableEntity"] = 422] = "UnprocessableEntity"; + /** RFC 4918, 11.3 */ + Status[Status["Locked"] = 423] = "Locked"; + /** RFC 4918, 11.4 */ + Status[Status["FailedDependency"] = 424] = "FailedDependency"; + /** RFC 8470, 5.2 */ + Status[Status["TooEarly"] = 425] = "TooEarly"; + /** RFC 7231, 6.5.15 */ + Status[Status["UpgradeRequired"] = 426] = "UpgradeRequired"; + /** RFC 6585, 3 */ + Status[Status["PreconditionRequired"] = 428] = "PreconditionRequired"; + /** RFC 6585, 4 */ + Status[Status["TooManyRequests"] = 429] = "TooManyRequests"; + /** RFC 6585, 5 */ + Status[Status["RequestHeaderFieldsTooLarge"] = 431] = + "RequestHeaderFieldsTooLarge"; + /** RFC 7725, 3 */ + Status[Status["UnavailableForLegalReasons"] = 451] = + "UnavailableForLegalReasons"; + /** RFC 7231, 6.6.1 */ + Status[Status["InternalServerError"] = 500] = "InternalServerError"; + /** RFC 7231, 6.6.2 */ + Status[Status["NotImplemented"] = 501] = "NotImplemented"; + /** RFC 7231, 6.6.3 */ + Status[Status["BadGateway"] = 502] = "BadGateway"; + /** RFC 7231, 6.6.4 */ + Status[Status["ServiceUnavailable"] = 503] = "ServiceUnavailable"; + /** RFC 7231, 6.6.5 */ + Status[Status["GatewayTimeout"] = 504] = "GatewayTimeout"; + /** RFC 7231, 6.6.6 */ + Status[Status["HTTPVersionNotSupported"] = 505] = + "HTTPVersionNotSupported"; + /** RFC 2295, 8.1 */ + Status[Status["VariantAlsoNegotiates"] = 506] = + "VariantAlsoNegotiates"; + /** RFC 4918, 11.5 */ + Status[Status["InsufficientStorage"] = 507] = "InsufficientStorage"; + /** RFC 5842, 7.2 */ + Status[Status["LoopDetected"] = 508] = "LoopDetected"; + /** RFC 2774, 7 */ + Status[Status["NotExtended"] = 510] = "NotExtended"; + /** RFC 6585, 6 */ + Status[Status["NetworkAuthenticationRequired"] = 511] = + "NetworkAuthenticationRequired"; + })(Status || (Status = {})); + exports_23("Status", Status); + exports_23( + "STATUS_TEXT", + STATUS_TEXT = new Map([ + [Status.Continue, "Continue"], + [Status.SwitchingProtocols, "Switching Protocols"], + [Status.Processing, "Processing"], + [Status.EarlyHints, "Early Hints"], + [Status.OK, "OK"], + [Status.Created, "Created"], + [Status.Accepted, "Accepted"], + [Status.NonAuthoritativeInfo, "Non-Authoritative Information"], + [Status.NoContent, "No Content"], + [Status.ResetContent, "Reset Content"], + [Status.PartialContent, "Partial Content"], + [Status.MultiStatus, "Multi-Status"], + [Status.AlreadyReported, "Already Reported"], + [Status.IMUsed, "IM Used"], + [Status.MultipleChoices, "Multiple Choices"], + [Status.MovedPermanently, "Moved Permanently"], + [Status.Found, "Found"], + [Status.SeeOther, "See Other"], + [Status.NotModified, "Not Modified"], + [Status.UseProxy, "Use Proxy"], + [Status.TemporaryRedirect, "Temporary Redirect"], + [Status.PermanentRedirect, "Permanent Redirect"], + [Status.BadRequest, "Bad Request"], + [Status.Unauthorized, "Unauthorized"], + [Status.PaymentRequired, "Payment Required"], + [Status.Forbidden, "Forbidden"], + [Status.NotFound, "Not Found"], + [Status.MethodNotAllowed, "Method Not Allowed"], + [Status.NotAcceptable, "Not Acceptable"], + [Status.ProxyAuthRequired, "Proxy Authentication Required"], + [Status.RequestTimeout, "Request Timeout"], + [Status.Conflict, "Conflict"], + [Status.Gone, "Gone"], + [Status.LengthRequired, "Length Required"], + [Status.PreconditionFailed, "Precondition Failed"], + [Status.RequestEntityTooLarge, "Request Entity Too Large"], + [Status.RequestURITooLong, "Request URI Too Long"], + [Status.UnsupportedMediaType, "Unsupported Media Type"], + [ + Status.RequestedRangeNotSatisfiable, + "Requested Range Not Satisfiable", + ], + [Status.ExpectationFailed, "Expectation Failed"], + [Status.Teapot, "I'm a teapot"], + [Status.MisdirectedRequest, "Misdirected Request"], + [Status.UnprocessableEntity, "Unprocessable Entity"], + [Status.Locked, "Locked"], + [Status.FailedDependency, "Failed Dependency"], + [Status.TooEarly, "Too Early"], + [Status.UpgradeRequired, "Upgrade Required"], + [Status.PreconditionRequired, "Precondition Required"], + [Status.TooManyRequests, "Too Many Requests"], + [ + Status.RequestHeaderFieldsTooLarge, + "Request Header Fields Too Large", + ], + [ + Status.UnavailableForLegalReasons, + "Unavailable For Legal Reasons", + ], + [Status.InternalServerError, "Internal Server Error"], + [Status.NotImplemented, "Not Implemented"], + [Status.BadGateway, "Bad Gateway"], + [Status.ServiceUnavailable, "Service Unavailable"], + [Status.GatewayTimeout, "Gateway Timeout"], + [Status.HTTPVersionNotSupported, "HTTP Version Not Supported"], + [Status.VariantAlsoNegotiates, "Variant Also Negotiates"], + [Status.InsufficientStorage, "Insufficient Storage"], + [Status.LoopDetected, "Loop Detected"], + [Status.NotExtended, "Not Extended"], + [ + Status.NetworkAuthenticationRequired, + "Network Authentication Required", + ], + ]), + ); + }, + }; + }, +); +System.register( + "https://deno.land/std@0.56.0/http/_io", + [ + "https://deno.land/std@0.56.0/io/bufio", + "https://deno.land/std@0.56.0/textproto/mod", + "https://deno.land/std@0.56.0/testing/asserts", + "https://deno.land/std@0.56.0/encoding/utf8", + "https://deno.land/std@0.56.0/http/server", + "https://deno.land/std@0.56.0/http/http_status", + ], + function (exports_24, context_24) { + "use strict"; + var bufio_ts_1, + mod_ts_3, + asserts_ts_4, + utf8_ts_3, + server_ts_1, + http_status_ts_1; + var __moduleName = context_24 && context_24.id; + function emptyReader() { + return { + read(_) { + return Promise.resolve(null); + }, + }; + } + exports_24("emptyReader", emptyReader); + function bodyReader(contentLength, r) { + let totalRead = 0; + let finished = false; + async function read(buf) { + if (finished) { + return null; + } + let result; + const remaining = contentLength - totalRead; + if (remaining >= buf.byteLength) { + result = await r.read(buf); + } else { + const readBuf = buf.subarray(0, remaining); + result = await r.read(readBuf); + } + if (result !== null) { + totalRead += result; + } + finished = totalRead === contentLength; + return result; + } + return { read }; + } + exports_24("bodyReader", bodyReader); + function chunkedBodyReader(h, r) { + // Based on https://tools.ietf.org/html/rfc2616#section-19.4.6 + const tp = new mod_ts_3.TextProtoReader(r); + let finished = false; + const chunks = []; + async function read(buf) { + if (finished) { + return null; + } + const [chunk] = chunks; + if (chunk) { + const chunkRemaining = chunk.data.byteLength - chunk.offset; + const readLength = Math.min(chunkRemaining, buf.byteLength); + for (let i = 0; i < readLength; i++) { + buf[i] = chunk.data[chunk.offset + i]; + } + chunk.offset += readLength; + if (chunk.offset === chunk.data.byteLength) { + chunks.shift(); + // Consume \r\n; + if ((await tp.readLine()) === null) { + throw new Deno.errors.UnexpectedEof(); + } + } + return readLength; + } + const line = await tp.readLine(); + if (line === null) { + throw new Deno.errors.UnexpectedEof(); + } + // TODO: handle chunk extension + const [chunkSizeString] = line.split(";"); + const chunkSize = parseInt(chunkSizeString, 16); + if (Number.isNaN(chunkSize) || chunkSize < 0) { + throw new Error("Invalid chunk size"); + } + if (chunkSize > 0) { + if (chunkSize > buf.byteLength) { + let eof = await r.readFull(buf); + if (eof === null) { + throw new Deno.errors.UnexpectedEof(); + } + const restChunk = new Uint8Array(chunkSize - buf.byteLength); + eof = await r.readFull(restChunk); + if (eof === null) { + throw new Deno.errors.UnexpectedEof(); + } else { + chunks.push({ + offset: 0, + data: restChunk, + }); + } + return buf.byteLength; + } else { + const bufToFill = buf.subarray(0, chunkSize); + const eof = await r.readFull(bufToFill); + if (eof === null) { + throw new Deno.errors.UnexpectedEof(); + } + // Consume \r\n + if ((await tp.readLine()) === null) { + throw new Deno.errors.UnexpectedEof(); + } + return chunkSize; + } + } else { + asserts_ts_4.assert(chunkSize === 0); + // Consume \r\n + if ((await r.readLine()) === null) { + throw new Deno.errors.UnexpectedEof(); + } + await readTrailers(h, r); + finished = true; + return null; + } + } + return { read }; + } + exports_24("chunkedBodyReader", chunkedBodyReader); + function isProhibidedForTrailer(key) { + const s = new Set(["transfer-encoding", "content-length", "trailer"]); + return s.has(key.toLowerCase()); + } + /** + * Read trailer headers from reader and append values to headers. + * "trailer" field will be deleted. + * */ + async function readTrailers(headers, r) { + const headerKeys = parseTrailer(headers.get("trailer")); + if (!headerKeys) { + return; + } + const tp = new mod_ts_3.TextProtoReader(r); + const result = await tp.readMIMEHeader(); + asserts_ts_4.assert(result !== null, "trailer must be set"); + for (const [k, v] of result) { + if (!headerKeys.has(k)) { + throw new Error("Undeclared trailer field"); + } + headerKeys.delete(k); + headers.append(k, v); + } + asserts_ts_4.assert( + Array.from(headerKeys).length === 0, + "Missing trailers", + ); + headers.delete("trailer"); + } + exports_24("readTrailers", readTrailers); + function parseTrailer(field) { + if (field == null) { + return undefined; + } + const keys = field.split(",").map((v) => v.trim().toLowerCase()); + if (keys.length === 0) { + throw new Error("Empty trailer"); + } + for (const key of keys) { + if (isProhibidedForTrailer(key)) { + throw new Error(`Prohibited field for trailer`); + } + } + return new Headers(keys.map((key) => [key, ""])); + } + async function writeChunkedBody(w, r) { + const writer = bufio_ts_1.BufWriter.create(w); + for await (const chunk of Deno.iter(r)) { + if (chunk.byteLength <= 0) { + continue; + } + const start = utf8_ts_3.encoder.encode( + `${chunk.byteLength.toString(16)}\r\n`, + ); + const end = utf8_ts_3.encoder.encode("\r\n"); + await writer.write(start); + await writer.write(chunk); + await writer.write(end); + } + const endChunk = utf8_ts_3.encoder.encode("0\r\n\r\n"); + await writer.write(endChunk); + } + exports_24("writeChunkedBody", writeChunkedBody); + /** write trailer headers to writer. it mostly should be called after writeResponse */ + async function writeTrailers(w, headers, trailers) { + const trailer = headers.get("trailer"); + if (trailer === null) { + throw new Error('response headers must have "trailer" header field'); + } + const transferEncoding = headers.get("transfer-encoding"); + if (transferEncoding === null || !transferEncoding.match(/^chunked/)) { + throw new Error( + `trailer headers is only allowed for "transfer-encoding: chunked": got "${transferEncoding}"`, + ); + } + const writer = bufio_ts_1.BufWriter.create(w); + const trailerHeaderFields = trailer + .split(",") + .map((s) => s.trim().toLowerCase()); + for (const f of trailerHeaderFields) { + asserts_ts_4.assert( + !isProhibidedForTrailer(f), + `"${f}" is prohibited for trailer header`, + ); + } + for (const [key, value] of trailers) { + asserts_ts_4.assert( + trailerHeaderFields.includes(key), + `Not trailer header field: ${key}`, + ); + await writer.write(utf8_ts_3.encoder.encode(`${key}: ${value}\r\n`)); + } + await writer.write(utf8_ts_3.encoder.encode("\r\n")); + await writer.flush(); + } + exports_24("writeTrailers", writeTrailers); + async function writeResponse(w, r) { + const protoMajor = 1; + const protoMinor = 1; + const statusCode = r.status || 200; + const statusText = http_status_ts_1.STATUS_TEXT.get(statusCode); + const writer = bufio_ts_1.BufWriter.create(w); + if (!statusText) { + throw new Deno.errors.InvalidData("Bad status code"); + } + if (!r.body) { + r.body = new Uint8Array(); + } + if (typeof r.body === "string") { + r.body = utf8_ts_3.encoder.encode(r.body); + } + let out = + `HTTP/${protoMajor}.${protoMinor} ${statusCode} ${statusText}\r\n`; + const headers = r.headers ?? new Headers(); + if (r.body && !headers.get("content-length")) { + if (r.body instanceof Uint8Array) { + out += `content-length: ${r.body.byteLength}\r\n`; + } else if (!headers.get("transfer-encoding")) { + out += "transfer-encoding: chunked\r\n"; + } + } + for (const [key, value] of headers) { + out += `${key}: ${value}\r\n`; + } + out += `\r\n`; + const header = utf8_ts_3.encoder.encode(out); + const n = await writer.write(header); + asserts_ts_4.assert(n === header.byteLength); + if (r.body instanceof Uint8Array) { + const n = await writer.write(r.body); + asserts_ts_4.assert(n === r.body.byteLength); + } else if (headers.has("content-length")) { + const contentLength = headers.get("content-length"); + asserts_ts_4.assert(contentLength != null); + const bodyLength = parseInt(contentLength); + const n = await Deno.copy(r.body, writer); + asserts_ts_4.assert(n === bodyLength); + } else { + await writeChunkedBody(writer, r.body); + } + if (r.trailers) { + const t = await r.trailers(); + await writeTrailers(writer, headers, t); + } + await writer.flush(); + } + exports_24("writeResponse", writeResponse); + /** + * ParseHTTPVersion parses a HTTP version string. + * "HTTP/1.0" returns (1, 0). + * Ported from https://github.com/golang/go/blob/f5c43b9/src/net/http/request.go#L766-L792 + */ + function parseHTTPVersion(vers) { + switch (vers) { + case "HTTP/1.1": + return [1, 1]; + case "HTTP/1.0": + return [1, 0]; + default: { + const Big = 1000000; // arbitrary upper bound + if (!vers.startsWith("HTTP/")) { + break; + } + const dot = vers.indexOf("."); + if (dot < 0) { + break; + } + const majorStr = vers.substring(vers.indexOf("/") + 1, dot); + const major = Number(majorStr); + if (!Number.isInteger(major) || major < 0 || major > Big) { + break; + } + const minorStr = vers.substring(dot + 1); + const minor = Number(minorStr); + if (!Number.isInteger(minor) || minor < 0 || minor > Big) { + break; + } + return [major, minor]; + } + } + throw new Error(`malformed HTTP version ${vers}`); + } + exports_24("parseHTTPVersion", parseHTTPVersion); + async function readRequest(conn, bufr) { + const tp = new mod_ts_3.TextProtoReader(bufr); + const firstLine = await tp.readLine(); // e.g. GET /index.html HTTP/1.0 + if (firstLine === null) { + return null; + } + const headers = await tp.readMIMEHeader(); + if (headers === null) { + throw new Deno.errors.UnexpectedEof(); + } + const req = new server_ts_1.ServerRequest(); + req.conn = conn; + req.r = bufr; + [req.method, req.url, req.proto] = firstLine.split(" ", 3); + [req.protoMinor, req.protoMajor] = parseHTTPVersion(req.proto); + req.headers = headers; + fixLength(req); + return req; + } + exports_24("readRequest", readRequest); + function fixLength(req) { + const contentLength = req.headers.get("Content-Length"); + if (contentLength) { + const arrClen = contentLength.split(","); + if (arrClen.length > 1) { + const distinct = [...new Set(arrClen.map((e) => e.trim()))]; + if (distinct.length > 1) { + throw Error("cannot contain multiple Content-Length headers"); + } else { + req.headers.set("Content-Length", distinct[0]); + } + } + const c = req.headers.get("Content-Length"); + if (req.method === "HEAD" && c && c !== "0") { + throw Error("http: method cannot contain a Content-Length"); + } + if (c && req.headers.has("transfer-encoding")) { + // A sender MUST NOT send a Content-Length header field in any message + // that contains a Transfer-Encoding header field. + // rfc: https://tools.ietf.org/html/rfc7230#section-3.3.2 + throw new Error( + "http: Transfer-Encoding and Content-Length cannot be send together", + ); + } + } + } + return { + setters: [ + function (bufio_ts_1_1) { + bufio_ts_1 = bufio_ts_1_1; + }, + function (mod_ts_3_1) { + mod_ts_3 = mod_ts_3_1; + }, + function (asserts_ts_4_1) { + asserts_ts_4 = asserts_ts_4_1; + }, + function (utf8_ts_3_1) { + utf8_ts_3 = utf8_ts_3_1; + }, + function (server_ts_1_1) { + server_ts_1 = server_ts_1_1; + }, + function (http_status_ts_1_1) { + http_status_ts_1 = http_status_ts_1_1; + }, + ], + execute: function () { + }, + }; + }, +); +System.register( + "https://deno.land/std@0.56.0/http/server", + [ + "https://deno.land/std@0.56.0/encoding/utf8", + "https://deno.land/std@0.56.0/io/bufio", + "https://deno.land/std@0.56.0/testing/asserts", + "https://deno.land/std@0.56.0/async/mod", + "https://deno.land/std@0.56.0/http/_io", + ], + function (exports_25, context_25) { + "use strict"; + var utf8_ts_4, + bufio_ts_2, + asserts_ts_5, + mod_ts_4, + _io_ts_1, + listen, + listenTls, + ServerRequest, + Server; + var __moduleName = context_25 && context_25.id; + /** + * Create a HTTP server + * + * import { serve } from "https://deno.land/std/http/server.ts"; + * const body = "Hello World\n"; + * const server = serve({ port: 8000 }); + * for await (const req of server) { + * req.respond({ body }); + * } + */ + function serve(addr) { + if (typeof addr === "string") { + const [hostname, port] = addr.split(":"); + addr = { hostname, port: Number(port) }; + } + const listener = listen(addr); + return new Server(listener); + } + exports_25("serve", serve); + /** + * Start an HTTP server with given options and request handler + * + * const body = "Hello World\n"; + * const options = { port: 8000 }; + * listenAndServe(options, (req) => { + * req.respond({ body }); + * }); + * + * @param options Server configuration + * @param handler Request handler + */ + async function listenAndServe(addr, handler) { + const server = serve(addr); + for await (const request of server) { + handler(request); + } + } + exports_25("listenAndServe", listenAndServe); + /** + * Create an HTTPS server with given options + * + * const body = "Hello HTTPS"; + * const options = { + * hostname: "localhost", + * port: 443, + * certFile: "./path/to/localhost.crt", + * keyFile: "./path/to/localhost.key", + * }; + * for await (const req of serveTLS(options)) { + * req.respond({ body }); + * } + * + * @param options Server configuration + * @return Async iterable server instance for incoming requests + */ + function serveTLS(options) { + const tlsOptions = { + ...options, + transport: "tcp", + }; + const listener = listenTls(tlsOptions); + return new Server(listener); + } + exports_25("serveTLS", serveTLS); + /** + * Start an HTTPS server with given options and request handler + * + * const body = "Hello HTTPS"; + * const options = { + * hostname: "localhost", + * port: 443, + * certFile: "./path/to/localhost.crt", + * keyFile: "./path/to/localhost.key", + * }; + * listenAndServeTLS(options, (req) => { + * req.respond({ body }); + * }); + * + * @param options Server configuration + * @param handler Request handler + */ + async function listenAndServeTLS(options, handler) { + const server = serveTLS(options); + for await (const request of server) { + handler(request); + } + } + exports_25("listenAndServeTLS", listenAndServeTLS); + return { + setters: [ + function (utf8_ts_4_1) { + utf8_ts_4 = utf8_ts_4_1; + }, + function (bufio_ts_2_1) { + bufio_ts_2 = bufio_ts_2_1; + }, + function (asserts_ts_5_1) { + asserts_ts_5 = asserts_ts_5_1; + }, + function (mod_ts_4_1) { + mod_ts_4 = mod_ts_4_1; + }, + function (_io_ts_1_1) { + _io_ts_1 = _io_ts_1_1; + }, + ], + execute: function () { + listen = Deno.listen, listenTls = Deno.listenTls; + ServerRequest = class ServerRequest { + constructor() { + this.done = mod_ts_4.deferred(); + this._contentLength = undefined; + this._body = null; + this.finalized = false; + } + /** + * Value of Content-Length header. + * If null, then content length is invalid or not given (e.g. chunked encoding). + */ + get contentLength() { + // undefined means not cached. + // null means invalid or not provided. + if (this._contentLength === undefined) { + const cl = this.headers.get("content-length"); + if (cl) { + this._contentLength = parseInt(cl); + // Convert NaN to null (as NaN harder to test) + if (Number.isNaN(this._contentLength)) { + this._contentLength = null; + } + } else { + this._contentLength = null; + } + } + return this._contentLength; + } + /** + * Body of the request. The easiest way to consume the body is: + * + * const buf: Uint8Array = await Deno.readAll(req.body); + */ + get body() { + if (!this._body) { + if (this.contentLength != null) { + this._body = _io_ts_1.bodyReader(this.contentLength, this.r); + } else { + const transferEncoding = this.headers.get("transfer-encoding"); + if (transferEncoding != null) { + const parts = transferEncoding + .split(",") + .map((e) => e.trim().toLowerCase()); + asserts_ts_5.assert( + parts.includes("chunked"), + 'transfer-encoding must include "chunked" if content-length is not set', + ); + this._body = _io_ts_1.chunkedBodyReader(this.headers, this.r); + } else { + // Neither content-length nor transfer-encoding: chunked + this._body = _io_ts_1.emptyReader(); + } + } + } + return this._body; + } + async respond(r) { + let err; + try { + // Write our response! + await _io_ts_1.writeResponse(this.w, r); + } catch (e) { + try { + // Eagerly close on error. + this.conn.close(); + } catch {} + err = e; + } + // Signal that this request has been processed and the next pipelined + // request on the same connection can be accepted. + this.done.resolve(err); + if (err) { + // Error during responding, rethrow. + throw err; + } + } + async finalize() { + if (this.finalized) { + return; + } + // Consume unread body + const body = this.body; + const buf = new Uint8Array(1024); + while ((await body.read(buf)) !== null) {} + this.finalized = true; + } + }; + exports_25("ServerRequest", ServerRequest); + Server = class Server { + constructor(listener) { + this.listener = listener; + this.closing = false; + this.connections = []; + } + close() { + this.closing = true; + this.listener.close(); + for (const conn of this.connections) { + try { + conn.close(); + } catch (e) { + // Connection might have been already closed + if (!(e instanceof Deno.errors.BadResource)) { + throw e; + } + } + } + } + // Yields all HTTP requests on a single TCP connection. + async *iterateHttpRequests(conn) { + const reader = new bufio_ts_2.BufReader(conn); + const writer = new bufio_ts_2.BufWriter(conn); + while (!this.closing) { + let request; + try { + request = await _io_ts_1.readRequest(conn, reader); + } catch (error) { + if ( + error instanceof Deno.errors.InvalidData || + error instanceof Deno.errors.UnexpectedEof + ) { + // An error was thrown while parsing request headers. + await _io_ts_1.writeResponse(writer, { + status: 400, + body: utf8_ts_4.encode(`${error.message}\r\n\r\n`), + }); + } + break; + } + if (request === null) { + break; + } + request.w = writer; + yield request; + // Wait for the request to be processed before we accept a new request on + // this connection. + const responseError = await request.done; + if (responseError) { + // Something bad happened during response. + // (likely other side closed during pipelined req) + // req.done implies this connection already closed, so we can just return. + this.untrackConnection(request.conn); + return; + } + // Consume unread body and trailers if receiver didn't consume those data + await request.finalize(); + } + this.untrackConnection(conn); + try { + conn.close(); + } catch (e) { + // might have been already closed + } + } + trackConnection(conn) { + this.connections.push(conn); + } + untrackConnection(conn) { + const index = this.connections.indexOf(conn); + if (index !== -1) { + this.connections.splice(index, 1); + } + } + // Accepts a new TCP connection and yields all HTTP requests that arrive on + // it. When a connection is accepted, it also creates a new iterator of the + // same kind and adds it to the request multiplexer so that another TCP + // connection can be accepted. + async *acceptConnAndIterateHttpRequests(mux) { + if (this.closing) { + return; + } + // Wait for a new connection. + let conn; + try { + conn = await this.listener.accept(); + } catch (error) { + if (error instanceof Deno.errors.BadResource) { + return; + } + throw error; + } + this.trackConnection(conn); + // Try to accept another connection and add it to the multiplexer. + mux.add(this.acceptConnAndIterateHttpRequests(mux)); + // Yield the requests that arrive on the just-accepted connection. + yield* this.iterateHttpRequests(conn); + } + [Symbol.asyncIterator]() { + const mux = new mod_ts_4.MuxAsyncIterator(); + mux.add(this.acceptConnAndIterateHttpRequests(mux)); + return mux.iterate(); + } + }; + exports_25("Server", Server); + }, + }; + }, +); +System.register( + "file:///home/kou029w/deno-example/server", + ["https://deno.land/std@0.56.0/http/server"], + function (exports_26, context_26) { + "use strict"; + var server_ts_2; + var __moduleName = context_26 && context_26.id; + async function main() { + const port = 8000; + console.log(`http://localhost:${port}/`); + for await (const req of server_ts_2.serve({ port })) { + req.respond({ body: "Hello World\n" }); + } + } + return { + setters: [ + function (server_ts_2_1) { + server_ts_2 = server_ts_2_1; + }, + ], + execute: function () { + main(); + }, + }; + }, +); + +__instantiate("file:///home/kou029w/deno-example/server"); diff --git a/server.ts b/server.ts new file mode 100644 index 0000000..b72a681 --- /dev/null +++ b/server.ts @@ -0,0 +1,10 @@ +import { serve } from "https://deno.land/std@0.56.0/http/server.ts"; + +async function main() { + const port = 8000; + console.log(`http://localhost:${port}/`); + for await (const req of serve({ port })) { + req.respond({ body: "Hello World\n" }); + } +} +main();