Index: imaps-frontend/node_modules/enhanced-resolve/lib/util/entrypoints.js
===================================================================
--- imaps-frontend/node_modules/enhanced-resolve/lib/util/entrypoints.js	(revision 79a03170cdde4e801d12257ee86723774970427b)
+++ imaps-frontend/node_modules/enhanced-resolve/lib/util/entrypoints.js	(revision 79a03170cdde4e801d12257ee86723774970427b)
@@ -0,0 +1,573 @@
+/*
+	MIT License http://www.opensource.org/licenses/mit-license.php
+	Author Ivan Kopeykin @vankop
+*/
+
+"use strict";
+
+/** @typedef {string|(string|ConditionalMapping)[]} DirectMapping */
+/** @typedef {{[k: string]: MappingValue}} ConditionalMapping */
+/** @typedef {ConditionalMapping|DirectMapping|null} MappingValue */
+/** @typedef {Record<string, MappingValue>|ConditionalMapping|DirectMapping} ExportsField */
+/** @typedef {Record<string, MappingValue>} ImportsField */
+
+/**
+ * Processing exports/imports field
+ * @callback FieldProcessor
+ * @param {string} request request
+ * @param {Set<string>} conditionNames condition names
+ * @returns {[string[], string | null]} resolved paths with used field
+ */
+
+/*
+Example exports field:
+{
+  ".": "./main.js",
+  "./feature": {
+    "browser": "./feature-browser.js",
+    "default": "./feature.js"
+  }
+}
+Terminology:
+
+Enhanced-resolve name keys ("." and "./feature") as exports field keys.
+
+If value is string or string[], mapping is called as a direct mapping
+and value called as a direct export.
+
+If value is key-value object, mapping is called as a conditional mapping
+and value called as a conditional export.
+
+Key in conditional mapping is called condition name.
+
+Conditional mapping nested in another conditional mapping is called nested mapping.
+
+----------
+
+Example imports field:
+{
+  "#a": "./main.js",
+  "#moment": {
+    "browser": "./moment/index.js",
+    "default": "moment"
+  },
+  "#moment/": {
+    "browser": "./moment/",
+    "default": "moment/"
+  }
+}
+Terminology:
+
+Enhanced-resolve name keys ("#a" and "#moment/", "#moment") as imports field keys.
+
+If value is string or string[], mapping is called as a direct mapping
+and value called as a direct export.
+
+If value is key-value object, mapping is called as a conditional mapping
+and value called as a conditional export.
+
+Key in conditional mapping is called condition name.
+
+Conditional mapping nested in another conditional mapping is called nested mapping.
+
+*/
+
+const { parseIdentifier } = require("./identifier");
+const slashCode = "/".charCodeAt(0);
+const dotCode = ".".charCodeAt(0);
+const hashCode = "#".charCodeAt(0);
+const patternRegEx = /\*/g;
+
+/**
+ * @param {ExportsField} exportsField the exports field
+ * @returns {FieldProcessor} process callback
+ */
+module.exports.processExportsField = function processExportsField(
+	exportsField
+) {
+	return createFieldProcessor(
+		buildExportsField(exportsField),
+		request => (request.length === 0 ? "." : "./" + request),
+		assertExportsFieldRequest,
+		assertExportTarget
+	);
+};
+
+/**
+ * @param {ImportsField} importsField the exports field
+ * @returns {FieldProcessor} process callback
+ */
+module.exports.processImportsField = function processImportsField(
+	importsField
+) {
+	return createFieldProcessor(
+		importsField,
+		request => "#" + request,
+		assertImportsFieldRequest,
+		assertImportTarget
+	);
+};
+
+/**
+ * @param {ExportsField | ImportsField} field root
+ * @param {(s: string) => string} normalizeRequest Normalize request, for `imports` field it adds `#`, for `exports` field it adds `.` or `./`
+ * @param {(s: string) => string} assertRequest assertRequest
+ * @param {(s: string, f: boolean) => void} assertTarget assertTarget
+ * @returns {FieldProcessor} field processor
+ */
+function createFieldProcessor(
+	field,
+	normalizeRequest,
+	assertRequest,
+	assertTarget
+) {
+	return function fieldProcessor(request, conditionNames) {
+		request = assertRequest(request);
+
+		const match = findMatch(normalizeRequest(request), field);
+
+		if (match === null) return [[], null];
+
+		const [mapping, remainingRequest, isSubpathMapping, isPattern, usedField] =
+			match;
+
+		/** @type {DirectMapping|null} */
+		let direct = null;
+
+		if (isConditionalMapping(mapping)) {
+			direct = conditionalMapping(
+				/** @type {ConditionalMapping} */ (mapping),
+				conditionNames
+			);
+
+			// matching not found
+			if (direct === null) return [[], null];
+		} else {
+			direct = /** @type {DirectMapping} */ (mapping);
+		}
+
+		return [
+			directMapping(
+				remainingRequest,
+				isPattern,
+				isSubpathMapping,
+				direct,
+				conditionNames,
+				assertTarget
+			),
+			usedField
+		];
+	};
+}
+
+/**
+ * @param {string} request request
+ * @returns {string} updated request
+ */
+function assertExportsFieldRequest(request) {
+	if (request.charCodeAt(0) !== dotCode) {
+		throw new Error('Request should be relative path and start with "."');
+	}
+	if (request.length === 1) return "";
+	if (request.charCodeAt(1) !== slashCode) {
+		throw new Error('Request should be relative path and start with "./"');
+	}
+	if (request.charCodeAt(request.length - 1) === slashCode) {
+		throw new Error("Only requesting file allowed");
+	}
+
+	return request.slice(2);
+}
+
+/**
+ * @param {string} request request
+ * @returns {string} updated request
+ */
+function assertImportsFieldRequest(request) {
+	if (request.charCodeAt(0) !== hashCode) {
+		throw new Error('Request should start with "#"');
+	}
+	if (request.length === 1) {
+		throw new Error("Request should have at least 2 characters");
+	}
+	if (request.charCodeAt(1) === slashCode) {
+		throw new Error('Request should not start with "#/"');
+	}
+	if (request.charCodeAt(request.length - 1) === slashCode) {
+		throw new Error("Only requesting file allowed");
+	}
+
+	return request.slice(1);
+}
+
+/**
+ * @param {string} exp export target
+ * @param {boolean} expectFolder is folder expected
+ */
+function assertExportTarget(exp, expectFolder) {
+	const parsedIdentifier = parseIdentifier(exp);
+
+	if (!parsedIdentifier) {
+		return;
+	}
+
+	const [relativePath] = parsedIdentifier;
+	const isFolder =
+		relativePath.charCodeAt(relativePath.length - 1) === slashCode;
+
+	if (isFolder !== expectFolder) {
+		throw new Error(
+			expectFolder
+				? `Expecting folder to folder mapping. ${JSON.stringify(
+						exp
+				  )} should end with "/"`
+				: `Expecting file to file mapping. ${JSON.stringify(
+						exp
+				  )} should not end with "/"`
+		);
+	}
+}
+
+/**
+ * @param {string} imp import target
+ * @param {boolean} expectFolder is folder expected
+ */
+function assertImportTarget(imp, expectFolder) {
+	const parsedIdentifier = parseIdentifier(imp);
+
+	if (!parsedIdentifier) {
+		return;
+	}
+
+	const [relativePath] = parsedIdentifier;
+	const isFolder =
+		relativePath.charCodeAt(relativePath.length - 1) === slashCode;
+
+	if (isFolder !== expectFolder) {
+		throw new Error(
+			expectFolder
+				? `Expecting folder to folder mapping. ${JSON.stringify(
+						imp
+				  )} should end with "/"`
+				: `Expecting file to file mapping. ${JSON.stringify(
+						imp
+				  )} should not end with "/"`
+		);
+	}
+}
+
+/**
+ * @param {string} a first string
+ * @param {string} b second string
+ * @returns {number} compare result
+ */
+function patternKeyCompare(a, b) {
+	const aPatternIndex = a.indexOf("*");
+	const bPatternIndex = b.indexOf("*");
+	const baseLenA = aPatternIndex === -1 ? a.length : aPatternIndex + 1;
+	const baseLenB = bPatternIndex === -1 ? b.length : bPatternIndex + 1;
+
+	if (baseLenA > baseLenB) return -1;
+	if (baseLenB > baseLenA) return 1;
+	if (aPatternIndex === -1) return 1;
+	if (bPatternIndex === -1) return -1;
+	if (a.length > b.length) return -1;
+	if (b.length > a.length) return 1;
+
+	return 0;
+}
+
+/**
+ * Trying to match request to field
+ * @param {string} request request
+ * @param {ExportsField | ImportsField} field exports or import field
+ * @returns {[MappingValue, string, boolean, boolean, string]|null} match or null, number is negative and one less when it's a folder mapping, number is request.length + 1 for direct mappings
+ */
+function findMatch(request, field) {
+	if (
+		Object.prototype.hasOwnProperty.call(field, request) &&
+		!request.includes("*") &&
+		!request.endsWith("/")
+	) {
+		const target = /** @type {{[k: string]: MappingValue}} */ (field)[request];
+
+		return [target, "", false, false, request];
+	}
+
+	/** @type {string} */
+	let bestMatch = "";
+	/** @type {string|undefined} */
+	let bestMatchSubpath;
+
+	const keys = Object.getOwnPropertyNames(field);
+
+	for (let i = 0; i < keys.length; i++) {
+		const key = keys[i];
+		const patternIndex = key.indexOf("*");
+
+		if (patternIndex !== -1 && request.startsWith(key.slice(0, patternIndex))) {
+			const patternTrailer = key.slice(patternIndex + 1);
+
+			if (
+				request.length >= key.length &&
+				request.endsWith(patternTrailer) &&
+				patternKeyCompare(bestMatch, key) === 1 &&
+				key.lastIndexOf("*") === patternIndex
+			) {
+				bestMatch = key;
+				bestMatchSubpath = request.slice(
+					patternIndex,
+					request.length - patternTrailer.length
+				);
+			}
+		}
+		// For legacy `./foo/`
+		else if (
+			key[key.length - 1] === "/" &&
+			request.startsWith(key) &&
+			patternKeyCompare(bestMatch, key) === 1
+		) {
+			bestMatch = key;
+			bestMatchSubpath = request.slice(key.length);
+		}
+	}
+
+	if (bestMatch === "") return null;
+
+	const target = /** @type {{[k: string]: MappingValue}} */ (field)[bestMatch];
+	const isSubpathMapping = bestMatch.endsWith("/");
+	const isPattern = bestMatch.includes("*");
+
+	return [
+		target,
+		/** @type {string} */ (bestMatchSubpath),
+		isSubpathMapping,
+		isPattern,
+		bestMatch
+	];
+}
+
+/**
+ * @param {ConditionalMapping|DirectMapping|null} mapping mapping
+ * @returns {boolean} is conditional mapping
+ */
+function isConditionalMapping(mapping) {
+	return (
+		mapping !== null && typeof mapping === "object" && !Array.isArray(mapping)
+	);
+}
+
+/**
+ * @param {string|undefined} remainingRequest remaining request when folder mapping, undefined for file mappings
+ * @param {boolean} isPattern true, if mapping is a pattern (contains "*")
+ * @param {boolean} isSubpathMapping true, for subpath mappings
+ * @param {DirectMapping|null} mappingTarget direct export
+ * @param {Set<string>} conditionNames condition names
+ * @param {(d: string, f: boolean) => void} assert asserting direct value
+ * @returns {string[]} mapping result
+ */
+function directMapping(
+	remainingRequest,
+	isPattern,
+	isSubpathMapping,
+	mappingTarget,
+	conditionNames,
+	assert
+) {
+	if (mappingTarget === null) return [];
+
+	if (typeof mappingTarget === "string") {
+		return [
+			targetMapping(
+				remainingRequest,
+				isPattern,
+				isSubpathMapping,
+				mappingTarget,
+				assert
+			)
+		];
+	}
+
+	/** @type {string[]} */
+	const targets = [];
+
+	for (const exp of mappingTarget) {
+		if (typeof exp === "string") {
+			targets.push(
+				targetMapping(
+					remainingRequest,
+					isPattern,
+					isSubpathMapping,
+					exp,
+					assert
+				)
+			);
+			continue;
+		}
+
+		const mapping = conditionalMapping(exp, conditionNames);
+		if (!mapping) continue;
+		const innerExports = directMapping(
+			remainingRequest,
+			isPattern,
+			isSubpathMapping,
+			mapping,
+			conditionNames,
+			assert
+		);
+		for (const innerExport of innerExports) {
+			targets.push(innerExport);
+		}
+	}
+
+	return targets;
+}
+
+/**
+ * @param {string|undefined} remainingRequest remaining request when folder mapping, undefined for file mappings
+ * @param {boolean} isPattern true, if mapping is a pattern (contains "*")
+ * @param {boolean} isSubpathMapping true, for subpath mappings
+ * @param {string} mappingTarget direct export
+ * @param {(d: string, f: boolean) => void} assert asserting direct value
+ * @returns {string} mapping result
+ */
+function targetMapping(
+	remainingRequest,
+	isPattern,
+	isSubpathMapping,
+	mappingTarget,
+	assert
+) {
+	if (remainingRequest === undefined) {
+		assert(mappingTarget, false);
+
+		return mappingTarget;
+	}
+
+	if (isSubpathMapping) {
+		assert(mappingTarget, true);
+
+		return mappingTarget + remainingRequest;
+	}
+
+	assert(mappingTarget, false);
+
+	let result = mappingTarget;
+
+	if (isPattern) {
+		result = result.replace(
+			patternRegEx,
+			remainingRequest.replace(/\$/g, "$$")
+		);
+	}
+
+	return result;
+}
+
+/**
+ * @param {ConditionalMapping} conditionalMapping_ conditional mapping
+ * @param {Set<string>} conditionNames condition names
+ * @returns {DirectMapping|null} direct mapping if found
+ */
+function conditionalMapping(conditionalMapping_, conditionNames) {
+	/** @type {[ConditionalMapping, string[], number][]} */
+	let lookup = [[conditionalMapping_, Object.keys(conditionalMapping_), 0]];
+
+	loop: while (lookup.length > 0) {
+		const [mapping, conditions, j] = lookup[lookup.length - 1];
+
+		for (let i = j; i < conditions.length; i++) {
+			const condition = conditions[i];
+
+			if (condition === "default") {
+				const innerMapping = mapping[condition];
+				// is nested
+				if (isConditionalMapping(innerMapping)) {
+					const conditionalMapping = /** @type {ConditionalMapping} */ (
+						innerMapping
+					);
+					lookup[lookup.length - 1][2] = i + 1;
+					lookup.push([conditionalMapping, Object.keys(conditionalMapping), 0]);
+					continue loop;
+				}
+
+				return /** @type {DirectMapping} */ (innerMapping);
+			}
+
+			if (conditionNames.has(condition)) {
+				const innerMapping = mapping[condition];
+				// is nested
+				if (isConditionalMapping(innerMapping)) {
+					const conditionalMapping = /** @type {ConditionalMapping} */ (
+						innerMapping
+					);
+					lookup[lookup.length - 1][2] = i + 1;
+					lookup.push([conditionalMapping, Object.keys(conditionalMapping), 0]);
+					continue loop;
+				}
+
+				return /** @type {DirectMapping} */ (innerMapping);
+			}
+		}
+
+		lookup.pop();
+	}
+
+	return null;
+}
+
+/**
+ * @param {ExportsField} field exports field
+ * @returns {ExportsField} normalized exports field
+ */
+function buildExportsField(field) {
+	// handle syntax sugar, if exports field is direct mapping for "."
+	if (typeof field === "string" || Array.isArray(field)) {
+		return { ".": field };
+	}
+
+	const keys = Object.keys(field);
+
+	for (let i = 0; i < keys.length; i++) {
+		const key = keys[i];
+
+		if (key.charCodeAt(0) !== dotCode) {
+			// handle syntax sugar, if exports field is conditional mapping for "."
+			if (i === 0) {
+				while (i < keys.length) {
+					const charCode = keys[i].charCodeAt(0);
+					if (charCode === dotCode || charCode === slashCode) {
+						throw new Error(
+							`Exports field key should be relative path and start with "." (key: ${JSON.stringify(
+								key
+							)})`
+						);
+					}
+					i++;
+				}
+
+				return { ".": field };
+			}
+
+			throw new Error(
+				`Exports field key should be relative path and start with "." (key: ${JSON.stringify(
+					key
+				)})`
+			);
+		}
+
+		if (key.length === 1) {
+			continue;
+		}
+
+		if (key.charCodeAt(1) !== slashCode) {
+			throw new Error(
+				`Exports field key should be relative path and start with "./" (key: ${JSON.stringify(
+					key
+				)})`
+			);
+		}
+	}
+
+	return field;
+}
Index: imaps-frontend/node_modules/enhanced-resolve/lib/util/identifier.js
===================================================================
--- imaps-frontend/node_modules/enhanced-resolve/lib/util/identifier.js	(revision 79a03170cdde4e801d12257ee86723774970427b)
+++ imaps-frontend/node_modules/enhanced-resolve/lib/util/identifier.js	(revision 79a03170cdde4e801d12257ee86723774970427b)
@@ -0,0 +1,27 @@
+/*
+	MIT License http://www.opensource.org/licenses/mit-license.php
+	Author Ivan Kopeykin @vankop
+*/
+
+"use strict";
+
+const PATH_QUERY_FRAGMENT_REGEXP =
+	/^(#?(?:\0.|[^?#\0])*)(\?(?:\0.|[^#\0])*)?(#.*)?$/;
+
+/**
+ * @param {string} identifier identifier
+ * @returns {[string, string, string]|null} parsed identifier
+ */
+function parseIdentifier(identifier) {
+	const match = PATH_QUERY_FRAGMENT_REGEXP.exec(identifier);
+
+	if (!match) return null;
+
+	return [
+		match[1].replace(/\0(.)/g, "$1"),
+		match[2] ? match[2].replace(/\0(.)/g, "$1") : "",
+		match[3] || ""
+	];
+}
+
+module.exports.parseIdentifier = parseIdentifier;
Index: imaps-frontend/node_modules/enhanced-resolve/lib/util/module-browser.js
===================================================================
--- imaps-frontend/node_modules/enhanced-resolve/lib/util/module-browser.js	(revision 79a03170cdde4e801d12257ee86723774970427b)
+++ imaps-frontend/node_modules/enhanced-resolve/lib/util/module-browser.js	(revision 79a03170cdde4e801d12257ee86723774970427b)
@@ -0,0 +1,8 @@
+/*
+	MIT License http://www.opensource.org/licenses/mit-license.php
+	Author Tobias Koppers @sokra
+*/
+
+"use strict";
+
+module.exports = {};
Index: imaps-frontend/node_modules/enhanced-resolve/lib/util/path.js
===================================================================
--- imaps-frontend/node_modules/enhanced-resolve/lib/util/path.js	(revision 79a03170cdde4e801d12257ee86723774970427b)
+++ imaps-frontend/node_modules/enhanced-resolve/lib/util/path.js	(revision 79a03170cdde4e801d12257ee86723774970427b)
@@ -0,0 +1,203 @@
+/*
+	MIT License http://www.opensource.org/licenses/mit-license.php
+	Author Tobias Koppers @sokra
+*/
+
+"use strict";
+
+const path = require("path");
+
+const CHAR_HASH = "#".charCodeAt(0);
+const CHAR_SLASH = "/".charCodeAt(0);
+const CHAR_BACKSLASH = "\\".charCodeAt(0);
+const CHAR_A = "A".charCodeAt(0);
+const CHAR_Z = "Z".charCodeAt(0);
+const CHAR_LOWER_A = "a".charCodeAt(0);
+const CHAR_LOWER_Z = "z".charCodeAt(0);
+const CHAR_DOT = ".".charCodeAt(0);
+const CHAR_COLON = ":".charCodeAt(0);
+
+const posixNormalize = path.posix.normalize;
+const winNormalize = path.win32.normalize;
+
+/**
+ * @enum {number}
+ */
+const PathType = Object.freeze({
+	Empty: 0,
+	Normal: 1,
+	Relative: 2,
+	AbsoluteWin: 3,
+	AbsolutePosix: 4,
+	Internal: 5
+});
+exports.PathType = PathType;
+
+const invalidSegmentRegEx =
+	/(^|\\|\/)((\.|%2e)(\.|%2e)?|(n|%6e|%4e)(o|%6f|%4f)(d|%64|%44)(e|%65|%45)(_|%5f)(m|%6d|%4d)(o|%6f|%4f)(d|%64|%44)(u|%75|%55)(l|%6c|%4c)(e|%65|%45)(s|%73|%53))?(\\|\/|$)/i;
+exports.invalidSegmentRegEx = invalidSegmentRegEx;
+
+const deprecatedInvalidSegmentRegEx =
+	/(^|\\|\/)((\.|%2e)(\.|%2e)?|(n|%6e|%4e)(o|%6f|%4f)(d|%64|%44)(e|%65|%45)(_|%5f)(m|%6d|%4d)(o|%6f|%4f)(d|%64|%44)(u|%75|%55)(l|%6c|%4c)(e|%65|%45)(s|%73|%53))(\\|\/|$)/i;
+exports.deprecatedInvalidSegmentRegEx = deprecatedInvalidSegmentRegEx;
+
+/**
+ * @param {string} p a path
+ * @returns {PathType} type of path
+ */
+const getType = p => {
+	switch (p.length) {
+		case 0:
+			return PathType.Empty;
+		case 1: {
+			const c0 = p.charCodeAt(0);
+			switch (c0) {
+				case CHAR_DOT:
+					return PathType.Relative;
+				case CHAR_SLASH:
+					return PathType.AbsolutePosix;
+				case CHAR_HASH:
+					return PathType.Internal;
+			}
+			return PathType.Normal;
+		}
+		case 2: {
+			const c0 = p.charCodeAt(0);
+			switch (c0) {
+				case CHAR_DOT: {
+					const c1 = p.charCodeAt(1);
+					switch (c1) {
+						case CHAR_DOT:
+						case CHAR_SLASH:
+							return PathType.Relative;
+					}
+					return PathType.Normal;
+				}
+				case CHAR_SLASH:
+					return PathType.AbsolutePosix;
+				case CHAR_HASH:
+					return PathType.Internal;
+			}
+			const c1 = p.charCodeAt(1);
+			if (c1 === CHAR_COLON) {
+				if (
+					(c0 >= CHAR_A && c0 <= CHAR_Z) ||
+					(c0 >= CHAR_LOWER_A && c0 <= CHAR_LOWER_Z)
+				) {
+					return PathType.AbsoluteWin;
+				}
+			}
+			return PathType.Normal;
+		}
+	}
+	const c0 = p.charCodeAt(0);
+	switch (c0) {
+		case CHAR_DOT: {
+			const c1 = p.charCodeAt(1);
+			switch (c1) {
+				case CHAR_SLASH:
+					return PathType.Relative;
+				case CHAR_DOT: {
+					const c2 = p.charCodeAt(2);
+					if (c2 === CHAR_SLASH) return PathType.Relative;
+					return PathType.Normal;
+				}
+			}
+			return PathType.Normal;
+		}
+		case CHAR_SLASH:
+			return PathType.AbsolutePosix;
+		case CHAR_HASH:
+			return PathType.Internal;
+	}
+	const c1 = p.charCodeAt(1);
+	if (c1 === CHAR_COLON) {
+		const c2 = p.charCodeAt(2);
+		if (
+			(c2 === CHAR_BACKSLASH || c2 === CHAR_SLASH) &&
+			((c0 >= CHAR_A && c0 <= CHAR_Z) ||
+				(c0 >= CHAR_LOWER_A && c0 <= CHAR_LOWER_Z))
+		) {
+			return PathType.AbsoluteWin;
+		}
+	}
+	return PathType.Normal;
+};
+exports.getType = getType;
+
+/**
+ * @param {string} p a path
+ * @returns {string} the normalized path
+ */
+const normalize = p => {
+	switch (getType(p)) {
+		case PathType.Empty:
+			return p;
+		case PathType.AbsoluteWin:
+			return winNormalize(p);
+		case PathType.Relative: {
+			const r = posixNormalize(p);
+			return getType(r) === PathType.Relative ? r : `./${r}`;
+		}
+	}
+	return posixNormalize(p);
+};
+exports.normalize = normalize;
+
+/**
+ * @param {string} rootPath the root path
+ * @param {string | undefined} request the request path
+ * @returns {string} the joined path
+ */
+const join = (rootPath, request) => {
+	if (!request) return normalize(rootPath);
+	const requestType = getType(request);
+	switch (requestType) {
+		case PathType.AbsolutePosix:
+			return posixNormalize(request);
+		case PathType.AbsoluteWin:
+			return winNormalize(request);
+	}
+	switch (getType(rootPath)) {
+		case PathType.Normal:
+		case PathType.Relative:
+		case PathType.AbsolutePosix:
+			return posixNormalize(`${rootPath}/${request}`);
+		case PathType.AbsoluteWin:
+			return winNormalize(`${rootPath}\\${request}`);
+	}
+	switch (requestType) {
+		case PathType.Empty:
+			return rootPath;
+		case PathType.Relative: {
+			const r = posixNormalize(rootPath);
+			return getType(r) === PathType.Relative ? r : `./${r}`;
+		}
+	}
+	return posixNormalize(rootPath);
+};
+exports.join = join;
+
+/** @type {Map<string, Map<string, string | undefined>>} */
+const joinCache = new Map();
+
+/**
+ * @param {string} rootPath the root path
+ * @param {string} request the request path
+ * @returns {string} the joined path
+ */
+const cachedJoin = (rootPath, request) => {
+	/** @type {string | undefined} */
+	let cacheEntry;
+	let cache = joinCache.get(rootPath);
+	if (cache === undefined) {
+		joinCache.set(rootPath, (cache = new Map()));
+	} else {
+		cacheEntry = cache.get(request);
+		if (cacheEntry !== undefined) return cacheEntry;
+	}
+	cacheEntry = join(rootPath, request);
+	cache.set(request, cacheEntry);
+	return cacheEntry;
+};
+exports.cachedJoin = cachedJoin;
Index: imaps-frontend/node_modules/enhanced-resolve/lib/util/process-browser.js
===================================================================
--- imaps-frontend/node_modules/enhanced-resolve/lib/util/process-browser.js	(revision 79a03170cdde4e801d12257ee86723774970427b)
+++ imaps-frontend/node_modules/enhanced-resolve/lib/util/process-browser.js	(revision 79a03170cdde4e801d12257ee86723774970427b)
@@ -0,0 +1,22 @@
+/*
+	MIT License http://www.opensource.org/licenses/mit-license.php
+	Author Tobias Koppers @sokra
+*/
+
+"use strict";
+
+module.exports = {
+	/**
+	 * @type {Record<string, string>}
+	 */
+	versions: {},
+	/**
+	 * @param {function} fn function
+	 */
+	nextTick(fn) {
+		const args = Array.prototype.slice.call(arguments, 1);
+		Promise.resolve().then(function () {
+			fn.apply(null, args);
+		});
+	}
+};
