Something went wrong. Try again.
MIRROR: javascript for 🐜's, a tiny runtime with big ambitions ant.themackabu.dev
Something went wrong. Try again.
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717// Copyright Joyent, Inc. and other Node 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.
'use strict';
// Adapted from Node.js v26.5.1 lib/path.js; keep the algorithms in sync upstream.
const { ArrayPrototypeIncludes, ArrayPrototypeJoin, ArrayPrototypePush, ArrayPrototypeSlice, FunctionPrototypeBind, StringPrototypeCharCodeAt, StringPrototypeIncludes, StringPrototypeIndexOf, StringPrototypeLastIndexOf, StringPrototypeRepeat, StringPrototypeReplace, StringPrototypeSlice, StringPrototypeSplit, StringPrototypeToLowerCase, StringPrototypeToUpperCase,} = require('ant:internal/primordials');
const { CHAR_UPPERCASE_A, CHAR_LOWERCASE_A, CHAR_UPPERCASE_Z, CHAR_LOWERCASE_Z, CHAR_DOT, CHAR_FORWARD_SLASH, CHAR_BACKWARD_SLASH, CHAR_COLON, CHAR_QUESTION_MARK,} = require('ant:internal/path_helpers');
const { validateObject, validateString,} = require('ant:internal/path_helpers');
const { isWindows, getLazy,} = require('ant:internal/path_helpers');
const lazyMatchGlobPattern = getLazy(() => require('ant:internal/path_glob').matchGlobPattern);
function isPathSeparator(code) { return code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH;}
function isPosixPathSeparator(code) { return code === CHAR_FORWARD_SLASH;}
const WINDOWS_RESERVED_NAMES = [ 'CON', 'PRN', 'AUX', 'NUL', 'COM1', 'COM2', 'COM3', 'COM4', 'COM5', 'COM6', 'COM7', 'COM8', 'COM9', 'LPT1', 'LPT2', 'LPT3', 'LPT4', 'LPT5', 'LPT6', 'LPT7', 'LPT8', 'LPT9', 'COM\xb9', 'COM\xb2', 'COM\xb3', 'LPT\xb9', 'LPT\xb2', 'LPT\xb3',];
function isWindowsReservedName(path, colonIndex) { const devicePart = StringPrototypeToUpperCase(StringPrototypeSlice(path, 0, colonIndex)); return ArrayPrototypeIncludes(WINDOWS_RESERVED_NAMES, devicePart);}
function isWindowsDeviceRoot(code) { return (code >= CHAR_UPPERCASE_A && code <= CHAR_UPPERCASE_Z) || (code >= CHAR_LOWERCASE_A && code <= CHAR_LOWERCASE_Z);}
// Resolves . and .. elements in a path with directory namesfunction normalizeString(path, allowAboveRoot, separator, isPathSeparator) { let res = ''; let lastSegmentLength = 0; let lastSlash = -1; let dots = 0; let code = 0; for (let i = 0; i <= path.length; ++i) { if (i < path.length) code = StringPrototypeCharCodeAt(path, i); else if (isPathSeparator(code)) break; else code = CHAR_FORWARD_SLASH;
if (isPathSeparator(code)) { if (lastSlash === i - 1 || dots === 1) { // NOOP } else if (dots === 2) { if (res.length < 2 || lastSegmentLength !== 2 || StringPrototypeCharCodeAt(res, res.length - 1) !== CHAR_DOT || StringPrototypeCharCodeAt(res, res.length - 2) !== CHAR_DOT) { if (res.length > 2) { const lastSlashIndex = res.length - lastSegmentLength - 1; if (lastSlashIndex === -1) { res = ''; lastSegmentLength = 0; } else { res = StringPrototypeSlice(res, 0, lastSlashIndex); lastSegmentLength = res.length - 1 - StringPrototypeLastIndexOf(res, separator); } lastSlash = i; dots = 0; continue; } else if (res.length !== 0) { res = ''; lastSegmentLength = 0; lastSlash = i; dots = 0; continue; } } if (allowAboveRoot) { res += res.length > 0 ? `${separator}..` : '..'; lastSegmentLength = 2; } } else { if (res.length > 0) res += `${separator}${StringPrototypeSlice(path, lastSlash + 1, i)}`; else res = StringPrototypeSlice(path, lastSlash + 1, i); lastSegmentLength = i - lastSlash - 1; } lastSlash = i; dots = 0; } else if (code === CHAR_DOT && dots !== -1) { ++dots; } else { dots = -1; } } return res;}
function formatExt(ext) { return ext ? `${ext[0] === '.' ? '' : '.'}${ext}` : '';}
/** * @param {string} sep * @param {{ * dir?: string; * root?: string; * base?: string; * name?: string; * ext?: string; * }} pathObject * @returns {string} */function _format(sep, pathObject) { validateObject(pathObject, 'pathObject'); const dir = pathObject.dir || pathObject.root; const base = pathObject.base || `${pathObject.name || ''}${formatExt(pathObject.ext)}`; if (!dir) { return base; } return dir === pathObject.root ? `${dir}${base}` : `${dir}${sep}${base}`;}
const forwardSlashRegExp = /\//g;
const win32 = { /** * path.resolve([from ...], to) * @param {...string} args * @returns {string} */ resolve(...args) { let resolvedDevice = ''; let resolvedTail = ''; let resolvedAbsolute = false;
for (let i = args.length - 1; i >= -1; i--) { let path; if (i >= 0) { path = args[i]; validateString(path, `paths[${i}]`);
// Skip empty entries if (path.length === 0) { continue; } } else if (resolvedDevice.length === 0) { path = process.cwd(); // Fast path for current directory if (args.length === 0 || ((args.length === 1 && (args[0] === '' || args[0] === '.')) && isPathSeparator(StringPrototypeCharCodeAt(path, 0)))) { if (!isWindows) { path = StringPrototypeReplace(path, forwardSlashRegExp, '\\'); } return path; } } else { // Windows has the concept of drive-specific current working // directories. If we've resolved a drive letter but not yet an // absolute path, get cwd for that drive, or the process cwd if // the drive cwd is not available. We're sure the device is not // a UNC path at this points, because UNC paths are always absolute. path = process.env[`=${resolvedDevice}`] || process.cwd();
// Verify that a cwd was found and that it actually points // to our drive. If not, default to the drive's root. if (path === undefined || (StringPrototypeToLowerCase(StringPrototypeSlice(path, 0, 2)) !== StringPrototypeToLowerCase(resolvedDevice) && StringPrototypeCharCodeAt(path, 2) === CHAR_BACKWARD_SLASH)) { path = `${resolvedDevice}\\`; } }
const len = path.length; let rootEnd = 0; let device = ''; let isAbsolute = false; const code = StringPrototypeCharCodeAt(path, 0);
// Try to match a root if (len === 1) { if (isPathSeparator(code)) { // `path` contains just a path separator rootEnd = 1; isAbsolute = true; } } else if (isPathSeparator(code)) { // Possible UNC root
// If we started with a separator, we know we at least have an // absolute path of some kind (UNC or otherwise) isAbsolute = true;
if (isPathSeparator(StringPrototypeCharCodeAt(path, 1))) { // Matched double path separator at beginning let j = 2; let last = j; // Match 1 or more non-path separators while (j < len && !isPathSeparator(StringPrototypeCharCodeAt(path, j))) { j++; } if (j < len && j !== last) { const firstPart = StringPrototypeSlice(path, last, j); // Matched! last = j; // Match 1 or more path separators while (j < len && isPathSeparator(StringPrototypeCharCodeAt(path, j))) { j++; } if (j < len && j !== last) { // Matched! last = j; // Match 1 or more non-path separators while (j < len && !isPathSeparator(StringPrototypeCharCodeAt(path, j))) { j++; } if (j === len || j !== last) { if (firstPart !== '.' && firstPart !== '?') { // We matched a UNC root device = `\\\\${firstPart}\\${StringPrototypeSlice(path, last, j)}`; rootEnd = j; } else { // We matched a device root (e.g. \\\\.\\PHYSICALDRIVE0) device = `\\\\${firstPart}`; rootEnd = 4; } } } } } else { rootEnd = 1; } } else if (isWindowsDeviceRoot(code) && StringPrototypeCharCodeAt(path, 1) === CHAR_COLON) { // Possible device root device = StringPrototypeSlice(path, 0, 2); rootEnd = 2; if (len > 2 && isPathSeparator(StringPrototypeCharCodeAt(path, 2))) { // Treat separator following drive name as an absolute path // indicator isAbsolute = true; rootEnd = 3; } }
if (device.length > 0) { if (resolvedDevice.length > 0) { if (StringPrototypeToLowerCase(device) !== StringPrototypeToLowerCase(resolvedDevice)) // This path points to another device so it is not applicable continue; } else { resolvedDevice = device; } }
if (resolvedAbsolute) { if (resolvedDevice.length > 0) break; } else { resolvedTail = `${StringPrototypeSlice(path, rootEnd)}\\${resolvedTail}`; resolvedAbsolute = isAbsolute; if (isAbsolute && resolvedDevice.length > 0) { break; } } }
// At this point the path should be resolved to a full absolute path, // but handle relative paths to be safe (might happen when process.cwd() // fails)
// Normalize the tail path resolvedTail = normalizeString(resolvedTail, !resolvedAbsolute, '\\', isPathSeparator);
return resolvedAbsolute ? `${resolvedDevice}\\${resolvedTail}` : `${resolvedDevice}${resolvedTail}` || '.'; },
/** * @param {string} path * @returns {string} */ normalize(path) { validateString(path, 'path'); const len = path.length; if (len === 0) return '.'; let rootEnd = 0; let device; let isAbsolute = false; const code = StringPrototypeCharCodeAt(path, 0);
// Try to match a root if (len === 1) { // `path` contains just a single char, exit early to avoid // unnecessary work return isPosixPathSeparator(code) ? '\\' : path; } if (isPathSeparator(code)) { // Possible UNC root
// If we started with a separator, we know we at least have an absolute // path of some kind (UNC or otherwise) isAbsolute = true;
if (isPathSeparator(StringPrototypeCharCodeAt(path, 1))) { // Matched double path separator at beginning let j = 2; let last = j; // Match 1 or more non-path separators while (j < len && !isPathSeparator(StringPrototypeCharCodeAt(path, j))) { j++; } if (j < len && j !== last) { const firstPart = StringPrototypeSlice(path, last, j); // Matched! last = j; // Match 1 or more path separators while (j < len && isPathSeparator(StringPrototypeCharCodeAt(path, j))) { j++; } if (j < len && j !== last) { // Matched! last = j; // Match 1 or more non-path separators while (j < len && !isPathSeparator(StringPrototypeCharCodeAt(path, j))) { j++; } if (j === len || j !== last) { if (firstPart === '.' || firstPart === '?') { // We matched a device root (e.g. \\\\.\\PHYSICALDRIVE0) device = `\\\\${firstPart}`; rootEnd = 4; const colonIndex = StringPrototypeIndexOf(path, ':'); // Special case: handle \\?\COM1: or similar reserved device paths const possibleDevice = StringPrototypeSlice(path, 4, colonIndex + 1); if (isWindowsReservedName(possibleDevice, possibleDevice.length - 1)) { device = `\\\\?\\${possibleDevice}`; rootEnd = 4 + possibleDevice.length; } } else if (j === len) { // We matched a UNC root only // Return the normalized version of the UNC root since there // is nothing left to process return `\\\\${firstPart}\\${StringPrototypeSlice(path, last)}\\`; } else { // We matched a UNC root with leftovers device = `\\\\${firstPart}\\${StringPrototypeSlice(path, last, j)}`; rootEnd = j; } } } } } else { rootEnd = 1; } } else { const colonIndex = StringPrototypeIndexOf(path, ':'); if (colonIndex > 0) { if (isWindowsDeviceRoot(code) && colonIndex === 1) { device = StringPrototypeSlice(path, 0, 2); rootEnd = 2; if (len > 2 && isPathSeparator(StringPrototypeCharCodeAt(path, 2))) { isAbsolute = true; rootEnd = 3; } } else if (isWindowsReservedName(path, colonIndex)) { device = StringPrototypeSlice(path, 0, colonIndex + 1); rootEnd = colonIndex + 1;
} } }
let tail = rootEnd < len ? normalizeString(StringPrototypeSlice(path, rootEnd), !isAbsolute, '\\', isPathSeparator) : ''; if (tail.length === 0 && !isAbsolute) tail = '.'; if (tail.length > 0 && isPathSeparator(StringPrototypeCharCodeAt(path, len - 1))) tail += '\\'; if (!isAbsolute && device === undefined && StringPrototypeIncludes(path, ':')) { // If the original path was not absolute and if we have not been able to // resolve it relative to a particular device, we need to ensure that the // `tail` has not become something that Windows might interpret as an // absolute path. See CVE-2024-36139. if (tail.length >= 2 && isWindowsDeviceRoot(StringPrototypeCharCodeAt(tail, 0)) && StringPrototypeCharCodeAt(tail, 1) === CHAR_COLON) { return `.\\${tail}`; } let index = StringPrototypeIndexOf(path, ':');
do { if (index === len - 1 || isPathSeparator(StringPrototypeCharCodeAt(path, index + 1))) { return `.\\${tail}`; } } while ((index = StringPrototypeIndexOf(path, ':', index + 1)) !== -1); } const colonIndex = StringPrototypeIndexOf(path, ':'); if (colonIndex !== -1 && isWindowsReservedName(path, colonIndex)) { return `.\\${device ?? ''}${tail}`; } if (device === undefined) { return isAbsolute ? `\\${tail}` : tail; } return isAbsolute ? `${device}\\${tail}` : `${device}${tail}`; },
/** * @param {string} path * @returns {boolean} */ isAbsolute(path) { validateString(path, 'path'); const len = path.length; if (len === 0) return false;
const code = StringPrototypeCharCodeAt(path, 0); return isPathSeparator(code) || // Possible device root (len > 2 && isWindowsDeviceRoot(code) && StringPrototypeCharCodeAt(path, 1) === CHAR_COLON && isPathSeparator(StringPrototypeCharCodeAt(path, 2))); },
/** * @param {...string} args * @returns {string} */ join(...args) { if (args.length === 0) return '.';
const path = []; for (let i = 0; i < args.length; ++i) { const arg = args[i]; validateString(arg, 'path'); if (arg.length > 0) { ArrayPrototypePush(path, arg); } }
if (path.length === 0) return '.';
const firstPart = path[0]; let joined = ArrayPrototypeJoin(path, '\\');
// Make sure that the joined path doesn't start with two slashes, because // normalize() will mistake it for a UNC path then. // // This step is skipped when it is very clear that the user actually // intended to point at a UNC path. This is assumed when the first // non-empty string arguments starts with exactly two slashes followed by // at least one more non-slash character. // // Note that for normalize() to treat a path as a UNC path it needs to // have at least 2 components, so we don't filter for that here. // This means that the user can use join to construct UNC paths from // a server name and a share name; for example: // path.join('//server', 'share') -> '\\\\server\\share\\') let needsReplace = true; let slashCount = 0; if (isPathSeparator(StringPrototypeCharCodeAt(firstPart, 0))) { ++slashCount; const firstLen = firstPart.length; if (firstLen > 1 && isPathSeparator(StringPrototypeCharCodeAt(firstPart, 1))) { ++slashCount; if (firstLen > 2) { if (isPathSeparator(StringPrototypeCharCodeAt(firstPart, 2))) ++slashCount; else { // We matched a UNC path in the first part needsReplace = false; } } } } if (needsReplace) { // Find any more consecutive slashes we need to replace while (slashCount < joined.length && isPathSeparator(StringPrototypeCharCodeAt(joined, slashCount))) { slashCount++; }
// Replace the slashes if needed if (slashCount >= 2) joined = `\\${StringPrototypeSlice(joined, slashCount)}`; }
// Skip normalization when reserved device names are present const parts = []; let part = '';
for (let i = 0; i < joined.length; i++) { if (joined[i] === '\\') { if (part) parts.push(part); part = ''; // Skip consecutive backslashes while (i + 1 < joined.length && joined[i + 1] === '\\') i++; } else { part += joined[i]; } } // Add the final part if any if (part) parts.push(part);
// Check if any part has a Windows reserved name if (parts.some((p) => { const colonIndex = StringPrototypeIndexOf(p, ':'); return colonIndex !== -1 && isWindowsReservedName(p, colonIndex); })) { // Replace forward slashes with backslashes let result = ''; for (let i = 0; i < joined.length; i++) { result += joined[i] === '/' ? '\\' : joined[i]; } return result; }
return win32.normalize(joined); },
/** * It will solve the relative path from `from` to `to`, for instance * from = 'C:\\orandea\\test\\aaa' * to = 'C:\\orandea\\impl\\bbb' * The output of the function should be: '..\\..\\impl\\bbb' * @param {string} from * @param {string} to * @returns {string} */ relative(from, to) { validateString(from, 'from'); validateString(to, 'to');
if (from === to) return '';
const fromOrig = win32.resolve(from); const toOrig = win32.resolve(to);
if (fromOrig === toOrig) return '';
from = StringPrototypeToLowerCase(fromOrig); to = StringPrototypeToLowerCase(toOrig);
if (from === to) return '';
if (fromOrig.length !== from.length || toOrig.length !== to.length) { const fromSplit = StringPrototypeSplit(fromOrig, '\\'); const toSplit = StringPrototypeSplit(toOrig, '\\'); if (fromSplit[fromSplit.length - 1] === '') { fromSplit.pop(); } if (toSplit[toSplit.length - 1] === '') { toSplit.pop(); }
const fromLen = fromSplit.length; const toLen = toSplit.length; const length = fromLen < toLen ? fromLen : toLen;
let i; for (i = 0; i < length; i++) { if (StringPrototypeToLowerCase(fromSplit[i]) !== StringPrototypeToLowerCase(toSplit[i])) { break; } }
if (i === 0) { return toOrig; } else if (i === length) { if (toLen > length) { return ArrayPrototypeJoin(ArrayPrototypeSlice(toSplit, i), '\\'); } if (fromLen > length) { return StringPrototypeRepeat('..\\', fromLen - 1 - i) + '..'; } return ''; }
return StringPrototypeRepeat('..\\', fromLen - i) + ArrayPrototypeJoin(ArrayPrototypeSlice(toSplit, i), '\\'); }
// Trim any leading backslashes let fromStart = 0; while (fromStart < from.length && StringPrototypeCharCodeAt(from, fromStart) === CHAR_BACKWARD_SLASH) { fromStart++; } // Trim trailing backslashes (applicable to UNC paths only) let fromEnd = from.length; while ( fromEnd - 1 > fromStart && StringPrototypeCharCodeAt(from, fromEnd - 1) === CHAR_BACKWARD_SLASH ) { fromEnd--; } const fromLen = fromEnd - fromStart;
// Trim any leading backslashes let toStart = 0; while (toStart < to.length && StringPrototypeCharCodeAt(to, toStart) === CHAR_BACKWARD_SLASH) { toStart++; } // Trim trailing backslashes (applicable to UNC paths only) let toEnd = to.length; while (toEnd - 1 > toStart && StringPrototypeCharCodeAt(to, toEnd - 1) === CHAR_BACKWARD_SLASH) { toEnd--; } const toLen = toEnd - toStart;
// Compare paths to find the longest common path from root const length = fromLen < toLen ? fromLen : toLen; let lastCommonSep = -1; let i = 0; for (; i < length; i++) { const fromCode = StringPrototypeCharCodeAt(from, fromStart + i); if (fromCode !== StringPrototypeCharCodeAt(to, toStart + i)) break; else if (fromCode === CHAR_BACKWARD_SLASH) lastCommonSep = i; }
// We found a mismatch before the first common path separator was seen, so // return the original `to`. if (i !== length) { if (lastCommonSep === -1) return toOrig; } else { if (toLen > length) { if (StringPrototypeCharCodeAt(to, toStart + i) === CHAR_BACKWARD_SLASH) { // We get here if `from` is the exact base path for `to`. // For example: from='C:\\foo\\bar'; to='C:\\foo\\bar\\baz' return StringPrototypeSlice(toOrig, toStart + i + 1); } if (i === 2) { // We get here if `from` is the device root. // For example: from='C:\\'; to='C:\\foo' return StringPrototypeSlice(toOrig, toStart + i); } } if (fromLen > length) { if (StringPrototypeCharCodeAt(from, fromStart + i) === CHAR_BACKWARD_SLASH) { // We get here if `to` is the exact base path for `from`. // For example: from='C:\\foo\\bar'; to='C:\\foo' lastCommonSep = i; } else if (i === 2) { // We get here if `to` is the device root. // For example: from='C:\\foo\\bar'; to='C:\\' lastCommonSep = 3; } } if (lastCommonSep === -1) lastCommonSep = 0; }
let out = ''; // Generate the relative path based on the path difference between `to` and // `from` for (i = fromStart + lastCommonSep + 1; i <= fromEnd; ++i) { if (i === fromEnd || StringPrototypeCharCodeAt(from, i) === CHAR_BACKWARD_SLASH) { out += out.length === 0 ? '..' : '\\..'; } }
toStart += lastCommonSep;
// Lastly, append the rest of the destination (`to`) path that comes after // the common path parts if (out.length > 0) return `${out}${StringPrototypeSlice(toOrig, toStart, toEnd)}`;
if (StringPrototypeCharCodeAt(toOrig, toStart) === CHAR_BACKWARD_SLASH) ++toStart; return StringPrototypeSlice(toOrig, toStart, toEnd); },
/** * @param {string} path * @returns {string} */ toNamespacedPath(path) { // Note: this will *probably* throw somewhere. if (typeof path !== 'string' || path.length === 0) return path;
const resolvedPath = win32.resolve(path);
if (resolvedPath.length <= 2) return path;
if (StringPrototypeCharCodeAt(resolvedPath, 0) === CHAR_BACKWARD_SLASH) { // Possible UNC root if (StringPrototypeCharCodeAt(resolvedPath, 1) === CHAR_BACKWARD_SLASH) { const code = StringPrototypeCharCodeAt(resolvedPath, 2); if (code !== CHAR_QUESTION_MARK && code !== CHAR_DOT) { // Matched non-long UNC root, convert the path to a long UNC path return `\\\\?\\UNC\\${StringPrototypeSlice(resolvedPath, 2)}`; } } } else if ( isWindowsDeviceRoot(StringPrototypeCharCodeAt(resolvedPath, 0)) && StringPrototypeCharCodeAt(resolvedPath, 1) === CHAR_COLON && StringPrototypeCharCodeAt(resolvedPath, 2) === CHAR_BACKWARD_SLASH ) { // Matched device root, convert the path to a long UNC path return `\\\\?\\${resolvedPath}`; }
return resolvedPath; },
/** * @param {string} path * @returns {string} */ dirname(path) { validateString(path, 'path'); const len = path.length; if (len === 0) return '.'; let rootEnd = -1; let offset = 0; const code = StringPrototypeCharCodeAt(path, 0);
if (len === 1) { // `path` contains just a path separator, exit early to avoid // unnecessary work or a dot. return isPathSeparator(code) ? path : '.'; }
// Try to match a root if (isPathSeparator(code)) { // Possible UNC root
rootEnd = offset = 1;
if (isPathSeparator(StringPrototypeCharCodeAt(path, 1))) { // Matched double path separator at beginning let j = 2; let last = j; // Match 1 or more non-path separators while (j < len && !isPathSeparator(StringPrototypeCharCodeAt(path, j))) { j++; } if (j < len && j !== last) { // Matched! last = j; // Match 1 or more path separators while (j < len && isPathSeparator(StringPrototypeCharCodeAt(path, j))) { j++; } if (j < len && j !== last) { // Matched! last = j; // Match 1 or more non-path separators while (j < len && !isPathSeparator(StringPrototypeCharCodeAt(path, j))) { j++; } if (j === len) { // We matched a UNC root only return path; } if (j !== last) { // We matched a UNC root with leftovers
// Offset by 1 to include the separator after the UNC root to // treat it as a "normal root" on top of a (UNC) root rootEnd = offset = j + 1; } } } } // Possible device root } else if (isWindowsDeviceRoot(code) && StringPrototypeCharCodeAt(path, 1) === CHAR_COLON) { rootEnd = len > 2 && isPathSeparator(StringPrototypeCharCodeAt(path, 2)) ? 3 : 2; offset = rootEnd; }
let end = -1; let matchedSlash = true; for (let i = len - 1; i >= offset; --i) { if (isPathSeparator(StringPrototypeCharCodeAt(path, i))) { if (!matchedSlash) { end = i; break; } } else { // We saw the first non-path separator matchedSlash = false; } }
if (end === -1) { if (rootEnd === -1) return '.';
end = rootEnd; } return StringPrototypeSlice(path, 0, end); },
/** * @param {string} path * @param {string} [suffix] * @returns {string} */ basename(path, suffix) { if (suffix !== undefined) validateString(suffix, 'suffix'); validateString(path, 'path'); let start = 0; let end = -1; let matchedSlash = true;
// Check for a drive letter prefix so as not to mistake the following // path separator as an extra separator at the end of the path that can be // disregarded if (path.length >= 2 && isWindowsDeviceRoot(StringPrototypeCharCodeAt(path, 0)) && StringPrototypeCharCodeAt(path, 1) === CHAR_COLON) { start = 2; }
if (suffix !== undefined && suffix.length > 0 && suffix.length <= path.length) { if (suffix === path) return ''; let extIdx = suffix.length - 1; let firstNonSlashEnd = -1; for (let i = path.length - 1; i >= start; --i) { const code = StringPrototypeCharCodeAt(path, i); if (isPathSeparator(code)) { // If we reached a path separator that was not part of a set of path // separators at the end of the string, stop now if (!matchedSlash) { start = i + 1; break; } } else { if (firstNonSlashEnd === -1) { // We saw the first non-path separator, remember this index in case // we need it if the extension ends up not matching matchedSlash = false; firstNonSlashEnd = i + 1; } if (extIdx >= 0) { // Try to match the explicit extension if (code === StringPrototypeCharCodeAt(suffix, extIdx)) { if (--extIdx === -1) { // We matched the extension, so mark this as the end of our path // component end = i; } } else { // Extension does not match, so our result is the entire path // component extIdx = -1; end = firstNonSlashEnd; } } } }
if (start === end) end = firstNonSlashEnd; else if (end === -1) end = path.length; return StringPrototypeSlice(path, start, end); } for (let i = path.length - 1; i >= start; --i) { if (isPathSeparator(StringPrototypeCharCodeAt(path, i))) { // If we reached a path separator that was not part of a set of path // separators at the end of the string, stop now if (!matchedSlash) { start = i + 1; break; } } else if (end === -1) { // We saw the first non-path separator, mark this as the end of our // path component matchedSlash = false; end = i + 1; } }
if (end === -1) return ''; return StringPrototypeSlice(path, start, end); },
/** * @param {string} path * @returns {string} */ extname(path) { validateString(path, 'path'); let start = 0; let startDot = -1; let startPart = 0; let end = -1; let matchedSlash = true; // Track the state of characters (if any) we see before our first dot and // after any path separator we find let preDotState = 0;
// Check for a drive letter prefix so as not to mistake the following // path separator as an extra separator at the end of the path that can be // disregarded
if (path.length >= 2 && StringPrototypeCharCodeAt(path, 1) === CHAR_COLON && isWindowsDeviceRoot(StringPrototypeCharCodeAt(path, 0))) { start = startPart = 2; }
for (let i = path.length - 1; i >= start; --i) { const code = StringPrototypeCharCodeAt(path, i); if (isPathSeparator(code)) { // If we reached a path separator that was not part of a set of path // separators at the end of the string, stop now if (!matchedSlash) { startPart = i + 1; break; } continue; } if (end === -1) { // We saw the first non-path separator, mark this as the end of our // extension matchedSlash = false; end = i + 1; } if (code === CHAR_DOT) { // If this is our first dot, mark it as the start of our extension if (startDot === -1) startDot = i; else if (preDotState !== 1) preDotState = 1; } else if (startDot !== -1) { // We saw a non-dot and non-path separator before our dot, so we should // have a good chance at having a non-empty extension preDotState = -1; } }
if (startDot === -1 || end === -1 || // We saw a non-dot character immediately before the dot preDotState === 0 || // The (right-most) trimmed path component is exactly '..' (preDotState === 1 && startDot === end - 1 && startDot === startPart + 1)) { return ''; } return StringPrototypeSlice(path, startDot, end); },
format: FunctionPrototypeBind(_format, null, '\\'),
/** * @param {string} path * @returns {{ * dir: string; * root: string; * base: string; * name: string; * ext: string; * }} */ parse(path) { validateString(path, 'path');
const ret = { root: '', dir: '', base: '', ext: '', name: '' }; if (path.length === 0) return ret;
const len = path.length; let rootEnd = 0; let code = StringPrototypeCharCodeAt(path, 0);
if (len === 1) { if (isPathSeparator(code)) { // `path` contains just a path separator, exit early to avoid // unnecessary work ret.root = ret.dir = path; return ret; } ret.base = ret.name = path; return ret; } // Try to match a root if (isPathSeparator(code)) { // Possible UNC root
rootEnd = 1; if (isPathSeparator(StringPrototypeCharCodeAt(path, 1))) { // Matched double path separator at beginning let j = 2; let last = j; // Match 1 or more non-path separators while (j < len && !isPathSeparator(StringPrototypeCharCodeAt(path, j))) { j++; } if (j < len && j !== last) { // Matched! last = j; // Match 1 or more path separators while (j < len && isPathSeparator(StringPrototypeCharCodeAt(path, j))) { j++; } if (j < len && j !== last) { // Matched! last = j; // Match 1 or more non-path separators while (j < len && !isPathSeparator(StringPrototypeCharCodeAt(path, j))) { j++; } if (j === len) { // We matched a UNC root only rootEnd = j; } else if (j !== last) { // We matched a UNC root with leftovers rootEnd = j + 1; } } } } } else if (isWindowsDeviceRoot(code) && StringPrototypeCharCodeAt(path, 1) === CHAR_COLON) { // Possible device root if (len <= 2) { // `path` contains just a drive root, exit early to avoid // unnecessary work ret.root = ret.dir = path; return ret; } rootEnd = 2; if (isPathSeparator(StringPrototypeCharCodeAt(path, 2))) { if (len === 3) { // `path` contains just a drive root, exit early to avoid // unnecessary work ret.root = ret.dir = path; return ret; } rootEnd = 3; } } if (rootEnd > 0) ret.root = StringPrototypeSlice(path, 0, rootEnd);
let startDot = -1; let startPart = rootEnd; let end = -1; let matchedSlash = true; let i = path.length - 1;
// Track the state of characters (if any) we see before our first dot and // after any path separator we find let preDotState = 0;
// Get non-dir info for (; i >= rootEnd; --i) { code = StringPrototypeCharCodeAt(path, i); if (isPathSeparator(code)) { // If we reached a path separator that was not part of a set of path // separators at the end of the string, stop now if (!matchedSlash) { startPart = i + 1; break; } continue; } if (end === -1) { // We saw the first non-path separator, mark this as the end of our // extension matchedSlash = false; end = i + 1; } if (code === CHAR_DOT) { // If this is our first dot, mark it as the start of our extension if (startDot === -1) startDot = i; else if (preDotState !== 1) preDotState = 1; } else if (startDot !== -1) { // We saw a non-dot and non-path separator before our dot, so we should // have a good chance at having a non-empty extension preDotState = -1; } }
if (end !== -1) { if (startDot === -1 || // We saw a non-dot character immediately before the dot preDotState === 0 || // The (right-most) trimmed path component is exactly '..' (preDotState === 1 && startDot === end - 1 && startDot === startPart + 1)) { ret.base = ret.name = StringPrototypeSlice(path, startPart, end); } else { ret.name = StringPrototypeSlice(path, startPart, startDot); ret.base = StringPrototypeSlice(path, startPart, end); ret.ext = StringPrototypeSlice(path, startDot, end); } }
// If the directory is the root, use the entire root as the `dir` including // the trailing slash if any (`C:\abc` -> `C:\`). Otherwise, strip out the // trailing slash (`C:\abc\def` -> `C:\abc`). if (startPart > 0 && startPart !== rootEnd) ret.dir = StringPrototypeSlice(path, 0, startPart - 1); else ret.dir = ret.root;
return ret; },
matchesGlob(path, pattern) { return lazyMatchGlobPattern()(path, pattern, true); },
sep: '\\', delimiter: ';', win32: null, posix: null,};
const posixCwd = (() => { if (isWindows) { // Converts Windows' backslash path separators to POSIX forward slashes // and truncates any drive indicator const regexp = /\\/g; return () => { const cwd = StringPrototypeReplace(process.cwd(), regexp, '/'); return StringPrototypeSlice(cwd, StringPrototypeIndexOf(cwd, '/')); }; }
// We're already on POSIX, no need for any transformations return () => process.cwd();})();
const posix = { /** * path.resolve([from ...], to) * @param {...string} args * @returns {string} */ resolve(...args) { if (args.length === 0 || (args.length === 1 && (args[0] === '' || args[0] === '.'))) { const cwd = posixCwd(); if (StringPrototypeCharCodeAt(cwd, 0) === CHAR_FORWARD_SLASH) { return cwd; } } let resolvedPath = ''; let resolvedAbsolute = false;
for (let i = args.length - 1; i >= 0 && !resolvedAbsolute; i--) { const path = args[i]; validateString(path, `paths[${i}]`);
// Skip empty entries if (path.length === 0) { continue; }
resolvedPath = `${path}/${resolvedPath}`; resolvedAbsolute = StringPrototypeCharCodeAt(path, 0) === CHAR_FORWARD_SLASH; }
if (!resolvedAbsolute) { const cwd = posixCwd(); resolvedPath = `${cwd}/${resolvedPath}`; resolvedAbsolute = StringPrototypeCharCodeAt(cwd, 0) === CHAR_FORWARD_SLASH; }
// At this point the path should be resolved to a full absolute path, but // handle relative paths to be safe (might happen when process.cwd() fails)
// Normalize the path resolvedPath = normalizeString(resolvedPath, !resolvedAbsolute, '/', isPosixPathSeparator);
if (resolvedAbsolute) { return `/${resolvedPath}`; } return resolvedPath.length > 0 ? resolvedPath : '.'; },
/** * @param {string} path * @returns {string} */ normalize(path) { validateString(path, 'path');
if (path.length === 0) return '.';
const isAbsolute = StringPrototypeCharCodeAt(path, 0) === CHAR_FORWARD_SLASH; const trailingSeparator = StringPrototypeCharCodeAt(path, path.length - 1) === CHAR_FORWARD_SLASH;
// Normalize the path path = normalizeString(path, !isAbsolute, '/', isPosixPathSeparator);
if (path.length === 0) { if (isAbsolute) return '/'; return trailingSeparator ? './' : '.'; } if (trailingSeparator) path += '/';
return isAbsolute ? `/${path}` : path; },
/** * @param {string} path * @returns {boolean} */ isAbsolute(path) { validateString(path, 'path'); return path.length > 0 && StringPrototypeCharCodeAt(path, 0) === CHAR_FORWARD_SLASH; },
/** * @param {...string} args * @returns {string} */ join(...args) { if (args.length === 0) return '.';
const path = []; for (let i = 0; i < args.length; ++i) { const arg = args[i]; validateString(arg, 'path'); if (arg.length > 0) { path.push(arg); } }
if (path.length === 0) return '.';
return posix.normalize(ArrayPrototypeJoin(path, '/')); },
/** * @param {string} from * @param {string} to * @returns {string} */ relative(from, to) { validateString(from, 'from'); validateString(to, 'to');
if (from === to) return '';
// Trim leading forward slashes. from = posix.resolve(from); to = posix.resolve(to);
if (from === to) return '';
const fromStart = 1; const fromEnd = from.length; const fromLen = fromEnd - fromStart; const toStart = 1; const toLen = to.length - toStart;
// Compare paths to find the longest common path from root const length = (fromLen < toLen ? fromLen : toLen); let lastCommonSep = -1; let i = 0; for (; i < length; i++) { const fromCode = StringPrototypeCharCodeAt(from, fromStart + i); if (fromCode !== StringPrototypeCharCodeAt(to, toStart + i)) break; else if (fromCode === CHAR_FORWARD_SLASH) lastCommonSep = i; } if (i === length) { if (toLen > length) { if (StringPrototypeCharCodeAt(to, toStart + i) === CHAR_FORWARD_SLASH) { // We get here if `from` is the exact base path for `to`. // For example: from='/foo/bar'; to='/foo/bar/baz' return StringPrototypeSlice(to, toStart + i + 1); } if (i === 0) { // We get here if `from` is the root // For example: from='/'; to='/foo' return StringPrototypeSlice(to, toStart + i); } } else if (fromLen > length) { if (StringPrototypeCharCodeAt(from, fromStart + i) === CHAR_FORWARD_SLASH) { // We get here if `to` is the exact base path for `from`. // For example: from='/foo/bar/baz'; to='/foo/bar' lastCommonSep = i; } else if (i === 0) { // We get here if `to` is the root. // For example: from='/foo/bar'; to='/' lastCommonSep = 0; } } }
let out = ''; // Generate the relative path based on the path difference between `to` // and `from`. for (i = fromStart + lastCommonSep + 1; i <= fromEnd; ++i) { if (i === fromEnd || StringPrototypeCharCodeAt(from, i) === CHAR_FORWARD_SLASH) { out += out.length === 0 ? '..' : '/..'; } }
// Lastly, append the rest of the destination (`to`) path that comes after // the common path parts. return `${out}${StringPrototypeSlice(to, toStart + lastCommonSep)}`; },
/** * @param {string} path * @returns {string} */ toNamespacedPath(path) { // Non-op on posix systems return path; },
/** * @param {string} path * @returns {string} */ dirname(path) { validateString(path, 'path'); if (path.length === 0) return '.'; const hasRoot = StringPrototypeCharCodeAt(path, 0) === CHAR_FORWARD_SLASH; let end = -1; let matchedSlash = true; for (let i = path.length - 1; i >= 1; --i) { if (StringPrototypeCharCodeAt(path, i) === CHAR_FORWARD_SLASH) { if (!matchedSlash) { end = i; break; } } else { // We saw the first non-path separator matchedSlash = false; } }
if (end === -1) return hasRoot ? '/' : '.'; if (hasRoot && end === 1) return '//'; return StringPrototypeSlice(path, 0, end); },
/** * @param {string} path * @param {string} [suffix] * @returns {string} */ basename(path, suffix) { if (suffix !== undefined) validateString(suffix, 'suffix'); validateString(path, 'path');
let start = 0; let end = -1; let matchedSlash = true;
if (suffix !== undefined && suffix.length > 0 && suffix.length <= path.length) { if (suffix === path) return ''; let extIdx = suffix.length - 1; let firstNonSlashEnd = -1; for (let i = path.length - 1; i >= 0; --i) { const code = StringPrototypeCharCodeAt(path, i); if (code === CHAR_FORWARD_SLASH) { // If we reached a path separator that was not part of a set of path // separators at the end of the string, stop now if (!matchedSlash) { start = i + 1; break; } } else { if (firstNonSlashEnd === -1) { // We saw the first non-path separator, remember this index in case // we need it if the extension ends up not matching matchedSlash = false; firstNonSlashEnd = i + 1; } if (extIdx >= 0) { // Try to match the explicit extension if (code === StringPrototypeCharCodeAt(suffix, extIdx)) { if (--extIdx === -1) { // We matched the extension, so mark this as the end of our path // component end = i; } } else { // Extension does not match, so our result is the entire path // component extIdx = -1; end = firstNonSlashEnd; } } } }
if (start === end) end = firstNonSlashEnd; else if (end === -1) end = path.length; return StringPrototypeSlice(path, start, end); } for (let i = path.length - 1; i >= 0; --i) { if (StringPrototypeCharCodeAt(path, i) === CHAR_FORWARD_SLASH) { // If we reached a path separator that was not part of a set of path // separators at the end of the string, stop now if (!matchedSlash) { start = i + 1; break; } } else if (end === -1) { // We saw the first non-path separator, mark this as the end of our // path component matchedSlash = false; end = i + 1; } }
if (end === -1) return ''; return StringPrototypeSlice(path, start, end); },
/** * @param {string} path * @returns {string} */ extname(path) { validateString(path, 'path'); let startDot = -1; let startPart = 0; let end = -1; let matchedSlash = true; // Track the state of characters (if any) we see before our first dot and // after any path separator we find let preDotState = 0; for (let i = path.length - 1; i >= 0; --i) { const char = path[i]; if (char === '/') { // If we reached a path separator that was not part of a set of path // separators at the end of the string, stop now if (!matchedSlash) { startPart = i + 1; break; } continue; } if (end === -1) { // We saw the first non-path separator, mark this as the end of our // extension matchedSlash = false; end = i + 1; } if (char === '.') { // If this is our first dot, mark it as the start of our extension if (startDot === -1) startDot = i; else if (preDotState !== 1) preDotState = 1; } else if (startDot !== -1) { // We saw a non-dot and non-path separator before our dot, so we should // have a good chance at having a non-empty extension preDotState = -1; } }
if (startDot === -1 || end === -1 || // We saw a non-dot character immediately before the dot preDotState === 0 || // The (right-most) trimmed path component is exactly '..' (preDotState === 1 && startDot === end - 1 && startDot === startPart + 1)) { return ''; } return StringPrototypeSlice(path, startDot, end); },
format: FunctionPrototypeBind(_format, null, '/'),
/** * @param {string} path * @returns {{ * dir: string; * root: string; * base: string; * name: string; * ext: string; * }} */ parse(path) { validateString(path, 'path');
const ret = { root: '', dir: '', base: '', ext: '', name: '' }; if (path.length === 0) return ret; const isAbsolute = StringPrototypeCharCodeAt(path, 0) === CHAR_FORWARD_SLASH; let start; if (isAbsolute) { ret.root = '/'; start = 1; } else { start = 0; } let startDot = -1; let startPart = 0; let end = -1; let matchedSlash = true; let i = path.length - 1;
// Track the state of characters (if any) we see before our first dot and // after any path separator we find let preDotState = 0;
// Get non-dir info for (; i >= start; --i) { const code = StringPrototypeCharCodeAt(path, i); if (code === CHAR_FORWARD_SLASH) { // If we reached a path separator that was not part of a set of path // separators at the end of the string, stop now if (!matchedSlash) { startPart = i + 1; break; } continue; } if (end === -1) { // We saw the first non-path separator, mark this as the end of our // extension matchedSlash = false; end = i + 1; } if (code === CHAR_DOT) { // If this is our first dot, mark it as the start of our extension if (startDot === -1) startDot = i; else if (preDotState !== 1) preDotState = 1; } else if (startDot !== -1) { // We saw a non-dot and non-path separator before our dot, so we should // have a good chance at having a non-empty extension preDotState = -1; } }
if (end !== -1) { const start = startPart === 0 && isAbsolute ? 1 : startPart; if (startDot === -1 || // We saw a non-dot character immediately before the dot preDotState === 0 || // The (right-most) trimmed path component is exactly '..' (preDotState === 1 && startDot === end - 1 && startDot === startPart + 1)) { ret.base = ret.name = StringPrototypeSlice(path, start, end); } else { ret.name = StringPrototypeSlice(path, start, startDot); ret.base = StringPrototypeSlice(path, start, end); ret.ext = StringPrototypeSlice(path, startDot, end); } }
if (startPart > 0) ret.dir = StringPrototypeSlice(path, 0, startPart - 1); else if (isAbsolute) ret.dir = '/';
return ret; },
matchesGlob(path, pattern) { return lazyMatchGlobPattern()(path, pattern, false); },
sep: '/', delimiter: ':', win32: null, posix: null,};
posix.win32 = win32.win32 = win32;posix.posix = win32.posix = posix;
// Legacy internal API, docs-only deprecated: DEP0080win32._makeLong = win32.toNamespacedPath;posix._makeLong = posix.toNamespacedPath;
module.exports = isWindows ? win32 : posix;