metro-resolver
Advanced tools
Comparing version 0.80.10 to 0.80.11
{ | ||
"name": "metro-resolver", | ||
"version": "0.80.10", | ||
"version": "0.80.11", | ||
"description": "🚇 Implementation of Metro's resolution logic.", | ||
@@ -19,3 +19,3 @@ "main": "src", | ||
"devDependencies": { | ||
"metro": "0.80.10" | ||
"metro": "0.80.11" | ||
}, | ||
@@ -22,0 +22,0 @@ "dependencies": { |
@@ -8,4 +8,6 @@ "use strict"; | ||
"The module could not be resolved because none of these files exist:\n\n" + | ||
` * ${formatFileCandidates(candidates.file)}\n` + | ||
` * ${formatFileCandidates(candidates.dir)}` | ||
[candidates.file, candidates.dir] | ||
.filter(Boolean) | ||
.map((candidates) => ` * ${formatFileCandidates(candidates)}`) | ||
.join("\n") | ||
); | ||
@@ -12,0 +14,0 @@ this.candidates = candidates; |
@@ -70,8 +70,8 @@ "use strict"; | ||
} | ||
if (context.unstable_getRealPath != null) { | ||
const maybeRealPath = context.unstable_getRealPath(filePath); | ||
if (maybeRealPath != null) { | ||
if (context.unstable_fileSystemLookup != null) { | ||
const lookupResult = context.unstable_fileSystemLookup(filePath); | ||
if (lookupResult.exists && lookupResult.type === "f") { | ||
return { | ||
type: "sourceFile", | ||
filePath: maybeRealPath, | ||
filePath: lookupResult.realPath, | ||
}; | ||
@@ -101,4 +101,12 @@ } | ||
} | ||
const _normalizedExportsFields = new WeakMap(); | ||
function normalizeExportsField(exportsField, createConfigError) { | ||
let rootValue; | ||
if (typeof exportsField === "string") { | ||
return new Map([[".", exportsField]]); | ||
} | ||
const cachedValue = _normalizedExportsFields.get(exportsField); | ||
if (cachedValue) { | ||
return cachedValue; | ||
} | ||
if (Array.isArray(exportsField)) { | ||
@@ -119,5 +127,5 @@ if (exportsField.every((value) => typeof value === "string")) { | ||
if (typeof rootValue === "string") { | ||
return { | ||
".": rootValue, | ||
}; | ||
const result = new Map([[".", rootValue]]); | ||
_normalizedExportsFields.set(exportsField, result); | ||
return result; | ||
} | ||
@@ -129,3 +137,7 @@ const firstLevelKeys = Object.keys(rootValue); | ||
if (subpathKeys.length === firstLevelKeys.length) { | ||
return flattenLegacySubpathValues(rootValue, createConfigError); | ||
const result = new Map( | ||
Object.entries(flattenLegacySubpathValues(rootValue, createConfigError)) | ||
); | ||
_normalizedExportsFields.set(exportsField, result); | ||
return result; | ||
} | ||
@@ -138,25 +150,28 @@ if (subpathKeys.length !== 0) { | ||
} | ||
return { | ||
".": flattenLegacySubpathValues(rootValue, createConfigError), | ||
}; | ||
const result = new Map([ | ||
[".", flattenLegacySubpathValues(rootValue, createConfigError)], | ||
]); | ||
_normalizedExportsFields.set(exportsField, result); | ||
return result; | ||
} | ||
function flattenLegacySubpathValues(exportMap, createConfigError) { | ||
return Object.keys(exportMap).reduce((result, subpath) => { | ||
const value = exportMap[subpath]; | ||
if (Array.isArray(value) && (!value.length || Array.isArray(value[0]))) { | ||
throw createConfigError( | ||
'Could not parse non-standard array value in "exports" field.' | ||
); | ||
return Object.entries(exportMap).reduce((result, [subpath, value]) => { | ||
if (Array.isArray(value)) { | ||
if (!value.length || Array.isArray(value[0])) { | ||
throw createConfigError( | ||
'Could not parse non-standard array value in "exports" field.' | ||
); | ||
} | ||
result[subpath] = value[0]; | ||
} else { | ||
result[subpath] = value; | ||
} | ||
return { | ||
...result, | ||
[subpath]: Array.isArray(value) ? value[0] : value, | ||
}; | ||
return result; | ||
}, {}); | ||
} | ||
function isSubpathDefinedInExports(exportMap, subpath) { | ||
if (subpath in exportMap) { | ||
if (exportMap.has(subpath)) { | ||
return true; | ||
} | ||
for (const key in exportMap) { | ||
for (const key of exportMap.keys()) { | ||
if ( | ||
@@ -190,6 +205,6 @@ key.split("*").length === 2 && | ||
); | ||
let target = exportMapAfterConditions[subpath]; | ||
let target = exportMapAfterConditions.get(subpath); | ||
let patternMatch = null; | ||
if (target == null) { | ||
const expansionKeys = Object.keys(exportMapAfterConditions) | ||
const expansionKeys = [...exportMapAfterConditions.keys()] | ||
.filter((key) => key.includes("*")) | ||
@@ -199,3 +214,3 @@ .sort((key) => key.split("*")[0].length) | ||
for (const key of expansionKeys) { | ||
const value = exportMapAfterConditions[key]; | ||
const value = exportMapAfterConditions.get(key); | ||
if (typeof value === "string" && value.split("*").length !== 2) { | ||
@@ -212,3 +227,3 @@ break; | ||
return { | ||
target, | ||
target: target ?? null, | ||
patternMatch, | ||
@@ -218,20 +233,16 @@ }; | ||
function reduceExportMap(exportMap, conditionNames, createConfigError) { | ||
const result = {}; | ||
for (const subpath in exportMap) { | ||
const subpathValue = reduceConditionalExport( | ||
exportMap[subpath], | ||
conditionNames | ||
); | ||
const result = new Map(); | ||
for (const [subpath, value] of exportMap) { | ||
const subpathValue = reduceConditionalExport(value, conditionNames); | ||
if (subpathValue !== "no-match") { | ||
result[subpath] = subpathValue; | ||
result.set(subpath, subpathValue); | ||
} | ||
} | ||
const invalidValues = Object.values(result).filter( | ||
(value) => value != null && !value.startsWith("./") | ||
); | ||
if (invalidValues.length) { | ||
throw createConfigError( | ||
'One or more mappings for subpaths defined in "exports" are invalid. ' + | ||
'All values must begin with "./".' | ||
); | ||
for (const value of result.values()) { | ||
if (value != null && !value.startsWith("./")) { | ||
throw createConfigError( | ||
'One or more mappings for subpaths defined in "exports" are invalid. ' + | ||
'All values must begin with "./".' | ||
); | ||
} | ||
} | ||
@@ -238,0 +249,0 @@ return result; |
@@ -72,3 +72,3 @@ "use strict"; | ||
} | ||
if (context.allowHaste && !isDirectImport) { | ||
if (context.allowHaste) { | ||
const normalizedName = normalizePath(realModuleName); | ||
@@ -87,3 +87,6 @@ const result = resolveHasteName(context, normalizedName, platform); | ||
candidate = next; | ||
nodeModulesPaths.push(_path.default.join(candidate, "node_modules")); | ||
const nodeModulesPath = candidate.endsWith(_path.default.sep) | ||
? candidate + "node_modules" | ||
: candidate + _path.default.sep + "node_modules"; | ||
nodeModulesPaths.push(nodeModulesPath); | ||
next = _path.default.dirname(candidate); | ||
@@ -94,19 +97,27 @@ } while (candidate !== next); | ||
const extraPaths = []; | ||
const parsedSpecifier = parsePackageSpecifier(realModuleName); | ||
const { extraNodeModules } = context; | ||
if (extraNodeModules) { | ||
let bits = _path.default.normalize(moduleName).split(_path.default.sep); | ||
let packageName; | ||
if (bits.length >= 2 && bits[0].startsWith("@")) { | ||
packageName = bits.slice(0, 2).join("/"); | ||
bits = bits.slice(1); | ||
} else { | ||
packageName = bits[0]; | ||
} | ||
if (extraNodeModules[packageName]) { | ||
bits[0] = extraNodeModules[packageName]; | ||
extraPaths.push(_path.default.join.apply(_path.default, bits)); | ||
} | ||
if (extraNodeModules && extraNodeModules[parsedSpecifier.packageName]) { | ||
const newPackageName = extraNodeModules[parsedSpecifier.packageName]; | ||
extraPaths.push( | ||
_path.default.join(newPackageName, parsedSpecifier.posixSubpath) | ||
); | ||
} | ||
const allDirPaths = nodeModulesPaths | ||
.map((nodeModulePath) => _path.default.join(nodeModulePath, realModuleName)) | ||
.map((nodeModulePath) => { | ||
let lookupResult = null; | ||
if (context.unstable_fileSystemLookup) { | ||
const mustBeDirectory = | ||
parsedSpecifier.posixSubpath !== "." || | ||
parsedSpecifier.packageName.length > parsedSpecifier.firstPart.length | ||
? nodeModulePath + _path.default.sep + parsedSpecifier.firstPart | ||
: nodeModulePath; | ||
lookupResult = context.unstable_fileSystemLookup(mustBeDirectory); | ||
if (!lookupResult.exists || lookupResult.type !== "d") { | ||
return null; | ||
} | ||
} | ||
return _path.default.join(nodeModulePath, realModuleName); | ||
}) | ||
.filter(Boolean) | ||
.concat(extraPaths); | ||
@@ -127,2 +138,35 @@ for (let i = 0; i < allDirPaths.length; ++i) { | ||
} | ||
function parsePackageSpecifier(specifier) { | ||
const normalized = | ||
_path.default.sep === "/" ? specifier : specifier.replaceAll("\\", "/"); | ||
const firstSepIdx = normalized.indexOf("/"); | ||
if (normalized.startsWith("@") && firstSepIdx !== -1) { | ||
const secondSepIdx = normalized.indexOf("/", firstSepIdx + 1); | ||
if (secondSepIdx === -1) { | ||
return { | ||
firstPart: normalized.slice(0, firstSepIdx), | ||
packageName: normalized, | ||
posixSubpath: ".", | ||
}; | ||
} | ||
return { | ||
firstPart: normalized.slice(0, firstSepIdx), | ||
packageName: normalized.slice(0, secondSepIdx), | ||
posixSubpath: "." + normalized.slice(secondSepIdx), | ||
}; | ||
} | ||
if (firstSepIdx === -1) { | ||
return { | ||
firstPart: normalized, | ||
packageName: normalized, | ||
posixSubpath: ".", | ||
}; | ||
} | ||
const packageName = normalized.slice(0, firstSepIdx); | ||
return { | ||
firstPart: packageName, | ||
packageName, | ||
posixSubpath: "." + normalized.slice(firstSepIdx), | ||
}; | ||
} | ||
function resolveModulePath(context, toModuleName, platform) { | ||
@@ -143,4 +187,6 @@ const modulePath = _path.default.isAbsolute(toModuleName) | ||
const fileName = _path.default.basename(redirectedPath); | ||
const fileResult = resolveFile(context, dirPath, fileName, platform); | ||
if (fileResult.type === "resolved") { | ||
const fileResult = redirectedPath.endsWith(_path.default.sep) | ||
? null | ||
: resolveFile(context, dirPath, fileName, platform); | ||
if (fileResult != null && fileResult.type === "resolved") { | ||
return fileResult; | ||
@@ -153,3 +199,3 @@ } | ||
return failedFor({ | ||
file: fileResult.candidates, | ||
file: fileResult?.candidates ?? null, | ||
dir: dirResult.candidates, | ||
@@ -198,6 +244,9 @@ }); | ||
"the package. Indeed, none of these files exist:\n\n" + | ||
` * \`${(0, _formatFileCandidates.default)( | ||
opts.candidates.file | ||
)}\`\n` + | ||
` * \`${(0, _formatFileCandidates.default)(opts.candidates.dir)}\`` | ||
[opts.candidates.file, opts.candidates.dir] | ||
.filter(Boolean) | ||
.map( | ||
(candidates) => | ||
` * \`${(0, _formatFileCandidates.default)(candidates)}\`` | ||
) | ||
.join("\n") | ||
); | ||
@@ -254,2 +303,13 @@ Object.assign(this, opts); | ||
function resolvePackageEntryPoint(context, packagePath, platform) { | ||
const dirLookup = context.unstable_fileSystemLookup?.(packagePath); | ||
if ( | ||
dirLookup != null && | ||
(dirLookup.exists === false || dirLookup.type !== "d") | ||
) { | ||
return failedFor({ | ||
type: "sourceFile", | ||
filePathPrefix: packagePath, | ||
candidateExts: [], | ||
}); | ||
} | ||
const packageJsonPath = _path.default.join(packagePath, "package.json"); | ||
@@ -365,6 +425,6 @@ if (!context.doesFileExist(packageJsonPath)) { | ||
} | ||
if (context.unstable_getRealPath) { | ||
const maybeRealPath = context.unstable_getRealPath(redirectedPath); | ||
if (maybeRealPath != null) { | ||
return maybeRealPath; | ||
if (context.unstable_fileSystemLookup) { | ||
const lookupResult = context.unstable_fileSystemLookup(redirectedPath); | ||
if (lookupResult.exists && lookupResult.type === "f") { | ||
return lookupResult.realPath; | ||
} | ||
@@ -371,0 +431,0 @@ } else if (context.doesFileExist(redirectedPath)) { |
@@ -77,4 +77,11 @@ /** | ||
export type DoesFileExist = (filePath: string) => boolean; | ||
export type GetRealPath = (path: string) => string | null; | ||
export type IsAssetFile = (fileName: string) => boolean; | ||
/** | ||
* Performs a lookup against an absolute or project-relative path to determine | ||
* whether it exists as a file or directory. Follows any symlinks, and returns | ||
* a real absolute path on existence. | ||
*/ | ||
export type FileSystemLookup = ( | ||
absoluteOrProjectRelativePath: string, | ||
) => {exists: false} | {exists: true; type: 'f' | 'd'; realPath: string}; | ||
@@ -162,3 +169,3 @@ /** | ||
unstable_enablePackageExports: boolean; | ||
unstable_getRealPath?: GetRealPath | null; | ||
unstable_fileSystemLookup?: FileSystemLookup | null; | ||
unstable_logWarning: (message: string) => void; | ||
@@ -165,0 +172,0 @@ } |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
97392
1182