summaryrefslogtreecommitdiff
path: root/ext/web/00_infra.js
diff options
context:
space:
mode:
authorRyan Dahl <ry@tinyclouds.org>2021-08-11 12:27:05 +0200
committerGitHub <noreply@github.com>2021-08-11 12:27:05 +0200
commita0285e2eb88f6254f6494b0ecd1878db3a3b2a58 (patch)
tree90671b004537e20f9493fd3277ffd21d30b39a0e /ext/web/00_infra.js
parent3a6994115176781b3a93d70794b1b81bc95e42b4 (diff)
Rename extensions/ directory to ext/ (#11643)
Diffstat (limited to 'ext/web/00_infra.js')
-rw-r--r--ext/web/00_infra.js264
1 files changed, 264 insertions, 0 deletions
diff --git a/ext/web/00_infra.js b/ext/web/00_infra.js
new file mode 100644
index 000000000..7c065bcd3
--- /dev/null
+++ b/ext/web/00_infra.js
@@ -0,0 +1,264 @@
+// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
+
+// @ts-check
+/// <reference path="../../core/internal.d.ts" />
+/// <reference path="../../core/lib.deno_core.d.ts" />
+/// <reference path="../web/internal.d.ts" />
+/// <reference path="../web/lib.deno_web.d.ts" />
+
+"use strict";
+
+((window) => {
+ const core = Deno.core;
+ const {
+ RegExp,
+ ArrayPrototypeMap,
+ StringPrototypeCharCodeAt,
+ NumberPrototypeToString,
+ StringPrototypePadStart,
+ TypeError,
+ ArrayPrototypeJoin,
+ StringPrototypeCharAt,
+ StringPrototypeSlice,
+ String,
+ StringPrototypeReplace,
+ StringPrototypeToUpperCase,
+ StringPrototypeToLowerCase,
+ StringPrototypeSubstring,
+ } = window.__bootstrap.primordials;
+
+ const ASCII_DIGIT = ["\u0030-\u0039"];
+ const ASCII_UPPER_ALPHA = ["\u0041-\u005A"];
+ const ASCII_LOWER_ALPHA = ["\u0061-\u007A"];
+ const ASCII_ALPHA = [...ASCII_UPPER_ALPHA, ...ASCII_LOWER_ALPHA];
+ const ASCII_ALPHANUMERIC = [...ASCII_DIGIT, ...ASCII_ALPHA];
+
+ const HTTP_TAB_OR_SPACE = ["\u0009", "\u0020"];
+ const HTTP_WHITESPACE = ["\u000A", "\u000D", ...HTTP_TAB_OR_SPACE];
+
+ const HTTP_TOKEN_CODE_POINT = [
+ "\u0021",
+ "\u0023",
+ "\u0024",
+ "\u0025",
+ "\u0026",
+ "\u0027",
+ "\u002A",
+ "\u002B",
+ "\u002D",
+ "\u002E",
+ "\u005E",
+ "\u005F",
+ "\u0060",
+ "\u007C",
+ "\u007E",
+ ...ASCII_ALPHANUMERIC,
+ ];
+ const HTTP_TOKEN_CODE_POINT_RE = new RegExp(
+ `^[${regexMatcher(HTTP_TOKEN_CODE_POINT)}]+$`,
+ );
+ const HTTP_QUOTED_STRING_TOKEN_POINT = [
+ "\u0009",
+ "\u0020-\u007E",
+ "\u0080-\u00FF",
+ ];
+ const HTTP_QUOTED_STRING_TOKEN_POINT_RE = new RegExp(
+ `^[${regexMatcher(HTTP_QUOTED_STRING_TOKEN_POINT)}]+$`,
+ );
+ const HTTP_TAB_OR_SPACE_MATCHER = regexMatcher(HTTP_TAB_OR_SPACE);
+ const HTTP_TAB_OR_SPACE_PREFIX_RE = new RegExp(
+ `^[${HTTP_TAB_OR_SPACE_MATCHER}]+`,
+ "g",
+ );
+ const HTTP_TAB_OR_SPACE_SUFFIX_RE = new RegExp(
+ `[${HTTP_TAB_OR_SPACE_MATCHER}]+$`,
+ "g",
+ );
+ const HTTP_WHITESPACE_MATCHER = regexMatcher(HTTP_WHITESPACE);
+ const HTTP_WHITESPACE_PREFIX_RE = new RegExp(
+ `^[${HTTP_WHITESPACE_MATCHER}]+`,
+ "g",
+ );
+ const HTTP_WHITESPACE_SUFFIX_RE = new RegExp(
+ `[${HTTP_WHITESPACE_MATCHER}]+$`,
+ "g",
+ );
+
+ /**
+ * Turn a string of chars into a regex safe matcher.
+ * @param {string[]} chars
+ * @returns {string}
+ */
+ function regexMatcher(chars) {
+ const matchers = ArrayPrototypeMap(chars, (char) => {
+ if (char.length === 1) {
+ const a = StringPrototypePadStart(
+ NumberPrototypeToString(StringPrototypeCharCodeAt(char, 0), 16),
+ 4,
+ "0",
+ );
+ return `\\u${a}`;
+ } else if (char.length === 3 && char[1] === "-") {
+ const a = StringPrototypePadStart(
+ NumberPrototypeToString(StringPrototypeCharCodeAt(char, 0), 16),
+ 4,
+ "0",
+ );
+ const b = StringPrototypePadStart(
+ NumberPrototypeToString(StringPrototypeCharCodeAt(char, 2), 16),
+ 4,
+ "0",
+ );
+ return `\\u${a}-\\u${b}`;
+ } else {
+ throw TypeError("unreachable");
+ }
+ });
+ return ArrayPrototypeJoin(matchers, "");
+ }
+
+ /**
+ * https://infra.spec.whatwg.org/#collect-a-sequence-of-code-points
+ * @param {string} input
+ * @param {number} position
+ * @param {(char: string) => boolean} condition
+ * @returns {{result: string, position: number}}
+ */
+ function collectSequenceOfCodepoints(input, position, condition) {
+ const start = position;
+ for (
+ let c = StringPrototypeCharAt(input, position);
+ position < input.length && condition(c);
+ c = StringPrototypeCharAt(input, ++position)
+ );
+ return { result: StringPrototypeSlice(input, start, position), position };
+ }
+
+ /**
+ * @param {string} s
+ * @returns {string}
+ */
+ function byteUpperCase(s) {
+ return StringPrototypeReplace(
+ String(s),
+ /[a-z]/g,
+ function byteUpperCaseReplace(c) {
+ return StringPrototypeToUpperCase(c);
+ },
+ );
+ }
+
+ /**
+ * @param {string} s
+ * @returns {string}
+ */
+ function byteLowerCase(s) {
+ return StringPrototypeReplace(
+ String(s),
+ /[A-Z]/g,
+ function byteUpperCaseReplace(c) {
+ return StringPrototypeToLowerCase(c);
+ },
+ );
+ }
+
+ /**
+ * https://fetch.spec.whatwg.org/#collect-an-http-quoted-string
+ * @param {string} input
+ * @param {number} position
+ * @param {boolean} extractValue
+ * @returns {{result: string, position: number}}
+ */
+ function collectHttpQuotedString(input, position, extractValue) {
+ // 1.
+ const positionStart = position;
+ // 2.
+ let value = "";
+ // 3.
+ if (input[position] !== "\u0022") throw new TypeError('must be "');
+ // 4.
+ position++;
+ // 5.
+ while (true) {
+ // 5.1.
+ const res = collectSequenceOfCodepoints(
+ input,
+ position,
+ (c) => c !== "\u0022" && c !== "\u005C",
+ );
+ value += res.result;
+ position = res.position;
+ // 5.2.
+ if (position >= input.length) break;
+ // 5.3.
+ const quoteOrBackslash = input[position];
+ // 5.4.
+ position++;
+ // 5.5.
+ if (quoteOrBackslash === "\u005C") {
+ // 5.5.1.
+ if (position >= input.length) {
+ value += "\u005C";
+ break;
+ }
+ // 5.5.2.
+ value += input[position];
+ // 5.5.3.
+ position++;
+ } else { // 5.6.
+ // 5.6.1
+ if (quoteOrBackslash !== "\u0022") throw new TypeError('must be "');
+ // 5.6.2
+ break;
+ }
+ }
+ // 6.
+ if (extractValue) return { result: value, position };
+ // 7.
+ return {
+ result: StringPrototypeSubstring(input, positionStart, position + 1),
+ position,
+ };
+ }
+
+ /**
+ * @param {Uint8Array} data
+ * @returns {string}
+ */
+ function forgivingBase64Encode(data) {
+ return core.opSync("op_base64_encode", data);
+ }
+
+ /**
+ * @param {string} data
+ * @returns {Uint8Array}
+ */
+ function forgivingBase64Decode(data) {
+ return core.opSync("op_base64_decode", data);
+ }
+
+ window.__bootstrap.infra = {
+ collectSequenceOfCodepoints,
+ ASCII_DIGIT,
+ ASCII_UPPER_ALPHA,
+ ASCII_LOWER_ALPHA,
+ ASCII_ALPHA,
+ ASCII_ALPHANUMERIC,
+ HTTP_TAB_OR_SPACE,
+ HTTP_WHITESPACE,
+ HTTP_TOKEN_CODE_POINT,
+ HTTP_TOKEN_CODE_POINT_RE,
+ HTTP_QUOTED_STRING_TOKEN_POINT,
+ HTTP_QUOTED_STRING_TOKEN_POINT_RE,
+ HTTP_TAB_OR_SPACE_PREFIX_RE,
+ HTTP_TAB_OR_SPACE_SUFFIX_RE,
+ HTTP_WHITESPACE_PREFIX_RE,
+ HTTP_WHITESPACE_SUFFIX_RE,
+ regexMatcher,
+ byteUpperCase,
+ byteLowerCase,
+ collectHttpQuotedString,
+ forgivingBase64Encode,
+ forgivingBase64Decode,
+ };
+})(globalThis);