aboutsummaryrefslogtreecommitdiffstats
path: root/vanilla/node_modules/@vitest/utils
diff options
context:
space:
mode:
Diffstat (limited to 'vanilla/node_modules/@vitest/utils')
-rw-r--r--vanilla/node_modules/@vitest/utils/LICENSE21
-rw-r--r--vanilla/node_modules/@vitest/utils/diff.d.ts1
-rw-r--r--vanilla/node_modules/@vitest/utils/dist/chunk-_commonjsHelpers.js5
-rw-r--r--vanilla/node_modules/@vitest/utils/dist/chunk-pathe.M-eThtNZ.js156
-rw-r--r--vanilla/node_modules/@vitest/utils/dist/constants.d.ts21
-rw-r--r--vanilla/node_modules/@vitest/utils/dist/constants.js49
-rw-r--r--vanilla/node_modules/@vitest/utils/dist/diff.d.ts93
-rw-r--r--vanilla/node_modules/@vitest/utils/dist/diff.js2199
-rw-r--r--vanilla/node_modules/@vitest/utils/dist/display.d.ts29
-rw-r--r--vanilla/node_modules/@vitest/utils/dist/display.js742
-rw-r--r--vanilla/node_modules/@vitest/utils/dist/error.d.ts7
-rw-r--r--vanilla/node_modules/@vitest/utils/dist/error.js42
-rw-r--r--vanilla/node_modules/@vitest/utils/dist/helpers.d.ts73
-rw-r--r--vanilla/node_modules/@vitest/utils/dist/helpers.js295
-rw-r--r--vanilla/node_modules/@vitest/utils/dist/highlight.d.ts9
-rw-r--r--vanilla/node_modules/@vitest/utils/dist/highlight.js538
-rw-r--r--vanilla/node_modules/@vitest/utils/dist/index.d.ts5
-rw-r--r--vanilla/node_modules/@vitest/utils/dist/index.js1
-rw-r--r--vanilla/node_modules/@vitest/utils/dist/offset.d.ts5
-rw-r--r--vanilla/node_modules/@vitest/utils/dist/offset.js32
-rw-r--r--vanilla/node_modules/@vitest/utils/dist/resolver.d.ts7
-rw-r--r--vanilla/node_modules/@vitest/utils/dist/resolver.js71
-rw-r--r--vanilla/node_modules/@vitest/utils/dist/serialize.d.ts3
-rw-r--r--vanilla/node_modules/@vitest/utils/dist/serialize.js118
-rw-r--r--vanilla/node_modules/@vitest/utils/dist/source-map.d.ts55
-rw-r--r--vanilla/node_modules/@vitest/utils/dist/source-map.js478
-rw-r--r--vanilla/node_modules/@vitest/utils/dist/timers.d.ts33
-rw-r--r--vanilla/node_modules/@vitest/utils/dist/timers.js49
-rw-r--r--vanilla/node_modules/@vitest/utils/dist/types.d-BCElaP-c.d.ts53
-rw-r--r--vanilla/node_modules/@vitest/utils/dist/types.d.ts34
-rw-r--r--vanilla/node_modules/@vitest/utils/dist/types.js1
-rw-r--r--vanilla/node_modules/@vitest/utils/error.d.ts1
-rw-r--r--vanilla/node_modules/@vitest/utils/helpers.d.ts1
-rw-r--r--vanilla/node_modules/@vitest/utils/package.json98
34 files changed, 5325 insertions, 0 deletions
diff --git a/vanilla/node_modules/@vitest/utils/LICENSE b/vanilla/node_modules/@vitest/utils/LICENSE
new file mode 100644
index 0000000..0e5771d
--- /dev/null
+++ b/vanilla/node_modules/@vitest/utils/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2021-Present VoidZero Inc. and Vitest contributors
+
+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/vanilla/node_modules/@vitest/utils/diff.d.ts b/vanilla/node_modules/@vitest/utils/diff.d.ts
new file mode 100644
index 0000000..0a66b86
--- /dev/null
+++ b/vanilla/node_modules/@vitest/utils/diff.d.ts
@@ -0,0 +1 @@
+export * from './dist/diff.js'
diff --git a/vanilla/node_modules/@vitest/utils/dist/chunk-_commonjsHelpers.js b/vanilla/node_modules/@vitest/utils/dist/chunk-_commonjsHelpers.js
new file mode 100644
index 0000000..c9366dd
--- /dev/null
+++ b/vanilla/node_modules/@vitest/utils/dist/chunk-_commonjsHelpers.js
@@ -0,0 +1,5 @@
+function getDefaultExportFromCjs(x) {
+ return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, "default") ? x["default"] : x;
+}
+
+export { getDefaultExportFromCjs as g };
diff --git a/vanilla/node_modules/@vitest/utils/dist/chunk-pathe.M-eThtNZ.js b/vanilla/node_modules/@vitest/utils/dist/chunk-pathe.M-eThtNZ.js
new file mode 100644
index 0000000..74d0dab
--- /dev/null
+++ b/vanilla/node_modules/@vitest/utils/dist/chunk-pathe.M-eThtNZ.js
@@ -0,0 +1,156 @@
+const _DRIVE_LETTER_START_RE = /^[A-Za-z]:\//;
+function normalizeWindowsPath(input = "") {
+ if (!input) {
+ return input;
+ }
+ return input.replace(/\\/g, "/").replace(_DRIVE_LETTER_START_RE, (r) => r.toUpperCase());
+}
+
+const _UNC_REGEX = /^[/\\]{2}/;
+const _IS_ABSOLUTE_RE = /^[/\\](?![/\\])|^[/\\]{2}(?!\.)|^[A-Za-z]:[/\\]/;
+const _DRIVE_LETTER_RE = /^[A-Za-z]:$/;
+const normalize = function(path) {
+ if (path.length === 0) {
+ return ".";
+ }
+ path = normalizeWindowsPath(path);
+ const isUNCPath = path.match(_UNC_REGEX);
+ const isPathAbsolute = isAbsolute(path);
+ const trailingSeparator = path[path.length - 1] === "/";
+ path = normalizeString(path, !isPathAbsolute);
+ if (path.length === 0) {
+ if (isPathAbsolute) {
+ return "/";
+ }
+ return trailingSeparator ? "./" : ".";
+ }
+ if (trailingSeparator) {
+ path += "/";
+ }
+ if (_DRIVE_LETTER_RE.test(path)) {
+ path += "/";
+ }
+ if (isUNCPath) {
+ if (!isPathAbsolute) {
+ return `//./${path}`;
+ }
+ return `//${path}`;
+ }
+ return isPathAbsolute && !isAbsolute(path) ? `/${path}` : path;
+};
+const join = function(...segments) {
+ let path = "";
+ for (const seg of segments) {
+ if (!seg) {
+ continue;
+ }
+ if (path.length > 0) {
+ const pathTrailing = path[path.length - 1] === "/";
+ const segLeading = seg[0] === "/";
+ const both = pathTrailing && segLeading;
+ if (both) {
+ path += seg.slice(1);
+ } else {
+ path += pathTrailing || segLeading ? seg : `/${seg}`;
+ }
+ } else {
+ path += seg;
+ }
+ }
+ return normalize(path);
+};
+function cwd() {
+ if (typeof process !== "undefined" && typeof process.cwd === "function") {
+ return process.cwd().replace(/\\/g, "/");
+ }
+ return "/";
+}
+const resolve = function(...arguments_) {
+ arguments_ = arguments_.map((argument) => normalizeWindowsPath(argument));
+ let resolvedPath = "";
+ let resolvedAbsolute = false;
+ for (let index = arguments_.length - 1; index >= -1 && !resolvedAbsolute; index--) {
+ const path = index >= 0 ? arguments_[index] : cwd();
+ if (!path || path.length === 0) {
+ continue;
+ }
+ resolvedPath = `${path}/${resolvedPath}`;
+ resolvedAbsolute = isAbsolute(path);
+ }
+ resolvedPath = normalizeString(resolvedPath, !resolvedAbsolute);
+ if (resolvedAbsolute && !isAbsolute(resolvedPath)) {
+ return `/${resolvedPath}`;
+ }
+ return resolvedPath.length > 0 ? resolvedPath : ".";
+};
+function normalizeString(path, allowAboveRoot) {
+ let res = "";
+ let lastSegmentLength = 0;
+ let lastSlash = -1;
+ let dots = 0;
+ let char = null;
+ for (let index = 0; index <= path.length; ++index) {
+ if (index < path.length) {
+ char = path[index];
+ } else if (char === "/") {
+ break;
+ } else {
+ char = "/";
+ }
+ if (char === "/") {
+ if (lastSlash === index - 1 || dots === 1) ; else if (dots === 2) {
+ if (res.length < 2 || lastSegmentLength !== 2 || res[res.length - 1] !== "." || res[res.length - 2] !== ".") {
+ if (res.length > 2) {
+ const lastSlashIndex = res.lastIndexOf("/");
+ if (lastSlashIndex === -1) {
+ res = "";
+ lastSegmentLength = 0;
+ } else {
+ res = res.slice(0, lastSlashIndex);
+ lastSegmentLength = res.length - 1 - res.lastIndexOf("/");
+ }
+ lastSlash = index;
+ dots = 0;
+ continue;
+ } else if (res.length > 0) {
+ res = "";
+ lastSegmentLength = 0;
+ lastSlash = index;
+ dots = 0;
+ continue;
+ }
+ }
+ if (allowAboveRoot) {
+ res += res.length > 0 ? "/.." : "..";
+ lastSegmentLength = 2;
+ }
+ } else {
+ if (res.length > 0) {
+ res += `/${path.slice(lastSlash + 1, index)}`;
+ } else {
+ res = path.slice(lastSlash + 1, index);
+ }
+ lastSegmentLength = index - lastSlash - 1;
+ }
+ lastSlash = index;
+ dots = 0;
+ } else if (char === "." && dots !== -1) {
+ ++dots;
+ } else {
+ dots = -1;
+ }
+ }
+ return res;
+}
+const isAbsolute = function(p) {
+ return _IS_ABSOLUTE_RE.test(p);
+};
+const dirname = function(p) {
+ const segments = normalizeWindowsPath(p).replace(/\/$/, "").split("/").slice(0, -1);
+ if (segments.length === 1 && _DRIVE_LETTER_RE.test(segments[0])) {
+ segments[0] += "/";
+ }
+ return segments.join("/") || (isAbsolute(p) ? "/" : ".");
+};
+
+export { dirname as d, join as j, resolve as r };
diff --git a/vanilla/node_modules/@vitest/utils/dist/constants.d.ts b/vanilla/node_modules/@vitest/utils/dist/constants.d.ts
new file mode 100644
index 0000000..bd5ad65
--- /dev/null
+++ b/vanilla/node_modules/@vitest/utils/dist/constants.d.ts
@@ -0,0 +1,21 @@
+declare const KNOWN_ASSET_TYPES: string[];
+declare const KNOWN_ASSET_RE: RegExp;
+declare const CSS_LANGS_RE: RegExp;
+/**
+* Prefix for resolved Ids that are not valid browser import specifiers
+*/
+declare const VALID_ID_PREFIX = "/@id/";
+/**
+* Plugins that use 'virtual modules' (e.g. for helper functions), prefix the
+* module ID with `\0`, a convention from the rollup ecosystem.
+* This prevents other plugins from trying to process the id (like node resolution),
+* and core features like sourcemaps can use this info to differentiate between
+* virtual modules and regular files.
+* `\0` is not a permitted char in import URLs so we have to replace them during
+* import analysis. The id will be decoded back before entering the plugins pipeline.
+* These encoded virtual ids are also prefixed by the VALID_ID_PREFIX, so virtual
+* modules in the browser end up encoded as `/@id/__x00__{id}`
+*/
+declare const NULL_BYTE_PLACEHOLDER = "__x00__";
+
+export { CSS_LANGS_RE, KNOWN_ASSET_RE, KNOWN_ASSET_TYPES, NULL_BYTE_PLACEHOLDER, VALID_ID_PREFIX };
diff --git a/vanilla/node_modules/@vitest/utils/dist/constants.js b/vanilla/node_modules/@vitest/utils/dist/constants.js
new file mode 100644
index 0000000..385045b
--- /dev/null
+++ b/vanilla/node_modules/@vitest/utils/dist/constants.js
@@ -0,0 +1,49 @@
+// TODO: this is all copy pasted from Vite - can they expose a module that exports only constants?
+const KNOWN_ASSET_TYPES = [
+ "apng",
+ "bmp",
+ "png",
+ "jpe?g",
+ "jfif",
+ "pjpeg",
+ "pjp",
+ "gif",
+ "svg",
+ "ico",
+ "webp",
+ "avif",
+ "mp4",
+ "webm",
+ "ogg",
+ "mp3",
+ "wav",
+ "flac",
+ "aac",
+ "woff2?",
+ "eot",
+ "ttf",
+ "otf",
+ "webmanifest",
+ "pdf",
+ "txt"
+];
+const KNOWN_ASSET_RE = new RegExp(`\\.(${KNOWN_ASSET_TYPES.join("|")})$`);
+const CSS_LANGS_RE = /\.(css|less|sass|scss|styl|stylus|pcss|postcss|sss)(?:$|\?)/;
+/**
+* Prefix for resolved Ids that are not valid browser import specifiers
+*/
+const VALID_ID_PREFIX = `/@id/`;
+/**
+* Plugins that use 'virtual modules' (e.g. for helper functions), prefix the
+* module ID with `\0`, a convention from the rollup ecosystem.
+* This prevents other plugins from trying to process the id (like node resolution),
+* and core features like sourcemaps can use this info to differentiate between
+* virtual modules and regular files.
+* `\0` is not a permitted char in import URLs so we have to replace them during
+* import analysis. The id will be decoded back before entering the plugins pipeline.
+* These encoded virtual ids are also prefixed by the VALID_ID_PREFIX, so virtual
+* modules in the browser end up encoded as `/@id/__x00__{id}`
+*/
+const NULL_BYTE_PLACEHOLDER = `__x00__`;
+
+export { CSS_LANGS_RE, KNOWN_ASSET_RE, KNOWN_ASSET_TYPES, NULL_BYTE_PLACEHOLDER, VALID_ID_PREFIX };
diff --git a/vanilla/node_modules/@vitest/utils/dist/diff.d.ts b/vanilla/node_modules/@vitest/utils/dist/diff.d.ts
new file mode 100644
index 0000000..603569d
--- /dev/null
+++ b/vanilla/node_modules/@vitest/utils/dist/diff.d.ts
@@ -0,0 +1,93 @@
+import { D as DiffOptions } from './types.d-BCElaP-c.js';
+export { a as DiffOptionsColor, S as SerializedDiffOptions } from './types.d-BCElaP-c.js';
+import '@vitest/pretty-format';
+
+/**
+* Diff Match and Patch
+* Copyright 2018 The diff-match-patch Authors.
+* https://github.com/google/diff-match-patch
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+/**
+* @fileoverview Computes the difference between two texts to create a patch.
+* Applies the patch onto another text, allowing for errors.
+* @author fraser@google.com (Neil Fraser)
+*/
+/**
+* CHANGES by pedrottimark to diff_match_patch_uncompressed.ts file:
+*
+* 1. Delete anything not needed to use diff_cleanupSemantic method
+* 2. Convert from prototype properties to var declarations
+* 3. Convert Diff to class from constructor and prototype
+* 4. Add type annotations for arguments and return values
+* 5. Add exports
+*/
+/**
+* The data structure representing a diff is an array of tuples:
+* [[DIFF_DELETE, 'Hello'], [DIFF_INSERT, 'Goodbye'], [DIFF_EQUAL, ' world.']]
+* which means: delete 'Hello', add 'Goodbye' and keep ' world.'
+*/
+declare const DIFF_DELETE = -1;
+declare const DIFF_INSERT = 1;
+declare const DIFF_EQUAL = 0;
+/**
+* Class representing one diff tuple.
+* Attempts to look like a two-element array (which is what this used to be).
+* @param {number} op Operation, one of: DIFF_DELETE, DIFF_INSERT, DIFF_EQUAL.
+* @param {string} text Text to be deleted, inserted, or retained.
+* @constructor
+*/
+declare class Diff {
+ 0: number;
+ 1: string;
+ constructor(op: number, text: string);
+}
+
+/**
+* Copyright (c) Meta Platforms, Inc. and affiliates.
+*
+* This source code is licensed under the MIT license found in the
+* LICENSE file in the root directory of this source tree.
+*/
+
+declare function diffLinesUnified(aLines: Array<string>, bLines: Array<string>, options?: DiffOptions): string;
+declare function diffLinesUnified2(aLinesDisplay: Array<string>, bLinesDisplay: Array<string>, aLinesCompare: Array<string>, bLinesCompare: Array<string>, options?: DiffOptions): string;
+declare function diffLinesRaw(aLines: Array<string>, bLines: Array<string>, options?: DiffOptions): [Array<Diff>, boolean];
+
+/**
+* Copyright (c) Meta Platforms, Inc. and affiliates.
+*
+* This source code is licensed under the MIT license found in the
+* LICENSE file in the root directory of this source tree.
+*/
+
+declare function diffStringsUnified(a: string, b: string, options?: DiffOptions): string;
+declare function diffStringsRaw(a: string, b: string, cleanup: boolean, options?: DiffOptions): [Array<Diff>, boolean];
+
+/**
+* @param a Expected value
+* @param b Received value
+* @param options Diff options
+* @returns {string | null} a string diff
+*/
+declare function diff(a: any, b: any, options?: DiffOptions): string | undefined;
+declare function printDiffOrStringify(received: unknown, expected: unknown, options?: DiffOptions): string | undefined;
+declare function replaceAsymmetricMatcher(actual: any, expected: any, actualReplaced?: WeakSet<WeakKey>, expectedReplaced?: WeakSet<WeakKey>): {
+ replacedActual: any;
+ replacedExpected: any;
+};
+type PrintLabel = (string: string) => string;
+declare function getLabelPrinter(...strings: Array<string>): PrintLabel;
+
+export { DIFF_DELETE, DIFF_EQUAL, DIFF_INSERT, Diff, DiffOptions, diff, diffLinesRaw, diffLinesUnified, diffLinesUnified2, diffStringsRaw, diffStringsUnified, getLabelPrinter, printDiffOrStringify, replaceAsymmetricMatcher };
diff --git a/vanilla/node_modules/@vitest/utils/dist/diff.js b/vanilla/node_modules/@vitest/utils/dist/diff.js
new file mode 100644
index 0000000..415a4f1
--- /dev/null
+++ b/vanilla/node_modules/@vitest/utils/dist/diff.js
@@ -0,0 +1,2199 @@
+import { plugins, format } from '@vitest/pretty-format';
+import c from 'tinyrainbow';
+import { stringify } from './display.js';
+import { deepClone, getOwnProperties, getType as getType$1 } from './helpers.js';
+import { g as getDefaultExportFromCjs } from './chunk-_commonjsHelpers.js';
+import './constants.js';
+
+/**
+* Diff Match and Patch
+* Copyright 2018 The diff-match-patch Authors.
+* https://github.com/google/diff-match-patch
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+/**
+* @fileoverview Computes the difference between two texts to create a patch.
+* Applies the patch onto another text, allowing for errors.
+* @author fraser@google.com (Neil Fraser)
+*/
+/**
+* CHANGES by pedrottimark to diff_match_patch_uncompressed.ts file:
+*
+* 1. Delete anything not needed to use diff_cleanupSemantic method
+* 2. Convert from prototype properties to var declarations
+* 3. Convert Diff to class from constructor and prototype
+* 4. Add type annotations for arguments and return values
+* 5. Add exports
+*/
+/**
+* The data structure representing a diff is an array of tuples:
+* [[DIFF_DELETE, 'Hello'], [DIFF_INSERT, 'Goodbye'], [DIFF_EQUAL, ' world.']]
+* which means: delete 'Hello', add 'Goodbye' and keep ' world.'
+*/
+const DIFF_DELETE = -1;
+const DIFF_INSERT = 1;
+const DIFF_EQUAL = 0;
+/**
+* Class representing one diff tuple.
+* Attempts to look like a two-element array (which is what this used to be).
+* @param {number} op Operation, one of: DIFF_DELETE, DIFF_INSERT, DIFF_EQUAL.
+* @param {string} text Text to be deleted, inserted, or retained.
+* @constructor
+*/
+class Diff {
+ 0;
+ 1;
+ constructor(op, text) {
+ this[0] = op;
+ this[1] = text;
+ }
+}
+/**
+* Determine the common prefix of two strings.
+* @param {string} text1 First string.
+* @param {string} text2 Second string.
+* @return {number} The number of characters common to the start of each
+* string.
+*/
+function diff_commonPrefix(text1, text2) {
+ // Quick check for common null cases.
+ if (!text1 || !text2 || text1.charAt(0) !== text2.charAt(0)) {
+ return 0;
+ }
+ // Binary search.
+ // Performance analysis: https://neil.fraser.name/news/2007/10/09/
+ let pointermin = 0;
+ let pointermax = Math.min(text1.length, text2.length);
+ let pointermid = pointermax;
+ let pointerstart = 0;
+ while (pointermin < pointermid) {
+ if (text1.substring(pointerstart, pointermid) === text2.substring(pointerstart, pointermid)) {
+ pointermin = pointermid;
+ pointerstart = pointermin;
+ } else {
+ pointermax = pointermid;
+ }
+ pointermid = Math.floor((pointermax - pointermin) / 2 + pointermin);
+ }
+ return pointermid;
+}
+/**
+* Determine the common suffix of two strings.
+* @param {string} text1 First string.
+* @param {string} text2 Second string.
+* @return {number} The number of characters common to the end of each string.
+*/
+function diff_commonSuffix(text1, text2) {
+ // Quick check for common null cases.
+ if (!text1 || !text2 || text1.charAt(text1.length - 1) !== text2.charAt(text2.length - 1)) {
+ return 0;
+ }
+ // Binary search.
+ // Performance analysis: https://neil.fraser.name/news/2007/10/09/
+ let pointermin = 0;
+ let pointermax = Math.min(text1.length, text2.length);
+ let pointermid = pointermax;
+ let pointerend = 0;
+ while (pointermin < pointermid) {
+ if (text1.substring(text1.length - pointermid, text1.length - pointerend) === text2.substring(text2.length - pointermid, text2.length - pointerend)) {
+ pointermin = pointermid;
+ pointerend = pointermin;
+ } else {
+ pointermax = pointermid;
+ }
+ pointermid = Math.floor((pointermax - pointermin) / 2 + pointermin);
+ }
+ return pointermid;
+}
+/**
+* Determine if the suffix of one string is the prefix of another.
+* @param {string} text1 First string.
+* @param {string} text2 Second string.
+* @return {number} The number of characters common to the end of the first
+* string and the start of the second string.
+* @private
+*/
+function diff_commonOverlap_(text1, text2) {
+ // Cache the text lengths to prevent multiple calls.
+ const text1_length = text1.length;
+ const text2_length = text2.length;
+ // Eliminate the null case.
+ if (text1_length === 0 || text2_length === 0) {
+ return 0;
+ }
+ // Truncate the longer string.
+ if (text1_length > text2_length) {
+ text1 = text1.substring(text1_length - text2_length);
+ } else if (text1_length < text2_length) {
+ text2 = text2.substring(0, text1_length);
+ }
+ const text_length = Math.min(text1_length, text2_length);
+ // Quick check for the worst case.
+ if (text1 === text2) {
+ return text_length;
+ }
+ // Start by looking for a single character match
+ // and increase length until no match is found.
+ // Performance analysis: https://neil.fraser.name/news/2010/11/04/
+ let best = 0;
+ let length = 1;
+ while (true) {
+ const pattern = text1.substring(text_length - length);
+ const found = text2.indexOf(pattern);
+ if (found === -1) {
+ return best;
+ }
+ length += found;
+ if (found === 0 || text1.substring(text_length - length) === text2.substring(0, length)) {
+ best = length;
+ length++;
+ }
+ }
+}
+/**
+* Reduce the number of edits by eliminating semantically trivial equalities.
+* @param {!Array.<!diff_match_patch.Diff>} diffs Array of diff tuples.
+*/
+function diff_cleanupSemantic(diffs) {
+ let changes = false;
+ const equalities = [];
+ let equalitiesLength = 0;
+ /** @type {?string} */
+ let lastEquality = null;
+ // Always equal to diffs[equalities[equalitiesLength - 1]][1]
+ let pointer = 0;
+ // Number of characters that changed prior to the equality.
+ let length_insertions1 = 0;
+ let length_deletions1 = 0;
+ // Number of characters that changed after the equality.
+ let length_insertions2 = 0;
+ let length_deletions2 = 0;
+ while (pointer < diffs.length) {
+ if (diffs[pointer][0] === DIFF_EQUAL) {
+ // Equality found.
+ equalities[equalitiesLength++] = pointer;
+ length_insertions1 = length_insertions2;
+ length_deletions1 = length_deletions2;
+ length_insertions2 = 0;
+ length_deletions2 = 0;
+ lastEquality = diffs[pointer][1];
+ } else {
+ // An insertion or deletion.
+ if (diffs[pointer][0] === DIFF_INSERT) {
+ length_insertions2 += diffs[pointer][1].length;
+ } else {
+ length_deletions2 += diffs[pointer][1].length;
+ }
+ // Eliminate an equality that is smaller or equal to the edits on both
+ // sides of it.
+ if (lastEquality && lastEquality.length <= Math.max(length_insertions1, length_deletions1) && lastEquality.length <= Math.max(length_insertions2, length_deletions2)) {
+ // Duplicate record.
+ diffs.splice(equalities[equalitiesLength - 1], 0, new Diff(DIFF_DELETE, lastEquality));
+ // Change second copy to insert.
+ diffs[equalities[equalitiesLength - 1] + 1][0] = DIFF_INSERT;
+ // Throw away the equality we just deleted.
+ equalitiesLength--;
+ // Throw away the previous equality (it needs to be reevaluated).
+ equalitiesLength--;
+ pointer = equalitiesLength > 0 ? equalities[equalitiesLength - 1] : -1;
+ length_insertions1 = 0;
+ length_deletions1 = 0;
+ length_insertions2 = 0;
+ length_deletions2 = 0;
+ lastEquality = null;
+ changes = true;
+ }
+ }
+ pointer++;
+ }
+ // Normalize the diff.
+ if (changes) {
+ diff_cleanupMerge(diffs);
+ }
+ diff_cleanupSemanticLossless(diffs);
+ // Find any overlaps between deletions and insertions.
+ // e.g: <del>abcxxx</del><ins>xxxdef</ins>
+ // -> <del>abc</del>xxx<ins>def</ins>
+ // e.g: <del>xxxabc</del><ins>defxxx</ins>
+ // -> <ins>def</ins>xxx<del>abc</del>
+ // Only extract an overlap if it is as big as the edit ahead or behind it.
+ pointer = 1;
+ while (pointer < diffs.length) {
+ if (diffs[pointer - 1][0] === DIFF_DELETE && diffs[pointer][0] === DIFF_INSERT) {
+ const deletion = diffs[pointer - 1][1];
+ const insertion = diffs[pointer][1];
+ const overlap_length1 = diff_commonOverlap_(deletion, insertion);
+ const overlap_length2 = diff_commonOverlap_(insertion, deletion);
+ if (overlap_length1 >= overlap_length2) {
+ if (overlap_length1 >= deletion.length / 2 || overlap_length1 >= insertion.length / 2) {
+ // Overlap found. Insert an equality and trim the surrounding edits.
+ diffs.splice(pointer, 0, new Diff(DIFF_EQUAL, insertion.substring(0, overlap_length1)));
+ diffs[pointer - 1][1] = deletion.substring(0, deletion.length - overlap_length1);
+ diffs[pointer + 1][1] = insertion.substring(overlap_length1);
+ pointer++;
+ }
+ } else {
+ if (overlap_length2 >= deletion.length / 2 || overlap_length2 >= insertion.length / 2) {
+ // Reverse overlap found.
+ // Insert an equality and swap and trim the surrounding edits.
+ diffs.splice(pointer, 0, new Diff(DIFF_EQUAL, deletion.substring(0, overlap_length2)));
+ diffs[pointer - 1][0] = DIFF_INSERT;
+ diffs[pointer - 1][1] = insertion.substring(0, insertion.length - overlap_length2);
+ diffs[pointer + 1][0] = DIFF_DELETE;
+ diffs[pointer + 1][1] = deletion.substring(overlap_length2);
+ pointer++;
+ }
+ }
+ pointer++;
+ }
+ pointer++;
+ }
+}
+// Define some regex patterns for matching boundaries.
+const nonAlphaNumericRegex_ = /[^a-z0-9]/i;
+const whitespaceRegex_ = /\s/;
+const linebreakRegex_ = /[\r\n]/;
+const blanklineEndRegex_ = /\n\r?\n$/;
+const blanklineStartRegex_ = /^\r?\n\r?\n/;
+/**
+* Look for single edits surrounded on both sides by equalities
+* which can be shifted sideways to align the edit to a word boundary.
+* e.g: The c<ins>at c</ins>ame. -> The <ins>cat </ins>came.
+* @param {!Array.<!diff_match_patch.Diff>} diffs Array of diff tuples.
+*/
+function diff_cleanupSemanticLossless(diffs) {
+ let pointer = 1;
+ // Intentionally ignore the first and last element (don't need checking).
+ while (pointer < diffs.length - 1) {
+ if (diffs[pointer - 1][0] === DIFF_EQUAL && diffs[pointer + 1][0] === DIFF_EQUAL) {
+ // This is a single edit surrounded by equalities.
+ let equality1 = diffs[pointer - 1][1];
+ let edit = diffs[pointer][1];
+ let equality2 = diffs[pointer + 1][1];
+ // First, shift the edit as far left as possible.
+ const commonOffset = diff_commonSuffix(equality1, edit);
+ if (commonOffset) {
+ const commonString = edit.substring(edit.length - commonOffset);
+ equality1 = equality1.substring(0, equality1.length - commonOffset);
+ edit = commonString + edit.substring(0, edit.length - commonOffset);
+ equality2 = commonString + equality2;
+ }
+ // Second, step character by character right, looking for the best fit.
+ let bestEquality1 = equality1;
+ let bestEdit = edit;
+ let bestEquality2 = equality2;
+ let bestScore = diff_cleanupSemanticScore_(equality1, edit) + diff_cleanupSemanticScore_(edit, equality2);
+ while (edit.charAt(0) === equality2.charAt(0)) {
+ equality1 += edit.charAt(0);
+ edit = edit.substring(1) + equality2.charAt(0);
+ equality2 = equality2.substring(1);
+ const score = diff_cleanupSemanticScore_(equality1, edit) + diff_cleanupSemanticScore_(edit, equality2);
+ // The >= encourages trailing rather than leading whitespace on edits.
+ if (score >= bestScore) {
+ bestScore = score;
+ bestEquality1 = equality1;
+ bestEdit = edit;
+ bestEquality2 = equality2;
+ }
+ }
+ if (diffs[pointer - 1][1] !== bestEquality1) {
+ // We have an improvement, save it back to the diff.
+ if (bestEquality1) {
+ diffs[pointer - 1][1] = bestEquality1;
+ } else {
+ diffs.splice(pointer - 1, 1);
+ pointer--;
+ }
+ diffs[pointer][1] = bestEdit;
+ if (bestEquality2) {
+ diffs[pointer + 1][1] = bestEquality2;
+ } else {
+ diffs.splice(pointer + 1, 1);
+ pointer--;
+ }
+ }
+ }
+ pointer++;
+ }
+}
+/**
+* Reorder and merge like edit sections. Merge equalities.
+* Any edit section can move as long as it doesn't cross an equality.
+* @param {!Array.<!diff_match_patch.Diff>} diffs Array of diff tuples.
+*/
+function diff_cleanupMerge(diffs) {
+ var _diffs$at;
+ // Add a dummy entry at the end.
+ diffs.push(new Diff(DIFF_EQUAL, ""));
+ let pointer = 0;
+ let count_delete = 0;
+ let count_insert = 0;
+ let text_delete = "";
+ let text_insert = "";
+ let commonlength;
+ while (pointer < diffs.length) {
+ switch (diffs[pointer][0]) {
+ case DIFF_INSERT:
+ count_insert++;
+ text_insert += diffs[pointer][1];
+ pointer++;
+ break;
+ case DIFF_DELETE:
+ count_delete++;
+ text_delete += diffs[pointer][1];
+ pointer++;
+ break;
+ case DIFF_EQUAL:
+ // Upon reaching an equality, check for prior redundancies.
+ if (count_delete + count_insert > 1) {
+ if (count_delete !== 0 && count_insert !== 0) {
+ // Factor out any common prefixes.
+ commonlength = diff_commonPrefix(text_insert, text_delete);
+ if (commonlength !== 0) {
+ if (pointer - count_delete - count_insert > 0 && diffs[pointer - count_delete - count_insert - 1][0] === DIFF_EQUAL) {
+ diffs[pointer - count_delete - count_insert - 1][1] += text_insert.substring(0, commonlength);
+ } else {
+ diffs.splice(0, 0, new Diff(DIFF_EQUAL, text_insert.substring(0, commonlength)));
+ pointer++;
+ }
+ text_insert = text_insert.substring(commonlength);
+ text_delete = text_delete.substring(commonlength);
+ }
+ // Factor out any common suffixes.
+ commonlength = diff_commonSuffix(text_insert, text_delete);
+ if (commonlength !== 0) {
+ diffs[pointer][1] = text_insert.substring(text_insert.length - commonlength) + diffs[pointer][1];
+ text_insert = text_insert.substring(0, text_insert.length - commonlength);
+ text_delete = text_delete.substring(0, text_delete.length - commonlength);
+ }
+ }
+ // Delete the offending records and add the merged ones.
+ pointer -= count_delete + count_insert;
+ diffs.splice(pointer, count_delete + count_insert);
+ if (text_delete.length) {
+ diffs.splice(pointer, 0, new Diff(DIFF_DELETE, text_delete));
+ pointer++;
+ }
+ if (text_insert.length) {
+ diffs.splice(pointer, 0, new Diff(DIFF_INSERT, text_insert));
+ pointer++;
+ }
+ pointer++;
+ } else if (pointer !== 0 && diffs[pointer - 1][0] === DIFF_EQUAL) {
+ // Merge this equality with the previous one.
+ diffs[pointer - 1][1] += diffs[pointer][1];
+ diffs.splice(pointer, 1);
+ } else {
+ pointer++;
+ }
+ count_insert = 0;
+ count_delete = 0;
+ text_delete = "";
+ text_insert = "";
+ break;
+ }
+ }
+ if (((_diffs$at = diffs.at(-1)) === null || _diffs$at === void 0 ? void 0 : _diffs$at[1]) === "") {
+ diffs.pop();
+ }
+ // Second pass: look for single edits surrounded on both sides by equalities
+ // which can be shifted sideways to eliminate an equality.
+ // e.g: A<ins>BA</ins>C -> <ins>AB</ins>AC
+ let changes = false;
+ pointer = 1;
+ // Intentionally ignore the first and last element (don't need checking).
+ while (pointer < diffs.length - 1) {
+ if (diffs[pointer - 1][0] === DIFF_EQUAL && diffs[pointer + 1][0] === DIFF_EQUAL) {
+ // This is a single edit surrounded by equalities.
+ if (diffs[pointer][1].substring(diffs[pointer][1].length - diffs[pointer - 1][1].length) === diffs[pointer - 1][1]) {
+ // Shift the edit over the previous equality.
+ diffs[pointer][1] = diffs[pointer - 1][1] + diffs[pointer][1].substring(0, diffs[pointer][1].length - diffs[pointer - 1][1].length);
+ diffs[pointer + 1][1] = diffs[pointer - 1][1] + diffs[pointer + 1][1];
+ diffs.splice(pointer - 1, 1);
+ changes = true;
+ } else if (diffs[pointer][1].substring(0, diffs[pointer + 1][1].length) === diffs[pointer + 1][1]) {
+ // Shift the edit over the next equality.
+ diffs[pointer - 1][1] += diffs[pointer + 1][1];
+ diffs[pointer][1] = diffs[pointer][1].substring(diffs[pointer + 1][1].length) + diffs[pointer + 1][1];
+ diffs.splice(pointer + 1, 1);
+ changes = true;
+ }
+ }
+ pointer++;
+ }
+ // If shifts were made, the diff needs reordering and another shift sweep.
+ if (changes) {
+ diff_cleanupMerge(diffs);
+ }
+}
+/**
+* Given two strings, compute a score representing whether the internal
+* boundary falls on logical boundaries.
+* Scores range from 6 (best) to 0 (worst).
+* Closure, but does not reference any external variables.
+* @param {string} one First string.
+* @param {string} two Second string.
+* @return {number} The score.
+* @private
+*/
+function diff_cleanupSemanticScore_(one, two) {
+ if (!one || !two) {
+ // Edges are the best.
+ return 6;
+ }
+ // Each port of this function behaves slightly differently due to
+ // subtle differences in each language's definition of things like
+ // 'whitespace'. Since this function's purpose is largely cosmetic,
+ // the choice has been made to use each language's native features
+ // rather than force total conformity.
+ const char1 = one.charAt(one.length - 1);
+ const char2 = two.charAt(0);
+ const nonAlphaNumeric1 = char1.match(nonAlphaNumericRegex_);
+ const nonAlphaNumeric2 = char2.match(nonAlphaNumericRegex_);
+ const whitespace1 = nonAlphaNumeric1 && char1.match(whitespaceRegex_);
+ const whitespace2 = nonAlphaNumeric2 && char2.match(whitespaceRegex_);
+ const lineBreak1 = whitespace1 && char1.match(linebreakRegex_);
+ const lineBreak2 = whitespace2 && char2.match(linebreakRegex_);
+ const blankLine1 = lineBreak1 && one.match(blanklineEndRegex_);
+ const blankLine2 = lineBreak2 && two.match(blanklineStartRegex_);
+ if (blankLine1 || blankLine2) {
+ // Five points for blank lines.
+ return 5;
+ } else if (lineBreak1 || lineBreak2) {
+ // Four points for line breaks.
+ return 4;
+ } else if (nonAlphaNumeric1 && !whitespace1 && whitespace2) {
+ // Three points for end of sentences.
+ return 3;
+ } else if (whitespace1 || whitespace2) {
+ // Two points for whitespace.
+ return 2;
+ } else if (nonAlphaNumeric1 || nonAlphaNumeric2) {
+ // One point for non-alphanumeric.
+ return 1;
+ }
+ return 0;
+}
+
+/**
+* Copyright (c) Meta Platforms, Inc. and affiliates.
+*
+* This source code is licensed under the MIT license found in the
+* LICENSE file in the root directory of this source tree.
+*/
+const NO_DIFF_MESSAGE = "Compared values have no visual difference.";
+const SIMILAR_MESSAGE = "Compared values serialize to the same structure.\n" + "Printing internal object structure without calling `toJSON` instead.";
+
+var build = {};
+
+var hasRequiredBuild;
+
+function requireBuild () {
+ if (hasRequiredBuild) return build;
+ hasRequiredBuild = 1;
+
+ Object.defineProperty(build, '__esModule', {
+ value: true
+ });
+ build.default = diffSequence;
+ /**
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ *
+ */
+
+ // This diff-sequences package implements the linear space variation in
+ // An O(ND) Difference Algorithm and Its Variations by Eugene W. Myers
+
+ // Relationship in notation between Myers paper and this package:
+ // A is a
+ // N is aLength, aEnd - aStart, and so on
+ // x is aIndex, aFirst, aLast, and so on
+ // B is b
+ // M is bLength, bEnd - bStart, and so on
+ // y is bIndex, bFirst, bLast, and so on
+ // Δ = N - M is negative of baDeltaLength = bLength - aLength
+ // D is d
+ // k is kF
+ // k + Δ is kF = kR - baDeltaLength
+ // V is aIndexesF or aIndexesR (see comment below about Indexes type)
+ // index intervals [1, N] and [1, M] are [0, aLength) and [0, bLength)
+ // starting point in forward direction (0, 0) is (-1, -1)
+ // starting point in reverse direction (N + 1, M + 1) is (aLength, bLength)
+
+ // The “edit graph” for sequences a and b corresponds to items:
+ // in a on the horizontal axis
+ // in b on the vertical axis
+ //
+ // Given a-coordinate of a point in a diagonal, you can compute b-coordinate.
+ //
+ // Forward diagonals kF:
+ // zero diagonal intersects top left corner
+ // positive diagonals intersect top edge
+ // negative diagonals insersect left edge
+ //
+ // Reverse diagonals kR:
+ // zero diagonal intersects bottom right corner
+ // positive diagonals intersect right edge
+ // negative diagonals intersect bottom edge
+
+ // The graph contains a directed acyclic graph of edges:
+ // horizontal: delete an item from a
+ // vertical: insert an item from b
+ // diagonal: common item in a and b
+ //
+ // The algorithm solves dual problems in the graph analogy:
+ // Find longest common subsequence: path with maximum number of diagonal edges
+ // Find shortest edit script: path with minimum number of non-diagonal edges
+
+ // Input callback function compares items at indexes in the sequences.
+
+ // Output callback function receives the number of adjacent items
+ // and starting indexes of each common subsequence.
+ // Either original functions or wrapped to swap indexes if graph is transposed.
+ // Indexes in sequence a of last point of forward or reverse paths in graph.
+ // Myers algorithm indexes by diagonal k which for negative is bad deopt in V8.
+ // This package indexes by iF and iR which are greater than or equal to zero.
+ // and also updates the index arrays in place to cut memory in half.
+ // kF = 2 * iF - d
+ // kR = d - 2 * iR
+ // Division of index intervals in sequences a and b at the middle change.
+ // Invariant: intervals do not have common items at the start or end.
+ const pkg = 'diff-sequences'; // for error messages
+ const NOT_YET_SET = 0; // small int instead of undefined to avoid deopt in V8
+
+ // Return the number of common items that follow in forward direction.
+ // The length of what Myers paper calls a “snake” in a forward path.
+ const countCommonItemsF = (aIndex, aEnd, bIndex, bEnd, isCommon) => {
+ let nCommon = 0;
+ while (aIndex < aEnd && bIndex < bEnd && isCommon(aIndex, bIndex)) {
+ aIndex += 1;
+ bIndex += 1;
+ nCommon += 1;
+ }
+ return nCommon;
+ };
+
+ // Return the number of common items that precede in reverse direction.
+ // The length of what Myers paper calls a “snake” in a reverse path.
+ const countCommonItemsR = (aStart, aIndex, bStart, bIndex, isCommon) => {
+ let nCommon = 0;
+ while (aStart <= aIndex && bStart <= bIndex && isCommon(aIndex, bIndex)) {
+ aIndex -= 1;
+ bIndex -= 1;
+ nCommon += 1;
+ }
+ return nCommon;
+ };
+
+ // A simple function to extend forward paths from (d - 1) to d changes
+ // when forward and reverse paths cannot yet overlap.
+ const extendPathsF = (
+ d,
+ aEnd,
+ bEnd,
+ bF,
+ isCommon,
+ aIndexesF,
+ iMaxF // return the value because optimization might decrease it
+ ) => {
+ // Unroll the first iteration.
+ let iF = 0;
+ let kF = -d; // kF = 2 * iF - d
+ let aFirst = aIndexesF[iF]; // in first iteration always insert
+ let aIndexPrev1 = aFirst; // prev value of [iF - 1] in next iteration
+ aIndexesF[iF] += countCommonItemsF(
+ aFirst + 1,
+ aEnd,
+ bF + aFirst - kF + 1,
+ bEnd,
+ isCommon
+ );
+
+ // Optimization: skip diagonals in which paths cannot ever overlap.
+ const nF = d < iMaxF ? d : iMaxF;
+
+ // The diagonals kF are odd when d is odd and even when d is even.
+ for (iF += 1, kF += 2; iF <= nF; iF += 1, kF += 2) {
+ // To get first point of path segment, move one change in forward direction
+ // from last point of previous path segment in an adjacent diagonal.
+ // In last possible iteration when iF === d and kF === d always delete.
+ if (iF !== d && aIndexPrev1 < aIndexesF[iF]) {
+ aFirst = aIndexesF[iF]; // vertical to insert from b
+ } else {
+ aFirst = aIndexPrev1 + 1; // horizontal to delete from a
+
+ if (aEnd <= aFirst) {
+ // Optimization: delete moved past right of graph.
+ return iF - 1;
+ }
+ }
+
+ // To get last point of path segment, move along diagonal of common items.
+ aIndexPrev1 = aIndexesF[iF];
+ aIndexesF[iF] =
+ aFirst +
+ countCommonItemsF(aFirst + 1, aEnd, bF + aFirst - kF + 1, bEnd, isCommon);
+ }
+ return iMaxF;
+ };
+
+ // A simple function to extend reverse paths from (d - 1) to d changes
+ // when reverse and forward paths cannot yet overlap.
+ const extendPathsR = (
+ d,
+ aStart,
+ bStart,
+ bR,
+ isCommon,
+ aIndexesR,
+ iMaxR // return the value because optimization might decrease it
+ ) => {
+ // Unroll the first iteration.
+ let iR = 0;
+ let kR = d; // kR = d - 2 * iR
+ let aFirst = aIndexesR[iR]; // in first iteration always insert
+ let aIndexPrev1 = aFirst; // prev value of [iR - 1] in next iteration
+ aIndexesR[iR] -= countCommonItemsR(
+ aStart,
+ aFirst - 1,
+ bStart,
+ bR + aFirst - kR - 1,
+ isCommon
+ );
+
+ // Optimization: skip diagonals in which paths cannot ever overlap.
+ const nR = d < iMaxR ? d : iMaxR;
+
+ // The diagonals kR are odd when d is odd and even when d is even.
+ for (iR += 1, kR -= 2; iR <= nR; iR += 1, kR -= 2) {
+ // To get first point of path segment, move one change in reverse direction
+ // from last point of previous path segment in an adjacent diagonal.
+ // In last possible iteration when iR === d and kR === -d always delete.
+ if (iR !== d && aIndexesR[iR] < aIndexPrev1) {
+ aFirst = aIndexesR[iR]; // vertical to insert from b
+ } else {
+ aFirst = aIndexPrev1 - 1; // horizontal to delete from a
+
+ if (aFirst < aStart) {
+ // Optimization: delete moved past left of graph.
+ return iR - 1;
+ }
+ }
+
+ // To get last point of path segment, move along diagonal of common items.
+ aIndexPrev1 = aIndexesR[iR];
+ aIndexesR[iR] =
+ aFirst -
+ countCommonItemsR(
+ aStart,
+ aFirst - 1,
+ bStart,
+ bR + aFirst - kR - 1,
+ isCommon
+ );
+ }
+ return iMaxR;
+ };
+
+ // A complete function to extend forward paths from (d - 1) to d changes.
+ // Return true if a path overlaps reverse path of (d - 1) changes in its diagonal.
+ const extendOverlappablePathsF = (
+ d,
+ aStart,
+ aEnd,
+ bStart,
+ bEnd,
+ isCommon,
+ aIndexesF,
+ iMaxF,
+ aIndexesR,
+ iMaxR,
+ division // update prop values if return true
+ ) => {
+ const bF = bStart - aStart; // bIndex = bF + aIndex - kF
+ const aLength = aEnd - aStart;
+ const bLength = bEnd - bStart;
+ const baDeltaLength = bLength - aLength; // kF = kR - baDeltaLength
+
+ // Range of diagonals in which forward and reverse paths might overlap.
+ const kMinOverlapF = -baDeltaLength - (d - 1); // -(d - 1) <= kR
+ const kMaxOverlapF = -baDeltaLength + (d - 1); // kR <= (d - 1)
+
+ let aIndexPrev1 = NOT_YET_SET; // prev value of [iF - 1] in next iteration
+
+ // Optimization: skip diagonals in which paths cannot ever overlap.
+ const nF = d < iMaxF ? d : iMaxF;
+
+ // The diagonals kF = 2 * iF - d are odd when d is odd and even when d is even.
+ for (let iF = 0, kF = -d; iF <= nF; iF += 1, kF += 2) {
+ // To get first point of path segment, move one change in forward direction
+ // from last point of previous path segment in an adjacent diagonal.
+ // In first iteration when iF === 0 and kF === -d always insert.
+ // In last possible iteration when iF === d and kF === d always delete.
+ const insert = iF === 0 || (iF !== d && aIndexPrev1 < aIndexesF[iF]);
+ const aLastPrev = insert ? aIndexesF[iF] : aIndexPrev1;
+ const aFirst = insert
+ ? aLastPrev // vertical to insert from b
+ : aLastPrev + 1; // horizontal to delete from a
+
+ // To get last point of path segment, move along diagonal of common items.
+ const bFirst = bF + aFirst - kF;
+ const nCommonF = countCommonItemsF(
+ aFirst + 1,
+ aEnd,
+ bFirst + 1,
+ bEnd,
+ isCommon
+ );
+ const aLast = aFirst + nCommonF;
+ aIndexPrev1 = aIndexesF[iF];
+ aIndexesF[iF] = aLast;
+ if (kMinOverlapF <= kF && kF <= kMaxOverlapF) {
+ // Solve for iR of reverse path with (d - 1) changes in diagonal kF:
+ // kR = kF + baDeltaLength
+ // kR = (d - 1) - 2 * iR
+ const iR = (d - 1 - (kF + baDeltaLength)) / 2;
+
+ // If this forward path overlaps the reverse path in this diagonal,
+ // then this is the middle change of the index intervals.
+ if (iR <= iMaxR && aIndexesR[iR] - 1 <= aLast) {
+ // Unlike the Myers algorithm which finds only the middle “snake”
+ // this package can find two common subsequences per division.
+ // Last point of previous path segment is on an adjacent diagonal.
+ const bLastPrev = bF + aLastPrev - (insert ? kF + 1 : kF - 1);
+
+ // Because of invariant that intervals preceding the middle change
+ // cannot have common items at the end,
+ // move in reverse direction along a diagonal of common items.
+ const nCommonR = countCommonItemsR(
+ aStart,
+ aLastPrev,
+ bStart,
+ bLastPrev,
+ isCommon
+ );
+ const aIndexPrevFirst = aLastPrev - nCommonR;
+ const bIndexPrevFirst = bLastPrev - nCommonR;
+ const aEndPreceding = aIndexPrevFirst + 1;
+ const bEndPreceding = bIndexPrevFirst + 1;
+ division.nChangePreceding = d - 1;
+ if (d - 1 === aEndPreceding + bEndPreceding - aStart - bStart) {
+ // Optimization: number of preceding changes in forward direction
+ // is equal to number of items in preceding interval,
+ // therefore it cannot contain any common items.
+ division.aEndPreceding = aStart;
+ division.bEndPreceding = bStart;
+ } else {
+ division.aEndPreceding = aEndPreceding;
+ division.bEndPreceding = bEndPreceding;
+ }
+ division.nCommonPreceding = nCommonR;
+ if (nCommonR !== 0) {
+ division.aCommonPreceding = aEndPreceding;
+ division.bCommonPreceding = bEndPreceding;
+ }
+ division.nCommonFollowing = nCommonF;
+ if (nCommonF !== 0) {
+ division.aCommonFollowing = aFirst + 1;
+ division.bCommonFollowing = bFirst + 1;
+ }
+ const aStartFollowing = aLast + 1;
+ const bStartFollowing = bFirst + nCommonF + 1;
+ division.nChangeFollowing = d - 1;
+ if (d - 1 === aEnd + bEnd - aStartFollowing - bStartFollowing) {
+ // Optimization: number of changes in reverse direction
+ // is equal to number of items in following interval,
+ // therefore it cannot contain any common items.
+ division.aStartFollowing = aEnd;
+ division.bStartFollowing = bEnd;
+ } else {
+ division.aStartFollowing = aStartFollowing;
+ division.bStartFollowing = bStartFollowing;
+ }
+ return true;
+ }
+ }
+ }
+ return false;
+ };
+
+ // A complete function to extend reverse paths from (d - 1) to d changes.
+ // Return true if a path overlaps forward path of d changes in its diagonal.
+ const extendOverlappablePathsR = (
+ d,
+ aStart,
+ aEnd,
+ bStart,
+ bEnd,
+ isCommon,
+ aIndexesF,
+ iMaxF,
+ aIndexesR,
+ iMaxR,
+ division // update prop values if return true
+ ) => {
+ const bR = bEnd - aEnd; // bIndex = bR + aIndex - kR
+ const aLength = aEnd - aStart;
+ const bLength = bEnd - bStart;
+ const baDeltaLength = bLength - aLength; // kR = kF + baDeltaLength
+
+ // Range of diagonals in which forward and reverse paths might overlap.
+ const kMinOverlapR = baDeltaLength - d; // -d <= kF
+ const kMaxOverlapR = baDeltaLength + d; // kF <= d
+
+ let aIndexPrev1 = NOT_YET_SET; // prev value of [iR - 1] in next iteration
+
+ // Optimization: skip diagonals in which paths cannot ever overlap.
+ const nR = d < iMaxR ? d : iMaxR;
+
+ // The diagonals kR = d - 2 * iR are odd when d is odd and even when d is even.
+ for (let iR = 0, kR = d; iR <= nR; iR += 1, kR -= 2) {
+ // To get first point of path segment, move one change in reverse direction
+ // from last point of previous path segment in an adjacent diagonal.
+ // In first iteration when iR === 0 and kR === d always insert.
+ // In last possible iteration when iR === d and kR === -d always delete.
+ const insert = iR === 0 || (iR !== d && aIndexesR[iR] < aIndexPrev1);
+ const aLastPrev = insert ? aIndexesR[iR] : aIndexPrev1;
+ const aFirst = insert
+ ? aLastPrev // vertical to insert from b
+ : aLastPrev - 1; // horizontal to delete from a
+
+ // To get last point of path segment, move along diagonal of common items.
+ const bFirst = bR + aFirst - kR;
+ const nCommonR = countCommonItemsR(
+ aStart,
+ aFirst - 1,
+ bStart,
+ bFirst - 1,
+ isCommon
+ );
+ const aLast = aFirst - nCommonR;
+ aIndexPrev1 = aIndexesR[iR];
+ aIndexesR[iR] = aLast;
+ if (kMinOverlapR <= kR && kR <= kMaxOverlapR) {
+ // Solve for iF of forward path with d changes in diagonal kR:
+ // kF = kR - baDeltaLength
+ // kF = 2 * iF - d
+ const iF = (d + (kR - baDeltaLength)) / 2;
+
+ // If this reverse path overlaps the forward path in this diagonal,
+ // then this is a middle change of the index intervals.
+ if (iF <= iMaxF && aLast - 1 <= aIndexesF[iF]) {
+ const bLast = bFirst - nCommonR;
+ division.nChangePreceding = d;
+ if (d === aLast + bLast - aStart - bStart) {
+ // Optimization: number of changes in reverse direction
+ // is equal to number of items in preceding interval,
+ // therefore it cannot contain any common items.
+ division.aEndPreceding = aStart;
+ division.bEndPreceding = bStart;
+ } else {
+ division.aEndPreceding = aLast;
+ division.bEndPreceding = bLast;
+ }
+ division.nCommonPreceding = nCommonR;
+ if (nCommonR !== 0) {
+ // The last point of reverse path segment is start of common subsequence.
+ division.aCommonPreceding = aLast;
+ division.bCommonPreceding = bLast;
+ }
+ division.nChangeFollowing = d - 1;
+ if (d === 1) {
+ // There is no previous path segment.
+ division.nCommonFollowing = 0;
+ division.aStartFollowing = aEnd;
+ division.bStartFollowing = bEnd;
+ } else {
+ // Unlike the Myers algorithm which finds only the middle “snake”
+ // this package can find two common subsequences per division.
+ // Last point of previous path segment is on an adjacent diagonal.
+ const bLastPrev = bR + aLastPrev - (insert ? kR - 1 : kR + 1);
+
+ // Because of invariant that intervals following the middle change
+ // cannot have common items at the start,
+ // move in forward direction along a diagonal of common items.
+ const nCommonF = countCommonItemsF(
+ aLastPrev,
+ aEnd,
+ bLastPrev,
+ bEnd,
+ isCommon
+ );
+ division.nCommonFollowing = nCommonF;
+ if (nCommonF !== 0) {
+ // The last point of reverse path segment is start of common subsequence.
+ division.aCommonFollowing = aLastPrev;
+ division.bCommonFollowing = bLastPrev;
+ }
+ const aStartFollowing = aLastPrev + nCommonF; // aFirstPrev
+ const bStartFollowing = bLastPrev + nCommonF; // bFirstPrev
+
+ if (d - 1 === aEnd + bEnd - aStartFollowing - bStartFollowing) {
+ // Optimization: number of changes in forward direction
+ // is equal to number of items in following interval,
+ // therefore it cannot contain any common items.
+ division.aStartFollowing = aEnd;
+ division.bStartFollowing = bEnd;
+ } else {
+ division.aStartFollowing = aStartFollowing;
+ division.bStartFollowing = bStartFollowing;
+ }
+ }
+ return true;
+ }
+ }
+ }
+ return false;
+ };
+
+ // Given index intervals and input function to compare items at indexes,
+ // divide at the middle change.
+ //
+ // DO NOT CALL if start === end, because interval cannot contain common items
+ // and because this function will throw the “no overlap” error.
+ const divide = (
+ nChange,
+ aStart,
+ aEnd,
+ bStart,
+ bEnd,
+ isCommon,
+ aIndexesF,
+ aIndexesR,
+ division // output
+ ) => {
+ const bF = bStart - aStart; // bIndex = bF + aIndex - kF
+ const bR = bEnd - aEnd; // bIndex = bR + aIndex - kR
+ const aLength = aEnd - aStart;
+ const bLength = bEnd - bStart;
+
+ // Because graph has square or portrait orientation,
+ // length difference is minimum number of items to insert from b.
+ // Corresponding forward and reverse diagonals in graph
+ // depend on length difference of the sequences:
+ // kF = kR - baDeltaLength
+ // kR = kF + baDeltaLength
+ const baDeltaLength = bLength - aLength;
+
+ // Optimization: max diagonal in graph intersects corner of shorter side.
+ let iMaxF = aLength;
+ let iMaxR = aLength;
+
+ // Initialize no changes yet in forward or reverse direction:
+ aIndexesF[0] = aStart - 1; // at open start of interval, outside closed start
+ aIndexesR[0] = aEnd; // at open end of interval
+
+ if (baDeltaLength % 2 === 0) {
+ // The number of changes in paths is 2 * d if length difference is even.
+ const dMin = (nChange || baDeltaLength) / 2;
+ const dMax = (aLength + bLength) / 2;
+ for (let d = 1; d <= dMax; d += 1) {
+ iMaxF = extendPathsF(d, aEnd, bEnd, bF, isCommon, aIndexesF, iMaxF);
+ if (d < dMin) {
+ iMaxR = extendPathsR(d, aStart, bStart, bR, isCommon, aIndexesR, iMaxR);
+ } else if (
+ // If a reverse path overlaps a forward path in the same diagonal,
+ // return a division of the index intervals at the middle change.
+ extendOverlappablePathsR(
+ d,
+ aStart,
+ aEnd,
+ bStart,
+ bEnd,
+ isCommon,
+ aIndexesF,
+ iMaxF,
+ aIndexesR,
+ iMaxR,
+ division
+ )
+ ) {
+ return;
+ }
+ }
+ } else {
+ // The number of changes in paths is 2 * d - 1 if length difference is odd.
+ const dMin = ((nChange || baDeltaLength) + 1) / 2;
+ const dMax = (aLength + bLength + 1) / 2;
+
+ // Unroll first half iteration so loop extends the relevant pairs of paths.
+ // Because of invariant that intervals have no common items at start or end,
+ // and limitation not to call divide with empty intervals,
+ // therefore it cannot be called if a forward path with one change
+ // would overlap a reverse path with no changes, even if dMin === 1.
+ let d = 1;
+ iMaxF = extendPathsF(d, aEnd, bEnd, bF, isCommon, aIndexesF, iMaxF);
+ for (d += 1; d <= dMax; d += 1) {
+ iMaxR = extendPathsR(
+ d - 1,
+ aStart,
+ bStart,
+ bR,
+ isCommon,
+ aIndexesR,
+ iMaxR
+ );
+ if (d < dMin) {
+ iMaxF = extendPathsF(d, aEnd, bEnd, bF, isCommon, aIndexesF, iMaxF);
+ } else if (
+ // If a forward path overlaps a reverse path in the same diagonal,
+ // return a division of the index intervals at the middle change.
+ extendOverlappablePathsF(
+ d,
+ aStart,
+ aEnd,
+ bStart,
+ bEnd,
+ isCommon,
+ aIndexesF,
+ iMaxF,
+ aIndexesR,
+ iMaxR,
+ division
+ )
+ ) {
+ return;
+ }
+ }
+ }
+
+ /* istanbul ignore next */
+ throw new Error(
+ `${pkg}: no overlap aStart=${aStart} aEnd=${aEnd} bStart=${bStart} bEnd=${bEnd}`
+ );
+ };
+
+ // Given index intervals and input function to compare items at indexes,
+ // return by output function the number of adjacent items and starting indexes
+ // of each common subsequence. Divide and conquer with only linear space.
+ //
+ // The index intervals are half open [start, end) like array slice method.
+ // DO NOT CALL if start === end, because interval cannot contain common items
+ // and because divide function will throw the “no overlap” error.
+ const findSubsequences = (
+ nChange,
+ aStart,
+ aEnd,
+ bStart,
+ bEnd,
+ transposed,
+ callbacks,
+ aIndexesF,
+ aIndexesR,
+ division // temporary memory, not input nor output
+ ) => {
+ if (bEnd - bStart < aEnd - aStart) {
+ // Transpose graph so it has portrait instead of landscape orientation.
+ // Always compare shorter to longer sequence for consistency and optimization.
+ transposed = !transposed;
+ if (transposed && callbacks.length === 1) {
+ // Lazily wrap callback functions to swap args if graph is transposed.
+ const {foundSubsequence, isCommon} = callbacks[0];
+ callbacks[1] = {
+ foundSubsequence: (nCommon, bCommon, aCommon) => {
+ foundSubsequence(nCommon, aCommon, bCommon);
+ },
+ isCommon: (bIndex, aIndex) => isCommon(aIndex, bIndex)
+ };
+ }
+ const tStart = aStart;
+ const tEnd = aEnd;
+ aStart = bStart;
+ aEnd = bEnd;
+ bStart = tStart;
+ bEnd = tEnd;
+ }
+ const {foundSubsequence, isCommon} = callbacks[transposed ? 1 : 0];
+
+ // Divide the index intervals at the middle change.
+ divide(
+ nChange,
+ aStart,
+ aEnd,
+ bStart,
+ bEnd,
+ isCommon,
+ aIndexesF,
+ aIndexesR,
+ division
+ );
+ const {
+ nChangePreceding,
+ aEndPreceding,
+ bEndPreceding,
+ nCommonPreceding,
+ aCommonPreceding,
+ bCommonPreceding,
+ nCommonFollowing,
+ aCommonFollowing,
+ bCommonFollowing,
+ nChangeFollowing,
+ aStartFollowing,
+ bStartFollowing
+ } = division;
+
+ // Unless either index interval is empty, they might contain common items.
+ if (aStart < aEndPreceding && bStart < bEndPreceding) {
+ // Recursely find and return common subsequences preceding the division.
+ findSubsequences(
+ nChangePreceding,
+ aStart,
+ aEndPreceding,
+ bStart,
+ bEndPreceding,
+ transposed,
+ callbacks,
+ aIndexesF,
+ aIndexesR,
+ division
+ );
+ }
+
+ // Return common subsequences that are adjacent to the middle change.
+ if (nCommonPreceding !== 0) {
+ foundSubsequence(nCommonPreceding, aCommonPreceding, bCommonPreceding);
+ }
+ if (nCommonFollowing !== 0) {
+ foundSubsequence(nCommonFollowing, aCommonFollowing, bCommonFollowing);
+ }
+
+ // Unless either index interval is empty, they might contain common items.
+ if (aStartFollowing < aEnd && bStartFollowing < bEnd) {
+ // Recursely find and return common subsequences following the division.
+ findSubsequences(
+ nChangeFollowing,
+ aStartFollowing,
+ aEnd,
+ bStartFollowing,
+ bEnd,
+ transposed,
+ callbacks,
+ aIndexesF,
+ aIndexesR,
+ division
+ );
+ }
+ };
+ const validateLength = (name, arg) => {
+ if (typeof arg !== 'number') {
+ throw new TypeError(`${pkg}: ${name} typeof ${typeof arg} is not a number`);
+ }
+ if (!Number.isSafeInteger(arg)) {
+ throw new RangeError(`${pkg}: ${name} value ${arg} is not a safe integer`);
+ }
+ if (arg < 0) {
+ throw new RangeError(`${pkg}: ${name} value ${arg} is a negative integer`);
+ }
+ };
+ const validateCallback = (name, arg) => {
+ const type = typeof arg;
+ if (type !== 'function') {
+ throw new TypeError(`${pkg}: ${name} typeof ${type} is not a function`);
+ }
+ };
+
+ // Compare items in two sequences to find a longest common subsequence.
+ // Given lengths of sequences and input function to compare items at indexes,
+ // return by output function the number of adjacent items and starting indexes
+ // of each common subsequence.
+ function diffSequence(aLength, bLength, isCommon, foundSubsequence) {
+ validateLength('aLength', aLength);
+ validateLength('bLength', bLength);
+ validateCallback('isCommon', isCommon);
+ validateCallback('foundSubsequence', foundSubsequence);
+
+ // Count common items from the start in the forward direction.
+ const nCommonF = countCommonItemsF(0, aLength, 0, bLength, isCommon);
+ if (nCommonF !== 0) {
+ foundSubsequence(nCommonF, 0, 0);
+ }
+
+ // Unless both sequences consist of common items only,
+ // find common items in the half-trimmed index intervals.
+ if (aLength !== nCommonF || bLength !== nCommonF) {
+ // Invariant: intervals do not have common items at the start.
+ // The start of an index interval is closed like array slice method.
+ const aStart = nCommonF;
+ const bStart = nCommonF;
+
+ // Count common items from the end in the reverse direction.
+ const nCommonR = countCommonItemsR(
+ aStart,
+ aLength - 1,
+ bStart,
+ bLength - 1,
+ isCommon
+ );
+
+ // Invariant: intervals do not have common items at the end.
+ // The end of an index interval is open like array slice method.
+ const aEnd = aLength - nCommonR;
+ const bEnd = bLength - nCommonR;
+
+ // Unless one sequence consists of common items only,
+ // therefore the other trimmed index interval consists of changes only,
+ // find common items in the trimmed index intervals.
+ const nCommonFR = nCommonF + nCommonR;
+ if (aLength !== nCommonFR && bLength !== nCommonFR) {
+ const nChange = 0; // number of change items is not yet known
+ const transposed = false; // call the original unwrapped functions
+ const callbacks = [
+ {
+ foundSubsequence,
+ isCommon
+ }
+ ];
+
+ // Indexes in sequence a of last points in furthest reaching paths
+ // from outside the start at top left in the forward direction:
+ const aIndexesF = [NOT_YET_SET];
+ // from the end at bottom right in the reverse direction:
+ const aIndexesR = [NOT_YET_SET];
+
+ // Initialize one object as output of all calls to divide function.
+ const division = {
+ aCommonFollowing: NOT_YET_SET,
+ aCommonPreceding: NOT_YET_SET,
+ aEndPreceding: NOT_YET_SET,
+ aStartFollowing: NOT_YET_SET,
+ bCommonFollowing: NOT_YET_SET,
+ bCommonPreceding: NOT_YET_SET,
+ bEndPreceding: NOT_YET_SET,
+ bStartFollowing: NOT_YET_SET,
+ nChangeFollowing: NOT_YET_SET,
+ nChangePreceding: NOT_YET_SET,
+ nCommonFollowing: NOT_YET_SET,
+ nCommonPreceding: NOT_YET_SET
+ };
+
+ // Find and return common subsequences in the trimmed index intervals.
+ findSubsequences(
+ nChange,
+ aStart,
+ aEnd,
+ bStart,
+ bEnd,
+ transposed,
+ callbacks,
+ aIndexesF,
+ aIndexesR,
+ division
+ );
+ }
+ if (nCommonR !== 0) {
+ foundSubsequence(nCommonR, aEnd, bEnd);
+ }
+ }
+ }
+ return build;
+}
+
+var buildExports = /*@__PURE__*/ requireBuild();
+var diffSequences = /*@__PURE__*/getDefaultExportFromCjs(buildExports);
+
+function formatTrailingSpaces(line, trailingSpaceFormatter) {
+ return line.replace(/\s+$/, (match) => trailingSpaceFormatter(match));
+}
+function printDiffLine(line, isFirstOrLast, color, indicator, trailingSpaceFormatter, emptyFirstOrLastLinePlaceholder) {
+ return line.length !== 0 ? color(`${indicator} ${formatTrailingSpaces(line, trailingSpaceFormatter)}`) : indicator !== " " ? color(indicator) : isFirstOrLast && emptyFirstOrLastLinePlaceholder.length !== 0 ? color(`${indicator} ${emptyFirstOrLastLinePlaceholder}`) : "";
+}
+function printDeleteLine(line, isFirstOrLast, { aColor, aIndicator, changeLineTrailingSpaceColor, emptyFirstOrLastLinePlaceholder }) {
+ return printDiffLine(line, isFirstOrLast, aColor, aIndicator, changeLineTrailingSpaceColor, emptyFirstOrLastLinePlaceholder);
+}
+function printInsertLine(line, isFirstOrLast, { bColor, bIndicator, changeLineTrailingSpaceColor, emptyFirstOrLastLinePlaceholder }) {
+ return printDiffLine(line, isFirstOrLast, bColor, bIndicator, changeLineTrailingSpaceColor, emptyFirstOrLastLinePlaceholder);
+}
+function printCommonLine(line, isFirstOrLast, { commonColor, commonIndicator, commonLineTrailingSpaceColor, emptyFirstOrLastLinePlaceholder }) {
+ return printDiffLine(line, isFirstOrLast, commonColor, commonIndicator, commonLineTrailingSpaceColor, emptyFirstOrLastLinePlaceholder);
+}
+// In GNU diff format, indexes are one-based instead of zero-based.
+function createPatchMark(aStart, aEnd, bStart, bEnd, { patchColor }) {
+ return patchColor(`@@ -${aStart + 1},${aEnd - aStart} +${bStart + 1},${bEnd - bStart} @@`);
+}
+// jest --no-expand
+//
+// Given array of aligned strings with inverse highlight formatting,
+// return joined lines with diff formatting (and patch marks, if needed).
+function joinAlignedDiffsNoExpand(diffs, options) {
+ const iLength = diffs.length;
+ const nContextLines = options.contextLines;
+ const nContextLines2 = nContextLines + nContextLines;
+ // First pass: count output lines and see if it has patches.
+ let jLength = iLength;
+ let hasExcessAtStartOrEnd = false;
+ let nExcessesBetweenChanges = 0;
+ let i = 0;
+ while (i !== iLength) {
+ const iStart = i;
+ while (i !== iLength && diffs[i][0] === DIFF_EQUAL) {
+ i += 1;
+ }
+ if (iStart !== i) {
+ if (iStart === 0) {
+ // at start
+ if (i > nContextLines) {
+ jLength -= i - nContextLines;
+ hasExcessAtStartOrEnd = true;
+ }
+ } else if (i === iLength) {
+ // at end
+ const n = i - iStart;
+ if (n > nContextLines) {
+ jLength -= n - nContextLines;
+ hasExcessAtStartOrEnd = true;
+ }
+ } else {
+ // between changes
+ const n = i - iStart;
+ if (n > nContextLines2) {
+ jLength -= n - nContextLines2;
+ nExcessesBetweenChanges += 1;
+ }
+ }
+ }
+ while (i !== iLength && diffs[i][0] !== DIFF_EQUAL) {
+ i += 1;
+ }
+ }
+ const hasPatch = nExcessesBetweenChanges !== 0 || hasExcessAtStartOrEnd;
+ if (nExcessesBetweenChanges !== 0) {
+ jLength += nExcessesBetweenChanges + 1;
+ } else if (hasExcessAtStartOrEnd) {
+ jLength += 1;
+ }
+ const jLast = jLength - 1;
+ const lines = [];
+ let jPatchMark = 0;
+ if (hasPatch) {
+ lines.push("");
+ }
+ // Indexes of expected or received lines in current patch:
+ let aStart = 0;
+ let bStart = 0;
+ let aEnd = 0;
+ let bEnd = 0;
+ const pushCommonLine = (line) => {
+ const j = lines.length;
+ lines.push(printCommonLine(line, j === 0 || j === jLast, options));
+ aEnd += 1;
+ bEnd += 1;
+ };
+ const pushDeleteLine = (line) => {
+ const j = lines.length;
+ lines.push(printDeleteLine(line, j === 0 || j === jLast, options));
+ aEnd += 1;
+ };
+ const pushInsertLine = (line) => {
+ const j = lines.length;
+ lines.push(printInsertLine(line, j === 0 || j === jLast, options));
+ bEnd += 1;
+ };
+ // Second pass: push lines with diff formatting (and patch marks, if needed).
+ i = 0;
+ while (i !== iLength) {
+ let iStart = i;
+ while (i !== iLength && diffs[i][0] === DIFF_EQUAL) {
+ i += 1;
+ }
+ if (iStart !== i) {
+ if (iStart === 0) {
+ // at beginning
+ if (i > nContextLines) {
+ iStart = i - nContextLines;
+ aStart = iStart;
+ bStart = iStart;
+ aEnd = aStart;
+ bEnd = bStart;
+ }
+ for (let iCommon = iStart; iCommon !== i; iCommon += 1) {
+ pushCommonLine(diffs[iCommon][1]);
+ }
+ } else if (i === iLength) {
+ // at end
+ const iEnd = i - iStart > nContextLines ? iStart + nContextLines : i;
+ for (let iCommon = iStart; iCommon !== iEnd; iCommon += 1) {
+ pushCommonLine(diffs[iCommon][1]);
+ }
+ } else {
+ // between changes
+ const nCommon = i - iStart;
+ if (nCommon > nContextLines2) {
+ const iEnd = iStart + nContextLines;
+ for (let iCommon = iStart; iCommon !== iEnd; iCommon += 1) {
+ pushCommonLine(diffs[iCommon][1]);
+ }
+ lines[jPatchMark] = createPatchMark(aStart, aEnd, bStart, bEnd, options);
+ jPatchMark = lines.length;
+ lines.push("");
+ const nOmit = nCommon - nContextLines2;
+ aStart = aEnd + nOmit;
+ bStart = bEnd + nOmit;
+ aEnd = aStart;
+ bEnd = bStart;
+ for (let iCommon = i - nContextLines; iCommon !== i; iCommon += 1) {
+ pushCommonLine(diffs[iCommon][1]);
+ }
+ } else {
+ for (let iCommon = iStart; iCommon !== i; iCommon += 1) {
+ pushCommonLine(diffs[iCommon][1]);
+ }
+ }
+ }
+ }
+ while (i !== iLength && diffs[i][0] === DIFF_DELETE) {
+ pushDeleteLine(diffs[i][1]);
+ i += 1;
+ }
+ while (i !== iLength && diffs[i][0] === DIFF_INSERT) {
+ pushInsertLine(diffs[i][1]);
+ i += 1;
+ }
+ }
+ if (hasPatch) {
+ lines[jPatchMark] = createPatchMark(aStart, aEnd, bStart, bEnd, options);
+ }
+ return lines.join("\n");
+}
+// jest --expand
+//
+// Given array of aligned strings with inverse highlight formatting,
+// return joined lines with diff formatting.
+function joinAlignedDiffsExpand(diffs, options) {
+ return diffs.map((diff, i, diffs) => {
+ const line = diff[1];
+ const isFirstOrLast = i === 0 || i === diffs.length - 1;
+ switch (diff[0]) {
+ case DIFF_DELETE: return printDeleteLine(line, isFirstOrLast, options);
+ case DIFF_INSERT: return printInsertLine(line, isFirstOrLast, options);
+ default: return printCommonLine(line, isFirstOrLast, options);
+ }
+ }).join("\n");
+}
+
+const noColor = (string) => string;
+const DIFF_CONTEXT_DEFAULT = 5;
+const DIFF_TRUNCATE_THRESHOLD_DEFAULT = 0;
+function getDefaultOptions() {
+ return {
+ aAnnotation: "Expected",
+ aColor: c.green,
+ aIndicator: "-",
+ bAnnotation: "Received",
+ bColor: c.red,
+ bIndicator: "+",
+ changeColor: c.inverse,
+ changeLineTrailingSpaceColor: noColor,
+ commonColor: c.dim,
+ commonIndicator: " ",
+ commonLineTrailingSpaceColor: noColor,
+ compareKeys: undefined,
+ contextLines: DIFF_CONTEXT_DEFAULT,
+ emptyFirstOrLastLinePlaceholder: "",
+ expand: false,
+ includeChangeCounts: false,
+ omitAnnotationLines: false,
+ patchColor: c.yellow,
+ printBasicPrototype: false,
+ truncateThreshold: DIFF_TRUNCATE_THRESHOLD_DEFAULT,
+ truncateAnnotation: "... Diff result is truncated",
+ truncateAnnotationColor: noColor
+ };
+}
+function getCompareKeys(compareKeys) {
+ return compareKeys && typeof compareKeys === "function" ? compareKeys : undefined;
+}
+function getContextLines(contextLines) {
+ return typeof contextLines === "number" && Number.isSafeInteger(contextLines) && contextLines >= 0 ? contextLines : DIFF_CONTEXT_DEFAULT;
+}
+// Pure function returns options with all properties.
+function normalizeDiffOptions(options = {}) {
+ return {
+ ...getDefaultOptions(),
+ ...options,
+ compareKeys: getCompareKeys(options.compareKeys),
+ contextLines: getContextLines(options.contextLines)
+ };
+}
+
+function isEmptyString(lines) {
+ return lines.length === 1 && lines[0].length === 0;
+}
+function countChanges(diffs) {
+ let a = 0;
+ let b = 0;
+ diffs.forEach((diff) => {
+ switch (diff[0]) {
+ case DIFF_DELETE:
+ a += 1;
+ break;
+ case DIFF_INSERT:
+ b += 1;
+ break;
+ }
+ });
+ return {
+ a,
+ b
+ };
+}
+function printAnnotation({ aAnnotation, aColor, aIndicator, bAnnotation, bColor, bIndicator, includeChangeCounts, omitAnnotationLines }, changeCounts) {
+ if (omitAnnotationLines) {
+ return "";
+ }
+ let aRest = "";
+ let bRest = "";
+ if (includeChangeCounts) {
+ const aCount = String(changeCounts.a);
+ const bCount = String(changeCounts.b);
+ // Padding right aligns the ends of the annotations.
+ const baAnnotationLengthDiff = bAnnotation.length - aAnnotation.length;
+ const aAnnotationPadding = " ".repeat(Math.max(0, baAnnotationLengthDiff));
+ const bAnnotationPadding = " ".repeat(Math.max(0, -baAnnotationLengthDiff));
+ // Padding left aligns the ends of the counts.
+ const baCountLengthDiff = bCount.length - aCount.length;
+ const aCountPadding = " ".repeat(Math.max(0, baCountLengthDiff));
+ const bCountPadding = " ".repeat(Math.max(0, -baCountLengthDiff));
+ aRest = `${aAnnotationPadding} ${aIndicator} ${aCountPadding}${aCount}`;
+ bRest = `${bAnnotationPadding} ${bIndicator} ${bCountPadding}${bCount}`;
+ }
+ const a = `${aIndicator} ${aAnnotation}${aRest}`;
+ const b = `${bIndicator} ${bAnnotation}${bRest}`;
+ return `${aColor(a)}\n${bColor(b)}\n\n`;
+}
+function printDiffLines(diffs, truncated, options) {
+ return printAnnotation(options, countChanges(diffs)) + (options.expand ? joinAlignedDiffsExpand(diffs, options) : joinAlignedDiffsNoExpand(diffs, options)) + (truncated ? options.truncateAnnotationColor(`\n${options.truncateAnnotation}`) : "");
+}
+// Compare two arrays of strings line-by-line. Format as comparison lines.
+function diffLinesUnified(aLines, bLines, options) {
+ const normalizedOptions = normalizeDiffOptions(options);
+ const [diffs, truncated] = diffLinesRaw(isEmptyString(aLines) ? [] : aLines, isEmptyString(bLines) ? [] : bLines, normalizedOptions);
+ return printDiffLines(diffs, truncated, normalizedOptions);
+}
+// Given two pairs of arrays of strings:
+// Compare the pair of comparison arrays line-by-line.
+// Format the corresponding lines in the pair of displayable arrays.
+function diffLinesUnified2(aLinesDisplay, bLinesDisplay, aLinesCompare, bLinesCompare, options) {
+ if (isEmptyString(aLinesDisplay) && isEmptyString(aLinesCompare)) {
+ aLinesDisplay = [];
+ aLinesCompare = [];
+ }
+ if (isEmptyString(bLinesDisplay) && isEmptyString(bLinesCompare)) {
+ bLinesDisplay = [];
+ bLinesCompare = [];
+ }
+ if (aLinesDisplay.length !== aLinesCompare.length || bLinesDisplay.length !== bLinesCompare.length) {
+ // Fall back to diff of display lines.
+ return diffLinesUnified(aLinesDisplay, bLinesDisplay, options);
+ }
+ const [diffs, truncated] = diffLinesRaw(aLinesCompare, bLinesCompare, options);
+ // Replace comparison lines with displayable lines.
+ let aIndex = 0;
+ let bIndex = 0;
+ diffs.forEach((diff) => {
+ switch (diff[0]) {
+ case DIFF_DELETE:
+ diff[1] = aLinesDisplay[aIndex];
+ aIndex += 1;
+ break;
+ case DIFF_INSERT:
+ diff[1] = bLinesDisplay[bIndex];
+ bIndex += 1;
+ break;
+ default:
+ diff[1] = bLinesDisplay[bIndex];
+ aIndex += 1;
+ bIndex += 1;
+ }
+ });
+ return printDiffLines(diffs, truncated, normalizeDiffOptions(options));
+}
+// Compare two arrays of strings line-by-line.
+function diffLinesRaw(aLines, bLines, options) {
+ const truncate = (options === null || options === void 0 ? void 0 : options.truncateThreshold) ?? false;
+ const truncateThreshold = Math.max(Math.floor((options === null || options === void 0 ? void 0 : options.truncateThreshold) ?? 0), 0);
+ const aLength = truncate ? Math.min(aLines.length, truncateThreshold) : aLines.length;
+ const bLength = truncate ? Math.min(bLines.length, truncateThreshold) : bLines.length;
+ const truncated = aLength !== aLines.length || bLength !== bLines.length;
+ const isCommon = (aIndex, bIndex) => aLines[aIndex] === bLines[bIndex];
+ const diffs = [];
+ let aIndex = 0;
+ let bIndex = 0;
+ const foundSubsequence = (nCommon, aCommon, bCommon) => {
+ for (; aIndex !== aCommon; aIndex += 1) {
+ diffs.push(new Diff(DIFF_DELETE, aLines[aIndex]));
+ }
+ for (; bIndex !== bCommon; bIndex += 1) {
+ diffs.push(new Diff(DIFF_INSERT, bLines[bIndex]));
+ }
+ for (; nCommon !== 0; nCommon -= 1, aIndex += 1, bIndex += 1) {
+ diffs.push(new Diff(DIFF_EQUAL, bLines[bIndex]));
+ }
+ };
+ diffSequences(aLength, bLength, isCommon, foundSubsequence);
+ // After the last common subsequence, push remaining change items.
+ for (; aIndex !== aLength; aIndex += 1) {
+ diffs.push(new Diff(DIFF_DELETE, aLines[aIndex]));
+ }
+ for (; bIndex !== bLength; bIndex += 1) {
+ diffs.push(new Diff(DIFF_INSERT, bLines[bIndex]));
+ }
+ return [diffs, truncated];
+}
+
+// get the type of a value with handling the edge cases like `typeof []`
+// and `typeof null`
+function getType(value) {
+ if (value === undefined) {
+ return "undefined";
+ } else if (value === null) {
+ return "null";
+ } else if (Array.isArray(value)) {
+ return "array";
+ } else if (typeof value === "boolean") {
+ return "boolean";
+ } else if (typeof value === "function") {
+ return "function";
+ } else if (typeof value === "number") {
+ return "number";
+ } else if (typeof value === "string") {
+ return "string";
+ } else if (typeof value === "bigint") {
+ return "bigint";
+ } else if (typeof value === "object") {
+ if (value != null) {
+ if (value.constructor === RegExp) {
+ return "regexp";
+ } else if (value.constructor === Map) {
+ return "map";
+ } else if (value.constructor === Set) {
+ return "set";
+ } else if (value.constructor === Date) {
+ return "date";
+ }
+ }
+ return "object";
+ } else if (typeof value === "symbol") {
+ return "symbol";
+ }
+ throw new Error(`value of unknown type: ${value}`);
+}
+
+// platforms compatible
+function getNewLineSymbol(string) {
+ return string.includes("\r\n") ? "\r\n" : "\n";
+}
+function diffStrings(a, b, options) {
+ const truncate = (options === null || options === void 0 ? void 0 : options.truncateThreshold) ?? false;
+ const truncateThreshold = Math.max(Math.floor((options === null || options === void 0 ? void 0 : options.truncateThreshold) ?? 0), 0);
+ let aLength = a.length;
+ let bLength = b.length;
+ if (truncate) {
+ const aMultipleLines = a.includes("\n");
+ const bMultipleLines = b.includes("\n");
+ const aNewLineSymbol = getNewLineSymbol(a);
+ const bNewLineSymbol = getNewLineSymbol(b);
+ // multiple-lines string expects a newline to be appended at the end
+ const _a = aMultipleLines ? `${a.split(aNewLineSymbol, truncateThreshold).join(aNewLineSymbol)}\n` : a;
+ const _b = bMultipleLines ? `${b.split(bNewLineSymbol, truncateThreshold).join(bNewLineSymbol)}\n` : b;
+ aLength = _a.length;
+ bLength = _b.length;
+ }
+ const truncated = aLength !== a.length || bLength !== b.length;
+ const isCommon = (aIndex, bIndex) => a[aIndex] === b[bIndex];
+ let aIndex = 0;
+ let bIndex = 0;
+ const diffs = [];
+ const foundSubsequence = (nCommon, aCommon, bCommon) => {
+ if (aIndex !== aCommon) {
+ diffs.push(new Diff(DIFF_DELETE, a.slice(aIndex, aCommon)));
+ }
+ if (bIndex !== bCommon) {
+ diffs.push(new Diff(DIFF_INSERT, b.slice(bIndex, bCommon)));
+ }
+ aIndex = aCommon + nCommon;
+ bIndex = bCommon + nCommon;
+ diffs.push(new Diff(DIFF_EQUAL, b.slice(bCommon, bIndex)));
+ };
+ diffSequences(aLength, bLength, isCommon, foundSubsequence);
+ // After the last common subsequence, push remaining change items.
+ if (aIndex !== aLength) {
+ diffs.push(new Diff(DIFF_DELETE, a.slice(aIndex)));
+ }
+ if (bIndex !== bLength) {
+ diffs.push(new Diff(DIFF_INSERT, b.slice(bIndex)));
+ }
+ return [diffs, truncated];
+}
+
+// Given change op and array of diffs, return concatenated string:
+// * include common strings
+// * include change strings which have argument op with changeColor
+// * exclude change strings which have opposite op
+function concatenateRelevantDiffs(op, diffs, changeColor) {
+ return diffs.reduce((reduced, diff) => reduced + (diff[0] === DIFF_EQUAL ? diff[1] : diff[0] === op && diff[1].length !== 0 ? changeColor(diff[1]) : ""), "");
+}
+// Encapsulate change lines until either a common newline or the end.
+class ChangeBuffer {
+ op;
+ line;
+ lines;
+ changeColor;
+ constructor(op, changeColor) {
+ this.op = op;
+ this.line = [];
+ this.lines = [];
+ this.changeColor = changeColor;
+ }
+ pushSubstring(substring) {
+ this.pushDiff(new Diff(this.op, substring));
+ }
+ pushLine() {
+ // Assume call only if line has at least one diff,
+ // therefore an empty line must have a diff which has an empty string.
+ // If line has multiple diffs, then assume it has a common diff,
+ // therefore change diffs have change color;
+ // otherwise then it has line color only.
+ this.lines.push(this.line.length !== 1 ? new Diff(this.op, concatenateRelevantDiffs(this.op, this.line, this.changeColor)) : this.line[0][0] === this.op ? this.line[0] : new Diff(this.op, this.line[0][1]));
+ this.line.length = 0;
+ }
+ isLineEmpty() {
+ return this.line.length === 0;
+ }
+ // Minor input to buffer.
+ pushDiff(diff) {
+ this.line.push(diff);
+ }
+ // Main input to buffer.
+ align(diff) {
+ const string = diff[1];
+ if (string.includes("\n")) {
+ const substrings = string.split("\n");
+ const iLast = substrings.length - 1;
+ substrings.forEach((substring, i) => {
+ if (i < iLast) {
+ // The first substring completes the current change line.
+ // A middle substring is a change line.
+ this.pushSubstring(substring);
+ this.pushLine();
+ } else if (substring.length !== 0) {
+ // The last substring starts a change line, if it is not empty.
+ // Important: This non-empty condition also automatically omits
+ // the newline appended to the end of expected and received strings.
+ this.pushSubstring(substring);
+ }
+ });
+ } else {
+ // Append non-multiline string to current change line.
+ this.pushDiff(diff);
+ }
+ }
+ // Output from buffer.
+ moveLinesTo(lines) {
+ if (!this.isLineEmpty()) {
+ this.pushLine();
+ }
+ lines.push(...this.lines);
+ this.lines.length = 0;
+ }
+}
+// Encapsulate common and change lines.
+class CommonBuffer {
+ deleteBuffer;
+ insertBuffer;
+ lines;
+ constructor(deleteBuffer, insertBuffer) {
+ this.deleteBuffer = deleteBuffer;
+ this.insertBuffer = insertBuffer;
+ this.lines = [];
+ }
+ pushDiffCommonLine(diff) {
+ this.lines.push(diff);
+ }
+ pushDiffChangeLines(diff) {
+ const isDiffEmpty = diff[1].length === 0;
+ // An empty diff string is redundant, unless a change line is empty.
+ if (!isDiffEmpty || this.deleteBuffer.isLineEmpty()) {
+ this.deleteBuffer.pushDiff(diff);
+ }
+ if (!isDiffEmpty || this.insertBuffer.isLineEmpty()) {
+ this.insertBuffer.pushDiff(diff);
+ }
+ }
+ flushChangeLines() {
+ this.deleteBuffer.moveLinesTo(this.lines);
+ this.insertBuffer.moveLinesTo(this.lines);
+ }
+ // Input to buffer.
+ align(diff) {
+ const op = diff[0];
+ const string = diff[1];
+ if (string.includes("\n")) {
+ const substrings = string.split("\n");
+ const iLast = substrings.length - 1;
+ substrings.forEach((substring, i) => {
+ if (i === 0) {
+ const subdiff = new Diff(op, substring);
+ if (this.deleteBuffer.isLineEmpty() && this.insertBuffer.isLineEmpty()) {
+ // If both current change lines are empty,
+ // then the first substring is a common line.
+ this.flushChangeLines();
+ this.pushDiffCommonLine(subdiff);
+ } else {
+ // If either current change line is non-empty,
+ // then the first substring completes the change lines.
+ this.pushDiffChangeLines(subdiff);
+ this.flushChangeLines();
+ }
+ } else if (i < iLast) {
+ // A middle substring is a common line.
+ this.pushDiffCommonLine(new Diff(op, substring));
+ } else if (substring.length !== 0) {
+ // The last substring starts a change line, if it is not empty.
+ // Important: This non-empty condition also automatically omits
+ // the newline appended to the end of expected and received strings.
+ this.pushDiffChangeLines(new Diff(op, substring));
+ }
+ });
+ } else {
+ // Append non-multiline string to current change lines.
+ // Important: It cannot be at the end following empty change lines,
+ // because newline appended to the end of expected and received strings.
+ this.pushDiffChangeLines(diff);
+ }
+ }
+ // Output from buffer.
+ getLines() {
+ this.flushChangeLines();
+ return this.lines;
+ }
+}
+// Given diffs from expected and received strings,
+// return new array of diffs split or joined into lines.
+//
+// To correctly align a change line at the end, the algorithm:
+// * assumes that a newline was appended to the strings
+// * omits the last newline from the output array
+//
+// Assume the function is not called:
+// * if either expected or received is empty string
+// * if neither expected nor received is multiline string
+function getAlignedDiffs(diffs, changeColor) {
+ const deleteBuffer = new ChangeBuffer(DIFF_DELETE, changeColor);
+ const insertBuffer = new ChangeBuffer(DIFF_INSERT, changeColor);
+ const commonBuffer = new CommonBuffer(deleteBuffer, insertBuffer);
+ diffs.forEach((diff) => {
+ switch (diff[0]) {
+ case DIFF_DELETE:
+ deleteBuffer.align(diff);
+ break;
+ case DIFF_INSERT:
+ insertBuffer.align(diff);
+ break;
+ default: commonBuffer.align(diff);
+ }
+ });
+ return commonBuffer.getLines();
+}
+
+function hasCommonDiff(diffs, isMultiline) {
+ if (isMultiline) {
+ // Important: Ignore common newline that was appended to multiline strings!
+ const iLast = diffs.length - 1;
+ return diffs.some((diff, i) => diff[0] === DIFF_EQUAL && (i !== iLast || diff[1] !== "\n"));
+ }
+ return diffs.some((diff) => diff[0] === DIFF_EQUAL);
+}
+// Compare two strings character-by-character.
+// Format as comparison lines in which changed substrings have inverse colors.
+function diffStringsUnified(a, b, options) {
+ if (a !== b && a.length !== 0 && b.length !== 0) {
+ const isMultiline = a.includes("\n") || b.includes("\n");
+ // getAlignedDiffs assumes that a newline was appended to the strings.
+ const [diffs, truncated] = diffStringsRaw(isMultiline ? `${a}\n` : a, isMultiline ? `${b}\n` : b, true, options);
+ if (hasCommonDiff(diffs, isMultiline)) {
+ const optionsNormalized = normalizeDiffOptions(options);
+ const lines = getAlignedDiffs(diffs, optionsNormalized.changeColor);
+ return printDiffLines(lines, truncated, optionsNormalized);
+ }
+ }
+ // Fall back to line-by-line diff.
+ return diffLinesUnified(a.split("\n"), b.split("\n"), options);
+}
+// Compare two strings character-by-character.
+// Optionally clean up small common substrings, also known as chaff.
+function diffStringsRaw(a, b, cleanup, options) {
+ const [diffs, truncated] = diffStrings(a, b, options);
+ if (cleanup) {
+ diff_cleanupSemantic(diffs);
+ }
+ return [diffs, truncated];
+}
+
+function getCommonMessage(message, options) {
+ const { commonColor } = normalizeDiffOptions(options);
+ return commonColor(message);
+}
+const { AsymmetricMatcher, DOMCollection, DOMElement, Immutable, ReactElement, ReactTestComponent } = plugins;
+const PLUGINS = [
+ ReactTestComponent,
+ ReactElement,
+ DOMElement,
+ DOMCollection,
+ Immutable,
+ AsymmetricMatcher,
+ plugins.Error
+];
+const FORMAT_OPTIONS = {
+ maxDepth: 20,
+ plugins: PLUGINS
+};
+const FALLBACK_FORMAT_OPTIONS = {
+ callToJSON: false,
+ maxDepth: 8,
+ plugins: PLUGINS
+};
+// Generate a string that will highlight the difference between two values
+// with green and red. (similar to how github does code diffing)
+/**
+* @param a Expected value
+* @param b Received value
+* @param options Diff options
+* @returns {string | null} a string diff
+*/
+function diff(a, b, options) {
+ if (Object.is(a, b)) {
+ return "";
+ }
+ const aType = getType(a);
+ let expectedType = aType;
+ let omitDifference = false;
+ if (aType === "object" && typeof a.asymmetricMatch === "function") {
+ if (a.$$typeof !== Symbol.for("jest.asymmetricMatcher")) {
+ // Do not know expected type of user-defined asymmetric matcher.
+ return undefined;
+ }
+ if (typeof a.getExpectedType !== "function") {
+ // For example, expect.anything() matches either null or undefined
+ return undefined;
+ }
+ expectedType = a.getExpectedType();
+ // Primitive types boolean and number omit difference below.
+ // For example, omit difference for expect.stringMatching(regexp)
+ omitDifference = expectedType === "string";
+ }
+ if (expectedType !== getType(b)) {
+ const { aAnnotation, aColor, aIndicator, bAnnotation, bColor, bIndicator } = normalizeDiffOptions(options);
+ const formatOptions = getFormatOptions(FALLBACK_FORMAT_OPTIONS, options);
+ let aDisplay = format(a, formatOptions);
+ let bDisplay = format(b, formatOptions);
+ // even if prettyFormat prints successfully big objects,
+ // large string can choke later on (concatenation? RPC?),
+ // so truncate it to a reasonable length here.
+ // (For example, playwright's ElementHandle can become about 200_000_000 length string)
+ const MAX_LENGTH = 1e5;
+ function truncate(s) {
+ return s.length <= MAX_LENGTH ? s : `${s.slice(0, MAX_LENGTH)}...`;
+ }
+ aDisplay = truncate(aDisplay);
+ bDisplay = truncate(bDisplay);
+ const aDiff = `${aColor(`${aIndicator} ${aAnnotation}:`)} \n${aDisplay}`;
+ const bDiff = `${bColor(`${bIndicator} ${bAnnotation}:`)} \n${bDisplay}`;
+ return `${aDiff}\n\n${bDiff}`;
+ }
+ if (omitDifference) {
+ return undefined;
+ }
+ switch (aType) {
+ case "string": return diffLinesUnified(a.split("\n"), b.split("\n"), options);
+ case "boolean":
+ case "number": return comparePrimitive(a, b, options);
+ case "map": return compareObjects(sortMap(a), sortMap(b), options);
+ case "set": return compareObjects(sortSet(a), sortSet(b), options);
+ default: return compareObjects(a, b, options);
+ }
+}
+function comparePrimitive(a, b, options) {
+ const aFormat = format(a, FORMAT_OPTIONS);
+ const bFormat = format(b, FORMAT_OPTIONS);
+ return aFormat === bFormat ? "" : diffLinesUnified(aFormat.split("\n"), bFormat.split("\n"), options);
+}
+function sortMap(map) {
+ return new Map(Array.from(map.entries()).sort());
+}
+function sortSet(set) {
+ return new Set(Array.from(set.values()).sort());
+}
+function compareObjects(a, b, options) {
+ let difference;
+ let hasThrown = false;
+ try {
+ const formatOptions = getFormatOptions(FORMAT_OPTIONS, options);
+ difference = getObjectsDifference(a, b, formatOptions, options);
+ } catch {
+ hasThrown = true;
+ }
+ const noDiffMessage = getCommonMessage(NO_DIFF_MESSAGE, options);
+ // If the comparison yields no results, compare again but this time
+ // without calling `toJSON`. It's also possible that toJSON might throw.
+ if (difference === undefined || difference === noDiffMessage) {
+ const formatOptions = getFormatOptions(FALLBACK_FORMAT_OPTIONS, options);
+ difference = getObjectsDifference(a, b, formatOptions, options);
+ if (difference !== noDiffMessage && !hasThrown) {
+ difference = `${getCommonMessage(SIMILAR_MESSAGE, options)}\n\n${difference}`;
+ }
+ }
+ return difference;
+}
+function getFormatOptions(formatOptions, options) {
+ const { compareKeys, printBasicPrototype, maxDepth } = normalizeDiffOptions(options);
+ return {
+ ...formatOptions,
+ compareKeys,
+ printBasicPrototype,
+ maxDepth: maxDepth ?? formatOptions.maxDepth
+ };
+}
+function getObjectsDifference(a, b, formatOptions, options) {
+ const formatOptionsZeroIndent = {
+ ...formatOptions,
+ indent: 0
+ };
+ const aCompare = format(a, formatOptionsZeroIndent);
+ const bCompare = format(b, formatOptionsZeroIndent);
+ if (aCompare === bCompare) {
+ return getCommonMessage(NO_DIFF_MESSAGE, options);
+ } else {
+ const aDisplay = format(a, formatOptions);
+ const bDisplay = format(b, formatOptions);
+ return diffLinesUnified2(aDisplay.split("\n"), bDisplay.split("\n"), aCompare.split("\n"), bCompare.split("\n"), options);
+ }
+}
+const MAX_DIFF_STRING_LENGTH = 2e4;
+function isAsymmetricMatcher(data) {
+ const type = getType$1(data);
+ return type === "Object" && typeof data.asymmetricMatch === "function";
+}
+function isReplaceable(obj1, obj2) {
+ const obj1Type = getType$1(obj1);
+ const obj2Type = getType$1(obj2);
+ return obj1Type === obj2Type && (obj1Type === "Object" || obj1Type === "Array");
+}
+function printDiffOrStringify(received, expected, options) {
+ const { aAnnotation, bAnnotation } = normalizeDiffOptions(options);
+ if (typeof expected === "string" && typeof received === "string" && expected.length > 0 && received.length > 0 && expected.length <= MAX_DIFF_STRING_LENGTH && received.length <= MAX_DIFF_STRING_LENGTH && expected !== received) {
+ if (expected.includes("\n") || received.includes("\n")) {
+ return diffStringsUnified(expected, received, options);
+ }
+ const [diffs] = diffStringsRaw(expected, received, true);
+ const hasCommonDiff = diffs.some((diff) => diff[0] === DIFF_EQUAL);
+ const printLabel = getLabelPrinter(aAnnotation, bAnnotation);
+ const expectedLine = printLabel(aAnnotation) + printExpected(getCommonAndChangedSubstrings(diffs, DIFF_DELETE, hasCommonDiff));
+ const receivedLine = printLabel(bAnnotation) + printReceived(getCommonAndChangedSubstrings(diffs, DIFF_INSERT, hasCommonDiff));
+ return `${expectedLine}\n${receivedLine}`;
+ }
+ // if (isLineDiffable(expected, received)) {
+ const clonedExpected = deepClone(expected, { forceWritable: true });
+ const clonedReceived = deepClone(received, { forceWritable: true });
+ const { replacedExpected, replacedActual } = replaceAsymmetricMatcher(clonedReceived, clonedExpected);
+ const difference = diff(replacedExpected, replacedActual, options);
+ return difference;
+ // }
+ // const printLabel = getLabelPrinter(aAnnotation, bAnnotation)
+ // const expectedLine = printLabel(aAnnotation) + printExpected(expected)
+ // const receivedLine
+ // = printLabel(bAnnotation)
+ // + (stringify(expected) === stringify(received)
+ // ? 'serializes to the same string'
+ // : printReceived(received))
+ // return `${expectedLine}\n${receivedLine}`
+}
+function replaceAsymmetricMatcher(actual, expected, actualReplaced = new WeakSet(), expectedReplaced = new WeakSet()) {
+ // handle asymmetric Error.cause diff
+ if (actual instanceof Error && expected instanceof Error && typeof actual.cause !== "undefined" && typeof expected.cause === "undefined") {
+ delete actual.cause;
+ return {
+ replacedActual: actual,
+ replacedExpected: expected
+ };
+ }
+ if (!isReplaceable(actual, expected)) {
+ return {
+ replacedActual: actual,
+ replacedExpected: expected
+ };
+ }
+ if (actualReplaced.has(actual) || expectedReplaced.has(expected)) {
+ return {
+ replacedActual: actual,
+ replacedExpected: expected
+ };
+ }
+ actualReplaced.add(actual);
+ expectedReplaced.add(expected);
+ getOwnProperties(expected).forEach((key) => {
+ const expectedValue = expected[key];
+ const actualValue = actual[key];
+ if (isAsymmetricMatcher(expectedValue)) {
+ if (expectedValue.asymmetricMatch(actualValue)) {
+ // When matcher matches, replace expected with actual value
+ // so they appear the same in the diff
+ expected[key] = actualValue;
+ } else if ("sample" in expectedValue && expectedValue.sample !== undefined && isReplaceable(actualValue, expectedValue.sample)) {
+ // For container matchers (ArrayContaining, ObjectContaining), unwrap and recursively process
+ // Matcher doesn't match: unwrap but keep structure to show mismatch
+ const replaced = replaceAsymmetricMatcher(actualValue, expectedValue.sample, actualReplaced, expectedReplaced);
+ actual[key] = replaced.replacedActual;
+ expected[key] = replaced.replacedExpected;
+ }
+ } else if (isAsymmetricMatcher(actualValue)) {
+ if (actualValue.asymmetricMatch(expectedValue)) {
+ actual[key] = expectedValue;
+ } else if ("sample" in actualValue && actualValue.sample !== undefined && isReplaceable(actualValue.sample, expectedValue)) {
+ const replaced = replaceAsymmetricMatcher(actualValue.sample, expectedValue, actualReplaced, expectedReplaced);
+ actual[key] = replaced.replacedActual;
+ expected[key] = replaced.replacedExpected;
+ }
+ } else if (isReplaceable(actualValue, expectedValue)) {
+ const replaced = replaceAsymmetricMatcher(actualValue, expectedValue, actualReplaced, expectedReplaced);
+ actual[key] = replaced.replacedActual;
+ expected[key] = replaced.replacedExpected;
+ }
+ });
+ return {
+ replacedActual: actual,
+ replacedExpected: expected
+ };
+}
+function getLabelPrinter(...strings) {
+ const maxLength = strings.reduce((max, string) => string.length > max ? string.length : max, 0);
+ return (string) => `${string}: ${" ".repeat(maxLength - string.length)}`;
+}
+const SPACE_SYMBOL = "·";
+function replaceTrailingSpaces(text) {
+ return text.replace(/\s+$/gm, (spaces) => SPACE_SYMBOL.repeat(spaces.length));
+}
+function printReceived(object) {
+ return c.red(replaceTrailingSpaces(stringify(object)));
+}
+function printExpected(value) {
+ return c.green(replaceTrailingSpaces(stringify(value)));
+}
+function getCommonAndChangedSubstrings(diffs, op, hasCommonDiff) {
+ return diffs.reduce((reduced, diff) => reduced + (diff[0] === DIFF_EQUAL ? diff[1] : diff[0] === op ? hasCommonDiff ? c.inverse(diff[1]) : diff[1] : ""), "");
+}
+
+export { DIFF_DELETE, DIFF_EQUAL, DIFF_INSERT, Diff, diff, diffLinesRaw, diffLinesUnified, diffLinesUnified2, diffStringsRaw, diffStringsUnified, getLabelPrinter, printDiffOrStringify, replaceAsymmetricMatcher };
diff --git a/vanilla/node_modules/@vitest/utils/dist/display.d.ts b/vanilla/node_modules/@vitest/utils/dist/display.d.ts
new file mode 100644
index 0000000..576fa4c
--- /dev/null
+++ b/vanilla/node_modules/@vitest/utils/dist/display.d.ts
@@ -0,0 +1,29 @@
+import { PrettyFormatOptions } from '@vitest/pretty-format';
+
+type Inspect = (value: unknown, options: Options) => string;
+interface Options {
+ showHidden: boolean;
+ depth: number;
+ colors: boolean;
+ customInspect: boolean;
+ showProxy: boolean;
+ maxArrayLength: number;
+ breakLength: number;
+ truncate: number;
+ seen: unknown[];
+ inspect: Inspect;
+ stylize: (value: string, styleType: string) => string;
+}
+type LoupeOptions = Partial<Options>;
+interface StringifyOptions extends PrettyFormatOptions {
+ maxLength?: number;
+}
+declare function stringify(object: unknown, maxDepth?: number, { maxLength, ...options }?: StringifyOptions): string;
+declare const formatRegExp: RegExp;
+declare function format(...args: unknown[]): string;
+declare function browserFormat(...args: unknown[]): string;
+declare function inspect(obj: unknown, options?: LoupeOptions): string;
+declare function objDisplay(obj: unknown, options?: LoupeOptions): string;
+
+export { browserFormat, format, formatRegExp, inspect, objDisplay, stringify };
+export type { LoupeOptions, StringifyOptions };
diff --git a/vanilla/node_modules/@vitest/utils/dist/display.js b/vanilla/node_modules/@vitest/utils/dist/display.js
new file mode 100644
index 0000000..414e9c9
--- /dev/null
+++ b/vanilla/node_modules/@vitest/utils/dist/display.js
@@ -0,0 +1,742 @@
+import { plugins, format as format$1 } from '@vitest/pretty-format';
+
+const ansiColors = {
+ bold: ['1', '22'],
+ dim: ['2', '22'],
+ italic: ['3', '23'],
+ underline: ['4', '24'],
+ // 5 & 6 are blinking
+ inverse: ['7', '27'],
+ hidden: ['8', '28'],
+ strike: ['9', '29'],
+ // 10-20 are fonts
+ // 21-29 are resets for 1-9
+ black: ['30', '39'],
+ red: ['31', '39'],
+ green: ['32', '39'],
+ yellow: ['33', '39'],
+ blue: ['34', '39'],
+ magenta: ['35', '39'],
+ cyan: ['36', '39'],
+ white: ['37', '39'],
+ brightblack: ['30;1', '39'],
+ brightred: ['31;1', '39'],
+ brightgreen: ['32;1', '39'],
+ brightyellow: ['33;1', '39'],
+ brightblue: ['34;1', '39'],
+ brightmagenta: ['35;1', '39'],
+ brightcyan: ['36;1', '39'],
+ brightwhite: ['37;1', '39'],
+ grey: ['90', '39'],
+};
+const styles = {
+ special: 'cyan',
+ number: 'yellow',
+ bigint: 'yellow',
+ boolean: 'yellow',
+ undefined: 'grey',
+ null: 'bold',
+ string: 'green',
+ symbol: 'green',
+ date: 'magenta',
+ regexp: 'red',
+};
+const truncator = '…';
+function colorise(value, styleType) {
+ const color = ansiColors[styles[styleType]] || ansiColors[styleType] || '';
+ if (!color) {
+ return String(value);
+ }
+ return `\u001b[${color[0]}m${String(value)}\u001b[${color[1]}m`;
+}
+function normaliseOptions({ showHidden = false, depth = 2, colors = false, customInspect = true, showProxy = false, maxArrayLength = Infinity, breakLength = Infinity, seen = [],
+// eslint-disable-next-line no-shadow
+truncate = Infinity, stylize = String, } = {}, inspect) {
+ const options = {
+ showHidden: Boolean(showHidden),
+ depth: Number(depth),
+ colors: Boolean(colors),
+ customInspect: Boolean(customInspect),
+ showProxy: Boolean(showProxy),
+ maxArrayLength: Number(maxArrayLength),
+ breakLength: Number(breakLength),
+ truncate: Number(truncate),
+ seen,
+ inspect,
+ stylize,
+ };
+ if (options.colors) {
+ options.stylize = colorise;
+ }
+ return options;
+}
+function isHighSurrogate(char) {
+ return char >= '\ud800' && char <= '\udbff';
+}
+function truncate(string, length, tail = truncator) {
+ string = String(string);
+ const tailLength = tail.length;
+ const stringLength = string.length;
+ if (tailLength > length && stringLength > tailLength) {
+ return tail;
+ }
+ if (stringLength > length && stringLength > tailLength) {
+ let end = length - tailLength;
+ if (end > 0 && isHighSurrogate(string[end - 1])) {
+ end = end - 1;
+ }
+ return `${string.slice(0, end)}${tail}`;
+ }
+ return string;
+}
+// eslint-disable-next-line complexity
+function inspectList(list, options, inspectItem, separator = ', ') {
+ inspectItem = inspectItem || options.inspect;
+ const size = list.length;
+ if (size === 0)
+ return '';
+ const originalLength = options.truncate;
+ let output = '';
+ let peek = '';
+ let truncated = '';
+ for (let i = 0; i < size; i += 1) {
+ const last = i + 1 === list.length;
+ const secondToLast = i + 2 === list.length;
+ truncated = `${truncator}(${list.length - i})`;
+ const value = list[i];
+ // If there is more than one remaining we need to account for a separator of `, `
+ options.truncate = originalLength - output.length - (last ? 0 : separator.length);
+ const string = peek || inspectItem(value, options) + (last ? '' : separator);
+ const nextLength = output.length + string.length;
+ const truncatedLength = nextLength + truncated.length;
+ // If this is the last element, and adding it would
+ // take us over length, but adding the truncator wouldn't - then break now
+ if (last && nextLength > originalLength && output.length + truncated.length <= originalLength) {
+ break;
+ }
+ // If this isn't the last or second to last element to scan,
+ // but the string is already over length then break here
+ if (!last && !secondToLast && truncatedLength > originalLength) {
+ break;
+ }
+ // Peek at the next string to determine if we should
+ // break early before adding this item to the output
+ peek = last ? '' : inspectItem(list[i + 1], options) + (secondToLast ? '' : separator);
+ // If we have one element left, but this element and
+ // the next takes over length, the break early
+ if (!last && secondToLast && truncatedLength > originalLength && nextLength + peek.length > originalLength) {
+ break;
+ }
+ output += string;
+ // If the next element takes us to length -
+ // but there are more after that, then we should truncate now
+ if (!last && !secondToLast && nextLength + peek.length >= originalLength) {
+ truncated = `${truncator}(${list.length - i - 1})`;
+ break;
+ }
+ truncated = '';
+ }
+ return `${output}${truncated}`;
+}
+function quoteComplexKey(key) {
+ if (key.match(/^[a-zA-Z_][a-zA-Z_0-9]*$/)) {
+ return key;
+ }
+ return JSON.stringify(key)
+ .replace(/'/g, "\\'")
+ .replace(/\\"/g, '"')
+ .replace(/(^"|"$)/g, "'");
+}
+function inspectProperty([key, value], options) {
+ options.truncate -= 2;
+ if (typeof key === 'string') {
+ key = quoteComplexKey(key);
+ }
+ else if (typeof key !== 'number') {
+ key = `[${options.inspect(key, options)}]`;
+ }
+ options.truncate -= key.length;
+ value = options.inspect(value, options);
+ return `${key}: ${value}`;
+}
+
+function inspectArray(array, options) {
+ // Object.keys will always output the Array indices first, so we can slice by
+ // `array.length` to get non-index properties
+ const nonIndexProperties = Object.keys(array).slice(array.length);
+ if (!array.length && !nonIndexProperties.length)
+ return '[]';
+ options.truncate -= 4;
+ const listContents = inspectList(array, options);
+ options.truncate -= listContents.length;
+ let propertyContents = '';
+ if (nonIndexProperties.length) {
+ propertyContents = inspectList(nonIndexProperties.map(key => [key, array[key]]), options, inspectProperty);
+ }
+ return `[ ${listContents}${propertyContents ? `, ${propertyContents}` : ''} ]`;
+}
+
+const getArrayName = (array) => {
+ // We need to special case Node.js' Buffers, which report to be Uint8Array
+ // @ts-ignore
+ if (typeof Buffer === 'function' && array instanceof Buffer) {
+ return 'Buffer';
+ }
+ if (array[Symbol.toStringTag]) {
+ return array[Symbol.toStringTag];
+ }
+ return array.constructor.name;
+};
+function inspectTypedArray(array, options) {
+ const name = getArrayName(array);
+ options.truncate -= name.length + 4;
+ // Object.keys will always output the Array indices first, so we can slice by
+ // `array.length` to get non-index properties
+ const nonIndexProperties = Object.keys(array).slice(array.length);
+ if (!array.length && !nonIndexProperties.length)
+ return `${name}[]`;
+ // As we know TypedArrays only contain Unsigned Integers, we can skip inspecting each one and simply
+ // stylise the toString() value of them
+ let output = '';
+ for (let i = 0; i < array.length; i++) {
+ const string = `${options.stylize(truncate(array[i], options.truncate), 'number')}${i === array.length - 1 ? '' : ', '}`;
+ options.truncate -= string.length;
+ if (array[i] !== array.length && options.truncate <= 3) {
+ output += `${truncator}(${array.length - array[i] + 1})`;
+ break;
+ }
+ output += string;
+ }
+ let propertyContents = '';
+ if (nonIndexProperties.length) {
+ propertyContents = inspectList(nonIndexProperties.map(key => [key, array[key]]), options, inspectProperty);
+ }
+ return `${name}[ ${output}${propertyContents ? `, ${propertyContents}` : ''} ]`;
+}
+
+function inspectDate(dateObject, options) {
+ const stringRepresentation = dateObject.toJSON();
+ if (stringRepresentation === null) {
+ return 'Invalid Date';
+ }
+ const split = stringRepresentation.split('T');
+ const date = split[0];
+ // If we need to - truncate the time portion, but never the date
+ return options.stylize(`${date}T${truncate(split[1], options.truncate - date.length - 1)}`, 'date');
+}
+
+function inspectFunction(func, options) {
+ const functionType = func[Symbol.toStringTag] || 'Function';
+ const name = func.name;
+ if (!name) {
+ return options.stylize(`[${functionType}]`, 'special');
+ }
+ return options.stylize(`[${functionType} ${truncate(name, options.truncate - 11)}]`, 'special');
+}
+
+function inspectMapEntry([key, value], options) {
+ options.truncate -= 4;
+ key = options.inspect(key, options);
+ options.truncate -= key.length;
+ value = options.inspect(value, options);
+ return `${key} => ${value}`;
+}
+// IE11 doesn't support `map.entries()`
+function mapToEntries(map) {
+ const entries = [];
+ map.forEach((value, key) => {
+ entries.push([key, value]);
+ });
+ return entries;
+}
+function inspectMap(map, options) {
+ if (map.size === 0)
+ return 'Map{}';
+ options.truncate -= 7;
+ return `Map{ ${inspectList(mapToEntries(map), options, inspectMapEntry)} }`;
+}
+
+const isNaN = Number.isNaN || (i => i !== i); // eslint-disable-line no-self-compare
+function inspectNumber(number, options) {
+ if (isNaN(number)) {
+ return options.stylize('NaN', 'number');
+ }
+ if (number === Infinity) {
+ return options.stylize('Infinity', 'number');
+ }
+ if (number === -Infinity) {
+ return options.stylize('-Infinity', 'number');
+ }
+ if (number === 0) {
+ return options.stylize(1 / number === Infinity ? '+0' : '-0', 'number');
+ }
+ return options.stylize(truncate(String(number), options.truncate), 'number');
+}
+
+function inspectBigInt(number, options) {
+ let nums = truncate(number.toString(), options.truncate - 1);
+ if (nums !== truncator)
+ nums += 'n';
+ return options.stylize(nums, 'bigint');
+}
+
+function inspectRegExp(value, options) {
+ const flags = value.toString().split('/')[2];
+ const sourceLength = options.truncate - (2 + flags.length);
+ const source = value.source;
+ return options.stylize(`/${truncate(source, sourceLength)}/${flags}`, 'regexp');
+}
+
+// IE11 doesn't support `Array.from(set)`
+function arrayFromSet(set) {
+ const values = [];
+ set.forEach(value => {
+ values.push(value);
+ });
+ return values;
+}
+function inspectSet(set, options) {
+ if (set.size === 0)
+ return 'Set{}';
+ options.truncate -= 7;
+ return `Set{ ${inspectList(arrayFromSet(set), options)} }`;
+}
+
+const stringEscapeChars = new RegExp("['\\u0000-\\u001f\\u007f-\\u009f\\u00ad\\u0600-\\u0604\\u070f\\u17b4\\u17b5" +
+ '\\u200c-\\u200f\\u2028-\\u202f\\u2060-\\u206f\\ufeff\\ufff0-\\uffff]', 'g');
+const escapeCharacters = {
+ '\b': '\\b',
+ '\t': '\\t',
+ '\n': '\\n',
+ '\f': '\\f',
+ '\r': '\\r',
+ "'": "\\'",
+ '\\': '\\\\',
+};
+const hex = 16;
+function escape(char) {
+ return (escapeCharacters[char] ||
+ `\\u${`0000${char.charCodeAt(0).toString(hex)}`.slice(-4)}`);
+}
+function inspectString(string, options) {
+ if (stringEscapeChars.test(string)) {
+ string = string.replace(stringEscapeChars, escape);
+ }
+ return options.stylize(`'${truncate(string, options.truncate - 2)}'`, 'string');
+}
+
+function inspectSymbol(value) {
+ if ('description' in Symbol.prototype) {
+ return value.description ? `Symbol(${value.description})` : 'Symbol()';
+ }
+ return value.toString();
+}
+
+const getPromiseValue = () => 'Promise{…}';
+
+function inspectObject$1(object, options) {
+ const properties = Object.getOwnPropertyNames(object);
+ const symbols = Object.getOwnPropertySymbols ? Object.getOwnPropertySymbols(object) : [];
+ if (properties.length === 0 && symbols.length === 0) {
+ return '{}';
+ }
+ options.truncate -= 4;
+ options.seen = options.seen || [];
+ if (options.seen.includes(object)) {
+ return '[Circular]';
+ }
+ options.seen.push(object);
+ const propertyContents = inspectList(properties.map(key => [key, object[key]]), options, inspectProperty);
+ const symbolContents = inspectList(symbols.map(key => [key, object[key]]), options, inspectProperty);
+ options.seen.pop();
+ let sep = '';
+ if (propertyContents && symbolContents) {
+ sep = ', ';
+ }
+ return `{ ${propertyContents}${sep}${symbolContents} }`;
+}
+
+const toStringTag = typeof Symbol !== 'undefined' && Symbol.toStringTag ? Symbol.toStringTag : false;
+function inspectClass(value, options) {
+ let name = '';
+ if (toStringTag && toStringTag in value) {
+ name = value[toStringTag];
+ }
+ name = name || value.constructor.name;
+ // Babel transforms anonymous classes to the name `_class`
+ if (!name || name === '_class') {
+ name = '<Anonymous Class>';
+ }
+ options.truncate -= name.length;
+ return `${name}${inspectObject$1(value, options)}`;
+}
+
+function inspectArguments(args, options) {
+ if (args.length === 0)
+ return 'Arguments[]';
+ options.truncate -= 13;
+ return `Arguments[ ${inspectList(args, options)} ]`;
+}
+
+const errorKeys = [
+ 'stack',
+ 'line',
+ 'column',
+ 'name',
+ 'message',
+ 'fileName',
+ 'lineNumber',
+ 'columnNumber',
+ 'number',
+ 'description',
+ 'cause',
+];
+function inspectObject(error, options) {
+ const properties = Object.getOwnPropertyNames(error).filter(key => errorKeys.indexOf(key) === -1);
+ const name = error.name;
+ options.truncate -= name.length;
+ let message = '';
+ if (typeof error.message === 'string') {
+ message = truncate(error.message, options.truncate);
+ }
+ else {
+ properties.unshift('message');
+ }
+ message = message ? `: ${message}` : '';
+ options.truncate -= message.length + 5;
+ options.seen = options.seen || [];
+ if (options.seen.includes(error)) {
+ return '[Circular]';
+ }
+ options.seen.push(error);
+ const propertyContents = inspectList(properties.map(key => [key, error[key]]), options, inspectProperty);
+ return `${name}${message}${propertyContents ? ` { ${propertyContents} }` : ''}`;
+}
+
+function inspectAttribute([key, value], options) {
+ options.truncate -= 3;
+ if (!value) {
+ return `${options.stylize(String(key), 'yellow')}`;
+ }
+ return `${options.stylize(String(key), 'yellow')}=${options.stylize(`"${value}"`, 'string')}`;
+}
+function inspectNodeCollection(collection, options) {
+ return inspectList(collection, options, inspectNode, '\n');
+}
+function inspectNode(node, options) {
+ switch (node.nodeType) {
+ case 1:
+ return inspectHTML(node, options);
+ case 3:
+ return options.inspect(node.data, options);
+ default:
+ return options.inspect(node, options);
+ }
+}
+// @ts-ignore (Deno doesn't have Element)
+function inspectHTML(element, options) {
+ const properties = element.getAttributeNames();
+ const name = element.tagName.toLowerCase();
+ const head = options.stylize(`<${name}`, 'special');
+ const headClose = options.stylize(`>`, 'special');
+ const tail = options.stylize(`</${name}>`, 'special');
+ options.truncate -= name.length * 2 + 5;
+ let propertyContents = '';
+ if (properties.length > 0) {
+ propertyContents += ' ';
+ propertyContents += inspectList(properties.map((key) => [key, element.getAttribute(key)]), options, inspectAttribute, ' ');
+ }
+ options.truncate -= propertyContents.length;
+ const truncate = options.truncate;
+ let children = inspectNodeCollection(element.children, options);
+ if (children && children.length > truncate) {
+ children = `${truncator}(${element.children.length})`;
+ }
+ return `${head}${propertyContents}${headClose}${children}${tail}`;
+}
+
+/* !
+ * loupe
+ * Copyright(c) 2013 Jake Luer <jake@alogicalparadox.com>
+ * MIT Licensed
+ */
+const symbolsSupported = typeof Symbol === 'function' && typeof Symbol.for === 'function';
+const chaiInspect = symbolsSupported ? Symbol.for('chai/inspect') : '@@chai/inspect';
+const nodeInspect = Symbol.for('nodejs.util.inspect.custom');
+const constructorMap = new WeakMap();
+const stringTagMap = {};
+const baseTypesMap = {
+ undefined: (value, options) => options.stylize('undefined', 'undefined'),
+ null: (value, options) => options.stylize('null', 'null'),
+ boolean: (value, options) => options.stylize(String(value), 'boolean'),
+ Boolean: (value, options) => options.stylize(String(value), 'boolean'),
+ number: inspectNumber,
+ Number: inspectNumber,
+ bigint: inspectBigInt,
+ BigInt: inspectBigInt,
+ string: inspectString,
+ String: inspectString,
+ function: inspectFunction,
+ Function: inspectFunction,
+ symbol: inspectSymbol,
+ // A Symbol polyfill will return `Symbol` not `symbol` from typedetect
+ Symbol: inspectSymbol,
+ Array: inspectArray,
+ Date: inspectDate,
+ Map: inspectMap,
+ Set: inspectSet,
+ RegExp: inspectRegExp,
+ Promise: getPromiseValue,
+ // WeakSet, WeakMap are totally opaque to us
+ WeakSet: (value, options) => options.stylize('WeakSet{…}', 'special'),
+ WeakMap: (value, options) => options.stylize('WeakMap{…}', 'special'),
+ Arguments: inspectArguments,
+ Int8Array: inspectTypedArray,
+ Uint8Array: inspectTypedArray,
+ Uint8ClampedArray: inspectTypedArray,
+ Int16Array: inspectTypedArray,
+ Uint16Array: inspectTypedArray,
+ Int32Array: inspectTypedArray,
+ Uint32Array: inspectTypedArray,
+ Float32Array: inspectTypedArray,
+ Float64Array: inspectTypedArray,
+ Generator: () => '',
+ DataView: () => '',
+ ArrayBuffer: () => '',
+ Error: inspectObject,
+ HTMLCollection: inspectNodeCollection,
+ NodeList: inspectNodeCollection,
+};
+// eslint-disable-next-line complexity
+const inspectCustom = (value, options, type, inspectFn) => {
+ if (chaiInspect in value && typeof value[chaiInspect] === 'function') {
+ return value[chaiInspect](options);
+ }
+ if (nodeInspect in value && typeof value[nodeInspect] === 'function') {
+ return value[nodeInspect](options.depth, options, inspectFn);
+ }
+ if ('inspect' in value && typeof value.inspect === 'function') {
+ return value.inspect(options.depth, options);
+ }
+ if ('constructor' in value && constructorMap.has(value.constructor)) {
+ return constructorMap.get(value.constructor)(value, options);
+ }
+ if (stringTagMap[type]) {
+ return stringTagMap[type](value, options);
+ }
+ return '';
+};
+const toString = Object.prototype.toString;
+// eslint-disable-next-line complexity
+function inspect$1(value, opts = {}) {
+ const options = normaliseOptions(opts, inspect$1);
+ const { customInspect } = options;
+ let type = value === null ? 'null' : typeof value;
+ if (type === 'object') {
+ type = toString.call(value).slice(8, -1);
+ }
+ // If it is a base value that we already support, then use Loupe's inspector
+ if (type in baseTypesMap) {
+ return baseTypesMap[type](value, options);
+ }
+ // If `options.customInspect` is set to true then try to use the custom inspector
+ if (customInspect && value) {
+ const output = inspectCustom(value, options, type, inspect$1);
+ if (output) {
+ if (typeof output === 'string')
+ return output;
+ return inspect$1(output, options);
+ }
+ }
+ const proto = value ? Object.getPrototypeOf(value) : false;
+ // If it's a plain Object then use Loupe's inspector
+ if (proto === Object.prototype || proto === null) {
+ return inspectObject$1(value, options);
+ }
+ // Specifically account for HTMLElements
+ // @ts-ignore
+ if (value && typeof HTMLElement === 'function' && value instanceof HTMLElement) {
+ return inspectHTML(value, options);
+ }
+ if ('constructor' in value) {
+ // If it is a class, inspect it like an object but add the constructor name
+ if (value.constructor !== Object) {
+ return inspectClass(value, options);
+ }
+ // If it is an object with an anonymous prototype, display it as an object.
+ return inspectObject$1(value, options);
+ }
+ // last chance to check if it's an object
+ if (value === Object(value)) {
+ return inspectObject$1(value, options);
+ }
+ // We have run out of options! Just stringify the value
+ return options.stylize(String(value), type);
+}
+
+const { AsymmetricMatcher, DOMCollection, DOMElement, Immutable, ReactElement, ReactTestComponent } = plugins;
+const PLUGINS = [
+ ReactTestComponent,
+ ReactElement,
+ DOMElement,
+ DOMCollection,
+ Immutable,
+ AsymmetricMatcher
+];
+function stringify(object, maxDepth = 10, { maxLength, ...options } = {}) {
+ const MAX_LENGTH = maxLength ?? 1e4;
+ let result;
+ try {
+ result = format$1(object, {
+ maxDepth,
+ escapeString: false,
+ plugins: PLUGINS,
+ ...options
+ });
+ } catch {
+ result = format$1(object, {
+ callToJSON: false,
+ maxDepth,
+ escapeString: false,
+ plugins: PLUGINS,
+ ...options
+ });
+ }
+ // Prevents infinite loop https://github.com/vitest-dev/vitest/issues/7249
+ return result.length >= MAX_LENGTH && maxDepth > 1 ? stringify(object, Math.floor(Math.min(maxDepth, Number.MAX_SAFE_INTEGER) / 2), {
+ maxLength,
+ ...options
+ }) : result;
+}
+const formatRegExp = /%[sdjifoOc%]/g;
+function baseFormat(args, options = {}) {
+ const formatArg = (item, inspecOptions) => {
+ if (options.prettifyObject) {
+ return stringify(item, undefined, {
+ printBasicPrototype: false,
+ escapeString: false
+ });
+ }
+ return inspect(item, inspecOptions);
+ };
+ if (typeof args[0] !== "string") {
+ const objects = [];
+ for (let i = 0; i < args.length; i++) {
+ objects.push(formatArg(args[i], {
+ depth: 0,
+ colors: false
+ }));
+ }
+ return objects.join(" ");
+ }
+ const len = args.length;
+ let i = 1;
+ const template = args[0];
+ let str = String(template).replace(formatRegExp, (x) => {
+ if (x === "%%") {
+ return "%";
+ }
+ if (i >= len) {
+ return x;
+ }
+ switch (x) {
+ case "%s": {
+ const value = args[i++];
+ if (typeof value === "bigint") {
+ return `${value.toString()}n`;
+ }
+ if (typeof value === "number" && value === 0 && 1 / value < 0) {
+ return "-0";
+ }
+ if (typeof value === "object" && value !== null) {
+ if (typeof value.toString === "function" && value.toString !== Object.prototype.toString) {
+ return value.toString();
+ }
+ return formatArg(value, {
+ depth: 0,
+ colors: false
+ });
+ }
+ return String(value);
+ }
+ case "%d": {
+ const value = args[i++];
+ if (typeof value === "bigint") {
+ return `${value.toString()}n`;
+ }
+ return Number(value).toString();
+ }
+ case "%i": {
+ const value = args[i++];
+ if (typeof value === "bigint") {
+ return `${value.toString()}n`;
+ }
+ return Number.parseInt(String(value)).toString();
+ }
+ case "%f": return Number.parseFloat(String(args[i++])).toString();
+ case "%o": return formatArg(args[i++], {
+ showHidden: true,
+ showProxy: true
+ });
+ case "%O": return formatArg(args[i++]);
+ case "%c": {
+ i++;
+ return "";
+ }
+ case "%j": try {
+ return JSON.stringify(args[i++]);
+ } catch (err) {
+ const m = err.message;
+ if (m.includes("circular structure") || m.includes("cyclic structures") || m.includes("cyclic object")) {
+ return "[Circular]";
+ }
+ throw err;
+ }
+ default: return x;
+ }
+ });
+ for (let x = args[i]; i < len; x = args[++i]) {
+ if (x === null || typeof x !== "object") {
+ str += ` ${x}`;
+ } else {
+ str += ` ${formatArg(x)}`;
+ }
+ }
+ return str;
+}
+function format(...args) {
+ return baseFormat(args);
+}
+function browserFormat(...args) {
+ return baseFormat(args, { prettifyObject: true });
+}
+function inspect(obj, options = {}) {
+ if (options.truncate === 0) {
+ options.truncate = Number.POSITIVE_INFINITY;
+ }
+ return inspect$1(obj, options);
+}
+function objDisplay(obj, options = {}) {
+ if (typeof options.truncate === "undefined") {
+ options.truncate = 40;
+ }
+ const str = inspect(obj, options);
+ const type = Object.prototype.toString.call(obj);
+ if (options.truncate && str.length >= options.truncate) {
+ if (type === "[object Function]") {
+ const fn = obj;
+ return !fn.name ? "[Function]" : `[Function: ${fn.name}]`;
+ } else if (type === "[object Array]") {
+ return `[ Array(${obj.length}) ]`;
+ } else if (type === "[object Object]") {
+ const keys = Object.keys(obj);
+ const kstr = keys.length > 2 ? `${keys.splice(0, 2).join(", ")}, ...` : keys.join(", ");
+ return `{ Object (${kstr}) }`;
+ } else {
+ return str;
+ }
+ }
+ return str;
+}
+
+export { browserFormat, format, formatRegExp, inspect, objDisplay, stringify };
diff --git a/vanilla/node_modules/@vitest/utils/dist/error.d.ts b/vanilla/node_modules/@vitest/utils/dist/error.d.ts
new file mode 100644
index 0000000..ad5d628
--- /dev/null
+++ b/vanilla/node_modules/@vitest/utils/dist/error.d.ts
@@ -0,0 +1,7 @@
+import { D as DiffOptions } from './types.d-BCElaP-c.js';
+export { serializeValue as serializeError } from './serialize.js';
+import '@vitest/pretty-format';
+
+declare function processError(_err: any, diffOptions?: DiffOptions, seen?: WeakSet<WeakKey>): any;
+
+export { processError };
diff --git a/vanilla/node_modules/@vitest/utils/dist/error.js b/vanilla/node_modules/@vitest/utils/dist/error.js
new file mode 100644
index 0000000..14886d0
--- /dev/null
+++ b/vanilla/node_modules/@vitest/utils/dist/error.js
@@ -0,0 +1,42 @@
+import { printDiffOrStringify } from './diff.js';
+import { stringify } from './display.js';
+import { serializeValue } from './serialize.js';
+import '@vitest/pretty-format';
+import 'tinyrainbow';
+import './helpers.js';
+import './constants.js';
+import './chunk-_commonjsHelpers.js';
+
+function processError(_err, diffOptions, seen = new WeakSet()) {
+ if (!_err || typeof _err !== "object") {
+ return { message: String(_err) };
+ }
+ const err = _err;
+ if (err.showDiff || err.showDiff === undefined && err.expected !== undefined && err.actual !== undefined) {
+ err.diff = printDiffOrStringify(err.actual, err.expected, {
+ ...diffOptions,
+ ...err.diffOptions
+ });
+ }
+ if ("expected" in err && typeof err.expected !== "string") {
+ err.expected = stringify(err.expected, 10);
+ }
+ if ("actual" in err && typeof err.actual !== "string") {
+ err.actual = stringify(err.actual, 10);
+ }
+ // some Error implementations may not allow rewriting cause
+ // in most cases, the assignment will lead to "err.cause = err.cause"
+ try {
+ if (!seen.has(err) && typeof err.cause === "object") {
+ seen.add(err);
+ err.cause = processError(err.cause, diffOptions, seen);
+ }
+ } catch {}
+ try {
+ return serializeValue(err);
+ } catch (e) {
+ return serializeValue(new Error(`Failed to fully serialize error: ${e === null || e === void 0 ? void 0 : e.message}\nInner error message: ${err === null || err === void 0 ? void 0 : err.message}`));
+ }
+}
+
+export { processError, serializeValue as serializeError };
diff --git a/vanilla/node_modules/@vitest/utils/dist/helpers.d.ts b/vanilla/node_modules/@vitest/utils/dist/helpers.d.ts
new file mode 100644
index 0000000..493817b
--- /dev/null
+++ b/vanilla/node_modules/@vitest/utils/dist/helpers.d.ts
@@ -0,0 +1,73 @@
+import { Nullable, Arrayable } from './types.js';
+
+declare function nanoid(size?: number): string;
+
+declare function shuffle<T>(array: T[], seed?: number): T[];
+
+interface CloneOptions {
+ forceWritable?: boolean;
+}
+interface ErrorOptions {
+ message?: string;
+ stackTraceLimit?: number;
+}
+
+/**
+* Get original stacktrace without source map support the most performant way.
+* - Create only 1 stack frame.
+* - Rewrite prepareStackTrace to bypass "support-stack-trace" (usually takes ~250ms).
+*/
+declare function createSimpleStackTrace(options?: ErrorOptions): string;
+declare function notNullish<T>(v: T | null | undefined): v is NonNullable<T>;
+declare function assertTypes(value: unknown, name: string, types: string[]): void;
+declare function isPrimitive(value: unknown): boolean;
+declare function slash(path: string): string;
+declare function cleanUrl(url: string): string;
+declare const isExternalUrl: (url: string) => boolean;
+/**
+* Prepend `/@id/` and replace null byte so the id is URL-safe.
+* This is prepended to resolved ids that are not valid browser
+* import specifiers by the importAnalysis plugin.
+*/
+declare function wrapId(id: string): string;
+/**
+* Undo {@link wrapId}'s `/@id/` and null byte replacements.
+*/
+declare function unwrapId(id: string): string;
+declare function withTrailingSlash(path: string): string;
+declare function isBareImport(id: string): boolean;
+declare function toArray<T>(array?: Nullable<Arrayable<T>>): Array<T>;
+declare function isObject(item: unknown): boolean;
+declare function getType(value: unknown): string;
+declare function getOwnProperties(obj: any): (string | symbol)[];
+declare function deepClone<T>(val: T, options?: CloneOptions): T;
+declare function clone<T>(val: T, seen: WeakMap<any, any>, options?: CloneOptions): T;
+declare function noop(): void;
+declare function objectAttr(source: any, path: string, defaultValue?: undefined): any;
+type DeferPromise<T> = Promise<T> & {
+ resolve: (value: T | PromiseLike<T>) => void;
+ reject: (reason?: any) => void;
+};
+declare function createDefer<T>(): DeferPromise<T>;
+/**
+* If code starts with a function call, will return its last index, respecting arguments.
+* This will return 25 - last ending character of toMatch ")"
+* Also works with callbacks
+* ```
+* toMatch({ test: '123' });
+* toBeAliased('123')
+* ```
+*/
+declare function getCallLastIndex(code: string): number | null;
+declare function isNegativeNaN(val: number): boolean;
+/**
+* Deep merge :P
+*
+* Will merge objects only if they are plain
+*
+* Do not merge types - it is very expensive and usually it's better to case a type here
+*/
+declare function deepMerge<T extends object = object>(target: T, ...sources: any[]): T;
+
+export { assertTypes, cleanUrl, clone, createDefer, createSimpleStackTrace, deepClone, deepMerge, getCallLastIndex, getOwnProperties, getType, isBareImport, isExternalUrl, isNegativeNaN, isObject, isPrimitive, nanoid, noop, notNullish, objectAttr, shuffle, slash, toArray, unwrapId, withTrailingSlash, wrapId };
+export type { DeferPromise };
diff --git a/vanilla/node_modules/@vitest/utils/dist/helpers.js b/vanilla/node_modules/@vitest/utils/dist/helpers.js
new file mode 100644
index 0000000..b19970a
--- /dev/null
+++ b/vanilla/node_modules/@vitest/utils/dist/helpers.js
@@ -0,0 +1,295 @@
+import { VALID_ID_PREFIX, NULL_BYTE_PLACEHOLDER } from './constants.js';
+
+// port from nanoid
+// https://github.com/ai/nanoid
+const urlAlphabet = "useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict";
+function nanoid(size = 21) {
+ let id = "";
+ let i = size;
+ while (i--) {
+ id += urlAlphabet[Math.random() * 64 | 0];
+ }
+ return id;
+}
+
+const RealDate = Date;
+function random(seed) {
+ const x = Math.sin(seed++) * 1e4;
+ return x - Math.floor(x);
+}
+function shuffle(array, seed = RealDate.now()) {
+ let length = array.length;
+ while (length) {
+ const index = Math.floor(random(seed) * length--);
+ const previous = array[length];
+ array[length] = array[index];
+ array[index] = previous;
+ ++seed;
+ }
+ return array;
+}
+
+/**
+* Get original stacktrace without source map support the most performant way.
+* - Create only 1 stack frame.
+* - Rewrite prepareStackTrace to bypass "support-stack-trace" (usually takes ~250ms).
+*/
+function createSimpleStackTrace(options) {
+ const { message = "$$stack trace error", stackTraceLimit = 1 } = options || {};
+ const limit = Error.stackTraceLimit;
+ const prepareStackTrace = Error.prepareStackTrace;
+ Error.stackTraceLimit = stackTraceLimit;
+ Error.prepareStackTrace = (e) => e.stack;
+ const err = new Error(message);
+ const stackTrace = err.stack || "";
+ Error.prepareStackTrace = prepareStackTrace;
+ Error.stackTraceLimit = limit;
+ return stackTrace;
+}
+function notNullish(v) {
+ return v != null;
+}
+function assertTypes(value, name, types) {
+ const receivedType = typeof value;
+ const pass = types.includes(receivedType);
+ if (!pass) {
+ throw new TypeError(`${name} value must be ${types.join(" or ")}, received "${receivedType}"`);
+ }
+}
+function isPrimitive(value) {
+ return value === null || typeof value !== "function" && typeof value !== "object";
+}
+function slash(path) {
+ return path.replace(/\\/g, "/");
+}
+const postfixRE = /[?#].*$/;
+function cleanUrl(url) {
+ return url.replace(postfixRE, "");
+}
+const externalRE = /^(?:[a-z]+:)?\/\//;
+const isExternalUrl = (url) => externalRE.test(url);
+/**
+* Prepend `/@id/` and replace null byte so the id is URL-safe.
+* This is prepended to resolved ids that are not valid browser
+* import specifiers by the importAnalysis plugin.
+*/
+function wrapId(id) {
+ return id.startsWith(VALID_ID_PREFIX) ? id : VALID_ID_PREFIX + id.replace("\0", NULL_BYTE_PLACEHOLDER);
+}
+/**
+* Undo {@link wrapId}'s `/@id/` and null byte replacements.
+*/
+function unwrapId(id) {
+ return id.startsWith(VALID_ID_PREFIX) ? id.slice(VALID_ID_PREFIX.length).replace(NULL_BYTE_PLACEHOLDER, "\0") : id;
+}
+function withTrailingSlash(path) {
+ if (path.at(-1) !== "/") {
+ return `${path}/`;
+ }
+ return path;
+}
+const bareImportRE = /^(?![a-z]:)[\w@](?!.*:\/\/)/i;
+function isBareImport(id) {
+ return bareImportRE.test(id);
+}
+function toArray(array) {
+ if (array === null || array === undefined) {
+ array = [];
+ }
+ if (Array.isArray(array)) {
+ return array;
+ }
+ return [array];
+}
+function isObject(item) {
+ return item != null && typeof item === "object" && !Array.isArray(item);
+}
+function isFinalObj(obj) {
+ return obj === Object.prototype || obj === Function.prototype || obj === RegExp.prototype;
+}
+function getType(value) {
+ return Object.prototype.toString.apply(value).slice(8, -1);
+}
+function collectOwnProperties(obj, collector) {
+ const collect = typeof collector === "function" ? collector : (key) => collector.add(key);
+ Object.getOwnPropertyNames(obj).forEach(collect);
+ Object.getOwnPropertySymbols(obj).forEach(collect);
+}
+function getOwnProperties(obj) {
+ const ownProps = new Set();
+ if (isFinalObj(obj)) {
+ return [];
+ }
+ collectOwnProperties(obj, ownProps);
+ return Array.from(ownProps);
+}
+const defaultCloneOptions = { forceWritable: false };
+function deepClone(val, options = defaultCloneOptions) {
+ const seen = new WeakMap();
+ return clone(val, seen, options);
+}
+function clone(val, seen, options = defaultCloneOptions) {
+ let k, out;
+ if (seen.has(val)) {
+ return seen.get(val);
+ }
+ if (Array.isArray(val)) {
+ out = Array.from({ length: k = val.length });
+ seen.set(val, out);
+ while (k--) {
+ out[k] = clone(val[k], seen, options);
+ }
+ return out;
+ }
+ if (Object.prototype.toString.call(val) === "[object Object]") {
+ out = Object.create(Object.getPrototypeOf(val));
+ seen.set(val, out);
+ // we don't need properties from prototype
+ const props = getOwnProperties(val);
+ for (const k of props) {
+ const descriptor = Object.getOwnPropertyDescriptor(val, k);
+ if (!descriptor) {
+ continue;
+ }
+ const cloned = clone(val[k], seen, options);
+ if (options.forceWritable) {
+ Object.defineProperty(out, k, {
+ enumerable: descriptor.enumerable,
+ configurable: true,
+ writable: true,
+ value: cloned
+ });
+ } else if ("get" in descriptor) {
+ Object.defineProperty(out, k, {
+ ...descriptor,
+ get() {
+ return cloned;
+ }
+ });
+ } else {
+ Object.defineProperty(out, k, {
+ ...descriptor,
+ value: cloned
+ });
+ }
+ }
+ return out;
+ }
+ return val;
+}
+function noop() {}
+function objectAttr(source, path, defaultValue = undefined) {
+ // a[3].b -> a.3.b
+ const paths = path.replace(/\[(\d+)\]/g, ".$1").split(".");
+ let result = source;
+ for (const p of paths) {
+ result = new Object(result)[p];
+ if (result === undefined) {
+ return defaultValue;
+ }
+ }
+ return result;
+}
+function createDefer() {
+ let resolve = null;
+ let reject = null;
+ const p = new Promise((_resolve, _reject) => {
+ resolve = _resolve;
+ reject = _reject;
+ });
+ p.resolve = resolve;
+ p.reject = reject;
+ return p;
+}
+/**
+* If code starts with a function call, will return its last index, respecting arguments.
+* This will return 25 - last ending character of toMatch ")"
+* Also works with callbacks
+* ```
+* toMatch({ test: '123' });
+* toBeAliased('123')
+* ```
+*/
+function getCallLastIndex(code) {
+ let charIndex = -1;
+ let inString = null;
+ let startedBracers = 0;
+ let endedBracers = 0;
+ let beforeChar = null;
+ while (charIndex <= code.length) {
+ beforeChar = code[charIndex];
+ charIndex++;
+ const char = code[charIndex];
+ const isCharString = char === "\"" || char === "'" || char === "`";
+ if (isCharString && beforeChar !== "\\") {
+ if (inString === char) {
+ inString = null;
+ } else if (!inString) {
+ inString = char;
+ }
+ }
+ if (!inString) {
+ if (char === "(") {
+ startedBracers++;
+ }
+ if (char === ")") {
+ endedBracers++;
+ }
+ }
+ if (startedBracers && endedBracers && startedBracers === endedBracers) {
+ return charIndex;
+ }
+ }
+ return null;
+}
+function isNegativeNaN(val) {
+ if (!Number.isNaN(val)) {
+ return false;
+ }
+ const f64 = new Float64Array(1);
+ f64[0] = val;
+ const u32 = new Uint32Array(f64.buffer);
+ const isNegative = u32[1] >>> 31 === 1;
+ return isNegative;
+}
+function toString(v) {
+ return Object.prototype.toString.call(v);
+}
+function isPlainObject(val) {
+ return toString(val) === "[object Object]" && (!val.constructor || val.constructor.name === "Object");
+}
+function isMergeableObject(item) {
+ return isPlainObject(item) && !Array.isArray(item);
+}
+/**
+* Deep merge :P
+*
+* Will merge objects only if they are plain
+*
+* Do not merge types - it is very expensive and usually it's better to case a type here
+*/
+function deepMerge(target, ...sources) {
+ if (!sources.length) {
+ return target;
+ }
+ const source = sources.shift();
+ if (source === undefined) {
+ return target;
+ }
+ if (isMergeableObject(target) && isMergeableObject(source)) {
+ Object.keys(source).forEach((key) => {
+ const _source = source;
+ if (isMergeableObject(_source[key])) {
+ if (!target[key]) {
+ target[key] = {};
+ }
+ deepMerge(target[key], _source[key]);
+ } else {
+ target[key] = _source[key];
+ }
+ });
+ }
+ return deepMerge(target, ...sources);
+}
+
+export { assertTypes, cleanUrl, clone, createDefer, createSimpleStackTrace, deepClone, deepMerge, getCallLastIndex, getOwnProperties, getType, isBareImport, isExternalUrl, isNegativeNaN, isObject, isPrimitive, nanoid, noop, notNullish, objectAttr, shuffle, slash, toArray, unwrapId, withTrailingSlash, wrapId };
diff --git a/vanilla/node_modules/@vitest/utils/dist/highlight.d.ts b/vanilla/node_modules/@vitest/utils/dist/highlight.d.ts
new file mode 100644
index 0000000..b3420de
--- /dev/null
+++ b/vanilla/node_modules/@vitest/utils/dist/highlight.d.ts
@@ -0,0 +1,9 @@
+import { Colors } from 'tinyrainbow';
+
+interface HighlightOptions {
+ jsx?: boolean;
+ colors?: Colors;
+}
+declare function highlight(code: string, options?: HighlightOptions): string;
+
+export { highlight };
diff --git a/vanilla/node_modules/@vitest/utils/dist/highlight.js b/vanilla/node_modules/@vitest/utils/dist/highlight.js
new file mode 100644
index 0000000..1250062
--- /dev/null
+++ b/vanilla/node_modules/@vitest/utils/dist/highlight.js
@@ -0,0 +1,538 @@
+import { g as getDefaultExportFromCjs } from './chunk-_commonjsHelpers.js';
+import c from 'tinyrainbow';
+
+var jsTokens_1;
+var hasRequiredJsTokens;
+
+function requireJsTokens () {
+ if (hasRequiredJsTokens) return jsTokens_1;
+ hasRequiredJsTokens = 1;
+ // Copyright 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023 Simon Lydell
+ // License: MIT.
+ var Identifier, JSXIdentifier, JSXPunctuator, JSXString, JSXText, KeywordsWithExpressionAfter, KeywordsWithNoLineTerminatorAfter, LineTerminatorSequence, MultiLineComment, Newline, NumericLiteral, Punctuator, RegularExpressionLiteral, SingleLineComment, StringLiteral, Template, TokensNotPrecedingObjectLiteral, TokensPrecedingExpression, WhiteSpace;
+ RegularExpressionLiteral = /\/(?![*\/])(?:\[(?:(?![\]\\]).|\\.)*\]|(?![\/\\]).|\\.)*(\/[$_\u200C\u200D\p{ID_Continue}]*|\\)?/yu;
+ Punctuator = /--|\+\+|=>|\.{3}|\??\.(?!\d)|(?:&&|\|\||\?\?|[+\-%&|^]|\*{1,2}|<{1,2}|>{1,3}|!=?|={1,2}|\/(?![\/*]))=?|[?~,:;[\](){}]/y;
+ Identifier = /(\x23?)(?=[$_\p{ID_Start}\\])(?:[$_\u200C\u200D\p{ID_Continue}]|\\u[\da-fA-F]{4}|\\u\{[\da-fA-F]+\})+/yu;
+ StringLiteral = /(['"])(?:(?!\1)[^\\\n\r]|\\(?:\r\n|[^]))*(\1)?/y;
+ NumericLiteral = /(?:0[xX][\da-fA-F](?:_?[\da-fA-F])*|0[oO][0-7](?:_?[0-7])*|0[bB][01](?:_?[01])*)n?|0n|[1-9](?:_?\d)*n|(?:(?:0(?!\d)|0\d*[89]\d*|[1-9](?:_?\d)*)(?:\.(?:\d(?:_?\d)*)?)?|\.\d(?:_?\d)*)(?:[eE][+-]?\d(?:_?\d)*)?|0[0-7]+/y;
+ Template = /[`}](?:[^`\\$]|\\[^]|\$(?!\{))*(`|\$\{)?/y;
+ WhiteSpace = /[\t\v\f\ufeff\p{Zs}]+/yu;
+ LineTerminatorSequence = /\r?\n|[\r\u2028\u2029]/y;
+ MultiLineComment = /\/\*(?:[^*]|\*(?!\/))*(\*\/)?/y;
+ SingleLineComment = /\/\/.*/y;
+ JSXPunctuator = /[<>.:={}]|\/(?![\/*])/y;
+ JSXIdentifier = /[$_\p{ID_Start}][$_\u200C\u200D\p{ID_Continue}-]*/yu;
+ JSXString = /(['"])(?:(?!\1)[^])*(\1)?/y;
+ JSXText = /[^<>{}]+/y;
+ TokensPrecedingExpression = /^(?:[\/+-]|\.{3}|\?(?:InterpolationIn(?:JSX|Template)|NoLineTerminatorHere|NonExpressionParenEnd|UnaryIncDec))?$|[{}([,;<>=*%&|^!~?:]$/;
+ TokensNotPrecedingObjectLiteral = /^(?:=>|[;\]){}]|else|\?(?:NoLineTerminatorHere|NonExpressionParenEnd))?$/;
+ KeywordsWithExpressionAfter = /^(?:await|case|default|delete|do|else|instanceof|new|return|throw|typeof|void|yield)$/;
+ KeywordsWithNoLineTerminatorAfter = /^(?:return|throw|yield)$/;
+ Newline = RegExp(LineTerminatorSequence.source);
+ jsTokens_1 = function*(input, {jsx = false} = {}) {
+ var braces, firstCodePoint, isExpression, lastIndex, lastSignificantToken, length, match, mode, nextLastIndex, nextLastSignificantToken, parenNesting, postfixIncDec, punctuator, stack;
+ ({length} = input);
+ lastIndex = 0;
+ lastSignificantToken = "";
+ stack = [
+ {tag: "JS"}
+ ];
+ braces = [];
+ parenNesting = 0;
+ postfixIncDec = false;
+ while (lastIndex < length) {
+ mode = stack[stack.length - 1];
+ switch (mode.tag) {
+ case "JS":
+ case "JSNonExpressionParen":
+ case "InterpolationInTemplate":
+ case "InterpolationInJSX":
+ if (input[lastIndex] === "/" && (TokensPrecedingExpression.test(lastSignificantToken) || KeywordsWithExpressionAfter.test(lastSignificantToken))) {
+ RegularExpressionLiteral.lastIndex = lastIndex;
+ if (match = RegularExpressionLiteral.exec(input)) {
+ lastIndex = RegularExpressionLiteral.lastIndex;
+ lastSignificantToken = match[0];
+ postfixIncDec = true;
+ yield ({
+ type: "RegularExpressionLiteral",
+ value: match[0],
+ closed: match[1] !== void 0 && match[1] !== "\\"
+ });
+ continue;
+ }
+ }
+ Punctuator.lastIndex = lastIndex;
+ if (match = Punctuator.exec(input)) {
+ punctuator = match[0];
+ nextLastIndex = Punctuator.lastIndex;
+ nextLastSignificantToken = punctuator;
+ switch (punctuator) {
+ case "(":
+ if (lastSignificantToken === "?NonExpressionParenKeyword") {
+ stack.push({
+ tag: "JSNonExpressionParen",
+ nesting: parenNesting
+ });
+ }
+ parenNesting++;
+ postfixIncDec = false;
+ break;
+ case ")":
+ parenNesting--;
+ postfixIncDec = true;
+ if (mode.tag === "JSNonExpressionParen" && parenNesting === mode.nesting) {
+ stack.pop();
+ nextLastSignificantToken = "?NonExpressionParenEnd";
+ postfixIncDec = false;
+ }
+ break;
+ case "{":
+ Punctuator.lastIndex = 0;
+ isExpression = !TokensNotPrecedingObjectLiteral.test(lastSignificantToken) && (TokensPrecedingExpression.test(lastSignificantToken) || KeywordsWithExpressionAfter.test(lastSignificantToken));
+ braces.push(isExpression);
+ postfixIncDec = false;
+ break;
+ case "}":
+ switch (mode.tag) {
+ case "InterpolationInTemplate":
+ if (braces.length === mode.nesting) {
+ Template.lastIndex = lastIndex;
+ match = Template.exec(input);
+ lastIndex = Template.lastIndex;
+ lastSignificantToken = match[0];
+ if (match[1] === "${") {
+ lastSignificantToken = "?InterpolationInTemplate";
+ postfixIncDec = false;
+ yield ({
+ type: "TemplateMiddle",
+ value: match[0]
+ });
+ } else {
+ stack.pop();
+ postfixIncDec = true;
+ yield ({
+ type: "TemplateTail",
+ value: match[0],
+ closed: match[1] === "`"
+ });
+ }
+ continue;
+ }
+ break;
+ case "InterpolationInJSX":
+ if (braces.length === mode.nesting) {
+ stack.pop();
+ lastIndex += 1;
+ lastSignificantToken = "}";
+ yield ({
+ type: "JSXPunctuator",
+ value: "}"
+ });
+ continue;
+ }
+ }
+ postfixIncDec = braces.pop();
+ nextLastSignificantToken = postfixIncDec ? "?ExpressionBraceEnd" : "}";
+ break;
+ case "]":
+ postfixIncDec = true;
+ break;
+ case "++":
+ case "--":
+ nextLastSignificantToken = postfixIncDec ? "?PostfixIncDec" : "?UnaryIncDec";
+ break;
+ case "<":
+ if (jsx && (TokensPrecedingExpression.test(lastSignificantToken) || KeywordsWithExpressionAfter.test(lastSignificantToken))) {
+ stack.push({tag: "JSXTag"});
+ lastIndex += 1;
+ lastSignificantToken = "<";
+ yield ({
+ type: "JSXPunctuator",
+ value: punctuator
+ });
+ continue;
+ }
+ postfixIncDec = false;
+ break;
+ default:
+ postfixIncDec = false;
+ }
+ lastIndex = nextLastIndex;
+ lastSignificantToken = nextLastSignificantToken;
+ yield ({
+ type: "Punctuator",
+ value: punctuator
+ });
+ continue;
+ }
+ Identifier.lastIndex = lastIndex;
+ if (match = Identifier.exec(input)) {
+ lastIndex = Identifier.lastIndex;
+ nextLastSignificantToken = match[0];
+ switch (match[0]) {
+ case "for":
+ case "if":
+ case "while":
+ case "with":
+ if (lastSignificantToken !== "." && lastSignificantToken !== "?.") {
+ nextLastSignificantToken = "?NonExpressionParenKeyword";
+ }
+ }
+ lastSignificantToken = nextLastSignificantToken;
+ postfixIncDec = !KeywordsWithExpressionAfter.test(match[0]);
+ yield ({
+ type: match[1] === "#" ? "PrivateIdentifier" : "IdentifierName",
+ value: match[0]
+ });
+ continue;
+ }
+ StringLiteral.lastIndex = lastIndex;
+ if (match = StringLiteral.exec(input)) {
+ lastIndex = StringLiteral.lastIndex;
+ lastSignificantToken = match[0];
+ postfixIncDec = true;
+ yield ({
+ type: "StringLiteral",
+ value: match[0],
+ closed: match[2] !== void 0
+ });
+ continue;
+ }
+ NumericLiteral.lastIndex = lastIndex;
+ if (match = NumericLiteral.exec(input)) {
+ lastIndex = NumericLiteral.lastIndex;
+ lastSignificantToken = match[0];
+ postfixIncDec = true;
+ yield ({
+ type: "NumericLiteral",
+ value: match[0]
+ });
+ continue;
+ }
+ Template.lastIndex = lastIndex;
+ if (match = Template.exec(input)) {
+ lastIndex = Template.lastIndex;
+ lastSignificantToken = match[0];
+ if (match[1] === "${") {
+ lastSignificantToken = "?InterpolationInTemplate";
+ stack.push({
+ tag: "InterpolationInTemplate",
+ nesting: braces.length
+ });
+ postfixIncDec = false;
+ yield ({
+ type: "TemplateHead",
+ value: match[0]
+ });
+ } else {
+ postfixIncDec = true;
+ yield ({
+ type: "NoSubstitutionTemplate",
+ value: match[0],
+ closed: match[1] === "`"
+ });
+ }
+ continue;
+ }
+ break;
+ case "JSXTag":
+ case "JSXTagEnd":
+ JSXPunctuator.lastIndex = lastIndex;
+ if (match = JSXPunctuator.exec(input)) {
+ lastIndex = JSXPunctuator.lastIndex;
+ nextLastSignificantToken = match[0];
+ switch (match[0]) {
+ case "<":
+ stack.push({tag: "JSXTag"});
+ break;
+ case ">":
+ stack.pop();
+ if (lastSignificantToken === "/" || mode.tag === "JSXTagEnd") {
+ nextLastSignificantToken = "?JSX";
+ postfixIncDec = true;
+ } else {
+ stack.push({tag: "JSXChildren"});
+ }
+ break;
+ case "{":
+ stack.push({
+ tag: "InterpolationInJSX",
+ nesting: braces.length
+ });
+ nextLastSignificantToken = "?InterpolationInJSX";
+ postfixIncDec = false;
+ break;
+ case "/":
+ if (lastSignificantToken === "<") {
+ stack.pop();
+ if (stack[stack.length - 1].tag === "JSXChildren") {
+ stack.pop();
+ }
+ stack.push({tag: "JSXTagEnd"});
+ }
+ }
+ lastSignificantToken = nextLastSignificantToken;
+ yield ({
+ type: "JSXPunctuator",
+ value: match[0]
+ });
+ continue;
+ }
+ JSXIdentifier.lastIndex = lastIndex;
+ if (match = JSXIdentifier.exec(input)) {
+ lastIndex = JSXIdentifier.lastIndex;
+ lastSignificantToken = match[0];
+ yield ({
+ type: "JSXIdentifier",
+ value: match[0]
+ });
+ continue;
+ }
+ JSXString.lastIndex = lastIndex;
+ if (match = JSXString.exec(input)) {
+ lastIndex = JSXString.lastIndex;
+ lastSignificantToken = match[0];
+ yield ({
+ type: "JSXString",
+ value: match[0],
+ closed: match[2] !== void 0
+ });
+ continue;
+ }
+ break;
+ case "JSXChildren":
+ JSXText.lastIndex = lastIndex;
+ if (match = JSXText.exec(input)) {
+ lastIndex = JSXText.lastIndex;
+ lastSignificantToken = match[0];
+ yield ({
+ type: "JSXText",
+ value: match[0]
+ });
+ continue;
+ }
+ switch (input[lastIndex]) {
+ case "<":
+ stack.push({tag: "JSXTag"});
+ lastIndex++;
+ lastSignificantToken = "<";
+ yield ({
+ type: "JSXPunctuator",
+ value: "<"
+ });
+ continue;
+ case "{":
+ stack.push({
+ tag: "InterpolationInJSX",
+ nesting: braces.length
+ });
+ lastIndex++;
+ lastSignificantToken = "?InterpolationInJSX";
+ postfixIncDec = false;
+ yield ({
+ type: "JSXPunctuator",
+ value: "{"
+ });
+ continue;
+ }
+ }
+ WhiteSpace.lastIndex = lastIndex;
+ if (match = WhiteSpace.exec(input)) {
+ lastIndex = WhiteSpace.lastIndex;
+ yield ({
+ type: "WhiteSpace",
+ value: match[0]
+ });
+ continue;
+ }
+ LineTerminatorSequence.lastIndex = lastIndex;
+ if (match = LineTerminatorSequence.exec(input)) {
+ lastIndex = LineTerminatorSequence.lastIndex;
+ postfixIncDec = false;
+ if (KeywordsWithNoLineTerminatorAfter.test(lastSignificantToken)) {
+ lastSignificantToken = "?NoLineTerminatorHere";
+ }
+ yield ({
+ type: "LineTerminatorSequence",
+ value: match[0]
+ });
+ continue;
+ }
+ MultiLineComment.lastIndex = lastIndex;
+ if (match = MultiLineComment.exec(input)) {
+ lastIndex = MultiLineComment.lastIndex;
+ if (Newline.test(match[0])) {
+ postfixIncDec = false;
+ if (KeywordsWithNoLineTerminatorAfter.test(lastSignificantToken)) {
+ lastSignificantToken = "?NoLineTerminatorHere";
+ }
+ }
+ yield ({
+ type: "MultiLineComment",
+ value: match[0],
+ closed: match[1] !== void 0
+ });
+ continue;
+ }
+ SingleLineComment.lastIndex = lastIndex;
+ if (match = SingleLineComment.exec(input)) {
+ lastIndex = SingleLineComment.lastIndex;
+ postfixIncDec = false;
+ yield ({
+ type: "SingleLineComment",
+ value: match[0]
+ });
+ continue;
+ }
+ firstCodePoint = String.fromCodePoint(input.codePointAt(lastIndex));
+ lastIndex += firstCodePoint.length;
+ lastSignificantToken = firstCodePoint;
+ postfixIncDec = false;
+ yield ({
+ type: mode.tag.startsWith("JSX") ? "JSXInvalid" : "Invalid",
+ value: firstCodePoint
+ });
+ }
+ return void 0;
+ };
+ return jsTokens_1;
+}
+
+var jsTokensExports = /*@__PURE__*/ requireJsTokens();
+var jsTokens = /*@__PURE__*/getDefaultExportFromCjs(jsTokensExports);
+
+// src/index.ts
+var reservedWords = {
+ keyword: [
+ "break",
+ "case",
+ "catch",
+ "continue",
+ "debugger",
+ "default",
+ "do",
+ "else",
+ "finally",
+ "for",
+ "function",
+ "if",
+ "return",
+ "switch",
+ "throw",
+ "try",
+ "var",
+ "const",
+ "while",
+ "with",
+ "new",
+ "this",
+ "super",
+ "class",
+ "extends",
+ "export",
+ "import",
+ "null",
+ "true",
+ "false",
+ "in",
+ "instanceof",
+ "typeof",
+ "void",
+ "delete"
+ ],
+ strict: [
+ "implements",
+ "interface",
+ "let",
+ "package",
+ "private",
+ "protected",
+ "public",
+ "static",
+ "yield"
+ ]
+}, keywords = new Set(reservedWords.keyword), reservedWordsStrictSet = new Set(reservedWords.strict), sometimesKeywords = /* @__PURE__ */ new Set(["as", "async", "from", "get", "of", "set"]);
+function isReservedWord(word) {
+ return word === "await" || word === "enum";
+}
+function isStrictReservedWord(word) {
+ return isReservedWord(word) || reservedWordsStrictSet.has(word);
+}
+function isKeyword(word) {
+ return keywords.has(word);
+}
+var BRACKET = /^[()[\]{}]$/, getTokenType = function(token) {
+ if (token.type === "IdentifierName") {
+ if (isKeyword(token.value) || isStrictReservedWord(token.value) || sometimesKeywords.has(token.value))
+ return "Keyword";
+ if (token.value[0] && token.value[0] !== token.value[0].toLowerCase())
+ return "IdentifierCapitalized";
+ }
+ return token.type === "Punctuator" && BRACKET.test(token.value) ? "Bracket" : token.type === "Invalid" && (token.value === "@" || token.value === "#") ? "Punctuator" : token.type;
+};
+function getCallableType(token) {
+ if (token.type === "IdentifierName")
+ return "IdentifierCallable";
+ if (token.type === "PrivateIdentifier")
+ return "PrivateIdentifierCallable";
+ throw new Error("Not a callable token");
+}
+var colorize = (defs, type, value) => {
+ let colorize2 = defs[type];
+ return colorize2 ? colorize2(value) : value;
+}, highlightTokens = (defs, text, jsx) => {
+ let highlighted = "", lastPotentialCallable = null, stackedHighlight = "";
+ for (let token of jsTokens(text, { jsx })) {
+ let type = getTokenType(token);
+ if (type === "IdentifierName" || type === "PrivateIdentifier") {
+ lastPotentialCallable && (highlighted += colorize(defs, getTokenType(lastPotentialCallable), lastPotentialCallable.value) + stackedHighlight, stackedHighlight = ""), lastPotentialCallable = token;
+ continue;
+ }
+ if (lastPotentialCallable && (token.type === "WhiteSpace" || token.type === "LineTerminatorSequence" || token.type === "Punctuator" && (token.value === "?." || token.value === "!"))) {
+ stackedHighlight += colorize(defs, type, token.value);
+ continue;
+ }
+ if (stackedHighlight && !lastPotentialCallable && (highlighted += stackedHighlight, stackedHighlight = ""), lastPotentialCallable) {
+ let type2 = token.type === "Punctuator" && token.value === "(" ? getCallableType(lastPotentialCallable) : getTokenType(lastPotentialCallable);
+ highlighted += colorize(defs, type2, lastPotentialCallable.value) + stackedHighlight, stackedHighlight = "", lastPotentialCallable = null;
+ }
+ highlighted += colorize(defs, type, token.value);
+ }
+ return highlighted;
+};
+function highlight$1(code, options = { jsx: false, colors: {} }) {
+ return code && highlightTokens(options.colors || {}, code, options.jsx);
+}
+
+function getDefs(c) {
+ const Invalid = (text) => c.white(c.bgRed(c.bold(text)));
+ return {
+ Keyword: c.magenta,
+ IdentifierCapitalized: c.yellow,
+ Punctuator: c.yellow,
+ StringLiteral: c.green,
+ NoSubstitutionTemplate: c.green,
+ MultiLineComment: c.gray,
+ SingleLineComment: c.gray,
+ RegularExpressionLiteral: c.cyan,
+ NumericLiteral: c.blue,
+ TemplateHead: (text) => c.green(text.slice(0, text.length - 2)) + c.cyan(text.slice(-2)),
+ TemplateTail: (text) => c.cyan(text.slice(0, 1)) + c.green(text.slice(1)),
+ TemplateMiddle: (text) => c.cyan(text.slice(0, 1)) + c.green(text.slice(1, text.length - 2)) + c.cyan(text.slice(-2)),
+ IdentifierCallable: c.blue,
+ PrivateIdentifierCallable: (text) => `#${c.blue(text.slice(1))}`,
+ Invalid,
+ JSXString: c.green,
+ JSXIdentifier: c.yellow,
+ JSXInvalid: Invalid,
+ JSXPunctuator: c.yellow
+ };
+}
+function highlight(code, options = { jsx: false }) {
+ return highlight$1(code, {
+ jsx: options.jsx,
+ colors: getDefs(options.colors || c)
+ });
+}
+
+export { highlight };
diff --git a/vanilla/node_modules/@vitest/utils/dist/index.d.ts b/vanilla/node_modules/@vitest/utils/dist/index.d.ts
new file mode 100644
index 0000000..d4435cc
--- /dev/null
+++ b/vanilla/node_modules/@vitest/utils/dist/index.d.ts
@@ -0,0 +1,5 @@
+export { LoupeOptions, StringifyOptions } from './display.js';
+export { DeferPromise } from './helpers.js';
+export { SafeTimers } from './timers.js';
+export { ArgumentsType, Arrayable, Awaitable, Constructable, DeepMerge, MergeInsertions, Nullable, ParsedStack, SerializedError, TestError } from './types.js';
+import '@vitest/pretty-format';
diff --git a/vanilla/node_modules/@vitest/utils/dist/index.js b/vanilla/node_modules/@vitest/utils/dist/index.js
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/vanilla/node_modules/@vitest/utils/dist/index.js
@@ -0,0 +1 @@
+
diff --git a/vanilla/node_modules/@vitest/utils/dist/offset.d.ts b/vanilla/node_modules/@vitest/utils/dist/offset.d.ts
new file mode 100644
index 0000000..ae65386
--- /dev/null
+++ b/vanilla/node_modules/@vitest/utils/dist/offset.d.ts
@@ -0,0 +1,5 @@
+declare const lineSplitRE: RegExp;
+declare function positionToOffset(source: string, lineNumber: number, columnNumber: number): number;
+declare function offsetToLineNumber(source: string, offset: number): number;
+
+export { lineSplitRE, offsetToLineNumber, positionToOffset };
diff --git a/vanilla/node_modules/@vitest/utils/dist/offset.js b/vanilla/node_modules/@vitest/utils/dist/offset.js
new file mode 100644
index 0000000..d8cb08d
--- /dev/null
+++ b/vanilla/node_modules/@vitest/utils/dist/offset.js
@@ -0,0 +1,32 @@
+const lineSplitRE = /\r?\n/;
+function positionToOffset(source, lineNumber, columnNumber) {
+ const lines = source.split(lineSplitRE);
+ const nl = /\r\n/.test(source) ? 2 : 1;
+ let start = 0;
+ if (lineNumber > lines.length) {
+ return source.length;
+ }
+ for (let i = 0; i < lineNumber - 1; i++) {
+ start += lines[i].length + nl;
+ }
+ return start + columnNumber;
+}
+function offsetToLineNumber(source, offset) {
+ if (offset > source.length) {
+ throw new Error(`offset is longer than source length! offset ${offset} > length ${source.length}`);
+ }
+ const lines = source.split(lineSplitRE);
+ const nl = /\r\n/.test(source) ? 2 : 1;
+ let counted = 0;
+ let line = 0;
+ for (; line < lines.length; line++) {
+ const lineLength = lines[line].length + nl;
+ if (counted + lineLength >= offset) {
+ break;
+ }
+ counted += lineLength;
+ }
+ return line + 1;
+}
+
+export { lineSplitRE, offsetToLineNumber, positionToOffset };
diff --git a/vanilla/node_modules/@vitest/utils/dist/resolver.d.ts b/vanilla/node_modules/@vitest/utils/dist/resolver.d.ts
new file mode 100644
index 0000000..71ebc63
--- /dev/null
+++ b/vanilla/node_modules/@vitest/utils/dist/resolver.d.ts
@@ -0,0 +1,7 @@
+declare function findNearestPackageData(basedir: string): {
+ type?: "module" | "commonjs";
+};
+declare function getCachedData<T>(cache: Map<string, T>, basedir: string, originalBasedir: string): NonNullable<T> | undefined;
+declare function setCacheData<T>(cache: Map<string, T>, data: T, basedir: string, originalBasedir: string): void;
+
+export { findNearestPackageData, getCachedData, setCacheData };
diff --git a/vanilla/node_modules/@vitest/utils/dist/resolver.js b/vanilla/node_modules/@vitest/utils/dist/resolver.js
new file mode 100644
index 0000000..83bd3c1
--- /dev/null
+++ b/vanilla/node_modules/@vitest/utils/dist/resolver.js
@@ -0,0 +1,71 @@
+import fs from 'node:fs';
+import { j as join, d as dirname } from './chunk-pathe.M-eThtNZ.js';
+
+const packageCache = new Map();
+function findNearestPackageData(basedir) {
+ const originalBasedir = basedir;
+ while (basedir) {
+ var _tryStatSync;
+ const cached = getCachedData(packageCache, basedir, originalBasedir);
+ if (cached) {
+ return cached;
+ }
+ const pkgPath = join(basedir, "package.json");
+ if ((_tryStatSync = tryStatSync(pkgPath)) === null || _tryStatSync === void 0 ? void 0 : _tryStatSync.isFile()) {
+ const pkgData = JSON.parse(stripBomTag(fs.readFileSync(pkgPath, "utf8")));
+ if (packageCache) {
+ setCacheData(packageCache, pkgData, basedir, originalBasedir);
+ }
+ return pkgData;
+ }
+ const nextBasedir = dirname(basedir);
+ if (nextBasedir === basedir) {
+ break;
+ }
+ basedir = nextBasedir;
+ }
+ return {};
+}
+function stripBomTag(content) {
+ if (content.charCodeAt(0) === 65279) {
+ return content.slice(1);
+ }
+ return content;
+}
+function tryStatSync(file) {
+ try {
+ // The "throwIfNoEntry" is a performance optimization for cases where the file does not exist
+ return fs.statSync(file, { throwIfNoEntry: false });
+ } catch {}
+}
+function getCachedData(cache, basedir, originalBasedir) {
+ const pkgData = cache.get(getFnpdCacheKey(basedir));
+ if (pkgData) {
+ traverseBetweenDirs(originalBasedir, basedir, (dir) => {
+ cache.set(getFnpdCacheKey(dir), pkgData);
+ });
+ return pkgData;
+ }
+}
+function setCacheData(cache, data, basedir, originalBasedir) {
+ cache.set(getFnpdCacheKey(basedir), data);
+ traverseBetweenDirs(originalBasedir, basedir, (dir) => {
+ cache.set(getFnpdCacheKey(dir), data);
+ });
+}
+function getFnpdCacheKey(basedir) {
+ return `fnpd_${basedir}`;
+}
+/**
+* Traverse between `longerDir` (inclusive) and `shorterDir` (exclusive) and call `cb` for each dir.
+* @param longerDir Longer dir path, e.g. `/User/foo/bar/baz`
+* @param shorterDir Shorter dir path, e.g. `/User/foo`
+*/
+function traverseBetweenDirs(longerDir, shorterDir, cb) {
+ while (longerDir !== shorterDir) {
+ cb(longerDir);
+ longerDir = dirname(longerDir);
+ }
+}
+
+export { findNearestPackageData, getCachedData, setCacheData };
diff --git a/vanilla/node_modules/@vitest/utils/dist/serialize.d.ts b/vanilla/node_modules/@vitest/utils/dist/serialize.d.ts
new file mode 100644
index 0000000..dd8ee7d
--- /dev/null
+++ b/vanilla/node_modules/@vitest/utils/dist/serialize.d.ts
@@ -0,0 +1,3 @@
+declare function serializeValue(val: any, seen?: WeakMap<WeakKey, any>): any;
+
+export { serializeValue };
diff --git a/vanilla/node_modules/@vitest/utils/dist/serialize.js b/vanilla/node_modules/@vitest/utils/dist/serialize.js
new file mode 100644
index 0000000..f3ad0ad
--- /dev/null
+++ b/vanilla/node_modules/@vitest/utils/dist/serialize.js
@@ -0,0 +1,118 @@
+const IS_RECORD_SYMBOL = "@@__IMMUTABLE_RECORD__@@";
+const IS_COLLECTION_SYMBOL = "@@__IMMUTABLE_ITERABLE__@@";
+function isImmutable(v) {
+ return v && (v[IS_COLLECTION_SYMBOL] || v[IS_RECORD_SYMBOL]);
+}
+const OBJECT_PROTO = Object.getPrototypeOf({});
+function getUnserializableMessage(err) {
+ if (err instanceof Error) {
+ return `<unserializable>: ${err.message}`;
+ }
+ if (typeof err === "string") {
+ return `<unserializable>: ${err}`;
+ }
+ return "<unserializable>";
+}
+// https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm
+function serializeValue(val, seen = new WeakMap()) {
+ if (!val || typeof val === "string") {
+ return val;
+ }
+ if (val instanceof Error && "toJSON" in val && typeof val.toJSON === "function") {
+ const jsonValue = val.toJSON();
+ if (jsonValue && jsonValue !== val && typeof jsonValue === "object") {
+ if (typeof val.message === "string") {
+ safe(() => jsonValue.message ?? (jsonValue.message = normalizeErrorMessage(val.message)));
+ }
+ if (typeof val.stack === "string") {
+ safe(() => jsonValue.stack ?? (jsonValue.stack = val.stack));
+ }
+ if (typeof val.name === "string") {
+ safe(() => jsonValue.name ?? (jsonValue.name = val.name));
+ }
+ if (val.cause != null) {
+ safe(() => jsonValue.cause ?? (jsonValue.cause = serializeValue(val.cause, seen)));
+ }
+ }
+ return serializeValue(jsonValue, seen);
+ }
+ if (typeof val === "function") {
+ return `Function<${val.name || "anonymous"}>`;
+ }
+ if (typeof val === "symbol") {
+ return val.toString();
+ }
+ if (typeof val !== "object") {
+ return val;
+ }
+ if (typeof Buffer !== "undefined" && val instanceof Buffer) {
+ return `<Buffer(${val.length}) ...>`;
+ }
+ if (typeof Uint8Array !== "undefined" && val instanceof Uint8Array) {
+ return `<Uint8Array(${val.length}) ...>`;
+ }
+ // cannot serialize immutables as immutables
+ if (isImmutable(val)) {
+ return serializeValue(val.toJSON(), seen);
+ }
+ if (val instanceof Promise || val.constructor && val.constructor.prototype === "AsyncFunction") {
+ return "Promise";
+ }
+ if (typeof Element !== "undefined" && val instanceof Element) {
+ return val.tagName;
+ }
+ if (typeof val.toJSON === "function") {
+ return serializeValue(val.toJSON(), seen);
+ }
+ if (seen.has(val)) {
+ return seen.get(val);
+ }
+ if (Array.isArray(val)) {
+ // eslint-disable-next-line unicorn/no-new-array -- we need to keep sparse arrays ([1,,3])
+ const clone = new Array(val.length);
+ seen.set(val, clone);
+ val.forEach((e, i) => {
+ try {
+ clone[i] = serializeValue(e, seen);
+ } catch (err) {
+ clone[i] = getUnserializableMessage(err);
+ }
+ });
+ return clone;
+ } else {
+ // Objects with `Error` constructors appear to cause problems during worker communication
+ // using `MessagePort`, so the serialized error object is being recreated as plain object.
+ const clone = Object.create(null);
+ seen.set(val, clone);
+ let obj = val;
+ while (obj && obj !== OBJECT_PROTO) {
+ Object.getOwnPropertyNames(obj).forEach((key) => {
+ if (key in clone) {
+ return;
+ }
+ try {
+ clone[key] = serializeValue(val[key], seen);
+ } catch (err) {
+ // delete in case it has a setter from prototype that might throw
+ delete clone[key];
+ clone[key] = getUnserializableMessage(err);
+ }
+ });
+ obj = Object.getPrototypeOf(obj);
+ }
+ if (val instanceof Error) {
+ safe(() => val.message = normalizeErrorMessage(val.message));
+ }
+ return clone;
+ }
+}
+function safe(fn) {
+ try {
+ return fn();
+ } catch {}
+}
+function normalizeErrorMessage(message) {
+ return message.replace(/__(vite_ssr_import|vi_import)_\d+__\./g, "");
+}
+
+export { serializeValue };
diff --git a/vanilla/node_modules/@vitest/utils/dist/source-map.d.ts b/vanilla/node_modules/@vitest/utils/dist/source-map.d.ts
new file mode 100644
index 0000000..582d24f
--- /dev/null
+++ b/vanilla/node_modules/@vitest/utils/dist/source-map.d.ts
@@ -0,0 +1,55 @@
+import { TestError, ParsedStack } from './types.js';
+
+type OriginalMapping = {
+ source: string | null;
+ line: number;
+ column: number;
+ name: string | null;
+};
+
+interface StackTraceParserOptions {
+ ignoreStackEntries?: (RegExp | string)[];
+ getSourceMap?: (file: string) => unknown;
+ getUrlId?: (id: string) => string;
+ frameFilter?: (error: TestError, frame: ParsedStack) => boolean | void;
+}
+declare const stackIgnorePatterns: (string | RegExp)[];
+
+declare function parseSingleFFOrSafariStack(raw: string): ParsedStack | null;
+declare function parseSingleStack(raw: string): ParsedStack | null;
+declare function parseSingleV8Stack(raw: string): ParsedStack | null;
+declare function createStackString(stacks: ParsedStack[]): string;
+declare function parseStacktrace(stack: string, options?: StackTraceParserOptions): ParsedStack[];
+declare function parseErrorStacktrace(e: TestError | Error, options?: StackTraceParserOptions): ParsedStack[];
+interface SourceMapLike {
+ version: number;
+ mappings?: string;
+ names?: string[];
+ sources?: string[];
+ sourcesContent?: string[];
+ sourceRoot?: string;
+}
+interface Needle {
+ line: number;
+ column: number;
+}
+declare class DecodedMap {
+ map: SourceMapLike;
+ _encoded: string;
+ _decoded: undefined | number[][][];
+ _decodedMemo: Stats;
+ url: string;
+ version: number;
+ names: string[];
+ resolvedSources: string[];
+ constructor(map: SourceMapLike, from: string);
+}
+interface Stats {
+ lastKey: number;
+ lastNeedle: number;
+ lastIndex: number;
+}
+declare function getOriginalPosition(map: DecodedMap, needle: Needle): OriginalMapping | null;
+
+export { DecodedMap, createStackString, stackIgnorePatterns as defaultStackIgnorePatterns, getOriginalPosition, parseErrorStacktrace, parseSingleFFOrSafariStack, parseSingleStack, parseSingleV8Stack, parseStacktrace };
+export type { StackTraceParserOptions };
diff --git a/vanilla/node_modules/@vitest/utils/dist/source-map.js b/vanilla/node_modules/@vitest/utils/dist/source-map.js
new file mode 100644
index 0000000..b435c91
--- /dev/null
+++ b/vanilla/node_modules/@vitest/utils/dist/source-map.js
@@ -0,0 +1,478 @@
+import { isPrimitive, notNullish } from './helpers.js';
+import { r as resolve } from './chunk-pathe.M-eThtNZ.js';
+import './constants.js';
+
+// src/vlq.ts
+var comma = ",".charCodeAt(0);
+var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+var intToChar = new Uint8Array(64);
+var charToInt = new Uint8Array(128);
+for (let i = 0; i < chars.length; i++) {
+ const c = chars.charCodeAt(i);
+ intToChar[i] = c;
+ charToInt[c] = i;
+}
+function decodeInteger(reader, relative) {
+ let value = 0;
+ let shift = 0;
+ let integer = 0;
+ do {
+ const c = reader.next();
+ integer = charToInt[c];
+ value |= (integer & 31) << shift;
+ shift += 5;
+ } while (integer & 32);
+ const shouldNegate = value & 1;
+ value >>>= 1;
+ if (shouldNegate) {
+ value = -2147483648 | -value;
+ }
+ return relative + value;
+}
+function hasMoreVlq(reader, max) {
+ if (reader.pos >= max) return false;
+ return reader.peek() !== comma;
+}
+var StringReader = class {
+ constructor(buffer) {
+ this.pos = 0;
+ this.buffer = buffer;
+ }
+ next() {
+ return this.buffer.charCodeAt(this.pos++);
+ }
+ peek() {
+ return this.buffer.charCodeAt(this.pos);
+ }
+ indexOf(char) {
+ const { buffer, pos } = this;
+ const idx = buffer.indexOf(char, pos);
+ return idx === -1 ? buffer.length : idx;
+ }
+};
+
+// src/sourcemap-codec.ts
+function decode(mappings) {
+ const { length } = mappings;
+ const reader = new StringReader(mappings);
+ const decoded = [];
+ let genColumn = 0;
+ let sourcesIndex = 0;
+ let sourceLine = 0;
+ let sourceColumn = 0;
+ let namesIndex = 0;
+ do {
+ const semi = reader.indexOf(";");
+ const line = [];
+ let sorted = true;
+ let lastCol = 0;
+ genColumn = 0;
+ while (reader.pos < semi) {
+ let seg;
+ genColumn = decodeInteger(reader, genColumn);
+ if (genColumn < lastCol) sorted = false;
+ lastCol = genColumn;
+ if (hasMoreVlq(reader, semi)) {
+ sourcesIndex = decodeInteger(reader, sourcesIndex);
+ sourceLine = decodeInteger(reader, sourceLine);
+ sourceColumn = decodeInteger(reader, sourceColumn);
+ if (hasMoreVlq(reader, semi)) {
+ namesIndex = decodeInteger(reader, namesIndex);
+ seg = [genColumn, sourcesIndex, sourceLine, sourceColumn, namesIndex];
+ } else {
+ seg = [genColumn, sourcesIndex, sourceLine, sourceColumn];
+ }
+ } else {
+ seg = [genColumn];
+ }
+ line.push(seg);
+ reader.pos++;
+ }
+ if (!sorted) sort(line);
+ decoded.push(line);
+ reader.pos = semi + 1;
+ } while (reader.pos <= length);
+ return decoded;
+}
+function sort(line) {
+ line.sort(sortComparator);
+}
+function sortComparator(a, b) {
+ return a[0] - b[0];
+}
+
+// src/trace-mapping.ts
+
+// src/sourcemap-segment.ts
+var COLUMN = 0;
+var SOURCES_INDEX = 1;
+var SOURCE_LINE = 2;
+var SOURCE_COLUMN = 3;
+var NAMES_INDEX = 4;
+
+// src/binary-search.ts
+var found = false;
+function binarySearch(haystack, needle, low, high) {
+ while (low <= high) {
+ const mid = low + (high - low >> 1);
+ const cmp = haystack[mid][COLUMN] - needle;
+ if (cmp === 0) {
+ found = true;
+ return mid;
+ }
+ if (cmp < 0) {
+ low = mid + 1;
+ } else {
+ high = mid - 1;
+ }
+ }
+ found = false;
+ return low - 1;
+}
+function upperBound(haystack, needle, index) {
+ for (let i = index + 1; i < haystack.length; index = i++) {
+ if (haystack[i][COLUMN] !== needle) break;
+ }
+ return index;
+}
+function lowerBound(haystack, needle, index) {
+ for (let i = index - 1; i >= 0; index = i--) {
+ if (haystack[i][COLUMN] !== needle) break;
+ }
+ return index;
+}
+function memoizedBinarySearch(haystack, needle, state, key) {
+ const { lastKey, lastNeedle, lastIndex } = state;
+ let low = 0;
+ let high = haystack.length - 1;
+ if (key === lastKey) {
+ if (needle === lastNeedle) {
+ found = lastIndex !== -1 && haystack[lastIndex][COLUMN] === needle;
+ return lastIndex;
+ }
+ if (needle >= lastNeedle) {
+ low = lastIndex === -1 ? 0 : lastIndex;
+ } else {
+ high = lastIndex;
+ }
+ }
+ state.lastKey = key;
+ state.lastNeedle = needle;
+ return state.lastIndex = binarySearch(haystack, needle, low, high);
+}
+
+// src/trace-mapping.ts
+var LINE_GTR_ZERO = "`line` must be greater than 0 (lines start at line 1)";
+var COL_GTR_EQ_ZERO = "`column` must be greater than or equal to 0 (columns start at column 0)";
+var LEAST_UPPER_BOUND = -1;
+var GREATEST_LOWER_BOUND = 1;
+function cast(map) {
+ return map;
+}
+function decodedMappings(map) {
+ var _a;
+ return (_a = cast(map))._decoded || (_a._decoded = decode(cast(map)._encoded));
+}
+function originalPositionFor(map, needle) {
+ let { line, column, bias } = needle;
+ line--;
+ if (line < 0) throw new Error(LINE_GTR_ZERO);
+ if (column < 0) throw new Error(COL_GTR_EQ_ZERO);
+ const decoded = decodedMappings(map);
+ if (line >= decoded.length) return OMapping(null, null, null, null);
+ const segments = decoded[line];
+ const index = traceSegmentInternal(
+ segments,
+ cast(map)._decodedMemo,
+ line,
+ column,
+ bias || GREATEST_LOWER_BOUND
+ );
+ if (index === -1) return OMapping(null, null, null, null);
+ const segment = segments[index];
+ if (segment.length === 1) return OMapping(null, null, null, null);
+ const { names, resolvedSources } = map;
+ return OMapping(
+ resolvedSources[segment[SOURCES_INDEX]],
+ segment[SOURCE_LINE] + 1,
+ segment[SOURCE_COLUMN],
+ segment.length === 5 ? names[segment[NAMES_INDEX]] : null
+ );
+}
+function OMapping(source, line, column, name) {
+ return { source, line, column, name };
+}
+function traceSegmentInternal(segments, memo, line, column, bias) {
+ let index = memoizedBinarySearch(segments, column, memo, line);
+ if (found) {
+ index = (bias === LEAST_UPPER_BOUND ? upperBound : lowerBound)(segments, column, index);
+ } else if (bias === LEAST_UPPER_BOUND) index++;
+ if (index === -1 || index === segments.length) return -1;
+ return index;
+}
+
+const CHROME_IE_STACK_REGEXP = /^\s*at .*(?:\S:\d+|\(native\))/m;
+const SAFARI_NATIVE_CODE_REGEXP = /^(?:eval@)?(?:\[native code\])?$/;
+const stackIgnorePatterns = [
+ "node:internal",
+ /\/packages\/\w+\/dist\//,
+ /\/@vitest\/\w+\/dist\//,
+ "/vitest/dist/",
+ "/vitest/src/",
+ "/node_modules/chai/",
+ "/node_modules/tinyspy/",
+ "/vite/dist/node/module-runner",
+ "/rolldown-vite/dist/node/module-runner",
+ "/deps/chunk-",
+ "/deps/@vitest",
+ "/deps/loupe",
+ "/deps/chai",
+ "/browser-playwright/dist/locators.js",
+ "/browser-webdriverio/dist/locators.js",
+ "/browser-preview/dist/locators.js",
+ /node:\w+/,
+ /__vitest_test__/,
+ /__vitest_browser__/,
+ /\/deps\/vitest_/
+];
+function extractLocation(urlLike) {
+ // Fail-fast but return locations like "(native)"
+ if (!urlLike.includes(":")) {
+ return [urlLike];
+ }
+ const regExp = /(.+?)(?::(\d+))?(?::(\d+))?$/;
+ const parts = regExp.exec(urlLike.replace(/^\(|\)$/g, ""));
+ if (!parts) {
+ return [urlLike];
+ }
+ let url = parts[1];
+ if (url.startsWith("async ")) {
+ url = url.slice(6);
+ }
+ if (url.startsWith("http:") || url.startsWith("https:")) {
+ const urlObj = new URL(url);
+ urlObj.searchParams.delete("import");
+ urlObj.searchParams.delete("browserv");
+ url = urlObj.pathname + urlObj.hash + urlObj.search;
+ }
+ if (url.startsWith("/@fs/")) {
+ const isWindows = /^\/@fs\/[a-zA-Z]:\//.test(url);
+ url = url.slice(isWindows ? 5 : 4);
+ }
+ return [
+ url,
+ parts[2] || undefined,
+ parts[3] || undefined
+ ];
+}
+function parseSingleFFOrSafariStack(raw) {
+ let line = raw.trim();
+ if (SAFARI_NATIVE_CODE_REGEXP.test(line)) {
+ return null;
+ }
+ if (line.includes(" > eval")) {
+ line = line.replace(/ line (\d+)(?: > eval line \d+)* > eval:\d+:\d+/g, ":$1");
+ }
+ // Early return for lines that don't look like Firefox/Safari stack traces
+ // Firefox/Safari stack traces must contain '@' and should have location info after it
+ if (!line.includes("@")) {
+ return null;
+ }
+ // Find the correct @ that separates function name from location
+ // For cases like '@https://@fs/path' or 'functionName@https://@fs/path'
+ // we need to find the first @ that precedes a valid location (containing :)
+ let atIndex = -1;
+ let locationPart = "";
+ let functionName;
+ // Try each @ from left to right to find the one that gives us a valid location
+ for (let i = 0; i < line.length; i++) {
+ if (line[i] === "@") {
+ const candidateLocation = line.slice(i + 1);
+ // Minimum length 3 for valid location: 1 for filename + 1 for colon + 1 for line number (e.g., "a:1")
+ if (candidateLocation.includes(":") && candidateLocation.length >= 3) {
+ atIndex = i;
+ locationPart = candidateLocation;
+ functionName = i > 0 ? line.slice(0, i) : undefined;
+ break;
+ }
+ }
+ }
+ // Validate we found a valid location with minimum length (filename:line format)
+ if (atIndex === -1 || !locationPart.includes(":") || locationPart.length < 3) {
+ return null;
+ }
+ const [url, lineNumber, columnNumber] = extractLocation(locationPart);
+ if (!url || !lineNumber || !columnNumber) {
+ return null;
+ }
+ return {
+ file: url,
+ method: functionName || "",
+ line: Number.parseInt(lineNumber),
+ column: Number.parseInt(columnNumber)
+ };
+}
+function parseSingleStack(raw) {
+ const line = raw.trim();
+ if (!CHROME_IE_STACK_REGEXP.test(line)) {
+ return parseSingleFFOrSafariStack(line);
+ }
+ return parseSingleV8Stack(line);
+}
+// Based on https://github.com/stacktracejs/error-stack-parser
+// Credit to stacktracejs
+function parseSingleV8Stack(raw) {
+ let line = raw.trim();
+ if (!CHROME_IE_STACK_REGEXP.test(line)) {
+ return null;
+ }
+ if (line.includes("(eval ")) {
+ line = line.replace(/eval code/g, "eval").replace(/(\(eval at [^()]*)|(,.*$)/g, "");
+ }
+ let sanitizedLine = line.replace(/^\s+/, "").replace(/\(eval code/g, "(").replace(/^.*?\s+/, "");
+ // capture and preserve the parenthesized location "(/foo/my bar.js:12:87)" in
+ // case it has spaces in it, as the string is split on \s+ later on
+ const location = sanitizedLine.match(/ (\(.+\)$)/);
+ // remove the parenthesized location from the line, if it was matched
+ sanitizedLine = location ? sanitizedLine.replace(location[0], "") : sanitizedLine;
+ // if a location was matched, pass it to extractLocation() otherwise pass all sanitizedLine
+ // because this line doesn't have function name
+ const [url, lineNumber, columnNumber] = extractLocation(location ? location[1] : sanitizedLine);
+ let method = location && sanitizedLine || "";
+ let file = url && ["eval", "<anonymous>"].includes(url) ? undefined : url;
+ if (!file || !lineNumber || !columnNumber) {
+ return null;
+ }
+ if (method.startsWith("async ")) {
+ method = method.slice(6);
+ }
+ if (file.startsWith("file://")) {
+ file = file.slice(7);
+ }
+ // normalize Windows path (\ -> /)
+ file = file.startsWith("node:") || file.startsWith("internal:") ? file : resolve(file);
+ if (method) {
+ method = method.replace(/__vite_ssr_import_\d+__\./g, "").replace(/(Object\.)?__vite_ssr_export_default__\s?/g, "");
+ }
+ return {
+ method,
+ file,
+ line: Number.parseInt(lineNumber),
+ column: Number.parseInt(columnNumber)
+ };
+}
+function createStackString(stacks) {
+ return stacks.map((stack) => {
+ const line = `${stack.file}:${stack.line}:${stack.column}`;
+ if (stack.method) {
+ return ` at ${stack.method}(${line})`;
+ }
+ return ` at ${line}`;
+ }).join("\n");
+}
+function parseStacktrace(stack, options = {}) {
+ const { ignoreStackEntries = stackIgnorePatterns } = options;
+ const stacks = !CHROME_IE_STACK_REGEXP.test(stack) ? parseFFOrSafariStackTrace(stack) : parseV8Stacktrace(stack);
+ return stacks.map((stack) => {
+ var _options$getSourceMap;
+ if (options.getUrlId) {
+ stack.file = options.getUrlId(stack.file);
+ }
+ const map = (_options$getSourceMap = options.getSourceMap) === null || _options$getSourceMap === void 0 ? void 0 : _options$getSourceMap.call(options, stack.file);
+ if (!map || typeof map !== "object" || !map.version) {
+ return shouldFilter(ignoreStackEntries, stack.file) ? null : stack;
+ }
+ const traceMap = new DecodedMap(map, stack.file);
+ const position = getOriginalPosition(traceMap, stack);
+ if (!position) {
+ return stack;
+ }
+ const { line, column, source, name } = position;
+ let file = source || stack.file;
+ if (file.match(/\/\w:\//)) {
+ file = file.slice(1);
+ }
+ if (shouldFilter(ignoreStackEntries, file)) {
+ return null;
+ }
+ if (line != null && column != null) {
+ return {
+ line,
+ column,
+ file,
+ method: name || stack.method
+ };
+ }
+ return stack;
+ }).filter((s) => s != null);
+}
+function shouldFilter(ignoreStackEntries, file) {
+ return ignoreStackEntries.some((p) => file.match(p));
+}
+function parseFFOrSafariStackTrace(stack) {
+ return stack.split("\n").map((line) => parseSingleFFOrSafariStack(line)).filter(notNullish);
+}
+function parseV8Stacktrace(stack) {
+ return stack.split("\n").map((line) => parseSingleV8Stack(line)).filter(notNullish);
+}
+function parseErrorStacktrace(e, options = {}) {
+ if (!e || isPrimitive(e)) {
+ return [];
+ }
+ if ("stacks" in e && e.stacks) {
+ return e.stacks;
+ }
+ const stackStr = e.stack || "";
+ // if "stack" property was overwritten at runtime to be something else,
+ // ignore the value because we don't know how to process it
+ let stackFrames = typeof stackStr === "string" ? parseStacktrace(stackStr, options) : [];
+ if (!stackFrames.length) {
+ const e_ = e;
+ if (e_.fileName != null && e_.lineNumber != null && e_.columnNumber != null) {
+ stackFrames = parseStacktrace(`${e_.fileName}:${e_.lineNumber}:${e_.columnNumber}`, options);
+ }
+ if (e_.sourceURL != null && e_.line != null && e_._column != null) {
+ stackFrames = parseStacktrace(`${e_.sourceURL}:${e_.line}:${e_.column}`, options);
+ }
+ }
+ if (options.frameFilter) {
+ stackFrames = stackFrames.filter((f) => options.frameFilter(e, f) !== false);
+ }
+ e.stacks = stackFrames;
+ return stackFrames;
+}
+class DecodedMap {
+ _encoded;
+ _decoded;
+ _decodedMemo;
+ url;
+ version;
+ names = [];
+ resolvedSources;
+ constructor(map, from) {
+ this.map = map;
+ const { mappings, names, sources } = map;
+ this.version = map.version;
+ this.names = names || [];
+ this._encoded = mappings || "";
+ this._decodedMemo = memoizedState();
+ this.url = from;
+ this.resolvedSources = (sources || []).map((s) => resolve(s || "", from));
+ }
+}
+function memoizedState() {
+ return {
+ lastKey: -1,
+ lastNeedle: -1,
+ lastIndex: -1
+ };
+}
+function getOriginalPosition(map, needle) {
+ const result = originalPositionFor(map, needle);
+ if (result.column == null) {
+ return null;
+ }
+ return result;
+}
+
+export { DecodedMap, createStackString, stackIgnorePatterns as defaultStackIgnorePatterns, getOriginalPosition, parseErrorStacktrace, parseSingleFFOrSafariStack, parseSingleStack, parseSingleV8Stack, parseStacktrace };
diff --git a/vanilla/node_modules/@vitest/utils/dist/timers.d.ts b/vanilla/node_modules/@vitest/utils/dist/timers.d.ts
new file mode 100644
index 0000000..8dd6025
--- /dev/null
+++ b/vanilla/node_modules/@vitest/utils/dist/timers.d.ts
@@ -0,0 +1,33 @@
+interface SafeTimers {
+ nextTick?: (cb: () => void) => void;
+ setImmediate?: {
+ <TArgs extends any[]>(callback: (...args: TArgs) => void, ...args: TArgs): any;
+ __promisify__: <T = void>(value?: T, options?: any) => Promise<T>;
+ };
+ clearImmediate?: (immediateId: any) => void;
+ setTimeout: typeof setTimeout;
+ setInterval: typeof setInterval;
+ clearInterval: typeof clearInterval;
+ clearTimeout: typeof clearTimeout;
+ queueMicrotask: typeof queueMicrotask;
+}
+declare function getSafeTimers(): SafeTimers;
+declare function setSafeTimers(): void;
+/**
+* Returns a promise that resolves after the specified duration.
+*
+* @param timeout - Delay in milliseconds
+* @param scheduler - Timer function to use, defaults to `setTimeout`. Useful for mocked timers.
+*
+* @example
+* await delay(100)
+*
+* @example
+* // With mocked timers
+* const { setTimeout } = getSafeTimers()
+* await delay(100, setTimeout)
+*/
+declare function delay(timeout: number, scheduler?: typeof setTimeout): Promise<void>;
+
+export { delay, getSafeTimers, setSafeTimers };
+export type { SafeTimers };
diff --git a/vanilla/node_modules/@vitest/utils/dist/timers.js b/vanilla/node_modules/@vitest/utils/dist/timers.js
new file mode 100644
index 0000000..29229e5
--- /dev/null
+++ b/vanilla/node_modules/@vitest/utils/dist/timers.js
@@ -0,0 +1,49 @@
+const SAFE_TIMERS_SYMBOL = Symbol("vitest:SAFE_TIMERS");
+function getSafeTimers() {
+ const { setTimeout: safeSetTimeout, setInterval: safeSetInterval, clearInterval: safeClearInterval, clearTimeout: safeClearTimeout, setImmediate: safeSetImmediate, clearImmediate: safeClearImmediate, queueMicrotask: safeQueueMicrotask } = globalThis[SAFE_TIMERS_SYMBOL] || globalThis;
+ const { nextTick: safeNextTick } = globalThis[SAFE_TIMERS_SYMBOL] || globalThis.process || {};
+ return {
+ nextTick: safeNextTick,
+ setTimeout: safeSetTimeout,
+ setInterval: safeSetInterval,
+ clearInterval: safeClearInterval,
+ clearTimeout: safeClearTimeout,
+ setImmediate: safeSetImmediate,
+ clearImmediate: safeClearImmediate,
+ queueMicrotask: safeQueueMicrotask
+ };
+}
+function setSafeTimers() {
+ const { setTimeout: safeSetTimeout, setInterval: safeSetInterval, clearInterval: safeClearInterval, clearTimeout: safeClearTimeout, setImmediate: safeSetImmediate, clearImmediate: safeClearImmediate, queueMicrotask: safeQueueMicrotask } = globalThis;
+ const { nextTick: safeNextTick } = globalThis.process || {};
+ const timers = {
+ nextTick: safeNextTick,
+ setTimeout: safeSetTimeout,
+ setInterval: safeSetInterval,
+ clearInterval: safeClearInterval,
+ clearTimeout: safeClearTimeout,
+ setImmediate: safeSetImmediate,
+ clearImmediate: safeClearImmediate,
+ queueMicrotask: safeQueueMicrotask
+ };
+ globalThis[SAFE_TIMERS_SYMBOL] = timers;
+}
+/**
+* Returns a promise that resolves after the specified duration.
+*
+* @param timeout - Delay in milliseconds
+* @param scheduler - Timer function to use, defaults to `setTimeout`. Useful for mocked timers.
+*
+* @example
+* await delay(100)
+*
+* @example
+* // With mocked timers
+* const { setTimeout } = getSafeTimers()
+* await delay(100, setTimeout)
+*/
+function delay(timeout, scheduler = setTimeout) {
+ return new Promise((resolve) => scheduler(resolve, timeout));
+}
+
+export { delay, getSafeTimers, setSafeTimers };
diff --git a/vanilla/node_modules/@vitest/utils/dist/types.d-BCElaP-c.d.ts b/vanilla/node_modules/@vitest/utils/dist/types.d-BCElaP-c.d.ts
new file mode 100644
index 0000000..cba06c6
--- /dev/null
+++ b/vanilla/node_modules/@vitest/utils/dist/types.d-BCElaP-c.d.ts
@@ -0,0 +1,53 @@
+import { CompareKeys } from '@vitest/pretty-format';
+
+/**
+* Copyright (c) Meta Platforms, Inc. and affiliates.
+*
+* This source code is licensed under the MIT license found in the
+* LICENSE file in the root directory of this source tree.
+*/
+
+type DiffOptionsColor = (arg: string) => string;
+interface DiffOptions {
+ aAnnotation?: string;
+ aColor?: DiffOptionsColor;
+ aIndicator?: string;
+ bAnnotation?: string;
+ bColor?: DiffOptionsColor;
+ bIndicator?: string;
+ changeColor?: DiffOptionsColor;
+ changeLineTrailingSpaceColor?: DiffOptionsColor;
+ commonColor?: DiffOptionsColor;
+ commonIndicator?: string;
+ commonLineTrailingSpaceColor?: DiffOptionsColor;
+ contextLines?: number;
+ emptyFirstOrLastLinePlaceholder?: string;
+ expand?: boolean;
+ includeChangeCounts?: boolean;
+ omitAnnotationLines?: boolean;
+ patchColor?: DiffOptionsColor;
+ printBasicPrototype?: boolean;
+ maxDepth?: number;
+ compareKeys?: CompareKeys;
+ truncateThreshold?: number;
+ truncateAnnotation?: string;
+ truncateAnnotationColor?: DiffOptionsColor;
+}
+interface SerializedDiffOptions {
+ aAnnotation?: string;
+ aIndicator?: string;
+ bAnnotation?: string;
+ bIndicator?: string;
+ commonIndicator?: string;
+ contextLines?: number;
+ emptyFirstOrLastLinePlaceholder?: string;
+ expand?: boolean;
+ includeChangeCounts?: boolean;
+ omitAnnotationLines?: boolean;
+ printBasicPrototype?: boolean;
+ maxDepth?: number;
+ truncateThreshold?: number;
+ truncateAnnotation?: string;
+}
+
+export type { DiffOptions as D, SerializedDiffOptions as S, DiffOptionsColor as a };
diff --git a/vanilla/node_modules/@vitest/utils/dist/types.d.ts b/vanilla/node_modules/@vitest/utils/dist/types.d.ts
new file mode 100644
index 0000000..4e6d810
--- /dev/null
+++ b/vanilla/node_modules/@vitest/utils/dist/types.d.ts
@@ -0,0 +1,34 @@
+type Awaitable<T> = T | PromiseLike<T>;
+type Nullable<T> = T | null | undefined;
+type Arrayable<T> = T | Array<T>;
+type ArgumentsType<T> = T extends (...args: infer U) => any ? U : never;
+type MergeInsertions<T> = T extends object ? { [K in keyof T] : MergeInsertions<T[K]> } : T;
+type DeepMerge<
+ F,
+ S
+> = MergeInsertions<{ [K in keyof F | keyof S] : K extends keyof S & keyof F ? DeepMerge<F[K], S[K]> : K extends keyof S ? S[K] : K extends keyof F ? F[K] : never }>;
+interface Constructable {
+ new (...args: any[]): any;
+}
+interface ParsedStack {
+ method: string;
+ file: string;
+ line: number;
+ column: number;
+}
+interface SerializedError {
+ message: string;
+ stacks?: ParsedStack[];
+ stack?: string;
+ name?: string;
+ cause?: SerializedError;
+ [key: string]: unknown;
+}
+interface TestError extends SerializedError {
+ cause?: TestError;
+ diff?: string;
+ actual?: string;
+ expected?: string;
+}
+
+export type { ArgumentsType, Arrayable, Awaitable, Constructable, DeepMerge, MergeInsertions, Nullable, ParsedStack, SerializedError, TestError };
diff --git a/vanilla/node_modules/@vitest/utils/dist/types.js b/vanilla/node_modules/@vitest/utils/dist/types.js
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/vanilla/node_modules/@vitest/utils/dist/types.js
@@ -0,0 +1 @@
+
diff --git a/vanilla/node_modules/@vitest/utils/error.d.ts b/vanilla/node_modules/@vitest/utils/error.d.ts
new file mode 100644
index 0000000..9329baa
--- /dev/null
+++ b/vanilla/node_modules/@vitest/utils/error.d.ts
@@ -0,0 +1 @@
+export * from './dist/error.js'
diff --git a/vanilla/node_modules/@vitest/utils/helpers.d.ts b/vanilla/node_modules/@vitest/utils/helpers.d.ts
new file mode 100644
index 0000000..0add1d0
--- /dev/null
+++ b/vanilla/node_modules/@vitest/utils/helpers.d.ts
@@ -0,0 +1 @@
+export * from './dist/helpers.js'
diff --git a/vanilla/node_modules/@vitest/utils/package.json b/vanilla/node_modules/@vitest/utils/package.json
new file mode 100644
index 0000000..1b8b19d
--- /dev/null
+++ b/vanilla/node_modules/@vitest/utils/package.json
@@ -0,0 +1,98 @@
+{
+ "name": "@vitest/utils",
+ "type": "module",
+ "version": "4.0.18",
+ "description": "Shared Vitest utility functions",
+ "license": "MIT",
+ "funding": "https://opencollective.com/vitest",
+ "homepage": "https://github.com/vitest-dev/vitest/tree/main/packages/utils#readme",
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/vitest-dev/vitest.git",
+ "directory": "packages/utils"
+ },
+ "bugs": {
+ "url": "https://github.com/vitest-dev/vitest/issues"
+ },
+ "sideEffects": false,
+ "exports": {
+ ".": {
+ "types": "./dist/index.d.ts",
+ "default": "./dist/index.js"
+ },
+ "./diff": {
+ "types": "./dist/diff.d.ts",
+ "default": "./dist/diff.js"
+ },
+ "./resolver": {
+ "types": "./dist/resolver.d.ts",
+ "default": "./dist/resolver.js"
+ },
+ "./error": {
+ "types": "./dist/error.d.ts",
+ "default": "./dist/error.js"
+ },
+ "./helpers": {
+ "types": "./dist/helpers.d.ts",
+ "default": "./dist/helpers.js"
+ },
+ "./offset": {
+ "types": "./dist/offset.d.ts",
+ "default": "./dist/offset.js"
+ },
+ "./constants": {
+ "types": "./dist/constants.d.ts",
+ "default": "./dist/constants.js"
+ },
+ "./timers": {
+ "types": "./dist/timers.d.ts",
+ "default": "./dist/timers.js"
+ },
+ "./display": {
+ "types": "./dist/display.d.ts",
+ "default": "./dist/display.js"
+ },
+ "./highlight": {
+ "types": "./dist/highlight.d.ts",
+ "default": "./dist/highlight.js"
+ },
+ "./source-map": {
+ "types": "./dist/source-map.d.ts",
+ "default": "./dist/source-map.js"
+ },
+ "./serialize": {
+ "types": "./dist/serialize.d.ts",
+ "default": "./dist/serialize.js"
+ },
+ "./*": "./*"
+ },
+ "main": "./dist/index.js",
+ "module": "./dist/index.js",
+ "types": "./dist/index.d.ts",
+ "typesVersions": {
+ "*": {
+ "source-map": [
+ "dist/source-map.d.ts"
+ ]
+ }
+ },
+ "files": [
+ "*.d.ts",
+ "dist"
+ ],
+ "dependencies": {
+ "tinyrainbow": "^3.0.3",
+ "@vitest/pretty-format": "4.0.18"
+ },
+ "devDependencies": {
+ "@jridgewell/trace-mapping": "0.3.31",
+ "@types/estree": "^1.0.8",
+ "diff-sequences": "^29.6.3",
+ "loupe": "^3.2.1",
+ "tinyhighlight": "^0.3.2"
+ },
+ "scripts": {
+ "build": "premove dist && rollup -c",
+ "dev": "rollup -c --watch"
+ }
+} \ No newline at end of file