From 53176153a22c217ef2d2ed57063ad60293de23b5 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Mon, 20 Apr 2026 13:51:32 +0100 Subject: [PATCH] test: cover alias map cache context --- src/plugins/sdk-alias.test.ts | 50 +++++++++++++++++++++++++++++++++++ src/plugins/sdk-alias.ts | 24 ++++++++++++++++- 2 files changed, 73 insertions(+), 1 deletion(-) diff --git a/src/plugins/sdk-alias.test.ts b/src/plugins/sdk-alias.test.ts index 34e30633b82..6a3742f4490 100644 --- a/src/plugins/sdk-alias.test.ts +++ b/src/plugins/sdk-alias.test.ts @@ -1128,6 +1128,56 @@ describe("buildPluginLoaderAliasMap memoization", () => { expect(a).not.toBe(b); }); + it("does not reuse a public alias map after private qa aliases are enabled", () => { + const fixture = createPluginSdkAliasFixture({ + packageExports: { + "./plugin-sdk/core": { default: "./dist/plugin-sdk/core.js" }, + }, + }); + const sourceRootAlias = path.join(fixture.root, "src", "plugin-sdk", "root-alias.cjs"); + const sourceQaRuntimePath = path.join(fixture.root, "src", "plugin-sdk", "qa-runtime.ts"); + fs.writeFileSync(sourceRootAlias, "module.exports = {};\n", "utf-8"); + fs.writeFileSync(sourceQaRuntimePath, "export const qaRuntime = true;\n", "utf-8"); + const entry = writePluginEntry(fixture.root, bundledPluginFile("private-qa", "src/index.ts")); + + const publicAliases = withEnv({ OPENCLAW_ENABLE_PRIVATE_QA_CLI: undefined }, () => + buildPluginLoaderAliasMap(entry), + ); + const privateAliases = withEnv({ OPENCLAW_ENABLE_PRIVATE_QA_CLI: "1" }, () => + buildPluginLoaderAliasMap(entry), + ); + + expect(publicAliases).not.toBe(privateAliases); + expect(publicAliases["openclaw/plugin-sdk/qa-runtime"]).toBeUndefined(); + expect(fs.realpathSync(privateAliases["openclaw/plugin-sdk/qa-runtime"] ?? "")).toBe( + fs.realpathSync(sourceQaRuntimePath), + ); + }); + + it("does not reuse a development alias map in production mode", () => { + const fixture = createPluginSdkAliasFixture(); + const sourceRootAlias = path.join(fixture.root, "src", "plugin-sdk", "root-alias.cjs"); + const distRootAlias = path.join(fixture.root, "dist", "plugin-sdk", "root-alias.cjs"); + fs.writeFileSync(sourceRootAlias, "module.exports = { source: true };\n", "utf-8"); + fs.writeFileSync(distRootAlias, "module.exports = { dist: true };\n", "utf-8"); + const entry = writePluginEntry(fixture.root, bundledPluginFile("env-mode", "src/index.ts")); + + const developmentAliases = withEnv({ NODE_ENV: undefined }, () => + buildPluginLoaderAliasMap(entry), + ); + const productionAliases = withEnv({ NODE_ENV: "production" }, () => + buildPluginLoaderAliasMap(entry), + ); + + expect(developmentAliases).not.toBe(productionAliases); + expect(fs.realpathSync(developmentAliases["openclaw/plugin-sdk"] ?? "")).toBe( + fs.realpathSync(sourceRootAlias), + ); + expect(fs.realpathSync(productionAliases["openclaw/plugin-sdk"] ?? "")).toBe( + fs.realpathSync(distRootAlias), + ); + }); + it("memoized result has identical content to a freshly computed map", () => { const fixture = createPluginSdkAliasFixture(); fs.writeFileSync( diff --git a/src/plugins/sdk-alias.ts b/src/plugins/sdk-alias.ts index 18bd47d7155..2b14cd29297 100644 --- a/src/plugins/sdk-alias.ts +++ b/src/plugins/sdk-alias.ts @@ -437,13 +437,35 @@ export function resolveExtensionApiAlias(params: LoaderModuleResolveParams = {}) // the full cycle every time. See #68983. const aliasMapCache = new Map>(); +function buildPluginLoaderAliasMapCacheKey(params: { + modulePath: string; + argv1?: string; + moduleUrl?: string; + pluginSdkResolution: PluginSdkResolutionPreference; +}) { + return [ + params.modulePath, + params.argv1 ?? "", + params.moduleUrl ?? "", + params.pluginSdkResolution, + process.cwd(), + process.env.NODE_ENV === "production" ? "production" : "non-production", + shouldIncludePrivateLocalOnlyPluginSdkSubpaths() ? "private-qa" : "public", + ].join("\0"); +} + export function buildPluginLoaderAliasMap( modulePath: string, argv1: string | undefined = STARTUP_ARGV1, moduleUrl?: string, pluginSdkResolution: PluginSdkResolutionPreference = "auto", ): Record { - const cacheKey = `${modulePath}\0${argv1 ?? ""}\0${moduleUrl ?? ""}\0${pluginSdkResolution}`; + const cacheKey = buildPluginLoaderAliasMapCacheKey({ + modulePath, + argv1, + moduleUrl, + pluginSdkResolution, + }); const cached = aliasMapCache.get(cacheKey); if (cached) { return cached;