merge new into master

This commit is contained in:
2026-02-05 17:31:20 +00:00
16267 changed files with 2194867 additions and 0 deletions

577
node_modules/enhanced-resolve/lib/util/entrypoints.js generated vendored Normal file
View File

@@ -0,0 +1,577 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Ivan Kopeykin @vankop
*/
"use strict";
const { parseIdentifier } = require("./identifier");
/** @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 slashCode = "/".charCodeAt(0);
const dotCode = ".".charCodeAt(0);
const hashCode = "#".charCodeAt(0);
const patternRegEx = /\*/g;
/**
* @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 {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][]} */
const 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 {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 {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 {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 {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;
}
/**
* @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 {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 {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");
}
// Note: #/ patterns are now allowed per Node.js PR #60864
// https://github.com/nodejs/node/pull/60864
if (request.charCodeAt(request.length - 1) === slashCode) {
throw new Error("Only requesting file allowed");
}
return request.slice(1);
}
/**
* @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 {ImportsField} importsField the exports field
* @returns {FieldProcessor} process callback
*/
module.exports.processImportsField = function processImportsField(
importsField,
) {
return createFieldProcessor(
importsField,
(request) => `#${request}`,
assertImportsFieldRequest,
assertImportTarget,
);
};

38
node_modules/enhanced-resolve/lib/util/fs.js generated vendored Normal file
View File

@@ -0,0 +1,38 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Natsu @xiaoxiaojx
*/
"use strict";
/** @typedef {import("../Resolver").FileSystem} FileSystem */
/**
* Read and parse JSON file
* @template T
* @param {FileSystem} fileSystem the file system
* @param {string} jsonFilePath absolute path to JSON file
* @returns {Promise<T>} parsed JSON content
*/
async function readJson(fileSystem, jsonFilePath) {
const { readJson } = fileSystem;
if (readJson) {
return new Promise((resolve, reject) => {
readJson(jsonFilePath, (err, content) => {
if (err) return reject(err);
resolve(/** @type {T} */ (content));
});
});
}
const buf = await new Promise((resolve, reject) => {
fileSystem.readFile(jsonFilePath, (err, data) => {
if (err) return reject(err);
resolve(data);
});
});
return JSON.parse(/** @type {string} */ (buf.toString()));
}
module.exports.readJson = readJson;

77
node_modules/enhanced-resolve/lib/util/identifier.js generated vendored Normal file
View File

@@ -0,0 +1,77 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Ivan Kopeykin @vankop
*/
"use strict";
const memorize = require("./memoize");
const getUrl = memorize(() => require("url"));
const PATH_QUERY_FRAGMENT_REGEXP =
/^(#?(?:\0.|[^?#\0])*)(\?(?:\0.|[^#\0])*)?(#.*)?$/;
const ZERO_ESCAPE_REGEXP = /\0(.)/g;
const FILE_REG_EXP = /file:/i;
/**
* @param {string} identifier identifier
* @returns {[string, string, string] | null} parsed identifier
*/
function parseIdentifier(identifier) {
if (!identifier) {
return null;
}
if (FILE_REG_EXP.test(identifier)) {
identifier = getUrl().fileURLToPath(identifier);
}
const firstEscape = identifier.indexOf("\0");
// Handle `\0`
if (firstEscape !== -1) {
const match = PATH_QUERY_FRAGMENT_REGEXP.exec(identifier);
if (!match) return null;
return [
match[1].replace(ZERO_ESCAPE_REGEXP, "$1"),
match[2] ? match[2].replace(ZERO_ESCAPE_REGEXP, "$1") : "",
match[3] || "",
];
}
// Fast path for inputs that don't use \0 escaping.
const queryStart = identifier.indexOf("?");
// Start at index 1 to ignore a possible leading hash.
const fragmentStart = identifier.indexOf("#", 1);
if (fragmentStart < 0) {
if (queryStart < 0) {
// No fragment, no query
return [identifier, "", ""];
}
// Query, no fragment
return [identifier.slice(0, queryStart), identifier.slice(queryStart), ""];
}
if (queryStart < 0 || fragmentStart < queryStart) {
// Fragment, no query
return [
identifier.slice(0, fragmentStart),
"",
identifier.slice(fragmentStart),
];
}
// Query and fragment
return [
identifier.slice(0, queryStart),
identifier.slice(queryStart, fragmentStart),
identifier.slice(fragmentStart),
];
}
module.exports.parseIdentifier = parseIdentifier;

37
node_modules/enhanced-resolve/lib/util/memoize.js generated vendored Normal file
View File

@@ -0,0 +1,37 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
/**
* @template T
* @typedef {() => T} FunctionReturning
*/
/**
* @template T
* @param {FunctionReturning<T>} fn memorized function
* @returns {FunctionReturning<T>} new function
*/
const memoize = (fn) => {
let cache = false;
/** @type {T | undefined} */
let result;
return () => {
if (cache) {
return /** @type {T} */ (result);
}
result = fn();
cache = true;
// Allow to clean up memory for fn
// and all dependent resources
/** @type {FunctionReturning<T> | undefined} */
(fn) = undefined;
return /** @type {T} */ (result);
};
};
module.exports = memoize;

View File

@@ -0,0 +1,8 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
module.exports = {};

250
node_modules/enhanced-resolve/lib/util/path.js generated vendored Normal file
View File

@@ -0,0 +1,250 @@
/*
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,
});
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;
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;
/**
* @param {string} maybePath a path
* @returns {PathType} type of path
*/
const getType = (maybePath) => {
switch (maybePath.length) {
case 0:
return PathType.Empty;
case 1: {
const c0 = maybePath.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 = maybePath.charCodeAt(0);
switch (c0) {
case CHAR_DOT: {
const c1 = maybePath.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 = maybePath.charCodeAt(1);
if (
c1 === CHAR_COLON &&
((c0 >= CHAR_A && c0 <= CHAR_Z) ||
(c0 >= CHAR_LOWER_A && c0 <= CHAR_LOWER_Z))
) {
return PathType.AbsoluteWin;
}
return PathType.Normal;
}
}
const c0 = maybePath.charCodeAt(0);
switch (c0) {
case CHAR_DOT: {
const c1 = maybePath.charCodeAt(1);
switch (c1) {
case CHAR_SLASH:
return PathType.Relative;
case CHAR_DOT: {
const c2 = maybePath.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 = maybePath.charCodeAt(1);
if (c1 === CHAR_COLON) {
const c2 = maybePath.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;
};
/**
* @param {string} maybePath a path
* @returns {string} the normalized path
*/
const normalize = (maybePath) => {
switch (getType(maybePath)) {
case PathType.Empty:
return maybePath;
case PathType.AbsoluteWin:
return winNormalize(maybePath);
case PathType.Relative: {
const r = posixNormalize(maybePath);
return getType(r) === PathType.Relative ? r : `./${r}`;
}
}
return posixNormalize(maybePath);
};
/**
* @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);
};
/**
* @param {string} maybePath a path
* @returns {string} the directory name
*/
const dirname = (maybePath) => {
switch (getType(maybePath)) {
case PathType.AbsoluteWin:
return path.win32.dirname(maybePath);
}
return path.posix.dirname(maybePath);
};
/** @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;
};
/** @type {Map<string, string>} */
const dirnameCache = new Map();
/**
* @param {string} maybePath a path
* @returns {string} the directory name
*/
const cachedDirname = (maybePath) => {
const cacheEntry = dirnameCache.get(maybePath);
if (cacheEntry !== undefined) return cacheEntry;
const result = dirname(maybePath);
dirnameCache.set(maybePath, result);
return result;
};
/**
* Check if childPath is a subdirectory of parentPath
* @param {string} parentPath parent directory path
* @param {string} childPath child path to check
* @returns {boolean} true if childPath is under parentPath
*/
const isSubPath = (parentPath, childPath) => {
// Ensure parentPath ends with a separator to avoid false matches
// e.g., "/app" shouldn't match "/app-other"
const parentWithSlash =
parentPath.endsWith("/") || parentPath.endsWith("\\")
? parentPath
: normalize(`${parentPath}/`);
return childPath.startsWith(parentWithSlash);
};
module.exports.PathType = PathType;
module.exports.cachedDirname = cachedDirname;
module.exports.cachedJoin = cachedJoin;
module.exports.deprecatedInvalidSegmentRegEx = deprecatedInvalidSegmentRegEx;
module.exports.dirname = dirname;
module.exports.getType = getType;
module.exports.invalidSegmentRegEx = invalidSegmentRegEx;
module.exports.isSubPath = isSubPath;
module.exports.join = join;
module.exports.normalize = normalize;

View File

@@ -0,0 +1,23 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
module.exports = {
/**
* @type {Record<string, string>}
*/
versions: {},
// eslint-disable-next-line jsdoc/reject-function-type
/** @param {Function} fn function */
nextTick(fn) {
// eslint-disable-next-line prefer-rest-params
const args = Array.prototype.slice.call(arguments, 1);
Promise.resolve().then(() => {
// eslint-disable-next-line prefer-spread
fn.apply(null, args);
});
},
};