diff --git a/src/domain/javascript/javascriptSemanticRequireOrigin.ts b/src/domain/javascript/javascriptSemanticRequireOrigin.ts index 43c7ba063a..a4963db9e1 100644 --- a/src/domain/javascript/javascriptSemanticRequireOrigin.ts +++ b/src/domain/javascript/javascriptSemanticRequireOrigin.ts @@ -159,6 +159,8 @@ const requireLoaderValueAt = ( return semanticBindingHasPriorValueWrite(node, binding, state) ? "unknown" : "factory-loader"; + if (binding !== undefined && isSemanticCreateRequireBinding(binding, state)) + return "create-require"; if (loader.name !== "require") return "local"; if (binding === undefined) { if (semanticResolutionBlocked(state, loader, "require")) return "unknown"; @@ -195,7 +197,6 @@ const requireLoaderValueAt = ( !semanticBindingHasPriorValueWrite(node, wrapperBinding, state) ) return commonJsLoaderAt(node, state); - if (isSemanticCreateRequireBinding(binding, state)) return "create-require"; const initializer = semanticStableInitializer(binding, state)?.node; if ( (binding.kind === "function" || binding.kind === "class") && diff --git a/src/domain/javascript/javascriptStaticAnalysisLoaderInvocations.test.ts b/src/domain/javascript/javascriptStaticAnalysisLoaderInvocations.test.ts index 8841b2a1c9..84a68de0de 100644 --- a/src/domain/javascript/javascriptStaticAnalysisLoaderInvocations.test.ts +++ b/src/domain/javascript/javascriptStaticAnalysisLoaderInvocations.test.ts @@ -5,7 +5,7 @@ import { expect, it } from "vitest"; import { analyzeJavaScriptStaticSource } from "./javascriptStaticAnalysis.js"; import { parseJavaScriptSource } from "./javascriptSourceParser.js"; -import { unshadowedReferenceSourceRequireCalls } from "../referenceSourceRequireBindings.js"; +import { referenceSourceRequireCallBases } from "../referenceSourceRequireBindings.js"; it.each(["require", "require.resolve", "require.main"])( "distinguishes invoked loading from reference association for %s", @@ -25,9 +25,7 @@ it.each(["require", "require.resolve", "require.main"])( ); const parsed = parseJavaScriptSource(source); if (parsed === null) throw new Error("Expected loader association fixture"); - expect( - unshadowedReferenceSourceRequireCalls(parsed, "entry.cjs").size, - ).toBe(1); + expect(referenceSourceRequireCallBases(parsed, "entry.cjs").size).toBe(1); }, ); @@ -39,6 +37,12 @@ it.each([ 1, "node:path", ], + [ + "renamed proven factory", + `${imported}const load=make(import.meta.url);load('node:path');`, + 1, + "node:path", + ], [ "opaque replacement factory", "import*as mod from'node:module';mod.default.createRequire=replacement;const require=mod.default.createRequire(import.meta.url);require('node:path');", @@ -50,9 +54,9 @@ it.each([ (_name, source, associated, specifier) => { const parsed = parseJavaScriptSource(source); if (parsed === null) throw new Error("Expected factory proof fixture"); - expect( - unshadowedReferenceSourceRequireCalls(parsed, "entry.mjs").size, - ).toBe(associated); + expect(referenceSourceRequireCallBases(parsed, "entry.mjs").size).toBe( + associated, + ); const analysis = analyzeJavaScriptStaticSource(source); expect(analysis.parse_error_count).toBe(0); expect( @@ -61,6 +65,14 @@ it.each([ }, ); +it("associates a renamed createRequire resolve method with search options", () => { + const parsed = parseJavaScriptSource( + `${imported}const load=make(import.meta.url);load.resolve('node:path',{paths:[]});`, + ); + if (parsed === null) throw new Error("Expected factory proof fixture"); + expect(referenceSourceRequireCallBases(parsed, "entry.mjs").size).toBe(1); +}); + it.each([ [ "captured wrapper",