PHP WebShell
Текущая директория: /usr/lib/node_modules/bitgo/node_modules/metro-resolver/src
Просмотр файла: PackageExportsResolve.js.flow
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict-local
* @format
* @oncall react_native
*/
import type {
ExportMapWithFallbacks,
ExportsField,
ExportsLikeMap,
FileResolution,
NormalizedExportsLikeMap,
ResolutionContext,
} from './types';
import InvalidPackageConfigurationError from './errors/InvalidPackageConfigurationError';
import PackagePathNotExportedError from './errors/PackagePathNotExportedError';
import resolveAsset from './resolveAsset';
import isAssetFile from './utils/isAssetFile';
import {isSubpathDefinedInExportsLike} from './utils/isSubpathDefinedInExportsLike';
import {matchSubpathFromExportsLike} from './utils/matchSubpathFromExportsLike';
import toPosixPath from './utils/toPosixPath';
import path from 'path';
/**
* Resolve a package subpath based on the entry points defined in the package's
* "exports" field. If there is no match for the given subpath (which may be
* augmented by resolution of conditional exports for the passed `context`),
* throws a `PackagePathNotExportedError`.
*
* Implements modern package resolution behaviour based on the [Package Entry
* Points spec](https://nodejs.org/docs/latest-v19.x/api/packages.html#package-entry-points).
*
* @throws {InvalidPackageConfigurationError} Raised if configuration specified
* by `exportsField` is invalid.
* @throws {InvalidModuleSpecifierError} Raised if the resolved module specifier
* is invalid.
* @throws {PackagePathNotExportedError} Raised when the requested subpath is
* not exported.
*/
export function resolvePackageTargetFromExports(
context: ResolutionContext,
/**
* The path to the containing npm package directory.
*/
packagePath: string,
/**
* The unresolved absolute path to the target module. This will be converted
* to a package-relative subpath for comparison.
*/
modulePath: string,
packageRelativePath: string,
exportsField: ExportsField,
platform: string | null,
): FileResolution {
const createConfigError = (reason: string) => {
return new InvalidPackageConfigurationError({
reason,
packagePath,
});
};
const subpath = getExportsSubpath(packageRelativePath);
const exportMap = normalizeExportsField(exportsField, createConfigError);
if (!isSubpathDefinedInExportsLike(exportMap, subpath)) {
throw new PackagePathNotExportedError(
`Attempted to import the module "${modulePath}" which is not listed ` +
`in the "exports" of "${packagePath}" under the requested subpath ` +
`"${subpath}".`,
);
}
const {target, patternMatch} = matchSubpathFromExportsLike(
context,
subpath,
exportMap,
platform,
createConfigError,
);
if (target != null) {
const invalidSegmentInTarget = findInvalidPathSegment(target.slice(2));
if (invalidSegmentInTarget != null) {
throw createConfigError(
`The target for "${subpath}" defined in "exports" is "${target}", ` +
'however this value is an invalid subpath or subpath pattern ' +
`because it includes "${invalidSegmentInTarget}".`,
);
}
const filePath = path.join(
packagePath,
patternMatch != null ? target.replaceAll('*', patternMatch) : target,
);
if (isAssetFile(filePath, context.assetExts)) {
const assetResult = resolveAsset(context, filePath);
if (assetResult != null) {
return assetResult;
}
}
const lookupResult = context.fileSystemLookup(filePath);
if (lookupResult.exists && lookupResult.type === 'f') {
return {
type: 'sourceFile',
filePath: lookupResult.realPath,
};
}
throw createConfigError(
`The resolution for "${modulePath}" defined in "exports" is ${filePath}, ` +
'however this file does not exist.',
);
}
throw new PackagePathNotExportedError(
`Attempted to import the module "${modulePath}" which is listed in the ` +
`"exports" of "${packagePath}", however no match was resolved for this ` +
`request (platform = ${platform ?? 'null'}).`,
);
}
/**
* Convert a module path to the package-relative subpath key to attempt for
* "exports" field lookup.
*/
function getExportsSubpath(packageSubpath: string): string {
return packageSubpath === '' ? '.' : './' + toPosixPath(packageSubpath);
}
/**
* Maintain a WeakMap cache of the results of normalizedExportsField.
* Particularly in a large project, many source files depend on the same
* packages (eg @babel/runtime), and this avoids normalising the same JSON
* many times. Note that ExportsField is immutable, and the upstream package
* cache gives us a stable reference.
*
* The case where ExportsField is a string (not weakly referencable) has to be
* excluded, but those are very cheap to process anyway.
*
* (Ultimately this should be coupled more closely to the package cache, so that
* we can clean up immediately rather than on GC.)
*/
type ExcludeString<T> = T extends string ? empty : T;
const _normalizedExportsFields: WeakMap<
ExcludeString<ExportsField>,
NormalizedExportsLikeMap,
> = new WeakMap();
/**
* Normalise an "exports"-like field by parsing string shorthand and conditions
* shorthand at root, and flattening any legacy Node.js <13.7 array values.
*
* See https://nodejs.org/docs/latest-v19.x/api/packages.html#exports-sugar.
*/
function normalizeExportsField(
exportsField: ExportsField,
createConfigError: (reason: string) => Error,
): NormalizedExportsLikeMap {
let rootValue;
if (typeof exportsField === 'string') {
return new Map([['.', exportsField]]);
}
const cachedValue = _normalizedExportsFields.get(exportsField);
if (cachedValue) {
return cachedValue;
}
if (Array.isArray(exportsField)) {
// If an array of strings, use first value with valid specifier (root shorthand)
if (exportsField.every(value => typeof value === 'string')) {
// $FlowFixMe[incompatible-type] exportsField is refined to `string[]`
rootValue = exportsField.find((value: string) => value.startsWith('./'));
} else {
// Otherwise, should be a condition map and fallback string (Node.js <13.7)
rootValue = exportsField[0];
}
} else {
rootValue = exportsField;
}
if (rootValue == null || Array.isArray(rootValue)) {
throw createConfigError(
'Could not parse non-standard array value at root of "exports" field.',
);
}
if (typeof rootValue === 'string') {
const result: NormalizedExportsLikeMap = new Map([['.', rootValue]]);
_normalizedExportsFields.set(exportsField, result);
return result;
}
const firstLevelKeys = Object.keys(rootValue);
const subpathKeys = firstLevelKeys.filter(key => key.startsWith('.'));
const importKeys = firstLevelKeys.filter(key => key.startsWith('#'));
if (importKeys.length + subpathKeys.length === firstLevelKeys.length) {
const result: NormalizedExportsLikeMap = new Map(
Object.entries(flattenLegacySubpathValues(rootValue, createConfigError)),
);
_normalizedExportsFields.set(exportsField, result);
return result;
}
if (subpathKeys.length !== 0) {
throw createConfigError(
'The "exports" field cannot have keys which are both subpaths and ' +
'condition names at the same level.',
);
}
const result: NormalizedExportsLikeMap = new Map([
['.', flattenLegacySubpathValues(rootValue, createConfigError)],
]);
_normalizedExportsFields.set(exportsField, result);
return result;
}
/**
* Flatten legacy Node.js <13.7 array subpath values in an exports mapping.
*/
function flattenLegacySubpathValues(
exportMap: ExportsLikeMap | ExportMapWithFallbacks,
createConfigError: (reason: string) => Error,
): ExportsLikeMap {
return Object.entries(exportMap).reduce(
(result, [subpath, value]) => {
// We do not support empty or nested arrays (non-standard)
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;
},
{} as {[subpathOrCondition: string]: string | ExportsLikeMap | null},
);
}
function findInvalidPathSegment(subpath: string): ?string {
for (const segment of subpath.split(/[\\/]/)) {
if (
segment === '' ||
segment === '.' ||
segment === '..' ||
segment === 'node_modules'
) {
return segment;
}
}
return null;
}
Выполнить команду
Для локальной разработки. Не используйте в интернете!