Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 | 1x 1x 1x | /* eslint-disable no-await-in-loop, no-undefined */
import * as path from "path";
import {
InvalidModuleSpecifierError,
InvalidPackageTargetError,
isUrl,
} from "./utils";
/**
* Check for invalid path segments
*/
function includesInvalidSegments(
pathSegments: readonly string[],
moduleDirs: readonly string[],
) {
const invalidSegments = ["", ".", "..", ...moduleDirs];
// contains any "", ".", "..", or "node_modules" segments, including percent encoded variants
return pathSegments.some(
(v) =>
invalidSegments.includes(v) || invalidSegments.includes(decodeURI(v)),
);
}
interface ParamObject {
target: any;
patternMatch?: string;
isImports?: boolean;
validateImportsExports: boolean;
}
async function resolvePackageTarget(
context: any,
{
target,
patternMatch,
isImports,
validateImportsExports = true,
}: ParamObject,
): Promise<null | undefined | string | URL> {
// If target is a String, then
if (typeof target === "string") {
// If target does not start with "./", then
if (!target.startsWith("./")) {
// If isImports is false, or if target starts with "../" or "/", or if target is a valid URL, then
if (
!isImports ||
["/", "../"].some((p) => target.startsWith(p)) ||
isUrl(target)
) {
// Throw an Invalid Package Target error.
throw new InvalidPackageTargetError(
context,
`Invalid mapping: "${target}".`,
);
}
// If patternMatch is a String, then
if (typeof patternMatch === "string") {
// Return PACKAGE_RESOLVE(target with every instance of "*" replaced by patternMatch, packageURL + "/")
const result = await context.resolveId(
target.replace(/\*/g, patternMatch),
context.pkgURL,
);
return result ? result.location : null;
}
// Return PACKAGE_RESOLVE(target, packageURL + "/").
const result = await context.resolveId(target, context.pkgURL);
return result ? result.location : null;
}
// TODO: Drop if we do not support Node <= 16 anymore
// This behavior was removed in Node 17 (deprecated in Node 14), see DEP0148
if (context.allowExportsFolderMapping) {
target = target.replace(/\/$/, "/*");
}
// If target split on "/" or "\"
{
const pathSegments = target.split(/\/|\\/);
// after the first "." segment
const firstDot = pathSegments.indexOf(".");
firstDot !== -1 && pathSegments.slice(firstDot);
if (
firstDot !== -1 &&
firstDot < pathSegments.length - 1 &&
includesInvalidSegments(
pathSegments.slice(firstDot + 1),
context.moduleDirs,
)
) {
throw new InvalidPackageTargetError(
context,
`Invalid mapping: "${target}".`,
);
}
}
// Let resolvedTarget be the URL resolution of the concatenation of packageURL and target.
const resolvedTarget = path.resolve(context.pkgURL, target);
// Assert: resolvedTarget is contained in packageURL.
if (!resolvedTarget.startsWith(context.pkgURL)) {
throw new InvalidPackageTargetError(
context,
`Resolved to ${resolvedTarget} which is outside package ${context.pkgURL}`,
);
}
// If patternMatch is null, then
if (!patternMatch) {
// Return resolvedTarget.
return resolvedTarget;
}
// If patternMatch split on "/" or "\" contains invalid segments
if (
validateImportsExports &&
includesInvalidSegments(patternMatch.split(/\/|\\/), context.moduleDirs)
) {
// throw an Invalid Module Specifier error.
throw new InvalidModuleSpecifierError(context);
}
// Return the URL resolution of resolvedTarget with every instance of "*" replaced with patternMatch.
return resolvedTarget.replace(/\*/g, patternMatch);
}
// Otherwise, if target is an Array, then
if (Array.isArray(target)) {
// If _target.length is zero, return null.
if (target.length === 0) {
return null;
}
let lastError = null;
// For each item in target, do
for (const item of target) {
// Let resolved be the result of PACKAGE_TARGET_RESOLVE of the item
// continuing the loop on any Invalid Package Target error.
try {
const resolved = await resolvePackageTarget(context, {
target: item,
patternMatch,
isImports,
validateImportsExports,
});
// If resolved is undefined, continue the loop.
// Else Return resolved.
if (resolved !== undefined) {
return resolved;
}
} catch (error) {
if (!(error instanceof InvalidPackageTargetError)) {
throw error;
} else {
lastError = error;
}
}
}
// Return or throw the last fallback resolution null return or error
if (lastError) {
throw lastError;
}
return null;
}
// Otherwise, if target is a non-null Object, then
if (target && typeof target === "object") {
// For each property of target
for (const [key, value] of Object.entries(target)) {
// If exports contains any index property keys, as defined in ECMA-262 6.1.7 Array Index, throw an Invalid Package Configuration error.
// TODO: We do not check if the key is a number here...
// If key equals "default" or conditions contains an entry for the key, then
if (key === "default" || context.conditions.includes(key)) {
// Let targetValue be the value of the property in target.
// Let resolved be the result of PACKAGE_TARGET_RESOLVE of the targetValue
const resolved = await resolvePackageTarget(context, {
target: value,
patternMatch,
isImports,
validateImportsExports,
});
// If resolved is equal to undefined, continue the loop.
// Return resolved.
if (resolved !== undefined) {
return resolved;
}
}
}
// Return undefined.
return undefined;
}
// Otherwise, if target is null, return null.
if (target === null) {
return null;
}
// Otherwise throw an Invalid Package Target error.
throw new InvalidPackageTargetError(context, `Invalid exports field.`);
}
export default resolvePackageTarget;
|