mirror of
https://github.com/morluto/rea
synced 2026-10-25 22:08:11 -04:00
+6
-5
@@ -411,11 +411,12 @@ retain their targets; computed imports remain unknown. TypeScript import-equals
|
||||
dependencies remain `requires` relationships whether or not they are exported.
|
||||
|
||||
CommonJS `require` relationships retain the requested specifier. REA resolves
|
||||
them against the source file only when Node's default source-relative loader is
|
||||
proven; non-default `createRequire` bases and unsupported
|
||||
`require.resolve` search options remain partial with unknown resolution. An
|
||||
excluded `package.json` also leaves package-directory selection unknown rather
|
||||
than treating the manifest as absent and applying an `index` fallback.
|
||||
them only when the loader base is proven: this includes the exact
|
||||
`createRequire(new URL("./file.cjs", import.meta.url))` form and
|
||||
`require.resolve` with `{ paths: [__dirname] }`. Other custom bases and search
|
||||
options remain partial with unknown resolution. An excluded `package.json`
|
||||
also leaves package-directory selection unknown rather than treating the
|
||||
manifest as absent and applying an `index` fallback.
|
||||
|
||||
Historical-source import requires safe no-follow file opens on Linux or
|
||||
macOS. Native Windows returns `unsupported_host`; use Linux REA inside WSL
|
||||
|
||||
@@ -351,7 +351,8 @@ const appendFile = (
|
||||
if (parsed === undefined) return;
|
||||
output.limitations.push(...parsed.limitations);
|
||||
for (const relationship of parsed.relationships) {
|
||||
const { resolutionStrategy, ...graphRelationship } = relationship;
|
||||
const { resolutionStrategy, resolutionBasePath, ...graphRelationship } =
|
||||
relationship;
|
||||
if (graphRelationship.resolution !== "internal") {
|
||||
output.relationships.push(graphRelationship);
|
||||
continue;
|
||||
@@ -363,7 +364,7 @@ const appendFile = (
|
||||
? "source-require"
|
||||
: "source-import";
|
||||
const resolved = resolveInternalSpecifier(
|
||||
graphRelationship.from_path,
|
||||
resolutionBasePath ?? graphRelationship.from_path,
|
||||
graphRelationship.to,
|
||||
context,
|
||||
mode,
|
||||
|
||||
@@ -26,7 +26,10 @@ import {
|
||||
unwrapJavaScriptExpression,
|
||||
} from "./javascriptAstValues.js";
|
||||
import { semanticPropertyPathKeyMatches } from "./javascriptSemanticPropertyPaths.js";
|
||||
import { stringValue } from "./javascriptStaticAnalysisHelpers.js";
|
||||
import {
|
||||
staticSourceRelativeUrlPath,
|
||||
stringValue,
|
||||
} from "./javascriptStaticAnalysisHelpers.js";
|
||||
import {
|
||||
semanticEffectTiming,
|
||||
semanticBindingAtRead,
|
||||
@@ -46,7 +49,10 @@ import {
|
||||
type SemanticAliasSelectionPath,
|
||||
} from "./javascriptSemanticAliasSelections.js";
|
||||
import { SEMANTIC_ALIAS_SELECTION_LIMIT } from "./javascriptSemanticResourceLimits.js";
|
||||
import { isUnmodifiedImportMetaUrl } from "./javascriptSemanticAmbientWrites.js";
|
||||
import {
|
||||
isUnmodifiedGlobalReference,
|
||||
isUnmodifiedImportMetaUrl,
|
||||
} from "./javascriptSemanticAmbientWrites.js";
|
||||
import { semanticReferenceSourcesInactive } from "./javascriptSemanticReferenceSources.js";
|
||||
|
||||
export interface JavaScriptRequireOrigin {
|
||||
@@ -266,7 +272,12 @@ const createRequireFactoryCallAt = (
|
||||
initializer: t.Node | undefined,
|
||||
state: JavaScriptSemanticAnalysisState,
|
||||
factoryBindingIds: ReadonlySet<string> = new Set(),
|
||||
): Pick<JavaScriptRequireCallFact, "loader" | "sourceRelative"> | undefined =>
|
||||
):
|
||||
| Pick<
|
||||
JavaScriptRequireCallFact,
|
||||
"loader" | "sourceRelative" | "sourceRelativePath"
|
||||
>
|
||||
| undefined =>
|
||||
!t.isCallExpression(initializer)
|
||||
? undefined
|
||||
: selectedRequireSourcesAt(
|
||||
@@ -277,6 +288,32 @@ const createRequireFactoryCallAt = (
|
||||
"factory",
|
||||
);
|
||||
|
||||
const sourceRelativeCreateRequirePath = (
|
||||
value: t.Node | undefined,
|
||||
state: JavaScriptSemanticAnalysisState,
|
||||
): string | undefined => {
|
||||
if (value === undefined) return undefined;
|
||||
if (isUnmodifiedImportMetaUrl(value, state)) return ".";
|
||||
if (!t.isNewExpression(value) || value.arguments.length !== 2)
|
||||
return undefined;
|
||||
const callee = unwrapJavaScriptExpression(value.callee).node;
|
||||
if (
|
||||
!t.isIdentifier(callee, { name: "URL" }) ||
|
||||
!isUnmodifiedGlobalReference(callee, state, "URL") ||
|
||||
!isUnmodifiedImportMetaUrl(
|
||||
t.isNode(value.arguments[1]) ? value.arguments[1] : undefined,
|
||||
state,
|
||||
)
|
||||
)
|
||||
return undefined;
|
||||
const urlPath = staticSourceRelativeUrlPath(value);
|
||||
return urlPath === undefined ||
|
||||
urlPath.directory ||
|
||||
urlPath.path.startsWith("/")
|
||||
? undefined
|
||||
: urlPath.path;
|
||||
};
|
||||
|
||||
/** Eligibility for observable loader slots; an unknown factory is not invocation proof. */
|
||||
export const hasSemanticCreateRequireFactoryOrigin = (
|
||||
initializer: t.Node | undefined,
|
||||
@@ -318,7 +355,12 @@ const selectedRequireSourcesAt = (
|
||||
state: JavaScriptSemanticAnalysisState,
|
||||
factoryBindingIds: ReadonlySet<string>,
|
||||
target: "loader" | "factory" = "loader",
|
||||
): Pick<JavaScriptRequireCallFact, "loader" | "sourceRelative"> | undefined => {
|
||||
):
|
||||
| Pick<
|
||||
JavaScriptRequireCallFact,
|
||||
"loader" | "sourceRelative" | "sourceRelativePath"
|
||||
>
|
||||
| undefined => {
|
||||
const pending: ModuleObjectSource[] = [{ node: root, path: [] }];
|
||||
const seen = new WeakMap<t.Node, Set<string>>();
|
||||
let count = 0;
|
||||
@@ -329,6 +371,7 @@ const selectedRequireSourcesAt = (
|
||||
let local = false;
|
||||
let nativeMemberAlternative = false;
|
||||
let sourceRelative = true;
|
||||
let sourceRelativePath: string | undefined;
|
||||
while (pending.length > 0) {
|
||||
const current = pending.pop()!;
|
||||
const node = unwrapJavaScriptExpression(current.node).node;
|
||||
@@ -514,10 +557,17 @@ const selectedRequireSourcesAt = (
|
||||
selectedLoader !== "create-require");
|
||||
selectedLoader ??= "create-require";
|
||||
unknown ||= state.conditionallySkippedExpressions.has(node);
|
||||
sourceRelative &&= isUnmodifiedImportMetaUrl(
|
||||
const factoryPath = sourceRelativeCreateRequirePath(
|
||||
node.arguments[0],
|
||||
state,
|
||||
);
|
||||
if (factoryPath === undefined) sourceRelative = false;
|
||||
else if (sourceRelativePath === undefined)
|
||||
sourceRelativePath = factoryPath;
|
||||
else if (sourceRelativePath !== factoryPath) {
|
||||
sourceRelative = false;
|
||||
sourceRelativePath = undefined;
|
||||
}
|
||||
}
|
||||
} else if (factory?.loader === "local") local = true;
|
||||
else unknown = true;
|
||||
@@ -543,6 +593,9 @@ const selectedRequireSourcesAt = (
|
||||
? (selectedLoader ?? "unknown")
|
||||
: "local",
|
||||
sourceRelative: found && sourceRelative && !unknown,
|
||||
...(found && !unknown && sourceRelativePath !== undefined
|
||||
? { sourceRelativePath }
|
||||
: {}),
|
||||
}
|
||||
: undefined;
|
||||
};
|
||||
@@ -582,6 +635,8 @@ export interface JavaScriptRequireCallFact {
|
||||
| readonly t.CallExpression["arguments"][number][]
|
||||
| undefined;
|
||||
readonly sourceRelative: boolean;
|
||||
/** A createRequire filename relative to the current source directory, when proven. */
|
||||
readonly sourceRelativePath?: string;
|
||||
}
|
||||
|
||||
/** Classify the selected loader and normalize invocation arguments once. */
|
||||
@@ -610,6 +665,9 @@ export const semanticRequireCallAt = (
|
||||
loader: selected?.loader ?? loader,
|
||||
arguments: node.arguments,
|
||||
sourceRelative: selected?.sourceRelative ?? loader !== "create-require",
|
||||
...(selected?.sourceRelativePath === undefined
|
||||
? {}
|
||||
: { sourceRelativePath: selected.sourceRelativePath }),
|
||||
};
|
||||
}
|
||||
const interop = loaderInvocationInterop(state);
|
||||
@@ -637,7 +695,13 @@ export const semanticRequireCallAt = (
|
||||
];
|
||||
return interop.intrinsicPath(callee);
|
||||
});
|
||||
if (invocation?.path[0] === "require-loader")
|
||||
if (invocation?.path[0] === "require-loader") {
|
||||
const selected = selectedRequireSourcesAt(
|
||||
node.callee,
|
||||
node,
|
||||
state,
|
||||
factoryBindingIds,
|
||||
);
|
||||
return {
|
||||
loader:
|
||||
invocation.path[1] === "local"
|
||||
@@ -648,7 +712,11 @@ export const semanticRequireCallAt = (
|
||||
arguments: invocation.arguments,
|
||||
sourceRelative:
|
||||
invocation.kind === "known" && invocation.path[2] === "relative",
|
||||
...(selected?.sourceRelativePath === undefined
|
||||
? {}
|
||||
: { sourceRelativePath: selected.sourceRelativePath }),
|
||||
};
|
||||
}
|
||||
}
|
||||
const factory = semanticFactoryRequireLoaderAt(
|
||||
node,
|
||||
|
||||
@@ -255,7 +255,20 @@ const staticCallPath = (
|
||||
return parts.length === 0 ? undefined : posix.join(...parts);
|
||||
};
|
||||
|
||||
const staticFileUrlPath = (
|
||||
/** Normalized path facts from a source-relative file URL expression. */
|
||||
export interface JavaScriptStaticSourceUrlPath {
|
||||
readonly path: string;
|
||||
readonly directory: boolean;
|
||||
}
|
||||
|
||||
/** Read a literal `new URL(relative, import.meta.url)` shape without evaluation. */
|
||||
export const staticSourceRelativeUrlPath = (
|
||||
node: t.Node,
|
||||
): JavaScriptStaticSourceUrlPath | undefined =>
|
||||
isSourceFileUrl(node) ? sourceRelativeFileUrlPath(node) : undefined;
|
||||
|
||||
/** Convert an exact static file URL expression to a POSIX path. */
|
||||
export const staticFileUrlPath = (
|
||||
node: t.CallExpression | t.NewExpression,
|
||||
nodePathResolve?: JavaScriptStaticPathIntrinsicQuery,
|
||||
): string | undefined => {
|
||||
@@ -263,7 +276,8 @@ const staticFileUrlPath = (
|
||||
const rawArgument = argumentNode(node.arguments[0]);
|
||||
if (rawArgument === undefined) return undefined;
|
||||
const argument = unwrapJavaScriptExpression(rawArgument).node;
|
||||
if (isSourceFileUrl(argument)) return sourceRelativeFileUrlPath(argument);
|
||||
if (isSourceFileUrl(argument))
|
||||
return sourceRelativeFileUrlPath(argument)?.path;
|
||||
const value = staticPath(argument, nodePathResolve);
|
||||
const rawPath = value?.split(/[?#]/u, 1)[0] ?? "";
|
||||
if (
|
||||
@@ -291,7 +305,7 @@ const staticFileUrlPath = (
|
||||
/** Project a known source-relative URL through the actual file URL decoder. */
|
||||
const sourceRelativeFileUrlPath = (
|
||||
node: t.CallExpression | t.NewExpression,
|
||||
): string | undefined => {
|
||||
): JavaScriptStaticSourceUrlPath | undefined => {
|
||||
const value = stringValue(node.arguments[0]);
|
||||
if (
|
||||
value === undefined ||
|
||||
@@ -310,14 +324,19 @@ const sourceRelativeFileUrlPath = (
|
||||
try {
|
||||
const resolved = new URL(value, `file://${directory}entry.js`);
|
||||
const path = fileURLToPath(resolved, { windows: false });
|
||||
if (value.startsWith("/")) return path;
|
||||
if (value.startsWith("/"))
|
||||
return { path, directory: resolved.pathname.endsWith("/") };
|
||||
const relative = posix.relative(directory, path) || ".";
|
||||
// Keep the established explicit source-directory observation spelling.
|
||||
return value.startsWith("./") &&
|
||||
relative !== "." &&
|
||||
!relative.startsWith("../")
|
||||
? `./${relative}`
|
||||
: relative;
|
||||
return {
|
||||
path:
|
||||
value.startsWith("./") &&
|
||||
relative !== "." &&
|
||||
!relative.startsWith("../")
|
||||
? `./${relative}`
|
||||
: relative,
|
||||
directory: resolved.pathname.endsWith("/"),
|
||||
};
|
||||
} catch (cause: unknown) {
|
||||
// Malformed escapes and non-file URL forms remain unknown.
|
||||
void cause;
|
||||
|
||||
@@ -48,6 +48,8 @@ interface ReferenceSourceImportRelationship {
|
||||
readonly parse_state: ReferenceSourceImportParseState;
|
||||
/** Distinguishes call-form CommonJS require from TS import-equals `requires`. */
|
||||
readonly resolutionStrategy?: "runtime-require";
|
||||
/** Internal lookup origin for a proven createRequire URL base. */
|
||||
readonly resolutionBasePath?: string;
|
||||
}
|
||||
|
||||
interface ReferenceSourceParseFailure {
|
||||
@@ -126,6 +128,7 @@ const appendRelationship = (
|
||||
readonly parseState: ReferenceSourceImportParseState;
|
||||
readonly resolution?: ReferenceSourceImportResolution;
|
||||
readonly resolutionStrategy?: "runtime-require";
|
||||
readonly resolutionBasePath?: string;
|
||||
},
|
||||
): void => {
|
||||
if (input.to === undefined) return;
|
||||
@@ -144,6 +147,9 @@ const appendRelationship = (
|
||||
...(input.resolutionStrategy === undefined
|
||||
? {}
|
||||
: { resolutionStrategy: input.resolutionStrategy }),
|
||||
...(input.resolutionBasePath === undefined
|
||||
? {}
|
||||
: { resolutionBasePath: input.resolutionBasePath }),
|
||||
});
|
||||
};
|
||||
|
||||
@@ -236,7 +242,12 @@ const extractRequireAndDynamicImports = (
|
||||
from_path: string,
|
||||
relationships: ReferenceSourceImportRelationship[],
|
||||
limitations: string[],
|
||||
requireCallBases: ReadonlyMap<CallExpression, "source-file" | "unknown">,
|
||||
requireCallBases: ReadonlyMap<
|
||||
CallExpression,
|
||||
| "source-file"
|
||||
| { readonly kind: "source-relative-file"; readonly path: string }
|
||||
| "unknown"
|
||||
>,
|
||||
): void => {
|
||||
// Single traversal owner: iterative, VISITOR_KEYS-gated, no recursion over
|
||||
// loc/comment objects. Survives deeply nested generated member chains that
|
||||
@@ -280,6 +291,11 @@ const extractRequireAndDynamicImports = (
|
||||
...(uncertainResolution
|
||||
? {}
|
||||
: { resolutionStrategy: "runtime-require" as const }),
|
||||
...(typeof resolutionBase === "object"
|
||||
? {
|
||||
resolutionBasePath: resolutionBase.path,
|
||||
}
|
||||
: {}),
|
||||
});
|
||||
}
|
||||
continue;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import * as t from "@babel/types";
|
||||
import { posix } from "node:path";
|
||||
|
||||
import { semanticStaticPropertyKey } from "./javascript/javascriptAstValues.js";
|
||||
import { isUnmodifiedGlobalReference } from "./javascript/javascriptSemanticAmbientWrites.js";
|
||||
@@ -20,7 +21,10 @@ import {
|
||||
type ParsedJavaScriptSource,
|
||||
} from "./javascript/javascriptSourceParser.js";
|
||||
|
||||
export type ReferenceSourceRequireResolutionBase = "source-file" | "unknown";
|
||||
export type ReferenceSourceRequireResolutionBase =
|
||||
| "source-file"
|
||||
| { readonly kind: "source-relative-file"; readonly path: string }
|
||||
| "unknown";
|
||||
|
||||
/** Identify exact calls through a source-owned Node loader and their resolver base. */
|
||||
export const referenceSourceRequireCallBases = (
|
||||
@@ -45,7 +49,7 @@ export const referenceSourceRequireCallBases = (
|
||||
traverseJavaScriptAst(file.program, {
|
||||
enter: (node) => {
|
||||
if (!t.isCallExpression(node)) return;
|
||||
const identifier = requireCalleeIdentifier(node.callee);
|
||||
const identifier = callReceiverIdentifier(node.callee);
|
||||
if (identifier === undefined) return;
|
||||
let fact = semanticRequireLoaderAt(node, index.bindings, factoryBindings);
|
||||
if (fact === "create-require") {
|
||||
@@ -64,20 +68,40 @@ export const referenceSourceRequireCallBases = (
|
||||
index.bindings,
|
||||
factoryBindings,
|
||||
);
|
||||
const base =
|
||||
const sourceRelativePath = callFact?.sourceRelativePath;
|
||||
const normalizedSourceRelativePath =
|
||||
sourceRelativePath === undefined
|
||||
? undefined
|
||||
: posix.normalize(
|
||||
posix.join(posix.dirname(path), sourceRelativePath),
|
||||
);
|
||||
const base: ReferenceSourceRequireResolutionBase =
|
||||
fact === "create-require"
|
||||
? callFact?.sourceRelative === true
|
||||
? "source-file"
|
||||
: "unknown"
|
||||
? sourceRelativePath === undefined
|
||||
? callFact?.sourceRelative === true
|
||||
? "source-file"
|
||||
: "unknown"
|
||||
: normalizedSourceRelativePath === undefined ||
|
||||
normalizedSourceRelativePath === ".." ||
|
||||
normalizedSourceRelativePath.startsWith("../")
|
||||
? "unknown"
|
||||
: normalizedSourceRelativePath === path
|
||||
? "source-file"
|
||||
: {
|
||||
kind: "source-relative-file",
|
||||
path: normalizedSourceRelativePath,
|
||||
}
|
||||
: "source-file";
|
||||
const searchBase = requireResolveSearchBase(
|
||||
node,
|
||||
index.bindings,
|
||||
base,
|
||||
wrapperMode === "present",
|
||||
);
|
||||
candidates.push({
|
||||
call: node,
|
||||
identifier,
|
||||
resolutionBase:
|
||||
base === "source-file" &&
|
||||
isDefaultRequireResolveSearch(node, index.bindings)
|
||||
? "source-file"
|
||||
: "unknown",
|
||||
resolutionBase: searchBase,
|
||||
});
|
||||
},
|
||||
});
|
||||
@@ -95,38 +119,39 @@ export const referenceSourceRequireCallBases = (
|
||||
};
|
||||
|
||||
/** `require.resolve` options replace the default search paths unless exact current-directory paths are supplied. */
|
||||
const isDefaultRequireResolveSearch = (
|
||||
const requireResolveSearchBase = (
|
||||
call: t.CallExpression,
|
||||
bindings: JavaScriptSemanticAnalysisState,
|
||||
): boolean => {
|
||||
if (!isRequireResolveCall(call) || call.arguments.length < 2) return true;
|
||||
if (call.arguments.length !== 2) return false;
|
||||
loaderBase: ReferenceSourceRequireResolutionBase,
|
||||
hasCommonJsWrapper: boolean,
|
||||
): ReferenceSourceRequireResolutionBase => {
|
||||
if (!isRequireResolveCall(call) || call.arguments.length < 2)
|
||||
return loaderBase;
|
||||
if (call.arguments.length !== 2) return "unknown";
|
||||
const options = t.isExpression(call.arguments[1])
|
||||
? call.arguments[1]
|
||||
: undefined;
|
||||
if (options === undefined) return false;
|
||||
if (!t.isObjectExpression(options)) return false;
|
||||
if (options.properties.length === 0) return true;
|
||||
if (options.properties.length !== 1) return false;
|
||||
if (options === undefined || !t.isObjectExpression(options)) return "unknown";
|
||||
if (options.properties.length === 0) return loaderBase;
|
||||
if (options.properties.length !== 1) return "unknown";
|
||||
const property = options.properties[0];
|
||||
if (!t.isObjectProperty(property)) return false;
|
||||
if (!t.isObjectProperty(property)) return "unknown";
|
||||
if (semanticStaticPropertyKey(property.key, property.computed) !== "paths")
|
||||
return false;
|
||||
return "unknown";
|
||||
const value = t.isExpression(property.value) ? property.value : undefined;
|
||||
if (!t.isArrayExpression(value) || value.elements.length !== 1) return false;
|
||||
if (!t.isArrayExpression(value) || value.elements.length !== 1)
|
||||
return "unknown";
|
||||
const directory = value.elements[0];
|
||||
return (
|
||||
return hasCommonJsWrapper &&
|
||||
t.isIdentifier(directory, { name: "__dirname" }) &&
|
||||
isUnmodifiedGlobalReference(directory, bindings, "__dirname")
|
||||
);
|
||||
? "source-file"
|
||||
: "unknown";
|
||||
};
|
||||
|
||||
const isRequireResolveCall = (call: t.CallExpression): boolean => {
|
||||
const callee = call.callee;
|
||||
if (
|
||||
!t.isMemberExpression(callee) ||
|
||||
!t.isIdentifier(callee.object, { name: "require" })
|
||||
)
|
||||
if (!t.isMemberExpression(callee) && !t.isOptionalMemberExpression(callee))
|
||||
return false;
|
||||
return (
|
||||
semanticStaticPropertyKey(callee.property, callee.computed) === "resolve"
|
||||
@@ -164,23 +189,14 @@ const hasPriorMemberMutation = (
|
||||
);
|
||||
};
|
||||
|
||||
const requireCalleeIdentifier = (
|
||||
const callReceiverIdentifier = (
|
||||
callee: t.Node | null | undefined,
|
||||
): t.Identifier | undefined => {
|
||||
if (t.isIdentifier(callee, { name: "require" })) return callee;
|
||||
if (t.isIdentifier(callee)) return callee;
|
||||
if (
|
||||
!t.isMemberExpression(callee) ||
|
||||
!t.isIdentifier(callee.object, { name: "require" }) ||
|
||||
((!t.isIdentifier(callee.property) || callee.computed) &&
|
||||
!t.isStringLiteral(callee.property))
|
||||
(t.isMemberExpression(callee) || t.isOptionalMemberExpression(callee)) &&
|
||||
t.isIdentifier(callee.object)
|
||||
)
|
||||
return undefined;
|
||||
const propertyName = t.isIdentifier(callee.property)
|
||||
? callee.property.name
|
||||
: t.isStringLiteral(callee.property)
|
||||
? callee.property.value
|
||||
: undefined;
|
||||
return propertyName === "resolve" || propertyName === "main"
|
||||
? callee.object
|
||||
: undefined;
|
||||
return callee.object;
|
||||
return undefined;
|
||||
};
|
||||
|
||||
@@ -8,7 +8,7 @@ import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js";
|
||||
import { cliTest } from "../../support/cli/cliFixture.js";
|
||||
|
||||
cliTest(
|
||||
"preserves unknown CommonJS resolution when Node is given another base",
|
||||
"resolves a proven createRequire URL base and preserves unsupported alternatives",
|
||||
async ({ cli }) => {
|
||||
const root = await createTestTempDirectory("rea-reference-require-base-");
|
||||
const config = await createTestTempDirectory(
|
||||
@@ -24,10 +24,12 @@ cliTest(
|
||||
'custom("./dep.cjs");',
|
||||
"const local = createRequire(import.meta.url);",
|
||||
'local("./dep.cjs");',
|
||||
'local.resolve("./alias-options.cjs", { paths: [] });',
|
||||
].join("\n"),
|
||||
),
|
||||
writeFile(join(root, "dep.cjs"), "module.exports = 'root';\n"),
|
||||
writeFile(join(root, "sub", "dep.cjs"), "module.exports = 'sub';\n"),
|
||||
writeFile(join(root, "sub", "entry.cjs"), "module.exports = {};\n"),
|
||||
]);
|
||||
|
||||
const result = await cli.run({
|
||||
@@ -46,10 +48,10 @@ cliTest(
|
||||
expect.arrayContaining([
|
||||
{
|
||||
from_path: "main.mjs",
|
||||
to: "./dep.cjs",
|
||||
to: "sub/dep.cjs",
|
||||
kind: "requires",
|
||||
resolution: "unknown",
|
||||
parse_state: "partial",
|
||||
resolution: "internal",
|
||||
parse_state: "parsed",
|
||||
},
|
||||
{
|
||||
from_path: "main.mjs",
|
||||
@@ -58,6 +60,13 @@ cliTest(
|
||||
resolution: "internal",
|
||||
parse_state: "parsed",
|
||||
},
|
||||
{
|
||||
from_path: "main.mjs",
|
||||
to: "./alias-options.cjs",
|
||||
kind: "requires",
|
||||
resolution: "unknown",
|
||||
parse_state: "partial",
|
||||
},
|
||||
]),
|
||||
);
|
||||
},
|
||||
@@ -78,13 +87,16 @@ cliTest(
|
||||
join(root, "main.cjs"),
|
||||
[
|
||||
'require.resolve("./dep.cjs");',
|
||||
'require.resolve("./dep.cjs", { paths: [__dirname] });',
|
||||
'require.resolve("./same-path.cjs", { paths: [__dirname] });',
|
||||
'require.resolve("./dep.cjs", { paths: [__dirname + "/sub"] });',
|
||||
'require.resolve("./dep.cjs", { paths: [] });',
|
||||
'function shadow(__dirname) { require.resolve("./shadow.cjs", { paths: [__dirname] }); }',
|
||||
].join("\n"),
|
||||
),
|
||||
writeFile(join(root, "dep.cjs"), "module.exports = 'root';\n"),
|
||||
writeFile(join(root, "same-path.cjs"), "module.exports = 'same path';\n"),
|
||||
writeFile(join(root, "sub", "dep.cjs"), "module.exports = 'sub';\n"),
|
||||
writeFile(join(root, "shadow.cjs"), "module.exports = 'shadow';\n"),
|
||||
]);
|
||||
|
||||
const result = await cli.run({
|
||||
@@ -118,8 +130,22 @@ cliTest(
|
||||
resolution: "unknown",
|
||||
parse_state: "partial",
|
||||
},
|
||||
{
|
||||
from_path: "main.cjs",
|
||||
to: "same-path.cjs",
|
||||
kind: "requires",
|
||||
resolution: "internal",
|
||||
parse_state: "parsed",
|
||||
},
|
||||
{
|
||||
from_path: "main.cjs",
|
||||
to: "./shadow.cjs",
|
||||
kind: "requires",
|
||||
resolution: "unknown",
|
||||
parse_state: "partial",
|
||||
},
|
||||
]),
|
||||
);
|
||||
expect(relationships).toHaveLength(2);
|
||||
expect(relationships).toHaveLength(4);
|
||||
},
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user