
























@@ -7,6 +7,7 @@ import { normalizeOptionalString } from "../shared/string-coerce.js";
77import { normalizeOptionalTrimmedStringList } from "../shared/string-normalization.js";
88import type { PluginCandidate } from "./discovery.js";
99import { hashJson } from "./installed-plugin-index-hash.js";
10+import type { InstalledPluginFileSignature } from "./installed-plugin-index-hash.js";
1011import type { InstalledPluginIndex, InstalledPluginIndexRecord } from "./installed-plugin-index.js";
1112import { extractPluginInstallRecordsFromInstalledPluginIndex } from "./installed-plugin-index.js";
1213import { loadPluginManifestRegistry, type PluginManifestRegistry } from "./manifest-registry.js";
@@ -25,6 +26,37 @@ import {
2526type PluginDependencySpecMap,
2627} from "./status-dependencies.js";
272829+const installedManifestRegistryIndexFingerprintCache = new WeakMap<InstalledPluginIndex, string>();
30+31+function isDeepFrozenJsonLike(value: unknown, seen = new WeakSet<object>()): boolean {
32+if (!value || typeof value !== "object") {
33+return true;
34+}
35+const object = value as object;
36+if (seen.has(object)) {
37+return true;
38+}
39+if (!Object.isFrozen(object)) {
40+return false;
41+}
42+seen.add(object);
43+return Object.values(value).every((entry) => isDeepFrozenJsonLike(entry, seen));
44+}
45+46+function hasPersistedFileSignatures(index: InstalledPluginIndex): boolean {
47+return index.plugins.every(
48+(record) =>
49+record.manifestFile !== undefined &&
50+(record.packageJson === undefined || record.packageJson.fileSignature !== undefined),
51+);
52+}
53+54+function isInstalledManifestRegistryIndexFingerprintCacheable(
55+index: InstalledPluginIndex,
56+): boolean {
57+return hasPersistedFileSignatures(index) && isDeepFrozenJsonLike(index);
58+}
59+2860function isRelativePathInsideOrEqual(relativePath: string): boolean {
2961return (
3062relativePath === "" ||
@@ -61,12 +93,19 @@ function safeFileSignature(filePath: string | undefined): string | undefined {
6193}
6294try {
6395const stat = fs.statSync(filePath);
64-return `${filePath}:${stat.size}:${stat.mtimeMs}`;
96+return formatFileSignature(filePath, stat);
6597} catch {
6698return `${filePath}:missing`;
6799}
68100}
69101102+function formatFileSignature(
103+filePath: string,
104+signature: Pick<InstalledPluginFileSignature, "size" | "mtimeMs">,
105+): string {
106+return `${filePath}:${signature.size}:${signature.mtimeMs}`;
107+}
108+70109function buildInstalledManifestRegistryIndexKey(index: InstalledPluginIndex) {
71110const realpathCache = new Map<string, string>();
72111return {
@@ -78,9 +117,12 @@ function buildInstalledManifestRegistryIndexKey(index: InstalledPluginIndex) {
78117installRecords: index.installRecords,
79118diagnostics: index.diagnostics,
80119plugins: index.plugins.map((record) => {
81-const packageJsonFile =
82-record.packageJson?.fileSignature ??
83-safeFileSignature(resolvePackageJsonPath(record, realpathCache));
120+const packageJsonPath = resolvePackageJsonPath(record, realpathCache);
121+const packageJsonFile = record.packageJson?.fileSignature
122+ ? packageJsonPath
123+ ? formatFileSignature(packageJsonPath, record.packageJson.fileSignature)
124+ : undefined
125+ : safeFileSignature(packageJsonPath);
84126return {
85127pluginId: record.pluginId,
86128packageName: record.packageName,
@@ -91,7 +133,9 @@ function buildInstalledManifestRegistryIndexKey(index: InstalledPluginIndex) {
91133packageChannel: record.packageChannel,
92134manifestPath: record.manifestPath,
93135manifestHash: record.manifestHash,
94-manifestFile: safeFileSignature(record.manifestPath),
136+manifestFile: record.manifestFile
137+ ? formatFileSignature(record.manifestPath, record.manifestFile)
138+ : safeFileSignature(record.manifestPath),
95139format: record.format,
96140bundleFormat: record.bundleFormat,
97141source: record.source,
@@ -116,7 +160,15 @@ function buildInstalledManifestRegistryIndexKey(index: InstalledPluginIndex) {
116160export function resolveInstalledManifestRegistryIndexFingerprint(
117161index: InstalledPluginIndex,
118162): string {
119-return hashJson(buildInstalledManifestRegistryIndexKey(index));
163+const cached = installedManifestRegistryIndexFingerprintCache.get(index);
164+if (cached) {
165+return cached;
166+}
167+const fingerprint = hashJson(buildInstalledManifestRegistryIndexKey(index));
168+if (isInstalledManifestRegistryIndexFingerprintCacheable(index)) {
169+installedManifestRegistryIndexFingerprintCache.set(index, fingerprint);
170+}
171+return fingerprint;
120172}
121173122174function resolveInstalledPluginRootDir(record: InstalledPluginIndexRecord): string {
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。