summaryrefslogtreecommitdiff
path: root/includes/external/school/node_modules/whatwg-url
diff options
context:
space:
mode:
Diffstat (limited to 'includes/external/school/node_modules/whatwg-url')
-rw-r--r--includes/external/school/node_modules/whatwg-url/LICENSE.txt21
-rw-r--r--includes/external/school/node_modules/whatwg-url/README.md104
-rw-r--r--includes/external/school/node_modules/whatwg-url/dist/Function.js46
-rw-r--r--includes/external/school/node_modules/whatwg-url/dist/URL-impl.js217
-rw-r--r--includes/external/school/node_modules/whatwg-url/dist/URL.js417
-rw-r--r--includes/external/school/node_modules/whatwg-url/dist/URLSearchParams-impl.js122
-rw-r--r--includes/external/school/node_modules/whatwg-url/dist/URLSearchParams.js457
-rw-r--r--includes/external/school/node_modules/whatwg-url/dist/VoidFunction.js30
-rw-r--r--includes/external/school/node_modules/whatwg-url/dist/encoding.js26
-rw-r--r--includes/external/school/node_modules/whatwg-url/dist/infra.js26
-rw-r--r--includes/external/school/node_modules/whatwg-url/dist/percent-encoding.js141
-rw-r--r--includes/external/school/node_modules/whatwg-url/dist/url-state-machine.js1210
-rw-r--r--includes/external/school/node_modules/whatwg-url/dist/urlencoded.js102
-rw-r--r--includes/external/school/node_modules/whatwg-url/dist/utils.js141
-rw-r--r--includes/external/school/node_modules/whatwg-url/index.js24
-rw-r--r--includes/external/school/node_modules/whatwg-url/package.json60
-rw-r--r--includes/external/school/node_modules/whatwg-url/webidl2js-wrapper.js7
17 files changed, 3151 insertions, 0 deletions
diff --git a/includes/external/school/node_modules/whatwg-url/LICENSE.txt b/includes/external/school/node_modules/whatwg-url/LICENSE.txt
new file mode 100644
index 0000000..54dfac3
--- /dev/null
+++ b/includes/external/school/node_modules/whatwg-url/LICENSE.txt
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2015–2016 Sebastian Mayr
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/includes/external/school/node_modules/whatwg-url/README.md b/includes/external/school/node_modules/whatwg-url/README.md
new file mode 100644
index 0000000..1f9deae
--- /dev/null
+++ b/includes/external/school/node_modules/whatwg-url/README.md
@@ -0,0 +1,104 @@
+# whatwg-url
+
+whatwg-url is a full implementation of the WHATWG [URL Standard](https://url.spec.whatwg.org/). It can be used standalone, but it also exposes a lot of the internal algorithms that are useful for integrating a URL parser into a project like [jsdom](https://github.com/jsdom/jsdom).
+
+## Specification conformance
+
+whatwg-url is currently up to date with the URL spec up to commit [0672f2e](https://github.com/whatwg/url/commit/0672f2e2ef43aca18b59d90abb6dac21712399bb).
+
+For `file:` URLs, whose [origin is left unspecified](https://url.spec.whatwg.org/#concept-url-origin), whatwg-url chooses to use a new opaque origin (which serializes to `"null"`).
+
+whatwg-url does not yet implement any encoding handling beyond UTF-8. That is, the _encoding override_ parameter does not exist in our API.
+
+## API
+
+### The `URL` and `URLSearchParams` classes
+
+The main API is provided by the [`URL`](https://url.spec.whatwg.org/#url-class) and [`URLSearchParams`](https://url.spec.whatwg.org/#interface-urlsearchparams) exports, which follows the spec's behavior in all ways (including e.g. `USVString` conversion). Most consumers of this library will want to use these.
+
+### Low-level URL Standard API
+
+The following methods are exported for use by places like jsdom that need to implement things like [`HTMLHyperlinkElementUtils`](https://html.spec.whatwg.org/#htmlhyperlinkelementutils). They mostly operate on or return an "internal URL" or ["URL record"](https://url.spec.whatwg.org/#concept-url) type.
+
+- [URL parser](https://url.spec.whatwg.org/#concept-url-parser): `parseURL(input, { baseURL })`
+- [Basic URL parser](https://url.spec.whatwg.org/#concept-basic-url-parser): `basicURLParse(input, { baseURL, url, stateOverride })`
+- [URL serializer](https://url.spec.whatwg.org/#concept-url-serializer): `serializeURL(urlRecord, excludeFragment)`
+- [Host serializer](https://url.spec.whatwg.org/#concept-host-serializer): `serializeHost(hostFromURLRecord)`
+- [Serialize an integer](https://url.spec.whatwg.org/#serialize-an-integer): `serializeInteger(number)`
+- [Origin](https://url.spec.whatwg.org/#concept-url-origin) [serializer](https://html.spec.whatwg.org/multipage/origin.html#ascii-serialisation-of-an-origin): `serializeURLOrigin(urlRecord)`
+- [Set the username](https://url.spec.whatwg.org/#set-the-username): `setTheUsername(urlRecord, usernameString)`
+- [Set the password](https://url.spec.whatwg.org/#set-the-password): `setThePassword(urlRecord, passwordString)`
+- [Cannot have a username/password/port](https://url.spec.whatwg.org/#cannot-have-a-username-password-port): `cannotHaveAUsernamePasswordPort(urlRecord)`
+- [Percent decode](https://url.spec.whatwg.org/#percent-decode): `percentDecode(buffer)`
+
+The `stateOverride` parameter is one of the following strings:
+
+- [`"scheme start"`](https://url.spec.whatwg.org/#scheme-start-state)
+- [`"scheme"`](https://url.spec.whatwg.org/#scheme-state)
+- [`"no scheme"`](https://url.spec.whatwg.org/#no-scheme-state)
+- [`"special relative or authority"`](https://url.spec.whatwg.org/#special-relative-or-authority-state)
+- [`"path or authority"`](https://url.spec.whatwg.org/#path-or-authority-state)
+- [`"relative"`](https://url.spec.whatwg.org/#relative-state)
+- [`"relative slash"`](https://url.spec.whatwg.org/#relative-slash-state)
+- [`"special authority slashes"`](https://url.spec.whatwg.org/#special-authority-slashes-state)
+- [`"special authority ignore slashes"`](https://url.spec.whatwg.org/#special-authority-ignore-slashes-state)
+- [`"authority"`](https://url.spec.whatwg.org/#authority-state)
+- [`"host"`](https://url.spec.whatwg.org/#host-state)
+- [`"hostname"`](https://url.spec.whatwg.org/#hostname-state)
+- [`"port"`](https://url.spec.whatwg.org/#port-state)
+- [`"file"`](https://url.spec.whatwg.org/#file-state)
+- [`"file slash"`](https://url.spec.whatwg.org/#file-slash-state)
+- [`"file host"`](https://url.spec.whatwg.org/#file-host-state)
+- [`"path start"`](https://url.spec.whatwg.org/#path-start-state)
+- [`"path"`](https://url.spec.whatwg.org/#path-state)
+- [`"cannot-be-a-base-URL path"`](https://url.spec.whatwg.org/#cannot-be-a-base-url-path-state)
+- [`"query"`](https://url.spec.whatwg.org/#query-state)
+- [`"fragment"`](https://url.spec.whatwg.org/#fragment-state)
+
+The URL record type has the following API:
+
+- [`scheme`](https://url.spec.whatwg.org/#concept-url-scheme)
+- [`username`](https://url.spec.whatwg.org/#concept-url-username)
+- [`password`](https://url.spec.whatwg.org/#concept-url-password)
+- [`host`](https://url.spec.whatwg.org/#concept-url-host)
+- [`port`](https://url.spec.whatwg.org/#concept-url-port)
+- [`path`](https://url.spec.whatwg.org/#concept-url-path) (as an array)
+- [`query`](https://url.spec.whatwg.org/#concept-url-query)
+- [`fragment`](https://url.spec.whatwg.org/#concept-url-fragment)
+- [`cannotBeABaseURL`](https://url.spec.whatwg.org/#url-cannot-be-a-base-url-flag) (as a boolean)
+
+These properties should be treated with care, as in general changing them will cause the URL record to be in an inconsistent state until the appropriate invocation of `basicURLParse` is used to fix it up. You can see examples of this in the URL Standard, where there are many step sequences like "4. Set context object’s url’s fragment to the empty string. 5. Basic URL parse _input_ with context object’s url as _url_ and fragment state as _state override_." In between those two steps, a URL record is in an unusable state.
+
+The return value of "failure" in the spec is represented by `null`. That is, functions like `parseURL` and `basicURLParse` can return _either_ a URL record _or_ `null`.
+
+### `whatwg-url/webidl2js-wrapper` module
+
+This module exports the `URL` and `URLSearchParams` [interface wrappers API](https://github.com/jsdom/webidl2js#for-interfaces) generated by [webidl2js](https://github.com/jsdom/webidl2js).
+
+## Development instructions
+
+First, install [Node.js](https://nodejs.org/). Then, fetch the dependencies of whatwg-url, by running from this directory:
+
+ npm install
+
+To run tests:
+
+ npm test
+
+To generate a coverage report:
+
+ npm run coverage
+
+To build and run the live viewer:
+
+ npm run prepare
+ npm run build-live-viewer
+
+Serve the contents of the `live-viewer` directory using any web server.
+
+## Supporting whatwg-url
+
+The jsdom project (including whatwg-url) is a community-driven project maintained by a team of [volunteers](https://github.com/orgs/jsdom/people). You could support us by:
+
+- [Getting professional support for whatwg-url](https://tidelift.com/subscription/pkg/npm-whatwg-url?utm_source=npm-whatwg-url&utm_medium=referral&utm_campaign=readme) as part of a Tidelift subscription. Tidelift helps making open source sustainable for us while giving teams assurances for maintenance, licensing, and security.
+- Contributing directly to the project.
diff --git a/includes/external/school/node_modules/whatwg-url/dist/Function.js b/includes/external/school/node_modules/whatwg-url/dist/Function.js
new file mode 100644
index 0000000..bf5c808
--- /dev/null
+++ b/includes/external/school/node_modules/whatwg-url/dist/Function.js
@@ -0,0 +1,46 @@
+"use strict";
+
+const conversions = require("webidl-conversions");
+const utils = require("./utils.js");
+
+exports.convert = (value, { context = "The provided value" } = {}) => {
+ if (typeof value !== "function") {
+ throw new TypeError(context + " is not a function");
+ }
+
+ function invokeTheCallbackFunction(...args) {
+ if (new.target !== undefined) {
+ throw new Error("Internal error: invokeTheCallbackFunction is not a constructor");
+ }
+
+ const thisArg = utils.tryWrapperForImpl(this);
+ let callResult;
+
+ for (let i = 0; i < args.length; i++) {
+ args[i] = utils.tryWrapperForImpl(args[i]);
+ }
+
+ callResult = Reflect.apply(value, thisArg, args);
+
+ callResult = conversions["any"](callResult, { context: context });
+
+ return callResult;
+ }
+
+ invokeTheCallbackFunction.construct = (...args) => {
+ for (let i = 0; i < args.length; i++) {
+ args[i] = utils.tryWrapperForImpl(args[i]);
+ }
+
+ let callResult = Reflect.construct(value, args);
+
+ callResult = conversions["any"](callResult, { context: context });
+
+ return callResult;
+ };
+
+ invokeTheCallbackFunction[utils.wrapperSymbol] = value;
+ invokeTheCallbackFunction.objectReference = value;
+
+ return invokeTheCallbackFunction;
+};
diff --git a/includes/external/school/node_modules/whatwg-url/dist/URL-impl.js b/includes/external/school/node_modules/whatwg-url/dist/URL-impl.js
new file mode 100644
index 0000000..7a11661
--- /dev/null
+++ b/includes/external/school/node_modules/whatwg-url/dist/URL-impl.js
@@ -0,0 +1,217 @@
+"use strict";
+const usm = require("./url-state-machine");
+const urlencoded = require("./urlencoded");
+const URLSearchParams = require("./URLSearchParams");
+
+exports.implementation = class URLImpl {
+ constructor(globalObject, constructorArgs) {
+ const url = constructorArgs[0];
+ const base = constructorArgs[1];
+
+ let parsedBase = null;
+ if (base !== undefined) {
+ parsedBase = usm.basicURLParse(base);
+ if (parsedBase === null) {
+ throw new TypeError(`Invalid base URL: ${base}`);
+ }
+ }
+
+ const parsedURL = usm.basicURLParse(url, { baseURL: parsedBase });
+ if (parsedURL === null) {
+ throw new TypeError(`Invalid URL: ${url}`);
+ }
+
+ const query = parsedURL.query !== null ? parsedURL.query : "";
+
+ this._url = parsedURL;
+
+ // We cannot invoke the "new URLSearchParams object" algorithm without going through the constructor, which strips
+ // question mark by default. Therefore the doNotStripQMark hack is used.
+ this._query = URLSearchParams.createImpl(globalObject, [query], { doNotStripQMark: true });
+ this._query._url = this;
+ }
+
+ get href() {
+ return usm.serializeURL(this._url);
+ }
+
+ set href(v) {
+ const parsedURL = usm.basicURLParse(v);
+ if (parsedURL === null) {
+ throw new TypeError(`Invalid URL: ${v}`);
+ }
+
+ this._url = parsedURL;
+
+ this._query._list.splice(0);
+ const { query } = parsedURL;
+ if (query !== null) {
+ this._query._list = urlencoded.parseUrlencodedString(query);
+ }
+ }
+
+ get origin() {
+ return usm.serializeURLOrigin(this._url);
+ }
+
+ get protocol() {
+ return `${this._url.scheme}:`;
+ }
+
+ set protocol(v) {
+ usm.basicURLParse(`${v}:`, { url: this._url, stateOverride: "scheme start" });
+ }
+
+ get username() {
+ return this._url.username;
+ }
+
+ set username(v) {
+ if (usm.cannotHaveAUsernamePasswordPort(this._url)) {
+ return;
+ }
+
+ usm.setTheUsername(this._url, v);
+ }
+
+ get password() {
+ return this._url.password;
+ }
+
+ set password(v) {
+ if (usm.cannotHaveAUsernamePasswordPort(this._url)) {
+ return;
+ }
+
+ usm.setThePassword(this._url, v);
+ }
+
+ get host() {
+ const url = this._url;
+
+ if (url.host === null) {
+ return "";
+ }
+
+ if (url.port === null) {
+ return usm.serializeHost(url.host);
+ }
+
+ return `${usm.serializeHost(url.host)}:${usm.serializeInteger(url.port)}`;
+ }
+
+ set host(v) {
+ if (this._url.cannotBeABaseURL) {
+ return;
+ }
+
+ usm.basicURLParse(v, { url: this._url, stateOverride: "host" });
+ }
+
+ get hostname() {
+ if (this._url.host === null) {
+ return "";
+ }
+
+ return usm.serializeHost(this._url.host);
+ }
+
+ set hostname(v) {
+ if (this._url.cannotBeABaseURL) {
+ return;
+ }
+
+ usm.basicURLParse(v, { url: this._url, stateOverride: "hostname" });
+ }
+
+ get port() {
+ if (this._url.port === null) {
+ return "";
+ }
+
+ return usm.serializeInteger(this._url.port);
+ }
+
+ set port(v) {
+ if (usm.cannotHaveAUsernamePasswordPort(this._url)) {
+ return;
+ }
+
+ if (v === "") {
+ this._url.port = null;
+ } else {
+ usm.basicURLParse(v, { url: this._url, stateOverride: "port" });
+ }
+ }
+
+ get pathname() {
+ if (this._url.cannotBeABaseURL) {
+ return this._url.path[0];
+ }
+
+ if (this._url.path.length === 0) {
+ return "";
+ }
+
+ return `/${this._url.path.join("/")}`;
+ }
+
+ set pathname(v) {
+ if (this._url.cannotBeABaseURL) {
+ return;
+ }
+
+ this._url.path = [];
+ usm.basicURLParse(v, { url: this._url, stateOverride: "path start" });
+ }
+
+ get search() {
+ if (this._url.query === null || this._url.query === "") {
+ return "";
+ }
+
+ return `?${this._url.query}`;
+ }
+
+ set search(v) {
+ const url = this._url;
+
+ if (v === "") {
+ url.query = null;
+ this._query._list = [];
+ return;
+ }
+
+ const input = v[0] === "?" ? v.substring(1) : v;
+ url.query = "";
+ usm.basicURLParse(input, { url, stateOverride: "query" });
+ this._query._list = urlencoded.parseUrlencodedString(input);
+ }
+
+ get searchParams() {
+ return this._query;
+ }
+
+ get hash() {
+ if (this._url.fragment === null || this._url.fragment === "") {
+ return "";
+ }
+
+ return `#${this._url.fragment}`;
+ }
+
+ set hash(v) {
+ if (v === "") {
+ this._url.fragment = null;
+ return;
+ }
+
+ const input = v[0] === "#" ? v.substring(1) : v;
+ this._url.fragment = "";
+ usm.basicURLParse(input, { url: this._url, stateOverride: "fragment" });
+ }
+
+ toJSON() {
+ return this.href;
+ }
+};
diff --git a/includes/external/school/node_modules/whatwg-url/dist/URL.js b/includes/external/school/node_modules/whatwg-url/dist/URL.js
new file mode 100644
index 0000000..6d859d9
--- /dev/null
+++ b/includes/external/school/node_modules/whatwg-url/dist/URL.js
@@ -0,0 +1,417 @@
+"use strict";
+
+const conversions = require("webidl-conversions");
+const utils = require("./utils.js");
+
+const implSymbol = utils.implSymbol;
+const ctorRegistrySymbol = utils.ctorRegistrySymbol;
+
+const interfaceName = "URL";
+
+exports.is = value => {
+ return utils.isObject(value) && utils.hasOwn(value, implSymbol) && value[implSymbol] instanceof Impl.implementation;
+};
+exports.isImpl = value => {
+ return utils.isObject(value) && value instanceof Impl.implementation;
+};
+exports.convert = (value, { context = "The provided value" } = {}) => {
+ if (exports.is(value)) {
+ return utils.implForWrapper(value);
+ }
+ throw new TypeError(`${context} is not of type 'URL'.`);
+};
+
+function makeWrapper(globalObject) {
+ if (globalObject[ctorRegistrySymbol] === undefined) {
+ throw new Error("Internal error: invalid global object");
+ }
+
+ const ctor = globalObject[ctorRegistrySymbol]["URL"];
+ if (ctor === undefined) {
+ throw new Error("Internal error: constructor URL is not installed on the passed global object");
+ }
+
+ return Object.create(ctor.prototype);
+}
+
+exports.create = (globalObject, constructorArgs, privateData) => {
+ const wrapper = makeWrapper(globalObject);
+ return exports.setup(wrapper, globalObject, constructorArgs, privateData);
+};
+
+exports.createImpl = (globalObject, constructorArgs, privateData) => {
+ const wrapper = exports.create(globalObject, constructorArgs, privateData);
+ return utils.implForWrapper(wrapper);
+};
+
+exports._internalSetup = (wrapper, globalObject) => {};
+
+exports.setup = (wrapper, globalObject, constructorArgs = [], privateData = {}) => {
+ privateData.wrapper = wrapper;
+
+ exports._internalSetup(wrapper, globalObject);
+ Object.defineProperty(wrapper, implSymbol, {
+ value: new Impl.implementation(globalObject, constructorArgs, privateData),
+ configurable: true
+ });
+
+ wrapper[implSymbol][utils.wrapperSymbol] = wrapper;
+ if (Impl.init) {
+ Impl.init(wrapper[implSymbol]);
+ }
+ return wrapper;
+};
+
+exports.new = globalObject => {
+ const wrapper = makeWrapper(globalObject);
+
+ exports._internalSetup(wrapper, globalObject);
+ Object.defineProperty(wrapper, implSymbol, {
+ value: Object.create(Impl.implementation.prototype),
+ configurable: true
+ });
+
+ wrapper[implSymbol][utils.wrapperSymbol] = wrapper;
+ if (Impl.init) {
+ Impl.init(wrapper[implSymbol]);
+ }
+ return wrapper[implSymbol];
+};
+
+const exposed = new Set(["Window", "Worker"]);
+
+exports.install = (globalObject, globalNames) => {
+ if (!globalNames.some(globalName => exposed.has(globalName))) {
+ return;
+ }
+ class URL {
+ constructor(url) {
+ if (arguments.length < 1) {
+ throw new TypeError(
+ "Failed to construct 'URL': 1 argument required, but only " + arguments.length + " present."
+ );
+ }
+ const args = [];
+ {
+ let curArg = arguments[0];
+ curArg = conversions["USVString"](curArg, { context: "Failed to construct 'URL': parameter 1" });
+ args.push(curArg);
+ }
+ {
+ let curArg = arguments[1];
+ if (curArg !== undefined) {
+ curArg = conversions["USVString"](curArg, { context: "Failed to construct 'URL': parameter 2" });
+ }
+ args.push(curArg);
+ }
+ return exports.setup(Object.create(new.target.prototype), globalObject, args);
+ }
+
+ toJSON() {
+ const esValue = this !== null && this !== undefined ? this : globalObject;
+ if (!exports.is(esValue)) {
+ throw new TypeError("'toJSON' called on an object that is not a valid instance of URL.");
+ }
+
+ return esValue[implSymbol].toJSON();
+ }
+
+ get href() {
+ const esValue = this !== null && this !== undefined ? this : globalObject;
+
+ if (!exports.is(esValue)) {
+ throw new TypeError("'get href' called on an object that is not a valid instance of URL.");
+ }
+
+ return esValue[implSymbol]["href"];
+ }
+
+ set href(V) {
+ const esValue = this !== null && this !== undefined ? this : globalObject;
+
+ if (!exports.is(esValue)) {
+ throw new TypeError("'set href' called on an object that is not a valid instance of URL.");
+ }
+
+ V = conversions["USVString"](V, { context: "Failed to set the 'href' property on 'URL': The provided value" });
+
+ esValue[implSymbol]["href"] = V;
+ }
+
+ toString() {
+ const esValue = this;
+ if (!exports.is(esValue)) {
+ throw new TypeError("'toString' called on an object that is not a valid instance of URL.");
+ }
+
+ return esValue[implSymbol]["href"];
+ }
+
+ get origin() {
+ const esValue = this !== null && this !== undefined ? this : globalObject;
+
+ if (!exports.is(esValue)) {
+ throw new TypeError("'get origin' called on an object that is not a valid instance of URL.");
+ }
+
+ return esValue[implSymbol]["origin"];
+ }
+
+ get protocol() {
+ const esValue = this !== null && this !== undefined ? this : globalObject;
+
+ if (!exports.is(esValue)) {
+ throw new TypeError("'get protocol' called on an object that is not a valid instance of URL.");
+ }
+
+ return esValue[implSymbol]["protocol"];
+ }
+
+ set protocol(V) {
+ const esValue = this !== null && this !== undefined ? this : globalObject;
+
+ if (!exports.is(esValue)) {
+ throw new TypeError("'set protocol' called on an object that is not a valid instance of URL.");
+ }
+
+ V = conversions["USVString"](V, {
+ context: "Failed to set the 'protocol' property on 'URL': The provided value"
+ });
+
+ esValue[implSymbol]["protocol"] = V;
+ }
+
+ get username() {
+ const esValue = this !== null && this !== undefined ? this : globalObject;
+
+ if (!exports.is(esValue)) {
+ throw new TypeError("'get username' called on an object that is not a valid instance of URL.");
+ }
+
+ return esValue[implSymbol]["username"];
+ }
+
+ set username(V) {
+ const esValue = this !== null && this !== undefined ? this : globalObject;
+
+ if (!exports.is(esValue)) {
+ throw new TypeError("'set username' called on an object that is not a valid instance of URL.");
+ }
+
+ V = conversions["USVString"](V, {
+ context: "Failed to set the 'username' property on 'URL': The provided value"
+ });
+
+ esValue[implSymbol]["username"] = V;
+ }
+
+ get password() {
+ const esValue = this !== null && this !== undefined ? this : globalObject;
+
+ if (!exports.is(esValue)) {
+ throw new TypeError("'get password' called on an object that is not a valid instance of URL.");
+ }
+
+ return esValue[implSymbol]["password"];
+ }
+
+ set password(V) {
+ const esValue = this !== null && this !== undefined ? this : globalObject;
+
+ if (!exports.is(esValue)) {
+ throw new TypeError("'set password' called on an object that is not a valid instance of URL.");
+ }
+
+ V = conversions["USVString"](V, {
+ context: "Failed to set the 'password' property on 'URL': The provided value"
+ });
+
+ esValue[implSymbol]["password"] = V;
+ }
+
+ get host() {
+ const esValue = this !== null && this !== undefined ? this : globalObject;
+
+ if (!exports.is(esValue)) {
+ throw new TypeError("'get host' called on an object that is not a valid instance of URL.");
+ }
+
+ return esValue[implSymbol]["host"];
+ }
+
+ set host(V) {
+ const esValue = this !== null && this !== undefined ? this : globalObject;
+
+ if (!exports.is(esValue)) {
+ throw new TypeError("'set host' called on an object that is not a valid instance of URL.");
+ }
+
+ V = conversions["USVString"](V, { context: "Failed to set the 'host' property on 'URL': The provided value" });
+
+ esValue[implSymbol]["host"] = V;
+ }
+
+ get hostname() {
+ const esValue = this !== null && this !== undefined ? this : globalObject;
+
+ if (!exports.is(esValue)) {
+ throw new TypeError("'get hostname' called on an object that is not a valid instance of URL.");
+ }
+
+ return esValue[implSymbol]["hostname"];
+ }
+
+ set hostname(V) {
+ const esValue = this !== null && this !== undefined ? this : globalObject;
+
+ if (!exports.is(esValue)) {
+ throw new TypeError("'set hostname' called on an object that is not a valid instance of URL.");
+ }
+
+ V = conversions["USVString"](V, {
+ context: "Failed to set the 'hostname' property on 'URL': The provided value"
+ });
+
+ esValue[implSymbol]["hostname"] = V;
+ }
+
+ get port() {
+ const esValue = this !== null && this !== undefined ? this : globalObject;
+
+ if (!exports.is(esValue)) {
+ throw new TypeError("'get port' called on an object that is not a valid instance of URL.");
+ }
+
+ return esValue[implSymbol]["port"];
+ }
+
+ set port(V) {
+ const esValue = this !== null && this !== undefined ? this : globalObject;
+
+ if (!exports.is(esValue)) {
+ throw new TypeError("'set port' called on an object that is not a valid instance of URL.");
+ }
+
+ V = conversions["USVString"](V, { context: "Failed to set the 'port' property on 'URL': The provided value" });
+
+ esValue[implSymbol]["port"] = V;
+ }
+
+ get pathname() {
+ const esValue = this !== null && this !== undefined ? this : globalObject;
+
+ if (!exports.is(esValue)) {
+ throw new TypeError("'get pathname' called on an object that is not a valid instance of URL.");
+ }
+
+ return esValue[implSymbol]["pathname"];
+ }
+
+ set pathname(V) {
+ const esValue = this !== null && this !== undefined ? this : globalObject;
+
+ if (!exports.is(esValue)) {
+ throw new TypeError("'set pathname' called on an object that is not a valid instance of URL.");
+ }
+
+ V = conversions["USVString"](V, {
+ context: "Failed to set the 'pathname' property on 'URL': The provided value"
+ });
+
+ esValue[implSymbol]["pathname"] = V;
+ }
+
+ get search() {
+ const esValue = this !== null && this !== undefined ? this : globalObject;
+
+ if (!exports.is(esValue)) {
+ throw new TypeError("'get search' called on an object that is not a valid instance of URL.");
+ }
+
+ return esValue[implSymbol]["search"];
+ }
+
+ set search(V) {
+ const esValue = this !== null && this !== undefined ? this : globalObject;
+
+ if (!exports.is(esValue)) {
+ throw new TypeError("'set search' called on an object that is not a valid instance of URL.");
+ }
+
+ V = conversions["USVString"](V, { context: "Failed to set the 'search' property on 'URL': The provided value" });
+
+ esValue[implSymbol]["search"] = V;
+ }
+
+ get searchParams() {
+ const esValue = this !== null && this !== undefined ? this : globalObject;
+
+ if (!exports.is(esValue)) {
+ throw new TypeError("'get searchParams' called on an object that is not a valid instance of URL.");
+ }
+
+ return utils.getSameObject(this, "searchParams", () => {
+ return utils.tryWrapperForImpl(esValue[implSymbol]["searchParams"]);
+ });
+ }
+
+ get hash() {
+ const esValue = this !== null && this !== undefined ? this : globalObject;
+
+ if (!exports.is(esValue)) {
+ throw new TypeError("'get hash' called on an object that is not a valid instance of URL.");
+ }
+
+ return esValue[implSymbol]["hash"];
+ }
+
+ set hash(V) {
+ const esValue = this !== null && this !== undefined ? this : globalObject;
+
+ if (!exports.is(esValue)) {
+ throw new TypeError("'set hash' called on an object that is not a valid instance of URL.");
+ }
+
+ V = conversions["USVString"](V, { context: "Failed to set the 'hash' property on 'URL': The provided value" });
+
+ esValue[implSymbol]["hash"] = V;
+ }
+ }
+ Object.defineProperties(URL.prototype, {
+ toJSON: { enumerable: true },
+ href: { enumerable: true },
+ toString: { enumerable: true },
+ origin: { enumerable: true },
+ protocol: { enumerable: true },
+ username: { enumerable: true },
+ password: { enumerable: true },
+ host: { enumerable: true },
+ hostname: { enumerable: true },
+ port: { enumerable: true },
+ pathname: { enumerable: true },
+ search: { enumerable: true },
+ searchParams: { enumerable: true },
+ hash: { enumerable: true },
+ [Symbol.toStringTag]: { value: "URL", configurable: true }
+ });
+ if (globalObject[ctorRegistrySymbol] === undefined) {
+ globalObject[ctorRegistrySymbol] = Object.create(null);
+ }
+ globalObject[ctorRegistrySymbol][interfaceName] = URL;
+
+ Object.defineProperty(globalObject, interfaceName, {
+ configurable: true,
+ writable: true,
+ value: URL
+ });
+
+ if (globalNames.includes("Window")) {
+ Object.defineProperty(globalObject, "webkitURL", {
+ configurable: true,
+ writable: true,
+ value: URL
+ });
+ }
+};
+
+const Impl = require("./URL-impl.js");
diff --git a/includes/external/school/node_modules/whatwg-url/dist/URLSearchParams-impl.js b/includes/external/school/node_modules/whatwg-url/dist/URLSearchParams-impl.js
new file mode 100644
index 0000000..25c6294
--- /dev/null
+++ b/includes/external/school/node_modules/whatwg-url/dist/URLSearchParams-impl.js
@@ -0,0 +1,122 @@
+"use strict";
+const stableSortBy = require("lodash/sortBy");
+const urlencoded = require("./urlencoded");
+
+exports.implementation = class URLSearchParamsImpl {
+ constructor(globalObject, constructorArgs, { doNotStripQMark = false }) {
+ let init = constructorArgs[0];
+ this._list = [];
+ this._url = null;
+
+ if (!doNotStripQMark && typeof init === "string" && init[0] === "?") {
+ init = init.slice(1);
+ }
+
+ if (Array.isArray(init)) {
+ for (const pair of init) {
+ if (pair.length !== 2) {
+ throw new TypeError("Failed to construct 'URLSearchParams': parameter 1 sequence's element does not " +
+ "contain exactly two elements.");
+ }
+ this._list.push([pair[0], pair[1]]);
+ }
+ } else if (typeof init === "object" && Object.getPrototypeOf(init) === null) {
+ for (const name of Object.keys(init)) {
+ const value = init[name];
+ this._list.push([name, value]);
+ }
+ } else {
+ this._list = urlencoded.parseUrlencodedString(init);
+ }
+ }
+
+ _updateSteps() {
+ if (this._url !== null) {
+ let query = urlencoded.serializeUrlencoded(this._list);
+ if (query === "") {
+ query = null;
+ }
+ this._url._url.query = query;
+ }
+ }
+
+ append(name, value) {
+ this._list.push([name, value]);
+ this._updateSteps();
+ }
+
+ delete(name) {
+ let i = 0;
+ while (i < this._list.length) {
+ if (this._list[i][0] === name) {
+ this._list.splice(i, 1);
+ } else {
+ i++;
+ }
+ }
+ this._updateSteps();
+ }
+
+ get(name) {
+ for (const tuple of this._list) {
+ if (tuple[0] === name) {
+ return tuple[1];
+ }
+ }
+ return null;
+ }
+
+ getAll(name) {
+ const output = [];
+ for (const tuple of this._list) {
+ if (tuple[0] === name) {
+ output.push(tuple[1]);
+ }
+ }
+ return output;
+ }
+
+ has(name) {
+ for (const tuple of this._list) {
+ if (tuple[0] === name) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ set(name, value) {
+ let found = false;
+ let i = 0;
+ while (i < this._list.length) {
+ if (this._list[i][0] === name) {
+ if (found) {
+ this._list.splice(i, 1);
+ } else {
+ found = true;
+ this._list[i][1] = value;
+ i++;
+ }
+ } else {
+ i++;
+ }
+ }
+ if (!found) {
+ this._list.push([name, value]);
+ }
+ this._updateSteps();
+ }
+
+ sort() {
+ this._list = stableSortBy(this._list, [0]);
+ this._updateSteps();
+ }
+
+ [Symbol.iterator]() {
+ return this._list[Symbol.iterator]();
+ }
+
+ toString() {
+ return urlencoded.serializeUrlencoded(this._list);
+ }
+};
diff --git a/includes/external/school/node_modules/whatwg-url/dist/URLSearchParams.js b/includes/external/school/node_modules/whatwg-url/dist/URLSearchParams.js
new file mode 100644
index 0000000..ba29f06
--- /dev/null
+++ b/includes/external/school/node_modules/whatwg-url/dist/URLSearchParams.js
@@ -0,0 +1,457 @@
+"use strict";
+
+const conversions = require("webidl-conversions");
+const utils = require("./utils.js");
+
+const Function = require("./Function.js");
+const implSymbol = utils.implSymbol;
+const ctorRegistrySymbol = utils.ctorRegistrySymbol;
+
+const interfaceName = "URLSearchParams";
+
+const IteratorPrototype = Object.create(utils.IteratorPrototype, {
+ next: {
+ value: function next() {
+ const internal = this && this[utils.iterInternalSymbol];
+ if (!internal) {
+ throw new TypeError("next() called on a value that is not an iterator prototype object");
+ }
+
+ const { target, kind, index } = internal;
+ const values = Array.from(target[implSymbol]);
+ const len = values.length;
+ if (index >= len) {
+ return { value: undefined, done: true };
+ }
+
+ const pair = values[index];
+ internal.index = index + 1;
+ return utils.iteratorResult(pair.map(utils.tryWrapperForImpl), kind);
+ },
+ writable: true,
+ enumerable: true,
+ configurable: true
+ },
+ [Symbol.toStringTag]: {
+ value: "URLSearchParams Iterator",
+ configurable: true
+ }
+});
+
+exports.is = value => {
+ return utils.isObject(value) && utils.hasOwn(value, implSymbol) && value[implSymbol] instanceof Impl.implementation;
+};
+exports.isImpl = value => {
+ return utils.isObject(value) && value instanceof Impl.implementation;
+};
+exports.convert = (value, { context = "The provided value" } = {}) => {
+ if (exports.is(value)) {
+ return utils.implForWrapper(value);
+ }
+ throw new TypeError(`${context} is not of type 'URLSearchParams'.`);
+};
+
+exports.createDefaultIterator = (target, kind) => {
+ const iterator = Object.create(IteratorPrototype);
+ Object.defineProperty(iterator, utils.iterInternalSymbol, {
+ value: { target, kind, index: 0 },
+ configurable: true
+ });
+ return iterator;
+};
+
+function makeWrapper(globalObject) {
+ if (globalObject[ctorRegistrySymbol] === undefined) {
+ throw new Error("Internal error: invalid global object");
+ }
+
+ const ctor = globalObject[ctorRegistrySymbol]["URLSearchParams"];
+ if (ctor === undefined) {
+ throw new Error("Internal error: constructor URLSearchParams is not installed on the passed global object");
+ }
+
+ return Object.create(ctor.prototype);
+}
+
+exports.create = (globalObject, constructorArgs, privateData) => {
+ const wrapper = makeWrapper(globalObject);
+ return exports.setup(wrapper, globalObject, constructorArgs, privateData);
+};
+
+exports.createImpl = (globalObject, constructorArgs, privateData) => {
+ const wrapper = exports.create(globalObject, constructorArgs, privateData);
+ return utils.implForWrapper(wrapper);
+};
+
+exports._internalSetup = (wrapper, globalObject) => {};
+
+exports.setup = (wrapper, globalObject, constructorArgs = [], privateData = {}) => {
+ privateData.wrapper = wrapper;
+
+ exports._internalSetup(wrapper, globalObject);
+ Object.defineProperty(wrapper, implSymbol, {
+ value: new Impl.implementation(globalObject, constructorArgs, privateData),
+ configurable: true
+ });
+
+ wrapper[implSymbol][utils.wrapperSymbol] = wrapper;
+ if (Impl.init) {
+ Impl.init(wrapper[implSymbol]);
+ }
+ return wrapper;
+};
+
+exports.new = globalObject => {
+ const wrapper = makeWrapper(globalObject);
+
+ exports._internalSetup(wrapper, globalObject);
+ Object.defineProperty(wrapper, implSymbol, {
+ value: Object.create(Impl.implementation.prototype),
+ configurable: true
+ });
+
+ wrapper[implSymbol][utils.wrapperSymbol] = wrapper;
+ if (Impl.init) {
+ Impl.init(wrapper[implSymbol]);
+ }
+ return wrapper[implSymbol];
+};
+
+const exposed = new Set(["Window", "Worker"]);
+
+exports.install = (globalObject, globalNames) => {
+ if (!globalNames.some(globalName => exposed.has(globalName))) {
+ return;
+ }
+ class URLSearchParams {
+ constructor() {
+ const args = [];
+ {
+ let curArg = arguments[0];
+ if (curArg !== undefined) {
+ if (utils.isObject(curArg)) {
+ if (curArg[Symbol.iterator] !== undefined) {
+ if (!utils.isObject(curArg)) {
+ throw new TypeError(
+ "Failed to construct 'URLSearchParams': parameter 1" + " sequence" + " is not an iterable object."
+ );
+ } else {
+ const V = [];
+ const tmp = curArg;
+ for (let nextItem of tmp) {
+ if (!utils.isObject(nextItem)) {
+ throw new TypeError(
+ "Failed to construct 'URLSearchParams': parameter 1" +
+ " sequence" +
+ "'s element" +
+ " is not an iterable object."
+ );
+ } else {
+ const V = [];
+ const tmp = nextItem;
+ for (let nextItem of tmp) {
+ nextItem = conversions["USVString"](nextItem, {
+ context:
+ "Failed to construct 'URLSearchParams': parameter 1" +
+ " sequence" +
+ "'s element" +
+ "'s element"
+ });
+
+ V.push(nextItem);
+ }
+ nextItem = V;
+ }
+
+ V.push(nextItem);
+ }
+ curArg = V;
+ }
+ } else {
+ if (!utils.isObject(curArg)) {
+ throw new TypeError(
+ "Failed to construct 'URLSearchParams': parameter 1" + " record" + " is not an object."
+ );
+ } else {
+ const result = Object.create(null);
+ for (const key of Reflect.ownKeys(curArg)) {
+ const desc = Object.getOwnPropertyDescriptor(curArg, key);
+ if (desc && desc.enumerable) {
+ let typedKey = key;
+
+ typedKey = conversions["USVString"](typedKey, {
+ context: "Failed to construct 'URLSearchParams': parameter 1" + " record" + "'s key"
+ });
+
+ let typedValue = curArg[key];
+
+ typedValue = conversions["USVString"](typedValue, {
+ context: "Failed to construct 'URLSearchParams': parameter 1" + " record" + "'s value"
+ });
+
+ result[typedKey] = typedValue;
+ }
+ }
+ curArg = result;
+ }
+ }
+ } else {
+ curArg = conversions["USVString"](curArg, {
+ context: "Failed to construct 'URLSearchParams': parameter 1"
+ });
+ }
+ } else {
+ curArg = "";
+ }
+ args.push(curArg);
+ }
+ return exports.setup(Object.create(new.target.prototype), globalObject, args);
+ }
+
+ append(name, value) {
+ const esValue = this !== null && this !== undefined ? this : globalObject;
+ if (!exports.is(esValue)) {
+ throw new TypeError("'append' called on an object that is not a valid instance of URLSearchParams.");
+ }
+
+ if (arguments.length < 2) {
+ throw new TypeError(
+ "Failed to execute 'append' on 'URLSearchParams': 2 arguments required, but only " +
+ arguments.length +
+ " present."
+ );
+ }
+ const args = [];
+ {
+ let curArg = arguments[0];
+ curArg = conversions["USVString"](curArg, {
+ context: "Failed to execute 'append' on 'URLSearchParams': parameter 1"
+ });
+ args.push(curArg);
+ }
+ {
+ let curArg = arguments[1];
+ curArg = conversions["USVString"](curArg, {
+ context: "Failed to execute 'append' on 'URLSearchParams': parameter 2"
+ });
+ args.push(curArg);
+ }
+ return esValue[implSymbol].append(...args);
+ }
+
+ delete(name) {
+ const esValue = this !== null && this !== undefined ? this : globalObject;
+ if (!exports.is(esValue)) {
+ throw new TypeError("'delete' called on an object that is not a valid instance of URLSearchParams.");
+ }
+
+ if (arguments.length < 1) {
+ throw new TypeError(
+ "Failed to execute 'delete' on 'URLSearchParams': 1 argument required, but only " +
+ arguments.length +
+ " present."
+ );
+ }
+ const args = [];
+ {
+ let curArg = arguments[0];
+ curArg = conversions["USVString"](curArg, {
+ context: "Failed to execute 'delete' on 'URLSearchParams': parameter 1"
+ });
+ args.push(curArg);
+ }
+ return esValue[implSymbol].delete(...args);
+ }
+
+ get(name) {
+ const esValue = this !== null && this !== undefined ? this : globalObject;
+ if (!exports.is(esValue)) {
+ throw new TypeError("'get' called on an object that is not a valid instance of URLSearchParams.");
+ }
+
+ if (arguments.length < 1) {
+ throw new TypeError(
+ "Failed to execute 'get' on 'URLSearchParams': 1 argument required, but only " +
+ arguments.length +
+ " present."
+ );
+ }
+ const args = [];
+ {
+ let curArg = arguments[0];
+ curArg = conversions["USVString"](curArg, {
+ context: "Failed to execute 'get' on 'URLSearchParams': parameter 1"
+ });
+ args.push(curArg);
+ }
+ return esValue[implSymbol].get(...args);
+ }
+
+ getAll(name) {
+ const esValue = this !== null && this !== undefined ? this : globalObject;
+ if (!exports.is(esValue)) {
+ throw new TypeError("'getAll' called on an object that is not a valid instance of URLSearchParams.");
+ }
+
+ if (arguments.length < 1) {
+ throw new TypeError(
+ "Failed to execute 'getAll' on 'URLSearchParams': 1 argument required, but only " +
+ arguments.length +
+ " present."
+ );
+ }
+ const args = [];
+ {
+ let curArg = arguments[0];
+ curArg = conversions["USVString"](curArg, {
+ context: "Failed to execute 'getAll' on 'URLSearchParams': parameter 1"
+ });
+ args.push(curArg);
+ }
+ return utils.tryWrapperForImpl(esValue[implSymbol].getAll(...args));
+ }
+
+ has(name) {
+ const esValue = this !== null && this !== undefined ? this : globalObject;
+ if (!exports.is(esValue)) {
+ throw new TypeError("'has' called on an object that is not a valid instance of URLSearchParams.");
+ }
+
+ if (arguments.length < 1) {
+ throw new TypeError(
+ "Failed to execute 'has' on 'URLSearchParams': 1 argument required, but only " +
+ arguments.length +
+ " present."
+ );
+ }
+ const args = [];
+ {
+ let curArg = arguments[0];
+ curArg = conversions["USVString"](curArg, {
+ context: "Failed to execute 'has' on 'URLSearchParams': parameter 1"
+ });
+ args.push(curArg);
+ }
+ return esValue[implSymbol].has(...args);
+ }
+
+ set(name, value) {
+ const esValue = this !== null && this !== undefined ? this : globalObject;
+ if (!exports.is(esValue)) {
+ throw new TypeError("'set' called on an object that is not a valid instance of URLSearchParams.");
+ }
+
+ if (arguments.length < 2) {
+ throw new TypeError(
+ "Failed to execute 'set' on 'URLSearchParams': 2 arguments required, but only " +
+ arguments.length +
+ " present."
+ );
+ }
+ const args = [];
+ {
+ let curArg = arguments[0];
+ curArg = conversions["USVString"](curArg, {
+ context: "Failed to execute 'set' on 'URLSearchParams': parameter 1"
+ });
+ args.push(curArg);
+ }
+ {
+ let curArg = arguments[1];
+ curArg = conversions["USVString"](curArg, {
+ context: "Failed to execute 'set' on 'URLSearchParams': parameter 2"
+ });
+ args.push(curArg);
+ }
+ return esValue[implSymbol].set(...args);
+ }
+
+ sort() {
+ const esValue = this !== null && this !== undefined ? this : globalObject;
+ if (!exports.is(esValue)) {
+ throw new TypeError("'sort' called on an object that is not a valid instance of URLSearchParams.");
+ }
+
+ return esValue[implSymbol].sort();
+ }
+
+ toString() {
+ const esValue = this !== null && this !== undefined ? this : globalObject;
+ if (!exports.is(esValue)) {
+ throw new TypeError("'toString' called on an object that is not a valid instance of URLSearchParams.");
+ }
+
+ return esValue[implSymbol].toString();
+ }
+
+ keys() {
+ if (!exports.is(this)) {
+ throw new TypeError("'keys' called on an object that is not a valid instance of URLSearchParams.");
+ }
+ return exports.createDefaultIterator(this, "key");
+ }
+
+ values() {
+ if (!exports.is(this)) {
+ throw new TypeError("'values' called on an object that is not a valid instance of URLSearchParams.");
+ }
+ return exports.createDefaultIterator(this, "value");
+ }
+
+ entries() {
+ if (!exports.is(this)) {
+ throw new TypeError("'entries' called on an object that is not a valid instance of URLSearchParams.");
+ }
+ return exports.createDefaultIterator(this, "key+value");
+ }
+
+ forEach(callback) {
+ if (!exports.is(this)) {
+ throw new TypeError("'forEach' called on an object that is not a valid instance of URLSearchParams.");
+ }
+ if (arguments.length < 1) {
+ throw new TypeError("Failed to execute 'forEach' on 'iterable': 1 argument required, " + "but only 0 present.");
+ }
+ callback = Function.convert(callback, {
+ context: "Failed to execute 'forEach' on 'iterable': The callback provided as parameter 1"
+ });
+ const thisArg = arguments[1];
+ let pairs = Array.from(this[implSymbol]);
+ let i = 0;
+ while (i < pairs.length) {
+ const [key, value] = pairs[i].map(utils.tryWrapperForImpl);
+ callback.call(thisArg, value, key, this);
+ pairs = Array.from(this[implSymbol]);
+ i++;
+ }
+ }
+ }
+ Object.defineProperties(URLSearchParams.prototype, {
+ append: { enumerable: true },
+ delete: { enumerable: true },
+ get: { enumerable: true },
+ getAll: { enumerable: true },
+ has: { enumerable: true },
+ set: { enumerable: true },
+ sort: { enumerable: true },
+ toString: { enumerable: true },
+ keys: { enumerable: true },
+ values: { enumerable: true },
+ entries: { enumerable: true },
+ forEach: { enumerable: true },
+ [Symbol.toStringTag]: { value: "URLSearchParams", configurable: true },
+ [Symbol.iterator]: { value: URLSearchParams.prototype.entries, configurable: true, writable: true }
+ });
+ if (globalObject[ctorRegistrySymbol] === undefined) {
+ globalObject[ctorRegistrySymbol] = Object.create(null);
+ }
+ globalObject[ctorRegistrySymbol][interfaceName] = URLSearchParams;
+
+ Object.defineProperty(globalObject, interfaceName, {
+ configurable: true,
+ writable: true,
+ value: URLSearchParams
+ });
+};
+
+const Impl = require("./URLSearchParams-impl.js");
diff --git a/includes/external/school/node_modules/whatwg-url/dist/VoidFunction.js b/includes/external/school/node_modules/whatwg-url/dist/VoidFunction.js
new file mode 100644
index 0000000..43b0051
--- /dev/null
+++ b/includes/external/school/node_modules/whatwg-url/dist/VoidFunction.js
@@ -0,0 +1,30 @@
+"use strict";
+
+const conversions = require("webidl-conversions");
+const utils = require("./utils.js");
+
+exports.convert = (value, { context = "The provided value" } = {}) => {
+ if (typeof value !== "function") {
+ throw new TypeError(context + " is not a function");
+ }
+
+ function invokeTheCallbackFunction() {
+ if (new.target !== undefined) {
+ throw new Error("Internal error: invokeTheCallbackFunction is not a constructor");
+ }
+
+ const thisArg = utils.tryWrapperForImpl(this);
+ let callResult;
+
+ callResult = Reflect.apply(value, thisArg, []);
+ }
+
+ invokeTheCallbackFunction.construct = () => {
+ let callResult = Reflect.construct(value, []);
+ };
+
+ invokeTheCallbackFunction[utils.wrapperSymbol] = value;
+ invokeTheCallbackFunction.objectReference = value;
+
+ return invokeTheCallbackFunction;
+};
diff --git a/includes/external/school/node_modules/whatwg-url/dist/encoding.js b/includes/external/school/node_modules/whatwg-url/dist/encoding.js
new file mode 100644
index 0000000..2bf6fa3
--- /dev/null
+++ b/includes/external/school/node_modules/whatwg-url/dist/encoding.js
@@ -0,0 +1,26 @@
+"use strict";
+let { TextEncoder, TextDecoder } = require("util");
+// Handle browserify's lack of support (https://github.com/browserify/node-util/issues/46), which
+// is important for the live viewer:
+if (!TextEncoder) {
+ TextEncoder = global.TextEncoder;
+}
+if (!TextDecoder) {
+ TextDecoder = global.TextDecoder;
+}
+
+const utf8Encoder = new TextEncoder();
+const utf8Decoder = new TextDecoder("utf-8", { ignoreBOM: true });
+
+function utf8Encode(string) {
+ return utf8Encoder.encode(string);
+}
+
+function utf8DecodeWithoutBOM(bytes) {
+ return utf8Decoder.decode(bytes);
+}
+
+module.exports = {
+ utf8Encode,
+ utf8DecodeWithoutBOM
+};
diff --git a/includes/external/school/node_modules/whatwg-url/dist/infra.js b/includes/external/school/node_modules/whatwg-url/dist/infra.js
new file mode 100644
index 0000000..4a984a3
--- /dev/null
+++ b/includes/external/school/node_modules/whatwg-url/dist/infra.js
@@ -0,0 +1,26 @@
+"use strict";
+
+// Note that we take code points as JS numbers, not JS strings.
+
+function isASCIIDigit(c) {
+ return c >= 0x30 && c <= 0x39;
+}
+
+function isASCIIAlpha(c) {
+ return (c >= 0x41 && c <= 0x5A) || (c >= 0x61 && c <= 0x7A);
+}
+
+function isASCIIAlphanumeric(c) {
+ return isASCIIAlpha(c) || isASCIIDigit(c);
+}
+
+function isASCIIHex(c) {
+ return isASCIIDigit(c) || (c >= 0x41 && c <= 0x46) || (c >= 0x61 && c <= 0x66);
+}
+
+module.exports = {
+ isASCIIDigit,
+ isASCIIAlpha,
+ isASCIIAlphanumeric,
+ isASCIIHex
+};
diff --git a/includes/external/school/node_modules/whatwg-url/dist/percent-encoding.js b/includes/external/school/node_modules/whatwg-url/dist/percent-encoding.js
new file mode 100644
index 0000000..a12ab37
--- /dev/null
+++ b/includes/external/school/node_modules/whatwg-url/dist/percent-encoding.js
@@ -0,0 +1,141 @@
+"use strict";
+const { isASCIIHex } = require("./infra");
+const { utf8Encode } = require("./encoding");
+
+// https://url.spec.whatwg.org/#percent-encode
+function percentEncode(c) {
+ let hex = c.toString(16).toUpperCase();
+ if (hex.length === 1) {
+ hex = `0${hex}`;
+ }
+
+ return `%${hex}`;
+}
+
+// https://url.spec.whatwg.org/#percent-decode
+function percentDecodeBytes(input) {
+ const output = new Uint8Array(input.byteLength);
+ let outputIndex = 0;
+ for (let i = 0; i < input.byteLength; ++i) {
+ const byte = input[i];
+ if (byte !== 0x25) {
+ output[outputIndex++] = byte;
+ } else if (byte === 0x25 && (!isASCIIHex(input[i + 1]) || !isASCIIHex(input[i + 2]))) {
+ output[outputIndex++] = byte;
+ } else {
+ const bytePoint = parseInt(String.fromCodePoint(input[i + 1], input[i + 2]), 16);
+ output[outputIndex++] = bytePoint;
+ i += 2;
+ }
+ }
+
+ // TODO: remove the Buffer.from in the next major version; it's only needed for back-compat, and sticking to standard
+ // typed arrays is nicer and simpler.
+ // See https://github.com/jsdom/data-urls/issues/17 for background.
+ return Buffer.from(output.slice(0, outputIndex));
+}
+
+// https://url.spec.whatwg.org/#string-percent-decode
+function percentDecodeString(input) {
+ const bytes = utf8Encode(input);
+ return percentDecodeBytes(bytes);
+}
+
+// https://url.spec.whatwg.org/#c0-control-percent-encode-set
+function isC0ControlPercentEncode(c) {
+ return c <= 0x1F || c > 0x7E;
+}
+
+// https://url.spec.whatwg.org/#fragment-percent-encode-set
+const extraFragmentPercentEncodeSet = new Set([32, 34, 60, 62, 96]);
+function isFragmentPercentEncode(c) {
+ return isC0ControlPercentEncode(c) || extraFragmentPercentEncodeSet.has(c);
+}
+
+// https://url.spec.whatwg.org/#query-percent-encode-set
+const extraQueryPercentEncodeSet = new Set([32, 34, 35, 60, 62]);
+function isQueryPercentEncode(c) {
+ return isC0ControlPercentEncode(c) || extraQueryPercentEncodeSet.has(c);
+}
+
+// https://url.spec.whatwg.org/#special-query-percent-encode-set
+function isSpecialQueryPercentEncode(c) {
+ return isQueryPercentEncode(c) || c === 39;
+}
+
+// https://url.spec.whatwg.org/#path-percent-encode-set
+const extraPathPercentEncodeSet = new Set([63, 96, 123, 125]);
+function isPathPercentEncode(c) {
+ return isQueryPercentEncode(c) || extraPathPercentEncodeSet.has(c);
+}
+
+// https://url.spec.whatwg.org/#userinfo-percent-encode-set
+const extraUserinfoPercentEncodeSet =
+ new Set([47, 58, 59, 61, 64, 91, 92, 93, 94, 124]);
+function isUserinfoPercentEncode(c) {
+ return isPathPercentEncode(c) || extraUserinfoPercentEncodeSet.has(c);
+}
+
+// https://url.spec.whatwg.org/#component-percent-encode-set
+const extraComponentPercentEncodeSet = new Set([36, 37, 38, 43, 44]);
+function isComponentPercentEncode(c) {
+ return isUserinfoPercentEncode(c) || extraComponentPercentEncodeSet.has(c);
+}
+
+// https://url.spec.whatwg.org/#application-x-www-form-urlencoded-percent-encode-set
+const extraURLEncodedPercentEncodeSet = new Set([33, 39, 40, 41, 126]);
+function isURLEncodedPercentEncode(c) {
+ return isComponentPercentEncode(c) || extraURLEncodedPercentEncodeSet.has(c);
+}
+
+// https://url.spec.whatwg.org/#code-point-percent-encode-after-encoding
+// https://url.spec.whatwg.org/#utf-8-percent-encode
+// Assuming encoding is always utf-8 allows us to trim one of the logic branches. TODO: support encoding.
+// The "-Internal" variant here has code points as JS strings. The external version used by other files has code points
+// as JS numbers, like the rest of the codebase.
+function utf8PercentEncodeCodePointInternal(codePoint, percentEncodePredicate) {
+ const bytes = utf8Encode(codePoint);
+ let output = "";
+ for (const byte of bytes) {
+ // Our percentEncodePredicate operates on bytes, not code points, so this is slightly different from the spec.
+ if (!percentEncodePredicate(byte)) {
+ output += String.fromCharCode(byte);
+ } else {
+ output += percentEncode(byte);
+ }
+ }
+
+ return output;
+}
+
+function utf8PercentEncodeCodePoint(codePoint, percentEncodePredicate) {
+ return utf8PercentEncodeCodePointInternal(String.fromCodePoint(codePoint), percentEncodePredicate);
+}
+
+// https://url.spec.whatwg.org/#string-percent-encode-after-encoding
+// https://url.spec.whatwg.org/#string-utf-8-percent-encode
+function utf8PercentEncodeString(input, percentEncodePredicate, spaceAsPlus = false) {
+ let output = "";
+ for (const codePoint of input) {
+ if (spaceAsPlus && codePoint === " ") {
+ output += "+";
+ } else {
+ output += utf8PercentEncodeCodePointInternal(codePoint, percentEncodePredicate);
+ }
+ }
+ return output;
+}
+
+module.exports = {
+ isC0ControlPercentEncode,
+ isFragmentPercentEncode,
+ isQueryPercentEncode,
+ isSpecialQueryPercentEncode,
+ isPathPercentEncode,
+ isUserinfoPercentEncode,
+ isURLEncodedPercentEncode,
+ percentDecodeString,
+ percentDecodeBytes,
+ utf8PercentEncodeString,
+ utf8PercentEncodeCodePoint
+};
diff --git a/includes/external/school/node_modules/whatwg-url/dist/url-state-machine.js b/includes/external/school/node_modules/whatwg-url/dist/url-state-machine.js
new file mode 100644
index 0000000..3640024
--- /dev/null
+++ b/includes/external/school/node_modules/whatwg-url/dist/url-state-machine.js
@@ -0,0 +1,1210 @@
+"use strict";
+const punycode = require("punycode");
+const tr46 = require("tr46");
+
+const infra = require("./infra");
+const { utf8DecodeWithoutBOM } = require("./encoding");
+const { percentDecodeString, utf8PercentEncodeCodePoint, utf8PercentEncodeString, isC0ControlPercentEncode,
+ isFragmentPercentEncode, isQueryPercentEncode, isSpecialQueryPercentEncode, isPathPercentEncode,
+ isUserinfoPercentEncode } = require("./percent-encoding");
+
+const specialSchemes = {
+ ftp: 21,
+ file: null,
+ http: 80,
+ https: 443,
+ ws: 80,
+ wss: 443
+};
+
+const failure = Symbol("failure");
+
+function countSymbols(str) {
+ return [...str].length;
+}
+
+function at(input, idx) {
+ const c = input[idx];
+ return isNaN(c) ? undefined : String.fromCodePoint(c);
+}
+
+function isSingleDot(buffer) {
+ return buffer === "." || buffer.toLowerCase() === "%2e";
+}
+
+function isDoubleDot(buffer) {
+ buffer = buffer.toLowerCase();
+ return buffer === ".." || buffer === "%2e." || buffer === ".%2e" || buffer === "%2e%2e";
+}
+
+function isWindowsDriveLetterCodePoints(cp1, cp2) {
+ return infra.isASCIIAlpha(cp1) && (cp2 === 58 || cp2 === 124);
+}
+
+function isWindowsDriveLetterString(string) {
+ return string.length === 2 && infra.isASCIIAlpha(string.codePointAt(0)) && (string[1] === ":" || string[1] === "|");
+}
+
+function isNormalizedWindowsDriveLetterString(string) {
+ return string.length === 2 && infra.isASCIIAlpha(string.codePointAt(0)) && string[1] === ":";
+}
+
+function containsForbiddenHostCodePoint(string) {
+ return string.search(/\u0000|\u0009|\u000A|\u000D|\u0020|#|%|\/|:|<|>|\?|@|\[|\\|\]|\^|\|/u) !== -1;
+}
+
+function containsForbiddenHostCodePointExcludingPercent(string) {
+ return string.search(/\u0000|\u0009|\u000A|\u000D|\u0020|#|\/|:|<|>|\?|@|\[|\\|\]|\^|\|/u) !== -1;
+}
+
+function isSpecialScheme(scheme) {
+ return specialSchemes[scheme] !== undefined;
+}
+
+function isSpecial(url) {
+ return isSpecialScheme(url.scheme);
+}
+
+function isNotSpecial(url) {
+ return !isSpecialScheme(url.scheme);
+}
+
+function defaultPort(scheme) {
+ return specialSchemes[scheme];
+}
+
+function parseIPv4Number(input) {
+ let R = 10;
+
+ if (input.length >= 2 && input.charAt(0) === "0" && input.charAt(1).toLowerCase() === "x") {
+ input = input.substring(2);
+ R = 16;
+ } else if (input.length >= 2 && input.charAt(0) === "0") {
+ input = input.substring(1);
+ R = 8;
+ }
+
+ if (input === "") {
+ return 0;
+ }
+
+ let regex = /[^0-7]/u;
+ if (R === 10) {
+ regex = /[^0-9]/u;
+ }
+ if (R === 16) {
+ regex = /[^0-9A-Fa-f]/u;
+ }
+
+ if (regex.test(input)) {
+ return failure;
+ }
+
+ return parseInt(input, R);
+}
+
+function parseIPv4(input) {
+ const parts = input.split(".");
+ if (parts[parts.length - 1] === "") {
+ if (parts.length > 1) {
+ parts.pop();
+ }
+ }
+
+ if (parts.length > 4) {
+ return input;
+ }
+
+ const numbers = [];
+ for (const part of parts) {
+ if (part === "") {
+ return input;
+ }
+ const n = parseIPv4Number(part);
+ if (n === failure) {
+ return input;
+ }
+
+ numbers.push(n);
+ }
+
+ for (let i = 0; i < numbers.length - 1; ++i) {
+ if (numbers[i] > 255) {
+ return failure;
+ }
+ }
+ if (numbers[numbers.length - 1] >= 256 ** (5 - numbers.length)) {
+ return failure;
+ }
+
+ let ipv4 = numbers.pop();
+ let counter = 0;
+
+ for (const n of numbers) {
+ ipv4 += n * 256 ** (3 - counter);
+ ++counter;
+ }
+
+ return ipv4;
+}
+
+function serializeIPv4(address) {
+ let output = "";
+ let n = address;
+
+ for (let i = 1; i <= 4; ++i) {
+ output = String(n % 256) + output;
+ if (i !== 4) {
+ output = `.${output}`;
+ }
+ n = Math.floor(n / 256);
+ }
+
+ return output;
+}
+
+function parseIPv6(input) {
+ const address = [0, 0, 0, 0, 0, 0, 0, 0];
+ let pieceIndex = 0;
+ let compress = null;
+ let pointer = 0;
+
+ input = punycode.ucs2.decode(input);
+
+ if (input[pointer] === 58) {
+ if (input[pointer + 1] !== 58) {
+ return failure;
+ }
+
+ pointer += 2;
+ ++pieceIndex;
+ compress = pieceIndex;
+ }
+
+ while (pointer < input.length) {
+ if (pieceIndex === 8) {
+ return failure;
+ }
+
+ if (input[pointer] === 58) {
+ if (compress !== null) {
+ return failure;
+ }
+ ++pointer;
+ ++pieceIndex;
+ compress = pieceIndex;
+ continue;
+ }
+
+ let value = 0;
+ let length = 0;
+
+ while (length < 4 && infra.isASCIIHex(input[pointer])) {
+ value = value * 0x10 + parseInt(at(input, pointer), 16);
+ ++pointer;
+ ++length;
+ }
+
+ if (input[pointer] === 46) {
+ if (length === 0) {
+ return failure;
+ }
+
+ pointer -= length;
+
+ if (pieceIndex > 6) {
+ return failure;
+ }
+
+ let numbersSeen = 0;
+
+ while (input[pointer] !== undefined) {
+ let ipv4Piece = null;
+
+ if (numbersSeen > 0) {
+ if (input[pointer] === 46 && numbersSeen < 4) {
+ ++pointer;
+ } else {
+ return failure;
+ }
+ }
+
+ if (!infra.isASCIIDigit(input[pointer])) {
+ return failure;
+ }
+
+ while (infra.isASCIIDigit(input[pointer])) {
+ const number = parseInt(at(input, pointer));
+ if (ipv4Piece === null) {
+ ipv4Piece = number;
+ } else if (ipv4Piece === 0) {
+ return failure;
+ } else {
+ ipv4Piece = ipv4Piece * 10 + number;
+ }
+ if (ipv4Piece > 255) {
+ return failure;
+ }
+ ++pointer;
+ }
+
+ address[pieceIndex] = address[pieceIndex] * 0x100 + ipv4Piece;
+
+ ++numbersSeen;
+
+ if (numbersSeen === 2 || numbersSeen === 4) {
+ ++pieceIndex;
+ }
+ }
+
+ if (numbersSeen !== 4) {
+ return failure;
+ }
+
+ break;
+ } else if (input[pointer] === 58) {
+ ++pointer;
+ if (input[pointer] === undefined) {
+ return failure;
+ }
+ } else if (input[pointer] !== undefined) {
+ return failure;
+ }
+
+ address[pieceIndex] = value;
+ ++pieceIndex;
+ }
+
+ if (compress !== null) {
+ let swaps = pieceIndex - compress;
+ pieceIndex = 7;
+ while (pieceIndex !== 0 && swaps > 0) {
+ const temp = address[compress + swaps - 1];
+ address[compress + swaps - 1] = address[pieceIndex];
+ address[pieceIndex] = temp;
+ --pieceIndex;
+ --swaps;
+ }
+ } else if (compress === null && pieceIndex !== 8) {
+ return failure;
+ }
+
+ return address;
+}
+
+function serializeIPv6(address) {
+ let output = "";
+ const compress = findLongestZeroSequence(address);
+ let ignore0 = false;
+
+ for (let pieceIndex = 0; pieceIndex <= 7; ++pieceIndex) {
+ if (ignore0 && address[pieceIndex] === 0) {
+ continue;
+ } else if (ignore0) {
+ ignore0 = false;
+ }
+
+ if (compress === pieceIndex) {
+ const separator = pieceIndex === 0 ? "::" : ":";
+ output += separator;
+ ignore0 = true;
+ continue;
+ }
+
+ output += address[pieceIndex].toString(16);
+
+ if (pieceIndex !== 7) {
+ output += ":";
+ }
+ }
+
+ return output;
+}
+
+function parseHost(input, isNotSpecialArg = false) {
+ if (input[0] === "[") {
+ if (input[input.length - 1] !== "]") {
+ return failure;
+ }
+
+ return parseIPv6(input.substring(1, input.length - 1));
+ }
+
+ if (isNotSpecialArg) {
+ return parseOpaqueHost(input);
+ }
+
+ const domain = utf8DecodeWithoutBOM(percentDecodeString(input));
+ const asciiDomain = domainToASCII(domain);
+ if (asciiDomain === failure) {
+ return failure;
+ }
+
+ if (containsForbiddenHostCodePoint(asciiDomain)) {
+ return failure;
+ }
+
+ const ipv4Host = parseIPv4(asciiDomain);
+ if (typeof ipv4Host === "number" || ipv4Host === failure) {
+ return ipv4Host;
+ }
+
+ return asciiDomain;
+}
+
+function parseOpaqueHost(input) {
+ if (containsForbiddenHostCodePointExcludingPercent(input)) {
+ return failure;
+ }
+
+ return utf8PercentEncodeString(input, isC0ControlPercentEncode);
+}
+
+function findLongestZeroSequence(arr) {
+ let maxIdx = null;
+ let maxLen = 1; // only find elements > 1
+ let currStart = null;
+ let currLen = 0;
+
+ for (let i = 0; i < arr.length; ++i) {
+ if (arr[i] !== 0) {
+ if (currLen > maxLen) {
+ maxIdx = currStart;
+ maxLen = currLen;
+ }
+
+ currStart = null;
+ currLen = 0;
+ } else {
+ if (currStart === null) {
+ currStart = i;
+ }
+ ++currLen;
+ }
+ }
+
+ // if trailing zeros
+ if (currLen > maxLen) {
+ return currStart;
+ }
+
+ return maxIdx;
+}
+
+function serializeHost(host) {
+ if (typeof host === "number") {
+ return serializeIPv4(host);
+ }
+
+ // IPv6 serializer
+ if (host instanceof Array) {
+ return `[${serializeIPv6(host)}]`;
+ }
+
+ return host;
+}
+
+function domainToASCII(domain, beStrict = false) {
+ const result = tr46.toASCII(domain, {
+ checkBidi: true,
+ checkHyphens: false,
+ checkJoiners: true,
+ useSTD3ASCIIRules: beStrict,
+ verifyDNSLength: beStrict
+ });
+ if (result === null || result === "") {
+ return failure;
+ }
+ return result;
+}
+
+function trimControlChars(url) {
+ return url.replace(/^[\u0000-\u001F\u0020]+|[\u0000-\u001F\u0020]+$/ug, "");
+}
+
+function trimTabAndNewline(url) {
+ return url.replace(/\u0009|\u000A|\u000D/ug, "");
+}
+
+function shortenPath(url) {
+ const { path } = url;
+ if (path.length === 0) {
+ return;
+ }
+ if (url.scheme === "file" && path.length === 1 && isNormalizedWindowsDriveLetter(path[0])) {
+ return;
+ }
+
+ path.pop();
+}
+
+function includesCredentials(url) {
+ return url.username !== "" || url.password !== "";
+}
+
+function cannotHaveAUsernamePasswordPort(url) {
+ return url.host === null || url.host === "" || url.cannotBeABaseURL || url.scheme === "file";
+}
+
+function isNormalizedWindowsDriveLetter(string) {
+ return /^[A-Za-z]:$/u.test(string);
+}
+
+function URLStateMachine(input, base, encodingOverride, url, stateOverride) {
+ this.pointer = 0;
+ this.input = input;
+ this.base = base || null;
+ this.encodingOverride = encodingOverride || "utf-8";
+ this.stateOverride = stateOverride;
+ this.url = url;
+ this.failure = false;
+ this.parseError = false;
+
+ if (!this.url) {
+ this.url = {
+ scheme: "",
+ username: "",
+ password: "",
+ host: null,
+ port: null,
+ path: [],
+ query: null,
+ fragment: null,
+
+ cannotBeABaseURL: false
+ };
+
+ const res = trimControlChars(this.input);
+ if (res !== this.input) {
+ this.parseError = true;
+ }
+ this.input = res;
+ }
+
+ const res = trimTabAndNewline(this.input);
+ if (res !== this.input) {
+ this.parseError = true;
+ }
+ this.input = res;
+
+ this.state = stateOverride || "scheme start";
+
+ this.buffer = "";
+ this.atFlag = false;
+ this.arrFlag = false;
+ this.passwordTokenSeenFlag = false;
+
+ this.input = punycode.ucs2.decode(this.input);
+
+ for (; this.pointer <= this.input.length; ++this.pointer) {
+ const c = this.input[this.pointer];
+ const cStr = isNaN(c) ? undefined : String.fromCodePoint(c);
+
+ // exec state machine
+ const ret = this[`parse ${this.state}`](c, cStr);
+ if (!ret) {
+ break; // terminate algorithm
+ } else if (ret === failure) {
+ this.failure = true;
+ break;
+ }
+ }
+}
+
+URLStateMachine.prototype["parse scheme start"] = function parseSchemeStart(c, cStr) {
+ if (infra.isASCIIAlpha(c)) {
+ this.buffer += cStr.toLowerCase();
+ this.state = "scheme";
+ } else if (!this.stateOverride) {
+ this.state = "no scheme";
+ --this.pointer;
+ } else {
+ this.parseError = true;
+ return failure;
+ }
+
+ return true;
+};
+
+URLStateMachine.prototype["parse scheme"] = function parseScheme(c, cStr) {
+ if (infra.isASCIIAlphanumeric(c) || c === 43 || c === 45 || c === 46) {
+ this.buffer += cStr.toLowerCase();
+ } else if (c === 58) {
+ if (this.stateOverride) {
+ if (isSpecial(this.url) && !isSpecialScheme(this.buffer)) {
+ return false;
+ }
+
+ if (!isSpecial(this.url) && isSpecialScheme(this.buffer)) {
+ return false;
+ }
+
+ if ((includesCredentials(this.url) || this.url.port !== null) && this.buffer === "file") {
+ return false;
+ }
+
+ if (this.url.scheme === "file" && this.url.host === "") {
+ return false;
+ }
+ }
+ this.url.scheme = this.buffer;
+ if (this.stateOverride) {
+ if (this.url.port === defaultPort(this.url.scheme)) {
+ this.url.port = null;
+ }
+ return false;
+ }
+ this.buffer = "";
+ if (this.url.scheme === "file") {
+ if (this.input[this.pointer + 1] !== 47 || this.input[this.pointer + 2] !== 47) {
+ this.parseError = true;
+ }
+ this.state = "file";
+ } else if (isSpecial(this.url) && this.base !== null && this.base.scheme === this.url.scheme) {
+ this.state = "special relative or authority";
+ } else if (isSpecial(this.url)) {
+ this.state = "special authority slashes";
+ } else if (this.input[this.pointer + 1] === 47) {
+ this.state = "path or authority";
+ ++this.pointer;
+ } else {
+ this.url.cannotBeABaseURL = true;
+ this.url.path.push("");
+ this.state = "cannot-be-a-base-URL path";
+ }
+ } else if (!this.stateOverride) {
+ this.buffer = "";
+ this.state = "no scheme";
+ this.pointer = -1;
+ } else {
+ this.parseError = true;
+ return failure;
+ }
+
+ return true;
+};
+
+URLStateMachine.prototype["parse no scheme"] = function parseNoScheme(c) {
+ if (this.base === null || (this.base.cannotBeABaseURL && c !== 35)) {
+ return failure;
+ } else if (this.base.cannotBeABaseURL && c === 35) {
+ this.url.scheme = this.base.scheme;
+ this.url.path = this.base.path.slice();
+ this.url.query = this.base.query;
+ this.url.fragment = "";
+ this.url.cannotBeABaseURL = true;
+ this.state = "fragment";
+ } else if (this.base.scheme === "file") {
+ this.state = "file";
+ --this.pointer;
+ } else {
+ this.state = "relative";
+ --this.pointer;
+ }
+
+ return true;
+};
+
+URLStateMachine.prototype["parse special relative or authority"] = function parseSpecialRelativeOrAuthority(c) {
+ if (c === 47 && this.input[this.pointer + 1] === 47) {
+ this.state = "special authority ignore slashes";
+ ++this.pointer;
+ } else {
+ this.parseError = true;
+ this.state = "relative";
+ --this.pointer;
+ }
+
+ return true;
+};
+
+URLStateMachine.prototype["parse path or authority"] = function parsePathOrAuthority(c) {
+ if (c === 47) {
+ this.state = "authority";
+ } else {
+ this.state = "path";
+ --this.pointer;
+ }
+
+ return true;
+};
+
+URLStateMachine.prototype["parse relative"] = function parseRelative(c) {
+ this.url.scheme = this.base.scheme;
+ if (c === 47) {
+ this.state = "relative slash";
+ } else if (isSpecial(this.url) && c === 92) {
+ this.parseError = true;
+ this.state = "relative slash";
+ } else {
+ this.url.username = this.base.username;
+ this.url.password = this.base.password;
+ this.url.host = this.base.host;
+ this.url.port = this.base.port;
+ this.url.path = this.base.path.slice();
+ this.url.query = this.base.query;
+ if (c === 63) {
+ this.url.query = "";
+ this.state = "query";
+ } else if (c === 35) {
+ this.url.fragment = "";
+ this.state = "fragment";
+ } else if (!isNaN(c)) {
+ this.url.query = null;
+ this.url.path.pop();
+ this.state = "path";
+ --this.pointer;
+ }
+ }
+
+ return true;
+};
+
+URLStateMachine.prototype["parse relative slash"] = function parseRelativeSlash(c) {
+ if (isSpecial(this.url) && (c === 47 || c === 92)) {
+ if (c === 92) {
+ this.parseError = true;
+ }
+ this.state = "special authority ignore slashes";
+ } else if (c === 47) {
+ this.state = "authority";
+ } else {
+ this.url.username = this.base.username;
+ this.url.password = this.base.password;
+ this.url.host = this.base.host;
+ this.url.port = this.base.port;
+ this.state = "path";
+ --this.pointer;
+ }
+
+ return true;
+};
+
+URLStateMachine.prototype["parse special authority slashes"] = function parseSpecialAuthoritySlashes(c) {
+ if (c === 47 && this.input[this.pointer + 1] === 47) {
+ this.state = "special authority ignore slashes";
+ ++this.pointer;
+ } else {
+ this.parseError = true;
+ this.state = "special authority ignore slashes";
+ --this.pointer;
+ }
+
+ return true;
+};
+
+URLStateMachine.prototype["parse special authority ignore slashes"] = function parseSpecialAuthorityIgnoreSlashes(c) {
+ if (c !== 47 && c !== 92) {
+ this.state = "authority";
+ --this.pointer;
+ } else {
+ this.parseError = true;
+ }
+
+ return true;
+};
+
+URLStateMachine.prototype["parse authority"] = function parseAuthority(c, cStr) {
+ if (c === 64) {
+ this.parseError = true;
+ if (this.atFlag) {
+ this.buffer = `%40${this.buffer}`;
+ }
+ this.atFlag = true;
+
+ // careful, this is based on buffer and has its own pointer (this.pointer != pointer) and inner chars
+ const len = countSymbols(this.buffer);
+ for (let pointer = 0; pointer < len; ++pointer) {
+ const codePoint = this.buffer.codePointAt(pointer);
+
+ if (codePoint === 58 && !this.passwordTokenSeenFlag) {
+ this.passwordTokenSeenFlag = true;
+ continue;
+ }
+ const encodedCodePoints = utf8PercentEncodeCodePoint(codePoint, isUserinfoPercentEncode);
+ if (this.passwordTokenSeenFlag) {
+ this.url.password += encodedCodePoints;
+ } else {
+ this.url.username += encodedCodePoints;
+ }
+ }
+ this.buffer = "";
+ } else if (isNaN(c) || c === 47 || c === 63 || c === 35 ||
+ (isSpecial(this.url) && c === 92)) {
+ if (this.atFlag && this.buffer === "") {
+ this.parseError = true;
+ return failure;
+ }
+ this.pointer -= countSymbols(this.buffer) + 1;
+ this.buffer = "";
+ this.state = "host";
+ } else {
+ this.buffer += cStr;
+ }
+
+ return true;
+};
+
+URLStateMachine.prototype["parse hostname"] =
+URLStateMachine.prototype["parse host"] = function parseHostName(c, cStr) {
+ if (this.stateOverride && this.url.scheme === "file") {
+ --this.pointer;
+ this.state = "file host";
+ } else if (c === 58 && !this.arrFlag) {
+ if (this.buffer === "") {
+ this.parseError = true;
+ return failure;
+ }
+
+ if (this.stateOverride === "hostname") {
+ return false;
+ }
+
+ const host = parseHost(this.buffer, isNotSpecial(this.url));
+ if (host === failure) {
+ return failure;
+ }
+
+ this.url.host = host;
+ this.buffer = "";
+ this.state = "port";
+ } else if (isNaN(c) || c === 47 || c === 63 || c === 35 ||
+ (isSpecial(this.url) && c === 92)) {
+ --this.pointer;
+ if (isSpecial(this.url) && this.buffer === "") {
+ this.parseError = true;
+ return failure;
+ } else if (this.stateOverride && this.buffer === "" &&
+ (includesCredentials(this.url) || this.url.port !== null)) {
+ this.parseError = true;
+ return false;
+ }
+
+ const host = parseHost(this.buffer, isNotSpecial(this.url));
+ if (host === failure) {
+ return failure;
+ }
+
+ this.url.host = host;
+ this.buffer = "";
+ this.state = "path start";
+ if (this.stateOverride) {
+ return false;
+ }
+ } else {
+ if (c === 91) {
+ this.arrFlag = true;
+ } else if (c === 93) {
+ this.arrFlag = false;
+ }
+ this.buffer += cStr;
+ }
+
+ return true;
+};
+
+URLStateMachine.prototype["parse port"] = function parsePort(c, cStr) {
+ if (infra.isASCIIDigit(c)) {
+ this.buffer += cStr;
+ } else if (isNaN(c) || c === 47 || c === 63 || c === 35 ||
+ (isSpecial(this.url) && c === 92) ||
+ this.stateOverride) {
+ if (this.buffer !== "") {
+ const port = parseInt(this.buffer);
+ if (port > 2 ** 16 - 1) {
+ this.parseError = true;
+ return failure;
+ }
+ this.url.port = port === defaultPort(this.url.scheme) ? null : port;
+ this.buffer = "";
+ }
+ if (this.stateOverride) {
+ return false;
+ }
+ this.state = "path start";
+ --this.pointer;
+ } else {
+ this.parseError = true;
+ return failure;
+ }
+
+ return true;
+};
+
+const fileOtherwiseCodePoints = new Set([47, 92, 63, 35]);
+
+function startsWithWindowsDriveLetter(input, pointer) {
+ const length = input.length - pointer;
+ return length >= 2 &&
+ isWindowsDriveLetterCodePoints(input[pointer], input[pointer + 1]) &&
+ (length === 2 || fileOtherwiseCodePoints.has(input[pointer + 2]));
+}
+
+URLStateMachine.prototype["parse file"] = function parseFile(c) {
+ this.url.scheme = "file";
+ this.url.host = "";
+
+ if (c === 47 || c === 92) {
+ if (c === 92) {
+ this.parseError = true;
+ }
+ this.state = "file slash";
+ } else if (this.base !== null && this.base.scheme === "file") {
+ this.url.host = this.base.host;
+ this.url.path = this.base.path.slice();
+ this.url.query = this.base.query;
+ if (c === 63) {
+ this.url.query = "";
+ this.state = "query";
+ } else if (c === 35) {
+ this.url.fragment = "";
+ this.state = "fragment";
+ } else if (!isNaN(c)) {
+ this.url.query = null;
+ if (!startsWithWindowsDriveLetter(this.input, this.pointer)) {
+ shortenPath(this.url);
+ } else {
+ this.parseError = true;
+ this.url.path = [];
+ }
+
+ this.state = "path";
+ --this.pointer;
+ }
+ } else {
+ this.state = "path";
+ --this.pointer;
+ }
+
+ return true;
+};
+
+URLStateMachine.prototype["parse file slash"] = function parseFileSlash(c) {
+ if (c === 47 || c === 92) {
+ if (c === 92) {
+ this.parseError = true;
+ }
+ this.state = "file host";
+ } else {
+ if (this.base !== null && this.base.scheme === "file") {
+ if (!startsWithWindowsDriveLetter(this.input, this.pointer) &&
+ isNormalizedWindowsDriveLetterString(this.base.path[0])) {
+ this.url.path.push(this.base.path[0]);
+ }
+ this.url.host = this.base.host;
+ }
+ this.state = "path";
+ --this.pointer;
+ }
+
+ return true;
+};
+
+URLStateMachine.prototype["parse file host"] = function parseFileHost(c, cStr) {
+ if (isNaN(c) || c === 47 || c === 92 || c === 63 || c === 35) {
+ --this.pointer;
+ if (!this.stateOverride && isWindowsDriveLetterString(this.buffer)) {
+ this.parseError = true;
+ this.state = "path";
+ } else if (this.buffer === "") {
+ this.url.host = "";
+ if (this.stateOverride) {
+ return false;
+ }
+ this.state = "path start";
+ } else {
+ let host = parseHost(this.buffer, isNotSpecial(this.url));
+ if (host === failure) {
+ return failure;
+ }
+ if (host === "localhost") {
+ host = "";
+ }
+ this.url.host = host;
+
+ if (this.stateOverride) {
+ return false;
+ }
+
+ this.buffer = "";
+ this.state = "path start";
+ }
+ } else {
+ this.buffer += cStr;
+ }
+
+ return true;
+};
+
+URLStateMachine.prototype["parse path start"] = function parsePathStart(c) {
+ if (isSpecial(this.url)) {
+ if (c === 92) {
+ this.parseError = true;
+ }
+ this.state = "path";
+
+ if (c !== 47 && c !== 92) {
+ --this.pointer;
+ }
+ } else if (!this.stateOverride && c === 63) {
+ this.url.query = "";
+ this.state = "query";
+ } else if (!this.stateOverride && c === 35) {
+ this.url.fragment = "";
+ this.state = "fragment";
+ } else if (c !== undefined) {
+ this.state = "path";
+ if (c !== 47) {
+ --this.pointer;
+ }
+ } else if (this.stateOverride && this.url.host === null) {
+ this.url.path.push("");
+ }
+
+ return true;
+};
+
+URLStateMachine.prototype["parse path"] = function parsePath(c) {
+ if (isNaN(c) || c === 47 || (isSpecial(this.url) && c === 92) ||
+ (!this.stateOverride && (c === 63 || c === 35))) {
+ if (isSpecial(this.url) && c === 92) {
+ this.parseError = true;
+ }
+
+ if (isDoubleDot(this.buffer)) {
+ shortenPath(this.url);
+ if (c !== 47 && !(isSpecial(this.url) && c === 92)) {
+ this.url.path.push("");
+ }
+ } else if (isSingleDot(this.buffer) && c !== 47 &&
+ !(isSpecial(this.url) && c === 92)) {
+ this.url.path.push("");
+ } else if (!isSingleDot(this.buffer)) {
+ if (this.url.scheme === "file" && this.url.path.length === 0 && isWindowsDriveLetterString(this.buffer)) {
+ this.buffer = `${this.buffer[0]}:`;
+ }
+ this.url.path.push(this.buffer);
+ }
+ this.buffer = "";
+ if (c === 63) {
+ this.url.query = "";
+ this.state = "query";
+ }
+ if (c === 35) {
+ this.url.fragment = "";
+ this.state = "fragment";
+ }
+ } else {
+ // TODO: If c is not a URL code point and not "%", parse error.
+
+ if (c === 37 &&
+ (!infra.isASCIIHex(this.input[this.pointer + 1]) ||
+ !infra.isASCIIHex(this.input[this.pointer + 2]))) {
+ this.parseError = true;
+ }
+
+ this.buffer += utf8PercentEncodeCodePoint(c, isPathPercentEncode);
+ }
+
+ return true;
+};
+
+URLStateMachine.prototype["parse cannot-be-a-base-URL path"] = function parseCannotBeABaseURLPath(c) {
+ if (c === 63) {
+ this.url.query = "";
+ this.state = "query";
+ } else if (c === 35) {
+ this.url.fragment = "";
+ this.state = "fragment";
+ } else {
+ // TODO: Add: not a URL code point
+ if (!isNaN(c) && c !== 37) {
+ this.parseError = true;
+ }
+
+ if (c === 37 &&
+ (!infra.isASCIIHex(this.input[this.pointer + 1]) ||
+ !infra.isASCIIHex(this.input[this.pointer + 2]))) {
+ this.parseError = true;
+ }
+
+ if (!isNaN(c)) {
+ this.url.path[0] += utf8PercentEncodeCodePoint(c, isC0ControlPercentEncode);
+ }
+ }
+
+ return true;
+};
+
+URLStateMachine.prototype["parse query"] = function parseQuery(c, cStr) {
+ if (!isSpecial(this.url) || this.url.scheme === "ws" || this.url.scheme === "wss") {
+ this.encodingOverride = "utf-8";
+ }
+
+ if ((!this.stateOverride && c === 35) || isNaN(c)) {
+ const queryPercentEncodePredicate = isSpecial(this.url) ? isSpecialQueryPercentEncode : isQueryPercentEncode;
+ this.url.query += utf8PercentEncodeString(this.buffer, queryPercentEncodePredicate);
+
+ this.buffer = "";
+
+ if (c === 35) {
+ this.url.fragment = "";
+ this.state = "fragment";
+ }
+ } else if (!isNaN(c)) {
+ // TODO: If c is not a URL code point and not "%", parse error.
+
+ if (c === 37 &&
+ (!infra.isASCIIHex(this.input[this.pointer + 1]) ||
+ !infra.isASCIIHex(this.input[this.pointer + 2]))) {
+ this.parseError = true;
+ }
+
+ this.buffer += cStr;
+ }
+
+ return true;
+};
+
+URLStateMachine.prototype["parse fragment"] = function parseFragment(c) {
+ if (!isNaN(c)) {
+ // TODO: If c is not a URL code point and not "%", parse error.
+ if (c === 37 &&
+ (!infra.isASCIIHex(this.input[this.pointer + 1]) ||
+ !infra.isASCIIHex(this.input[this.pointer + 2]))) {
+ this.parseError = true;
+ }
+
+ this.url.fragment += utf8PercentEncodeCodePoint(c, isFragmentPercentEncode);
+ }
+
+ return true;
+};
+
+function serializeURL(url, excludeFragment) {
+ let output = `${url.scheme}:`;
+ if (url.host !== null) {
+ output += "//";
+
+ if (url.username !== "" || url.password !== "") {
+ output += url.username;
+ if (url.password !== "") {
+ output += `:${url.password}`;
+ }
+ output += "@";
+ }
+
+ output += serializeHost(url.host);
+
+ if (url.port !== null) {
+ output += `:${url.port}`;
+ }
+ }
+
+ if (url.cannotBeABaseURL) {
+ output += url.path[0];
+ } else {
+ if (url.host === null && url.path.length > 1 && url.path[0] === "") {
+ output += "/.";
+ }
+ for (const segment of url.path) {
+ output += `/${segment}`;
+ }
+ }
+
+ if (url.query !== null) {
+ output += `?${url.query}`;
+ }
+
+ if (!excludeFragment && url.fragment !== null) {
+ output += `#${url.fragment}`;
+ }
+
+ return output;
+}
+
+function serializeOrigin(tuple) {
+ let result = `${tuple.scheme}://`;
+ result += serializeHost(tuple.host);
+
+ if (tuple.port !== null) {
+ result += `:${tuple.port}`;
+ }
+
+ return result;
+}
+
+module.exports.serializeURL = serializeURL;
+
+module.exports.serializeURLOrigin = function (url) {
+ // https://url.spec.whatwg.org/#concept-url-origin
+ switch (url.scheme) {
+ case "blob":
+ try {
+ return module.exports.serializeURLOrigin(module.exports.parseURL(url.path[0]));
+ } catch (e) {
+ // serializing an opaque origin returns "null"
+ return "null";
+ }
+ case "ftp":
+ case "http":
+ case "https":
+ case "ws":
+ case "wss":
+ return serializeOrigin({
+ scheme: url.scheme,
+ host: url.host,
+ port: url.port
+ });
+ case "file":
+ // The spec says:
+ // > Unfortunate as it is, this is left as an exercise to the reader. When in doubt, return a new opaque origin.
+ // Browsers tested so far:
+ // - Chrome says "file://", but treats file: URLs as cross-origin for most (all?) purposes; see e.g.
+ // https://bugs.chromium.org/p/chromium/issues/detail?id=37586
+ // - Firefox says "null", but treats file: URLs as same-origin sometimes based on directory stuff; see
+ // https://developer.mozilla.org/en-US/docs/Archive/Misc_top_level/Same-origin_policy_for_file:_URIs
+ return "null";
+ default:
+ // serializing an opaque origin returns "null"
+ return "null";
+ }
+};
+
+module.exports.basicURLParse = function (input, options) {
+ if (options === undefined) {
+ options = {};
+ }
+
+ const usm = new URLStateMachine(input, options.baseURL, options.encodingOverride, options.url, options.stateOverride);
+ if (usm.failure) {
+ return null;
+ }
+
+ return usm.url;
+};
+
+module.exports.setTheUsername = function (url, username) {
+ url.username = utf8PercentEncodeString(username, isUserinfoPercentEncode);
+};
+
+module.exports.setThePassword = function (url, password) {
+ url.password = utf8PercentEncodeString(password, isUserinfoPercentEncode);
+};
+
+module.exports.serializeHost = serializeHost;
+
+module.exports.cannotHaveAUsernamePasswordPort = cannotHaveAUsernamePasswordPort;
+
+module.exports.serializeInteger = function (integer) {
+ return String(integer);
+};
+
+module.exports.parseURL = function (input, options) {
+ if (options === undefined) {
+ options = {};
+ }
+
+ // We don't handle blobs, so this just delegates:
+ return module.exports.basicURLParse(input, { baseURL: options.baseURL, encodingOverride: options.encodingOverride });
+};
diff --git a/includes/external/school/node_modules/whatwg-url/dist/urlencoded.js b/includes/external/school/node_modules/whatwg-url/dist/urlencoded.js
new file mode 100644
index 0000000..c2ccf3d
--- /dev/null
+++ b/includes/external/school/node_modules/whatwg-url/dist/urlencoded.js
@@ -0,0 +1,102 @@
+"use strict";
+const { utf8Encode, utf8DecodeWithoutBOM } = require("./encoding");
+const { percentDecodeBytes, utf8PercentEncodeString, isURLEncodedPercentEncode } = require("./percent-encoding");
+
+// https://url.spec.whatwg.org/#concept-urlencoded-parser
+function parseUrlencoded(input) {
+ const sequences = strictlySplitByteSequence(input, 38);
+ const output = [];
+ for (const bytes of sequences) {
+ if (bytes.length === 0) {
+ continue;
+ }
+
+ let name, value;
+ const indexOfEqual = bytes.indexOf(61);
+
+ if (indexOfEqual >= 0) {
+ name = bytes.slice(0, indexOfEqual);
+ value = bytes.slice(indexOfEqual + 1);
+ } else {
+ name = bytes;
+ value = new Uint8Array(0);
+ }
+
+ name = replaceByteInByteSequence(name, 0x2B, 0x20);
+ value = replaceByteInByteSequence(value, 0x2B, 0x20);
+
+ const nameString = utf8DecodeWithoutBOM(percentDecodeBytes(name));
+ const valueString = utf8DecodeWithoutBOM(percentDecodeBytes(value));
+
+ output.push([nameString, valueString]);
+ }
+ return output;
+}
+
+// https://url.spec.whatwg.org/#concept-urlencoded-string-parser
+function parseUrlencodedString(input) {
+ return parseUrlencoded(utf8Encode(input));
+}
+
+// https://url.spec.whatwg.org/#concept-urlencoded-serializer
+function serializeUrlencoded(tuples, encodingOverride = undefined) {
+ let encoding = "utf-8";
+ if (encodingOverride !== undefined) {
+ // TODO "get the output encoding", i.e. handle encoding labels vs. names.
+ encoding = encodingOverride;
+ }
+
+ let output = "";
+ for (const [i, tuple] of tuples.entries()) {
+ // TODO: handle encoding override
+
+ const name = utf8PercentEncodeString(tuple[0], isURLEncodedPercentEncode, true);
+
+ let value = tuple[1];
+ if (tuple.length > 2 && tuple[2] !== undefined) {
+ if (tuple[2] === "hidden" && name === "_charset_") {
+ value = encoding;
+ } else if (tuple[2] === "file") {
+ // value is a File object
+ value = value.name;
+ }
+ }
+
+ value = utf8PercentEncodeString(value, isURLEncodedPercentEncode, true);
+
+ if (i !== 0) {
+ output += "&";
+ }
+ output += `${name}=${value}`;
+ }
+ return output;
+}
+
+function strictlySplitByteSequence(buf, cp) {
+ const list = [];
+ let last = 0;
+ let i = buf.indexOf(cp);
+ while (i >= 0) {
+ list.push(buf.slice(last, i));
+ last = i + 1;
+ i = buf.indexOf(cp, last);
+ }
+ if (last !== buf.length) {
+ list.push(buf.slice(last));
+ }
+ return list;
+}
+
+function replaceByteInByteSequence(buf, from, to) {
+ let i = buf.indexOf(from);
+ while (i >= 0) {
+ buf[i] = to;
+ i = buf.indexOf(from, i + 1);
+ }
+ return buf;
+}
+
+module.exports = {
+ parseUrlencodedString,
+ serializeUrlencoded
+};
diff --git a/includes/external/school/node_modules/whatwg-url/dist/utils.js b/includes/external/school/node_modules/whatwg-url/dist/utils.js
new file mode 100644
index 0000000..cf6d232
--- /dev/null
+++ b/includes/external/school/node_modules/whatwg-url/dist/utils.js
@@ -0,0 +1,141 @@
+"use strict";
+
+// Returns "Type(value) is Object" in ES terminology.
+function isObject(value) {
+ return typeof value === "object" && value !== null || typeof value === "function";
+}
+
+const hasOwn = Function.prototype.call.bind(Object.prototype.hasOwnProperty);
+
+const wrapperSymbol = Symbol("wrapper");
+const implSymbol = Symbol("impl");
+const sameObjectCaches = Symbol("SameObject caches");
+const ctorRegistrySymbol = Symbol.for("[webidl2js] constructor registry");
+
+function getSameObject(wrapper, prop, creator) {
+ if (!wrapper[sameObjectCaches]) {
+ wrapper[sameObjectCaches] = Object.create(null);
+ }
+
+ if (prop in wrapper[sameObjectCaches]) {
+ return wrapper[sameObjectCaches][prop];
+ }
+
+ wrapper[sameObjectCaches][prop] = creator();
+ return wrapper[sameObjectCaches][prop];
+}
+
+function wrapperForImpl(impl) {
+ return impl ? impl[wrapperSymbol] : null;
+}
+
+function implForWrapper(wrapper) {
+ return wrapper ? wrapper[implSymbol] : null;
+}
+
+function tryWrapperForImpl(impl) {
+ const wrapper = wrapperForImpl(impl);
+ return wrapper ? wrapper : impl;
+}
+
+function tryImplForWrapper(wrapper) {
+ const impl = implForWrapper(wrapper);
+ return impl ? impl : wrapper;
+}
+
+const iterInternalSymbol = Symbol("internal");
+const IteratorPrototype = Object.getPrototypeOf(Object.getPrototypeOf([][Symbol.iterator]()));
+const AsyncIteratorPrototype = Object.getPrototypeOf(Object.getPrototypeOf(async function* () {}).prototype);
+
+function isArrayIndexPropName(P) {
+ if (typeof P !== "string") {
+ return false;
+ }
+ const i = P >>> 0;
+ if (i === Math.pow(2, 32) - 1) {
+ return false;
+ }
+ const s = `${i}`;
+ if (P !== s) {
+ return false;
+ }
+ return true;
+}
+
+const byteLengthGetter =
+ Object.getOwnPropertyDescriptor(ArrayBuffer.prototype, "byteLength").get;
+function isArrayBuffer(value) {
+ try {
+ byteLengthGetter.call(value);
+ return true;
+ } catch (e) {
+ return false;
+ }
+}
+
+function iteratorResult([key, value], kind) {
+ let result;
+ switch (kind) {
+ case "key":
+ result = key;
+ break;
+ case "value":
+ result = value;
+ break;
+ case "key+value":
+ result = [key, value];
+ break;
+ }
+ return { value: result, done: false };
+}
+
+const supportsPropertyIndex = Symbol("supports property index");
+const supportedPropertyIndices = Symbol("supported property indices");
+const supportsPropertyName = Symbol("supports property name");
+const supportedPropertyNames = Symbol("supported property names");
+const indexedGet = Symbol("indexed property get");
+const indexedSetNew = Symbol("indexed property set new");
+const indexedSetExisting = Symbol("indexed property set existing");
+const namedGet = Symbol("named property get");
+const namedSetNew = Symbol("named property set new");
+const namedSetExisting = Symbol("named property set existing");
+const namedDelete = Symbol("named property delete");
+
+const asyncIteratorNext = Symbol("async iterator get the next iteration result");
+const asyncIteratorReturn = Symbol("async iterator return steps");
+const asyncIteratorInit = Symbol("async iterator initialization steps");
+const asyncIteratorEOI = Symbol("async iterator end of iteration");
+
+module.exports = exports = {
+ isObject,
+ hasOwn,
+ wrapperSymbol,
+ implSymbol,
+ getSameObject,
+ ctorRegistrySymbol,
+ wrapperForImpl,
+ implForWrapper,
+ tryWrapperForImpl,
+ tryImplForWrapper,
+ iterInternalSymbol,
+ IteratorPrototype,
+ AsyncIteratorPrototype,
+ isArrayBuffer,
+ isArrayIndexPropName,
+ supportsPropertyIndex,
+ supportedPropertyIndices,
+ supportsPropertyName,
+ supportedPropertyNames,
+ indexedGet,
+ indexedSetNew,
+ indexedSetExisting,
+ namedGet,
+ namedSetNew,
+ namedSetExisting,
+ namedDelete,
+ asyncIteratorNext,
+ asyncIteratorReturn,
+ asyncIteratorInit,
+ asyncIteratorEOI,
+ iteratorResult
+};
diff --git a/includes/external/school/node_modules/whatwg-url/index.js b/includes/external/school/node_modules/whatwg-url/index.js
new file mode 100644
index 0000000..6951141
--- /dev/null
+++ b/includes/external/school/node_modules/whatwg-url/index.js
@@ -0,0 +1,24 @@
+"use strict";
+
+const { URL, URLSearchParams } = require("./webidl2js-wrapper");
+const urlStateMachine = require("./dist/url-state-machine");
+const percentEncoding = require("./dist/percent-encoding");
+
+const sharedGlobalObject = {};
+URL.install(sharedGlobalObject, ["Window"]);
+URLSearchParams.install(sharedGlobalObject, ["Window"]);
+
+exports.URL = sharedGlobalObject.URL;
+exports.URLSearchParams = sharedGlobalObject.URLSearchParams;
+
+exports.parseURL = urlStateMachine.parseURL;
+exports.basicURLParse = urlStateMachine.basicURLParse;
+exports.serializeURL = urlStateMachine.serializeURL;
+exports.serializeHost = urlStateMachine.serializeHost;
+exports.serializeInteger = urlStateMachine.serializeInteger;
+exports.serializeURLOrigin = urlStateMachine.serializeURLOrigin;
+exports.setTheUsername = urlStateMachine.setTheUsername;
+exports.setThePassword = urlStateMachine.setThePassword;
+exports.cannotHaveAUsernamePasswordPort = urlStateMachine.cannotHaveAUsernamePasswordPort;
+
+exports.percentDecode = percentEncoding.percentDecodeBytes;
diff --git a/includes/external/school/node_modules/whatwg-url/package.json b/includes/external/school/node_modules/whatwg-url/package.json
new file mode 100644
index 0000000..a9928d3
--- /dev/null
+++ b/includes/external/school/node_modules/whatwg-url/package.json
@@ -0,0 +1,60 @@
+{
+ "name": "whatwg-url",
+ "version": "8.7.0",
+ "description": "An implementation of the WHATWG URL Standard's URL API and parsing machinery",
+ "main": "index.js",
+ "files": [
+ "index.js",
+ "webidl2js-wrapper.js",
+ "dist/"
+ ],
+ "author": "Sebastian Mayr <github@smayr.name>",
+ "license": "MIT",
+ "repository": "jsdom/whatwg-url",
+ "dependencies": {
+ "lodash": "^4.7.0",
+ "tr46": "^2.1.0",
+ "webidl-conversions": "^6.1.0"
+ },
+ "devDependencies": {
+ "@domenic/eslint-config": "^1.2.0",
+ "browserify": "^17.0.0",
+ "domexception": "^2.0.1",
+ "eslint": "^7.29.0",
+ "glob": "^7.1.7",
+ "got": "^11.8.2",
+ "jest": "^27.0.5",
+ "recast": "^0.20.4",
+ "webidl2js": "^16.2.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "scripts": {
+ "coverage": "jest --coverage",
+ "lint": "eslint .",
+ "prepare": "node scripts/transform.js",
+ "pretest": "node scripts/get-latest-platform-tests.js && node scripts/transform.js",
+ "build-live-viewer": "browserify index.js --standalone whatwgURL > live-viewer/whatwg-url.js",
+ "test": "jest"
+ },
+ "jest": {
+ "collectCoverageFrom": [
+ "lib/**/*.js",
+ "!lib/utils.js"
+ ],
+ "coverageDirectory": "coverage",
+ "coverageReporters": [
+ "lcov",
+ "text-summary"
+ ],
+ "testEnvironment": "node",
+ "testMatch": [
+ "<rootDir>/test/**/*.js"
+ ],
+ "testPathIgnorePatterns": [
+ "^<rootDir>/test/testharness.js$",
+ "^<rootDir>/test/web-platform-tests/"
+ ]
+ }
+}
diff --git a/includes/external/school/node_modules/whatwg-url/webidl2js-wrapper.js b/includes/external/school/node_modules/whatwg-url/webidl2js-wrapper.js
new file mode 100644
index 0000000..849f6a7
--- /dev/null
+++ b/includes/external/school/node_modules/whatwg-url/webidl2js-wrapper.js
@@ -0,0 +1,7 @@
+"use strict";
+
+const URL = require("./dist/URL");
+const URLSearchParams = require("./dist/URLSearchParams");
+
+exports.URL = URL;
+exports.URLSearchParams = URLSearchParams;