ttsc 0.31.0 → 0.31.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cmd/platform/main.go +2 -2
- package/internal/sourceprocess/contain_windows.go +10 -13
- package/internal/sourceprocess/started_windows.go +41 -0
- package/internal/sourceprocess/windows_started_publication_distinguishes_pending_from_refusal_test.go +76 -0
- package/internal/watchhelper/run.go +30 -20
- package/internal/watchhelper/run_other.go +4 -4
- package/internal/watchhelper/run_windows.go +471 -0
- package/internal/watchhelper/watchhelper.go +8 -2
- package/internal/watchhelper/windows_notifications_preserve_mutations_without_access_noise_test.go +506 -0
- package/lib/compiler/internal/build/BuildExecution.d.ts +4 -2
- package/lib/compiler/internal/build/BuildExecution.js +40 -12
- package/lib/compiler/internal/build/BuildExecution.js.map +1 -1
- package/lib/compiler/internal/startResidentTransform.js +5 -4
- package/lib/compiler/internal/startResidentTransform.js.map +1 -1
- package/lib/compiler/internal/transformProjectInMemory.js +9 -7
- package/lib/compiler/internal/transformProjectInMemory.js.map +1 -1
- package/lib/internal/javascriptRuntimeCapabilities.d.ts +13 -4
- package/lib/internal/javascriptRuntimeCapabilities.js +56 -6
- package/lib/internal/javascriptRuntimeCapabilities.js.map +1 -1
- package/lib/internal/nativeBinary.d.ts +3 -3
- package/lib/internal/nativeBinary.js +3 -3
- package/lib/internal/pluginSource.d.ts +1 -0
- package/lib/internal/pluginSource.js +1 -0
- package/lib/internal/pluginSource.js.map +1 -1
- package/lib/internal/resolveNodeBinary.d.ts +6 -1
- package/lib/internal/resolveNodeBinary.js +6 -2
- package/lib/internal/resolveNodeBinary.js.map +1 -1
- package/lib/internal/runtimeExecutableIdentity.d.ts +22 -13
- package/lib/internal/runtimeExecutableIdentity.js +192 -102
- package/lib/internal/runtimeExecutableIdentity.js.map +1 -1
- package/lib/launcher/internal/runtime/installRuntimeHooks.js +58 -4
- package/lib/launcher/internal/runtime/installRuntimeHooks.js.map +1 -1
- package/lib/launcher/internal/ttscserver/captureLSPPluginSelectionInputs.d.ts +5 -1
- package/lib/launcher/internal/ttscserver/captureLSPPluginSelectionInputs.js +7 -2
- package/lib/launcher/internal/ttscserver/captureLSPPluginSelectionInputs.js.map +1 -1
- package/lib/launcher/internal/ttscserver/runTtscserver.js +8 -1
- package/lib/launcher/internal/ttscserver/runTtscserver.js.map +1 -1
- package/lib/plugin/internal/CapabilityResolutionFormat.d.ts +21 -62
- package/lib/plugin/internal/CapabilityResolutionFormat.js +15 -106
- package/lib/plugin/internal/CapabilityResolutionFormat.js.map +1 -1
- package/lib/plugin/internal/load/PluginDescriptorEvaluationCache.d.ts +6 -0
- package/lib/plugin/internal/load/PluginDescriptorEvaluationCache.js +4 -4
- package/lib/plugin/internal/load/PluginDescriptorEvaluationCache.js.map +1 -1
- package/lib/plugin/internal/load/loadProjectPlugins.d.ts +24 -14
- package/lib/plugin/internal/load/loadProjectPlugins.js +141 -56
- package/lib/plugin/internal/load/loadProjectPlugins.js.map +1 -1
- package/lib/plugin/internal/readCapabilityResolution.d.ts +6 -0
- package/lib/plugin/internal/readCapabilityResolution.js +8 -5
- package/lib/plugin/internal/readCapabilityResolution.js.map +1 -1
- package/lib/plugin/internal/source/GoEnvironmentReading.d.ts +48 -0
- package/lib/plugin/internal/source/GoEnvironmentReading.js +156 -0
- package/lib/plugin/internal/source/GoEnvironmentReading.js.map +1 -0
- package/lib/plugin/internal/source/NativeSourcePackages.d.ts +51 -13
- package/lib/plugin/internal/source/NativeSourcePackages.js +182 -27
- package/lib/plugin/internal/source/NativeSourcePackages.js.map +1 -1
- package/lib/plugin/internal/source/PluginBuildEnvironmentReadings.d.ts +42 -3
- package/lib/plugin/internal/source/PluginBuildEnvironmentReadings.js +68 -7
- package/lib/plugin/internal/source/PluginBuildEnvironmentReadings.js.map +1 -1
- package/lib/plugin/internal/source/PluginBuildEnvironmentWitness.d.ts +5 -3
- package/lib/plugin/internal/source/PluginBuildEnvironmentWitness.js +14 -8
- package/lib/plugin/internal/source/PluginBuildEnvironmentWitness.js.map +1 -1
- package/lib/plugin/internal/source/PluginContentIdentities.d.ts +265 -0
- package/lib/plugin/internal/source/PluginContentIdentities.js +452 -0
- package/lib/plugin/internal/source/PluginContentIdentities.js.map +1 -0
- package/lib/plugin/internal/source/PluginLoadAnswers.d.ts +63 -0
- package/lib/plugin/internal/source/PluginLoadAnswers.js +128 -0
- package/lib/plugin/internal/source/PluginLoadAnswers.js.map +1 -0
- package/lib/plugin/internal/source/SourceBuildCacheLayout.d.ts +10 -0
- package/lib/plugin/internal/source/SourceBuildCacheLayout.js +12 -0
- package/lib/plugin/internal/source/SourceBuildCacheLayout.js.map +1 -1
- package/lib/plugin/internal/source/SourcePluginWorkspace.d.ts +53 -19
- package/lib/plugin/internal/source/SourcePluginWorkspace.js +111 -22
- package/lib/plugin/internal/source/SourcePluginWorkspace.js.map +1 -1
- package/lib/plugin/internal/source/buildSourcePlugin.d.ts +34 -18
- package/lib/plugin/internal/source/buildSourcePlugin.js +52 -24
- package/lib/plugin/internal/source/buildSourcePlugin.js.map +1 -1
- package/lib/plugin/internal/source/computeCacheKey.d.ts +25 -7
- package/lib/plugin/internal/source/computeCacheKey.js +85 -34
- package/lib/plugin/internal/source/computeCacheKey.js.map +1 -1
- package/lib/plugin/internal/source/hashPluginBuildEnvironment.d.ts +7 -3
- package/lib/plugin/internal/source/hashPluginBuildEnvironment.js +75 -102
- package/lib/plugin/internal/source/hashPluginBuildEnvironment.js.map +1 -1
- package/lib/plugin/internal/source/pluginBuildEnvironment.d.ts +8 -3
- package/lib/plugin/internal/source/pluginBuildEnvironment.js +8 -4
- package/lib/plugin/internal/source/pluginBuildEnvironment.js.map +1 -1
- package/lib/plugin/internal/source/pluginBuildEnvironmentWorker.js +12 -2
- package/lib/plugin/internal/source/pluginBuildEnvironmentWorker.js.map +1 -1
- package/lib/plugin/internal/source/pluginBuildVersions.d.ts +2 -2
- package/lib/plugin/internal/source/pluginBuildVersions.js +4 -17
- package/lib/plugin/internal/source/pluginBuildVersions.js.map +1 -1
- package/lib/plugin/internal/source/pluginModuleReplaceDirectories.d.ts +6 -5
- package/lib/plugin/internal/source/pluginModuleReplaceDirectories.js +10 -17
- package/lib/plugin/internal/source/pluginModuleReplaceDirectories.js.map +1 -1
- package/lib/plugin/internal/source/pluginSourceState.d.ts +6 -2
- package/lib/plugin/internal/source/pluginSourceState.js +20 -8
- package/lib/plugin/internal/source/pluginSourceState.js.map +1 -1
- package/lib/plugin/internal/source/pluginSourceStateHolds.d.ts +7 -2
- package/lib/plugin/internal/source/pluginSourceStateHolds.js +12 -7
- package/lib/plugin/internal/source/pluginSourceStateHolds.js.map +1 -1
- package/lib/plugin/internal/source/processPluginBuildEnvironment.d.ts +7 -2
- package/lib/plugin/internal/source/processPluginBuildEnvironment.js +8 -3
- package/lib/plugin/internal/source/processPluginBuildEnvironment.js.map +1 -1
- package/lib/plugin/internal/source/provenPluginSourceDigest.d.ts +28 -0
- package/lib/plugin/internal/source/provenPluginSourceDigest.js +41 -0
- package/lib/plugin/internal/source/provenPluginSourceDigest.js.map +1 -0
- package/lib/plugin/internal/source/pruneCacheFileRoot.d.ts +3 -2
- package/lib/plugin/internal/source/pruneCacheFileRoot.js +3 -2
- package/lib/plugin/internal/source/pruneCacheFileRoot.js.map +1 -1
- package/lib/plugin/internal/source/ttscPackageVersion.d.ts +26 -0
- package/lib/plugin/internal/source/ttscPackageVersion.js +47 -0
- package/lib/plugin/internal/source/ttscPackageVersion.js.map +1 -0
- package/lib/plugin/internal/writeCapabilityResolution.d.ts +6 -0
- package/lib/plugin/internal/writeCapabilityResolution.js +11 -7
- package/lib/plugin/internal/writeCapabilityResolution.js.map +1 -1
- package/lib/plugin/resolveCapabilityPlugins.js +67 -15
- package/lib/plugin/resolveCapabilityPlugins.js.map +1 -1
- package/package.json +8 -8
- package/src/compiler/internal/build/BuildExecution.ts +46 -13
- package/src/compiler/internal/startResidentTransform.ts +12 -3
- package/src/compiler/internal/transformProjectInMemory.ts +10 -2
- package/src/internal/javascriptRuntimeCapabilities.ts +71 -5
- package/src/internal/nativeBinary.ts +3 -3
- package/src/internal/pluginSource.ts +1 -0
- package/src/internal/resolveNodeBinary.ts +12 -1
- package/src/internal/runtimeExecutableIdentity.ts +227 -141
- package/src/launcher/internal/runtime/installRuntimeHooks.ts +68 -3
- package/src/launcher/internal/ttscserver/captureLSPPluginSelectionInputs.ts +11 -2
- package/src/launcher/internal/ttscserver/runTtscserver.ts +18 -1
- package/src/plugin/internal/CapabilityResolutionFormat.ts +23 -107
- package/src/plugin/internal/load/PluginDescriptorEvaluationCache.ts +14 -4
- package/src/plugin/internal/load/loadProjectPlugins.ts +421 -211
- package/src/plugin/internal/readCapabilityResolution.ts +17 -6
- package/src/plugin/internal/source/GoEnvironmentReading.ts +178 -0
- package/src/plugin/internal/source/NativeSourcePackages.ts +365 -48
- package/src/plugin/internal/source/PluginBuildEnvironmentReadings.ts +83 -5
- package/src/plugin/internal/source/PluginBuildEnvironmentWitness.ts +18 -8
- package/src/plugin/internal/source/PluginContentIdentities.ts +563 -0
- package/src/plugin/internal/source/PluginLoadAnswers.ts +151 -0
- package/src/plugin/internal/source/SourceBuildCacheLayout.ts +14 -0
- package/src/plugin/internal/source/SourcePluginWorkspace.ts +148 -25
- package/src/plugin/internal/source/buildSourcePlugin.ts +104 -36
- package/src/plugin/internal/source/computeCacheKey.ts +129 -55
- package/src/plugin/internal/source/hashPluginBuildEnvironment.ts +152 -105
- package/src/plugin/internal/source/pluginBuildEnvironment.ts +9 -2
- package/src/plugin/internal/source/pluginBuildEnvironmentWorker.ts +18 -2
- package/src/plugin/internal/source/pluginBuildVersions.ts +5 -26
- package/src/plugin/internal/source/pluginModuleReplaceDirectories.ts +13 -25
- package/src/plugin/internal/source/pluginSourceState.ts +28 -12
- package/src/plugin/internal/source/pluginSourceStateHolds.ts +15 -8
- package/src/plugin/internal/source/processPluginBuildEnvironment.ts +8 -2
- package/src/plugin/internal/source/provenPluginSourceDigest.ts +45 -0
- package/src/plugin/internal/source/pruneCacheFileRoot.ts +3 -2
- package/src/plugin/internal/source/ttscPackageVersion.ts +45 -0
- package/src/plugin/internal/writeCapabilityResolution.ts +29 -8
- package/src/plugin/resolveCapabilityPlugins.ts +87 -13
|
@@ -22,13 +22,16 @@ import type { ITtscParsedProjectConfig } from "../../../structures/internal/ITts
|
|
|
22
22
|
import { pluginDescriptorFailureReason } from "../pluginDescriptorFailureReason";
|
|
23
23
|
import { pluginDescriptorProcessFailure } from "../pluginDescriptorProcessFailure";
|
|
24
24
|
import { NativeSourcePackages } from "../source/NativeSourcePackages";
|
|
25
|
+
import type { PluginBuildEnvironmentWitness } from "../source/PluginBuildEnvironmentWitness";
|
|
26
|
+
import { PluginContentIdentities } from "../source/PluginContentIdentities";
|
|
25
27
|
import { SourcePluginWorkspace } from "../source/SourcePluginWorkspace";
|
|
26
|
-
import { resolvePluginGoModule } from "../source/resolvePluginGoModule";
|
|
27
28
|
import { buildSourcePlugin } from "../source/buildSourcePlugin";
|
|
28
29
|
import { isPathWithin } from "../source/isPathWithin";
|
|
30
|
+
import { pluginBuildEnvironment } from "../source/pluginBuildEnvironment";
|
|
29
31
|
import { pluginBuildVersions } from "../source/pluginBuildVersions";
|
|
30
32
|
import { pluginModuleReplaceDirectories } from "../source/pluginModuleReplaceDirectories";
|
|
31
33
|
import { pluginSourceState } from "../source/pluginSourceState";
|
|
34
|
+
import { resolvePluginGoModule } from "../source/resolvePluginGoModule";
|
|
32
35
|
import { COMMONJS_PLUGIN_DESCRIPTOR_SHIM_SOURCE } from "./COMMONJS_PLUGIN_DESCRIPTOR_SHIM_SOURCE";
|
|
33
36
|
import { PLUGIN_DESCRIPTOR_SHIM_SOURCE } from "./PLUGIN_DESCRIPTOR_SHIM_SOURCE";
|
|
34
37
|
import { PluginDescriptorAdmission } from "./PluginDescriptorAdmission";
|
|
@@ -61,19 +64,18 @@ import { visitImportMappedCandidates } from "./visitImportMappedCandidates";
|
|
|
61
64
|
* under generic host manifests while preserving source-relative input layout.
|
|
62
65
|
* Main proposals must agree in their full owning module; linked proposals must
|
|
63
66
|
* agree inside every selected transform host. Errors or disagreement terminate
|
|
64
|
-
* the load rather than changing the proposed kind.
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
*
|
|
74
|
-
*
|
|
75
|
-
*
|
|
76
|
-
* linked-plugin host, are keyed but omitted from this report under the
|
|
67
|
+
* the load rather than changing the proposed kind. Watch callers first receive
|
|
68
|
+
* structurally selected source/module/contributor repair interests, before
|
|
69
|
+
* metadata can reject them. Valid records then narrow those interests to the
|
|
70
|
+
* exact build directories; interests alone never admit a plugin, certify a kind
|
|
71
|
+
* or supply reusable source-state proof. Returns the ordered native plugins,
|
|
72
|
+
* parsed project config, recorded JavaScript-host inputs and unresolved
|
|
73
|
+
* selection candidates, and the keyed state of reported Go source directories
|
|
74
|
+
* supplied to the builds (`pluginSources`): each plugin's module root and each
|
|
75
|
+
* contributor's source, with its state (`pluginSourceState`), the sources as
|
|
76
|
+
* the build read them together with the environment a build there is keyed on.
|
|
77
|
+
* Directories within ttsc's installed package, including its overlays and the
|
|
78
|
+
* fallback linked-plugin host, are keyed but omitted from this report under the
|
|
77
79
|
* installed-package/version ownership policy. That policy does not prove the
|
|
78
80
|
* installation cannot be edited in place. Descriptor completeness relies on the
|
|
79
81
|
* runtime recorder's status and the descriptor's explicit external-read
|
|
@@ -100,7 +102,7 @@ import { visitImportMappedCandidates } from "./visitImportMappedCandidates";
|
|
|
100
102
|
* @evidence contracts/common.md#meaningful-documentation Native JSDoc explains result provenance, environment and path options; helper comments explain input races, conservative proof omission, fallback authority and cleanup. Member/tag spacing and separated concepts follow the documentation skill.
|
|
101
103
|
* @evidence contracts/portability.md#os-neutral-implementation Native path/file-URL conversion, createRequire and hidden spawn with explicit argv/environment implement OS-neutral selection and process execution. Physical identities are preserved separately from lexical candidates; Bun-specific differences are capability decisions, not OS guesses.
|
|
102
104
|
* @evidence contracts/performance.md#efficient-algorithms Input merging and conflicts use Sets/maps and sorted path populations, with path/key/value byte costs. Discovery can repeat config/manifest/candidate reads and full hashes; descriptor work includes runtime probes, full observation/JSON processing and possibly synchronous evaluation. Watch-only preliminary publication can temporarily digest/watch the full admitted module as well as its package before kind is known; callbacks delegate topology reconciliation. Load-local replacement readings serve preliminary and final publication. Package selection groups equivalent module contexts and batches entries through Go list without dependency compilation; per-load selected-tool manifest readers share overlay readings. Builds delegate source/environment hashing, copying, cold materialized ownership admission and Go execution; per-load digest maps share selected work. Composition can be quadratic in configured plugins/aliases, and native lookup/file/output bytes are not bounded by plugin count alone.
|
|
103
|
-
* @evidence contracts/performance.md#reuse-equivalent-work Descriptor hits require the cache's context/environment/runtime/version identity and matching recorded projections, subject to producer declarations and sequential-observation limits. Per-load source/environment maps share directory-keyed digests and one selected transform host serves linked contributors;
|
|
105
|
+
* @evidence contracts/performance.md#reuse-equivalent-work Descriptor hits require the cache's context/environment/runtime/version identity and matching recorded projections, subject to producer declarations and sequential-observation limits. Per-load source/environment maps share directory-keyed digests between package selection and builds, and one selected transform host serves linked contributors. Across processes, the record store opened here proves unchanged sources, toolchain and runtime from separable metadata and answers equal package selections and runtime probes (#1721, #1722, #1723); a store whose root lies inside a plugin source is withdrawn before any source is proven. These identities do not certify every undeclared read or atomic filesystem stability.
|
|
104
106
|
* @evidence contracts/performance.md#bound-retention-and-release-resources Finally restores injected environment locators, attempts evaluator directory removal and closes direct-evaluator diagnostic descriptors. Close/removal can fail; synchronous completion concerns the selected evaluator and does not certify arbitrary descendants are gone. Generation maps/results scale with observed data, and disk diagnostics/result/observation files have no independent byte ceiling here. Default disk pruning has its own interval/protection/failure policy; explicit roots remain caller-owned.
|
|
105
107
|
*/
|
|
106
108
|
export function loadProjectPlugins(options: {
|
|
@@ -122,6 +124,12 @@ export function loadProjectPlugins(options: {
|
|
|
122
124
|
/** Explicit project config, resolved from cwd. */
|
|
123
125
|
file?: string;
|
|
124
126
|
|
|
127
|
+
/**
|
|
128
|
+
* Record store the caller already opened for this invocation, so its later
|
|
129
|
+
* native spawns share it; the loader opens its own when omitted.
|
|
130
|
+
*/
|
|
131
|
+
identities?: PluginContentIdentities.Store;
|
|
132
|
+
|
|
125
133
|
/** Observe plugin build roots before building, including failed builds. */
|
|
126
134
|
onWatchInputs?: (inputs: readonly string[]) => void;
|
|
127
135
|
|
|
@@ -169,6 +177,12 @@ export function loadProjectPlugins(options: {
|
|
|
169
177
|
*/
|
|
170
178
|
observationsComplete?: false;
|
|
171
179
|
|
|
180
|
+
/**
|
|
181
|
+
* Record store this load proved its inputs through, for the invocation's
|
|
182
|
+
* later native spawns (#1723); absent when the project loads no plugin.
|
|
183
|
+
*/
|
|
184
|
+
identities?: PluginContentIdentities.Store;
|
|
185
|
+
|
|
172
186
|
/** Check-stage entries followed by transform-stage entries in stable order. */
|
|
173
187
|
nativePlugins: ITtscLoadedNativePlugin[];
|
|
174
188
|
|
|
@@ -235,91 +249,111 @@ export function loadProjectPlugins(options: {
|
|
|
235
249
|
};
|
|
236
250
|
// Where isolated descriptor evaluations keep their answers across launches
|
|
237
251
|
// (`PluginDescriptorEvaluationCache`).
|
|
252
|
+
// WARNING (#1721, #1722, #1723): a warm load must prove its unchanged inputs
|
|
253
|
+
// from this store, not re-read them. Every launch is a new process, so any
|
|
254
|
+
// module-level memo of this load's work dies with it; a 27 s warm typia
|
|
255
|
+
// launch whose native build took 0.28 s is what that looked like.
|
|
256
|
+
const identities =
|
|
257
|
+
options.identities ??
|
|
258
|
+
PluginContentIdentities.open({
|
|
259
|
+
projectRoot: project.root,
|
|
260
|
+
cacheDir: options.cacheDir,
|
|
261
|
+
env: effectiveEnv,
|
|
262
|
+
});
|
|
238
263
|
const descriptorCache: DescriptorCacheOptions = {
|
|
239
264
|
cacheDir: options.cacheDir,
|
|
265
|
+
identities,
|
|
240
266
|
version: pluginBuildVersions(project.root).ttsc,
|
|
241
267
|
};
|
|
242
|
-
const loadedEntries = withPluginLoaderEnv(
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
268
|
+
const loadedEntries = withPluginLoaderEnv(
|
|
269
|
+
() =>
|
|
270
|
+
entries.map((entry) => {
|
|
271
|
+
const specifier = entry.config.transform;
|
|
272
|
+
if (typeof specifier !== "string" || specifier.length === 0) {
|
|
273
|
+
throw new Error(
|
|
274
|
+
`ttsc: plugin entry is missing a string "transform" field`,
|
|
275
|
+
);
|
|
276
|
+
}
|
|
277
|
+
const entryParent = path.join(entry.baseDir, "package.json");
|
|
278
|
+
const probedCandidates = collectModuleResolutionCandidates(
|
|
279
|
+
specifier,
|
|
280
|
+
entryParent,
|
|
281
|
+
undefined,
|
|
248
282
|
);
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
(
|
|
271
|
-
)
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
283
|
+
// Capture every candidate before resolution chooses the descriptor entry.
|
|
284
|
+
// A post-resolution snapshot could bless a higher-priority file created
|
|
285
|
+
// after the resolver had already selected the old entry.
|
|
286
|
+
const probedCandidateHashes = hashHostInputPaths(probedCandidates);
|
|
287
|
+
const probedCandidateRealpaths =
|
|
288
|
+
realpathHostInputPaths(probedCandidates);
|
|
289
|
+
const request = PluginPackageResolution.resolvePluginRequest(
|
|
290
|
+
specifier,
|
|
291
|
+
entry.baseDir,
|
|
292
|
+
);
|
|
293
|
+
// Keep the candidates of the search roots up to the one the entry
|
|
294
|
+
// resolved in: the lookup never read the roots after it
|
|
295
|
+
// (`moduleResolutionBaseSelects`).
|
|
296
|
+
const read = new Set(
|
|
297
|
+
collectModuleResolutionCandidates(
|
|
298
|
+
specifier,
|
|
299
|
+
entryParent,
|
|
300
|
+
request,
|
|
301
|
+
).map((candidate) => path.resolve(candidate)),
|
|
302
|
+
);
|
|
303
|
+
const entryCandidates = probedCandidates.filter((candidate) =>
|
|
304
|
+
read.has(path.resolve(candidate)),
|
|
305
|
+
);
|
|
306
|
+
const entryCandidateHashes = pickHostInputEntries(
|
|
307
|
+
probedCandidateHashes,
|
|
308
|
+
entryCandidates,
|
|
309
|
+
);
|
|
310
|
+
const entryCandidateRealpaths = pickHostInputEntries(
|
|
311
|
+
probedCandidateRealpaths,
|
|
312
|
+
entryCandidates,
|
|
313
|
+
);
|
|
314
|
+
const loaded = loadPluginEntry(
|
|
315
|
+
entry.config,
|
|
316
|
+
{ ...context, plugin: entry.config },
|
|
317
|
+
request,
|
|
318
|
+
effectiveEnv,
|
|
319
|
+
descriptorCache,
|
|
320
|
+
);
|
|
321
|
+
const loadedHostInputHashes = mergeObservedHostInputHashes(
|
|
322
|
+
loaded.hostInputHashes,
|
|
323
|
+
hashHostInputPaths(Object.keys(loaded.hostInputHashes)),
|
|
324
|
+
);
|
|
325
|
+
const loadedHostInputRealpaths = mergeObservedHostInputRealpaths(
|
|
326
|
+
loaded.hostInputRealpaths,
|
|
327
|
+
realpathHostInputPaths(Object.keys(loaded.hostInputRealpaths)),
|
|
328
|
+
);
|
|
329
|
+
const hostInputHashes = mergeObservedHostInputHashes(
|
|
330
|
+
entryCandidateHashes,
|
|
331
|
+
loadedHostInputHashes,
|
|
332
|
+
);
|
|
333
|
+
const hostInputRealpaths = mergeObservedHostInputRealpaths(
|
|
334
|
+
entryCandidateRealpaths,
|
|
335
|
+
loadedHostInputRealpaths,
|
|
336
|
+
);
|
|
337
|
+
for (const input of loaded.hostInputs) {
|
|
338
|
+
const absolute = path.resolve(input);
|
|
339
|
+
if (
|
|
340
|
+
!Object.prototype.hasOwnProperty.call(
|
|
341
|
+
loadedHostInputHashes,
|
|
342
|
+
absolute,
|
|
343
|
+
)
|
|
344
|
+
) {
|
|
345
|
+
delete hostInputHashes[absolute];
|
|
346
|
+
}
|
|
313
347
|
}
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
}
|
|
322
|
-
|
|
348
|
+
return {
|
|
349
|
+
...loaded,
|
|
350
|
+
hostInputHashes,
|
|
351
|
+
hostInputRealpaths,
|
|
352
|
+
hostInputs: [...loaded.hostInputs, ...entryCandidates],
|
|
353
|
+
request,
|
|
354
|
+
};
|
|
355
|
+
}),
|
|
356
|
+
identities,
|
|
323
357
|
);
|
|
324
358
|
const plugins = composePluginSources(
|
|
325
359
|
entries,
|
|
@@ -329,30 +363,68 @@ export function loadProjectPlugins(options: {
|
|
|
329
363
|
const { ttsc: ttscVersion, tsgo: tsgoVersion } = pluginBuildVersions(
|
|
330
364
|
context.projectRoot,
|
|
331
365
|
);
|
|
332
|
-
const candidates = plugins
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
366
|
+
const candidates = plugins
|
|
367
|
+
.map((plugin, index) => {
|
|
368
|
+
const stage = PluginDescriptorAdmission.stage(plugin);
|
|
369
|
+
validatePluginSource(plugin);
|
|
370
|
+
const contributors = validatePluginContributors(plugin);
|
|
371
|
+
const source = resolvePluginSource(plugin.source, context.projectRoot);
|
|
372
|
+
const label = pluginLabel(plugin, entries[index]!.config, index);
|
|
373
|
+
requirePluginSource(source, label);
|
|
374
|
+
return { plugin, index, stage, contributors, source, label };
|
|
375
|
+
})
|
|
376
|
+
.map((candidate) => ({
|
|
377
|
+
...candidate,
|
|
378
|
+
...resolvePluginGoModule(candidate.source, candidate.label),
|
|
379
|
+
}));
|
|
380
|
+
// One reading of each source directory, shared by package selection and
|
|
381
|
+
// every build below and reported as the state the binaries were keyed on.
|
|
382
|
+
const sourceDigests = new Map<string, string>();
|
|
383
|
+
// And one reading of the environment each build directory is keyed on, which
|
|
384
|
+
// a plugin module root's state reports as it is.
|
|
385
|
+
const environmentDigests = new Map<string, string>();
|
|
386
|
+
// With the witness of each such reading, so a build of a directory package
|
|
387
|
+
// selection already read keys on that reading instead of probing Go again.
|
|
388
|
+
const environmentWitnesses = new Map<
|
|
389
|
+
string,
|
|
390
|
+
PluginBuildEnvironmentWitness.Record
|
|
391
|
+
>();
|
|
392
|
+
const readings = {
|
|
393
|
+
sources: sourceDigests,
|
|
394
|
+
environments: environmentDigests,
|
|
395
|
+
witnesses: environmentWitnesses,
|
|
396
|
+
};
|
|
397
|
+
// Records describing sources must never land inside one, so the store is
|
|
398
|
+
// admitted for source proofs only once every source of the load is known.
|
|
399
|
+
const sourceIdentities = PluginContentIdentities.outside(identities, [
|
|
400
|
+
...candidates.flatMap((candidate) => [
|
|
401
|
+
candidate.moduleRoot,
|
|
402
|
+
candidate.packageDir,
|
|
403
|
+
...(candidate.contributors ?? []).map((input) => input.source),
|
|
404
|
+
]),
|
|
405
|
+
...SourcePluginWorkspace.findTtscOverlayDirs(),
|
|
406
|
+
]);
|
|
407
|
+
// One fixed-effective-environment load owns manifest syntax sharing from the
|
|
408
|
+
// first watch query through metadata and builds. Do not allocate this after
|
|
409
|
+
// watch projection: that silently repeats selected-Go work (#1712).
|
|
410
|
+
const packageReaders = new Map<string, SourcePluginWorkspace.GoModReader>();
|
|
411
|
+
const watchReplacements =
|
|
412
|
+
options.onWatchInputs === undefined
|
|
413
|
+
? undefined
|
|
414
|
+
: new Map<string, readonly string[]>();
|
|
347
415
|
if (options.onWatchInputs !== undefined) {
|
|
348
416
|
// The prospective context reads the admitted module layout and anchors its
|
|
349
417
|
// tool there before kind exists. Keep both possible final-root baselines:
|
|
350
418
|
// a linked package keeps packageDir, and an executable keeps moduleRoot.
|
|
351
|
-
const interests = new Set(
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
419
|
+
const interests = new Set(
|
|
420
|
+
candidates
|
|
421
|
+
.flatMap((candidate) => [
|
|
422
|
+
candidate.moduleRoot,
|
|
423
|
+
candidate.packageDir,
|
|
424
|
+
...(candidate.contributors ?? []).map((input) => input.source),
|
|
425
|
+
])
|
|
426
|
+
.filter(reportsPluginSource),
|
|
427
|
+
);
|
|
356
428
|
options.onWatchInputs([...interests].sort());
|
|
357
429
|
const initialSize = interests.size;
|
|
358
430
|
for (const candidate of candidates) {
|
|
@@ -360,77 +432,104 @@ export function loadProjectPlugins(options: {
|
|
|
360
432
|
// activate their irrelevant module graph just to discover watch inputs.
|
|
361
433
|
if (candidate.stage === "transform" && candidate.entry !== ".") continue;
|
|
362
434
|
for (const directory of pluginReplacementWatchDirectories(
|
|
363
|
-
candidate.moduleRoot,
|
|
364
|
-
|
|
435
|
+
candidate.moduleRoot,
|
|
436
|
+
effectiveEnv,
|
|
437
|
+
watchReplacements,
|
|
438
|
+
packageReaders,
|
|
439
|
+
))
|
|
440
|
+
if (reportsPluginSource(directory)) interests.add(directory);
|
|
365
441
|
}
|
|
366
442
|
if (interests.size !== initialSize)
|
|
367
443
|
options.onWatchInputs([...interests].sort());
|
|
368
444
|
}
|
|
369
|
-
const packageReaders = new Map<string, SourcePluginWorkspace.GoModReader>();
|
|
370
445
|
const proposals = NativeSourcePackages.propose(
|
|
371
446
|
candidates.map((candidate) => ({
|
|
372
|
-
...candidate,
|
|
373
|
-
|
|
447
|
+
...candidate,
|
|
448
|
+
ownModule: candidate.stage !== "transform",
|
|
449
|
+
})),
|
|
450
|
+
effectiveEnv,
|
|
451
|
+
packageReaders,
|
|
452
|
+
sourceIdentities,
|
|
453
|
+
readings,
|
|
374
454
|
);
|
|
375
|
-
const records = candidates.map(
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
455
|
+
const records = candidates.map(
|
|
456
|
+
({ plugin, index, stage, contributors, source, packageDir }) => {
|
|
457
|
+
const { kind, moduleRoot } = resolveNativeSource(
|
|
458
|
+
source,
|
|
459
|
+
plugin,
|
|
460
|
+
entries[index]!.config,
|
|
461
|
+
index,
|
|
462
|
+
{
|
|
463
|
+
env: effectiveEnv,
|
|
464
|
+
observation: proposals[index]!.observation,
|
|
465
|
+
},
|
|
382
466
|
);
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
hostInputs,
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
index,
|
|
397
|
-
hostInputs,
|
|
398
|
-
);
|
|
399
|
-
return {
|
|
400
|
-
capabilities: plugin.capabilities,
|
|
401
|
-
contributors,
|
|
402
|
-
config: entries[index]!.config,
|
|
403
|
-
kind,
|
|
404
|
-
label: pluginLabel(plugin, entries[index]!.config, index),
|
|
405
|
-
linkedContributorName,
|
|
406
|
-
name: plugin.name,
|
|
407
|
-
reportsTypeScriptDiagnostics:
|
|
408
|
-
plugin.reportsTypeScriptDiagnostics === true,
|
|
409
|
-
request: loadedEntries[index]!.request,
|
|
410
|
-
hostInputHashes: mergePluginHostInputHashes(
|
|
411
|
-
loadedEntries[index]!.hostInputHashes,
|
|
412
|
-
pluginHostInputHashes,
|
|
413
|
-
loadedEntries[index]!.hostInputs,
|
|
467
|
+
if (kind === "linked" && stage !== "transform") {
|
|
468
|
+
throw new Error(
|
|
469
|
+
`ttsc: plugin "${pluginLabel(plugin, entries[index]!.config, index)}" source is a linked Go package, but only transform-stage plugins can be linked into a compiler host`,
|
|
470
|
+
);
|
|
471
|
+
}
|
|
472
|
+
const linkedContributorName =
|
|
473
|
+
kind === "linked"
|
|
474
|
+
? `linked_${String(index).padStart(6, "0")}`
|
|
475
|
+
: undefined;
|
|
476
|
+
const hostInputs = validatePluginHostInputs(plugin, index);
|
|
477
|
+
const pluginHostInputHashes = validatePluginHostInputHashes(
|
|
478
|
+
plugin,
|
|
479
|
+
index,
|
|
414
480
|
hostInputs,
|
|
415
|
-
)
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
loadedEntries[index]!.hostInputs,
|
|
481
|
+
);
|
|
482
|
+
const pluginHostInputRealpaths = validatePluginHostInputRealpaths(
|
|
483
|
+
plugin,
|
|
484
|
+
index,
|
|
420
485
|
hostInputs,
|
|
421
|
-
)
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
486
|
+
);
|
|
487
|
+
return {
|
|
488
|
+
capabilities: plugin.capabilities,
|
|
489
|
+
contributors,
|
|
490
|
+
config: entries[index]!.config,
|
|
491
|
+
kind,
|
|
492
|
+
label: pluginLabel(plugin, entries[index]!.config, index),
|
|
493
|
+
linkedContributorName,
|
|
494
|
+
name: plugin.name,
|
|
495
|
+
reportsTypeScriptDiagnostics:
|
|
496
|
+
plugin.reportsTypeScriptDiagnostics === true,
|
|
497
|
+
request: loadedEntries[index]!.request,
|
|
498
|
+
hostInputHashes: mergePluginHostInputHashes(
|
|
499
|
+
loadedEntries[index]!.hostInputHashes,
|
|
500
|
+
pluginHostInputHashes,
|
|
501
|
+
loadedEntries[index]!.hostInputs,
|
|
502
|
+
hostInputs,
|
|
503
|
+
),
|
|
504
|
+
hostInputRealpaths: mergePluginHostInputHashes(
|
|
505
|
+
loadedEntries[index]!.hostInputRealpaths,
|
|
506
|
+
pluginHostInputRealpaths,
|
|
507
|
+
loadedEntries[index]!.hostInputs,
|
|
508
|
+
hostInputs,
|
|
509
|
+
),
|
|
510
|
+
hostInputs: [...loadedEntries[index]!.hostInputs, ...hostInputs],
|
|
511
|
+
moduleRoot,
|
|
512
|
+
packageDir,
|
|
513
|
+
source,
|
|
514
|
+
stage,
|
|
515
|
+
};
|
|
516
|
+
},
|
|
517
|
+
);
|
|
518
|
+
const executableCandidates = candidates.filter(
|
|
519
|
+
(candidate) =>
|
|
520
|
+
records[candidate.index]!.kind === "executable" &&
|
|
521
|
+
!proposals[candidate.index]!.ownModule,
|
|
522
|
+
);
|
|
431
523
|
// Admission can now narrow the provisional interests without restamping the
|
|
432
524
|
// retained package/module baselines. Final host errors still keep these roots.
|
|
433
|
-
options.onWatchInputs?.(
|
|
525
|
+
options.onWatchInputs?.(
|
|
526
|
+
pluginBuildDirectories(
|
|
527
|
+
records,
|
|
528
|
+
effectiveEnv,
|
|
529
|
+
watchReplacements,
|
|
530
|
+
packageReaders,
|
|
531
|
+
),
|
|
532
|
+
);
|
|
434
533
|
const linkedContributors = records
|
|
435
534
|
.filter((record) => record.stage === "transform")
|
|
436
535
|
.flatMap((record) =>
|
|
@@ -448,66 +547,101 @@ export function loadProjectPlugins(options: {
|
|
|
448
547
|
// a second executable host can select a genuinely different Go context.
|
|
449
548
|
const admittedExecutables = new Set<string>();
|
|
450
549
|
if (linkedContributors.length !== 0) {
|
|
451
|
-
const hosts =
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
550
|
+
const hosts =
|
|
551
|
+
transformHosts.length === 0
|
|
552
|
+
? [
|
|
553
|
+
{
|
|
554
|
+
source: path.join(ttscPackageRoot(), "cmd", "utility-host"),
|
|
555
|
+
label: "linked-plugin-host",
|
|
556
|
+
},
|
|
557
|
+
]
|
|
558
|
+
: transformHosts;
|
|
559
|
+
const contexts = new Map<
|
|
560
|
+
string,
|
|
561
|
+
{ source: string; label: string; records: typeof transformHosts }
|
|
562
|
+
>();
|
|
455
563
|
for (const host of hosts) {
|
|
456
|
-
const moduleRoot = resolvePluginGoModule(
|
|
564
|
+
const moduleRoot = resolvePluginGoModule(
|
|
565
|
+
host.source,
|
|
566
|
+
host.label,
|
|
567
|
+
).moduleRoot;
|
|
457
568
|
let context = contexts.get(moduleRoot);
|
|
458
569
|
if (context === undefined) {
|
|
459
570
|
context = { source: host.source, label: host.label, records: [] };
|
|
460
571
|
contexts.set(moduleRoot, context);
|
|
461
572
|
}
|
|
462
573
|
}
|
|
463
|
-
for (const record of transformHosts)
|
|
574
|
+
for (const record of transformHosts)
|
|
575
|
+
contexts.get(record.moduleRoot)!.records.push(record);
|
|
464
576
|
for (const host of contexts.values()) {
|
|
465
577
|
const moduleHosts = host.records;
|
|
466
578
|
const hostEntries = moduleHosts.map((record) => ({
|
|
467
579
|
entry: resolvePluginGoModule(record.source, record.label).entry,
|
|
468
580
|
}));
|
|
469
581
|
const observations = NativeSourcePackages.inspect({
|
|
470
|
-
source: host.source,
|
|
582
|
+
source: host.source,
|
|
583
|
+
pluginName: host.label,
|
|
584
|
+
env: effectiveEnv,
|
|
471
585
|
readers: packageReaders,
|
|
586
|
+
identities: sourceIdentities,
|
|
587
|
+
readings,
|
|
472
588
|
packages: [
|
|
473
589
|
...hostEntries,
|
|
474
590
|
...linkedContributors.map((input) => ({
|
|
475
|
-
...input,
|
|
591
|
+
...input,
|
|
592
|
+
entry: `./contrib/${input.name}`,
|
|
476
593
|
})),
|
|
477
594
|
],
|
|
478
595
|
});
|
|
479
596
|
moduleHosts.forEach((record, index) => {
|
|
480
|
-
NativeSourcePackages.kind(
|
|
597
|
+
NativeSourcePackages.kind(
|
|
598
|
+
observations[index]!,
|
|
599
|
+
record.label,
|
|
600
|
+
"executable",
|
|
601
|
+
);
|
|
481
602
|
admittedExecutables.add(record.source);
|
|
482
603
|
});
|
|
483
604
|
linkedContributors.forEach((input, index) => {
|
|
484
|
-
NativeSourcePackages.kind(
|
|
605
|
+
NativeSourcePackages.kind(
|
|
606
|
+
observations[hostEntries.length + index]!,
|
|
607
|
+
`${input.name} inside host ${host.label}`,
|
|
608
|
+
"linked",
|
|
609
|
+
);
|
|
485
610
|
});
|
|
486
611
|
}
|
|
487
612
|
}
|
|
488
613
|
// A nested main proposal still needs its actual owning manifests. Hosts
|
|
489
614
|
// with linked contributors were admitted together above; other equivalent
|
|
490
615
|
// entries share one standalone observation, with no repeated host copy.
|
|
491
|
-
const standaloneCandidates = executableCandidates.filter(
|
|
492
|
-
!admittedExecutables.has(candidate.source)
|
|
616
|
+
const standaloneCandidates = executableCandidates.filter(
|
|
617
|
+
(candidate) => !admittedExecutables.has(candidate.source),
|
|
618
|
+
);
|
|
493
619
|
const executablePackages = NativeSourcePackages.ownPackages(
|
|
494
|
-
standaloneCandidates,
|
|
620
|
+
standaloneCandidates,
|
|
621
|
+
effectiveEnv,
|
|
622
|
+
packageReaders,
|
|
623
|
+
sourceIdentities,
|
|
624
|
+
readings,
|
|
495
625
|
);
|
|
496
626
|
standaloneCandidates.forEach((candidate, index) => {
|
|
497
|
-
NativeSourcePackages.kind(
|
|
627
|
+
NativeSourcePackages.kind(
|
|
628
|
+
executablePackages[index]!,
|
|
629
|
+
candidate.label,
|
|
630
|
+
"executable",
|
|
631
|
+
);
|
|
498
632
|
});
|
|
499
633
|
const packageOwnership = (source: string, label: string, linked: boolean) => [
|
|
500
|
-
{
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
}
|
|
634
|
+
{
|
|
635
|
+
entry: resolvePluginGoModule(source, label).entry,
|
|
636
|
+
kind: "executable" as const,
|
|
637
|
+
},
|
|
638
|
+
...(linked
|
|
639
|
+
? linkedContributors.map((input) => ({
|
|
640
|
+
entry: `./contrib/${input.name}`,
|
|
641
|
+
kind: "linked" as const,
|
|
642
|
+
}))
|
|
643
|
+
: []),
|
|
504
644
|
];
|
|
505
|
-
// One reading of each source directory, shared by every build below and
|
|
506
|
-
// reported as the state the binaries were keyed on.
|
|
507
|
-
const sourceDigests = new Map<string, string>();
|
|
508
|
-
// And one reading of the environment each build directory is keyed on, which
|
|
509
|
-
// a plugin module root's state reports as it is.
|
|
510
|
-
const environmentDigests = new Map<string, string>();
|
|
511
645
|
const builtTransformHosts = new Map<object, string>();
|
|
512
646
|
for (const record of transformHosts) {
|
|
513
647
|
builtTransformHosts.set(
|
|
@@ -517,10 +651,13 @@ export function loadProjectPlugins(options: {
|
|
|
517
651
|
cacheDir: options.cacheDir,
|
|
518
652
|
contributors: mergeContributors(record.contributors, hostContributors),
|
|
519
653
|
env: effectiveEnv,
|
|
654
|
+
goModReaders: packageReaders,
|
|
655
|
+
identities: sourceIdentities,
|
|
520
656
|
pluginName: record.label,
|
|
521
657
|
packageOwnership: packageOwnership(record.source, record.label, true),
|
|
522
658
|
source: record.source,
|
|
523
659
|
environmentDigests,
|
|
660
|
+
environmentWitnesses,
|
|
524
661
|
sourceDigests,
|
|
525
662
|
ttscVersion,
|
|
526
663
|
tsgoVersion,
|
|
@@ -534,13 +671,18 @@ export function loadProjectPlugins(options: {
|
|
|
534
671
|
cacheDir: options.cacheDir,
|
|
535
672
|
contributors: linkedContributors,
|
|
536
673
|
env: effectiveEnv,
|
|
674
|
+
goModReaders: packageReaders,
|
|
675
|
+
identities: sourceIdentities,
|
|
537
676
|
label: "linked plugin host",
|
|
538
677
|
pluginName: "linked-plugin-host",
|
|
539
678
|
source: path.join(ttscPackageRoot(), "cmd", "utility-host"),
|
|
540
679
|
packageOwnership: packageOwnership(
|
|
541
|
-
path.join(ttscPackageRoot(), "cmd", "utility-host"),
|
|
680
|
+
path.join(ttscPackageRoot(), "cmd", "utility-host"),
|
|
681
|
+
"linked-plugin-host",
|
|
682
|
+
true,
|
|
542
683
|
),
|
|
543
684
|
environmentDigests,
|
|
685
|
+
environmentWitnesses,
|
|
544
686
|
sourceDigests,
|
|
545
687
|
ttscVersion,
|
|
546
688
|
tsgoVersion,
|
|
@@ -561,10 +703,17 @@ export function loadProjectPlugins(options: {
|
|
|
561
703
|
cacheDir: options.cacheDir,
|
|
562
704
|
contributors: record.contributors,
|
|
563
705
|
env: effectiveEnv,
|
|
706
|
+
goModReaders: packageReaders,
|
|
707
|
+
identities: sourceIdentities,
|
|
564
708
|
pluginName: record.label,
|
|
565
|
-
packageOwnership: packageOwnership(
|
|
709
|
+
packageOwnership: packageOwnership(
|
|
710
|
+
record.source,
|
|
711
|
+
record.label,
|
|
712
|
+
false,
|
|
713
|
+
),
|
|
566
714
|
source: record.source,
|
|
567
715
|
environmentDigests,
|
|
716
|
+
environmentWitnesses,
|
|
568
717
|
sourceDigests,
|
|
569
718
|
ttscVersion,
|
|
570
719
|
tsgoVersion,
|
|
@@ -616,6 +765,7 @@ export function loadProjectPlugins(options: {
|
|
|
616
765
|
entry.observationsComplete && declaresHostInputReads(entry.plugin),
|
|
617
766
|
),
|
|
618
767
|
discoveryInputsComplete: project.configInputsComplete === true,
|
|
768
|
+
...(identities === undefined ? {} : { identities }),
|
|
619
769
|
nativePlugins: orderNativePlugins(nativePlugins),
|
|
620
770
|
...(loadedEntries.some((entry) => !entry.observationsComplete)
|
|
621
771
|
? { observationsComplete: false as const }
|
|
@@ -631,9 +781,14 @@ export function loadProjectPlugins(options: {
|
|
|
631
781
|
pluginSourceState(directory, {
|
|
632
782
|
env: effectiveEnv,
|
|
633
783
|
sourceDigest,
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
784
|
+
environment:
|
|
785
|
+
environmentDigests.get(directory) ??
|
|
786
|
+
pluginBuildEnvironment(
|
|
787
|
+
directory,
|
|
788
|
+
effectiveEnv,
|
|
789
|
+
undefined,
|
|
790
|
+
sourceIdentities,
|
|
791
|
+
),
|
|
637
792
|
}),
|
|
638
793
|
]),
|
|
639
794
|
),
|
|
@@ -1209,7 +1364,12 @@ function loadPluginDescriptor(
|
|
|
1209
1364
|
) {
|
|
1210
1365
|
throw error;
|
|
1211
1366
|
}
|
|
1212
|
-
const loaded = loadDescriptorViaTtsx(
|
|
1367
|
+
const loaded = loadDescriptorViaTtsx(
|
|
1368
|
+
request,
|
|
1369
|
+
context,
|
|
1370
|
+
effectiveEnv,
|
|
1371
|
+
descriptorCache.identities,
|
|
1372
|
+
);
|
|
1213
1373
|
if (loaded === undefined) {
|
|
1214
1374
|
throw error;
|
|
1215
1375
|
}
|
|
@@ -1222,6 +1382,9 @@ interface DescriptorCacheOptions {
|
|
|
1222
1382
|
/** The plugin cache directory the caller selected, if any. */
|
|
1223
1383
|
cacheDir: string | undefined;
|
|
1224
1384
|
|
|
1385
|
+
/** Record store that proves the evaluating runtimes from metadata (#1723). */
|
|
1386
|
+
identities: PluginContentIdentities.Store | undefined;
|
|
1387
|
+
|
|
1225
1388
|
/** This ttsc build's version. */
|
|
1226
1389
|
version: string;
|
|
1227
1390
|
}
|
|
@@ -1271,21 +1434,28 @@ function loadCommonJsDescriptor(
|
|
|
1271
1434
|
runtime,
|
|
1272
1435
|
effectiveEnv,
|
|
1273
1436
|
context.projectRoot,
|
|
1437
|
+
descriptorCache.identities,
|
|
1274
1438
|
);
|
|
1275
1439
|
const node =
|
|
1276
1440
|
!runtimeCapabilities.bun &&
|
|
1277
1441
|
runtimeCapabilities.registerHooks &&
|
|
1278
1442
|
runtimeCapabilities.executable !== undefined
|
|
1279
1443
|
? runtimeCapabilities.executable
|
|
1280
|
-
: resolveNodeBinary(
|
|
1444
|
+
: resolveNodeBinary(
|
|
1445
|
+
effectiveEnv,
|
|
1446
|
+
context.projectRoot,
|
|
1447
|
+
descriptorCache.identities,
|
|
1448
|
+
);
|
|
1281
1449
|
const cacheAuthority = {
|
|
1282
1450
|
additionalRuntime: node,
|
|
1283
1451
|
cacheDir: descriptorCache.cacheDir,
|
|
1452
|
+
identities: descriptorCache.identities,
|
|
1284
1453
|
context,
|
|
1285
1454
|
// Everything the child receives besides the per-evaluation output paths.
|
|
1286
1455
|
env: {
|
|
1287
1456
|
...effectiveEnv,
|
|
1288
1457
|
...(node === undefined ? {} : { TTSC_NODE_BINARY: node }),
|
|
1458
|
+
...descriptorRecordRoot(descriptorCache.identities),
|
|
1289
1459
|
TTSC_TTSX_BINARY: ttsx,
|
|
1290
1460
|
},
|
|
1291
1461
|
projectRoot: context.projectRoot,
|
|
@@ -1375,6 +1545,7 @@ function loadCommonJsDescriptor(
|
|
|
1375
1545
|
// The direct evaluator may be Bun, but ttsx and native config
|
|
1376
1546
|
// loaders require a real Node runtime with synchronous hooks.
|
|
1377
1547
|
...(node === undefined ? {} : { TTSC_NODE_BINARY: node }),
|
|
1548
|
+
...descriptorRecordRoot(descriptorCache.identities),
|
|
1378
1549
|
TTSC_TTSX_BINARY: ttsx,
|
|
1379
1550
|
TTSC_PLUGIN_CONTEXT: JSON.stringify(context),
|
|
1380
1551
|
TTSC_PLUGIN_DESCRIPTOR_LOAD: "1",
|
|
@@ -1759,11 +1930,12 @@ function loadDescriptorViaTtsx(
|
|
|
1759
1930
|
request: string,
|
|
1760
1931
|
context: ITtscPluginFactoryContext,
|
|
1761
1932
|
effectiveEnv: NodeJS.ProcessEnv,
|
|
1933
|
+
identities: PluginContentIdentities.Store | undefined,
|
|
1762
1934
|
): IsolatedPluginDescriptor | undefined {
|
|
1763
1935
|
// Binary discovery prefers the instance environment, then the ambient
|
|
1764
1936
|
// process.env (where `withPluginLoaderEnv` injects ttsc's own node/ttsx paths
|
|
1765
1937
|
// just before this runs), then the running interpreter.
|
|
1766
|
-
const node = resolveNodeBinary(effectiveEnv, context.projectRoot);
|
|
1938
|
+
const node = resolveNodeBinary(effectiveEnv, context.projectRoot, identities);
|
|
1767
1939
|
const ttsx = effectiveEnv.TTSC_TTSX_BINARY ?? process.env.TTSC_TTSX_BINARY;
|
|
1768
1940
|
if (node === undefined || ttsx === undefined || ttsx.length === 0) {
|
|
1769
1941
|
return undefined;
|
|
@@ -1802,6 +1974,7 @@ function loadDescriptorViaTtsx(
|
|
|
1802
1974
|
// may recurse into further descriptor loads) finds them even when the
|
|
1803
1975
|
// instance-env snapshot predates `withPluginLoaderEnv`.
|
|
1804
1976
|
TTSC_NODE_BINARY: node,
|
|
1977
|
+
...descriptorRecordRoot(identities),
|
|
1805
1978
|
TTSC_TTSX_BINARY: ttsx,
|
|
1806
1979
|
TTSC_PLUGIN_CONTEXT: JSON.stringify({
|
|
1807
1980
|
binary: context.binary,
|
|
@@ -1886,6 +2059,20 @@ interface TtsxDescriptorResolutionRecord {
|
|
|
1886
2059
|
unstable?: boolean;
|
|
1887
2060
|
}
|
|
1888
2061
|
|
|
2062
|
+
/**
|
|
2063
|
+
* The private variable that hands a descriptor evaluator the plugin cache root
|
|
2064
|
+
* this load's record store selected, so the child proves the compiler it runs
|
|
2065
|
+
* from that root's records instead of streaming it (#1726) and never selects a
|
|
2066
|
+
* cache root of its own. Absent without a store.
|
|
2067
|
+
*/
|
|
2068
|
+
function descriptorRecordRoot(
|
|
2069
|
+
identities: PluginContentIdentities.Store | undefined,
|
|
2070
|
+
): { TTSC_PLUGIN_RECORD_ROOT?: string } {
|
|
2071
|
+
return identities === undefined
|
|
2072
|
+
? {}
|
|
2073
|
+
: { TTSC_PLUGIN_RECORD_ROOT: identities.root };
|
|
2074
|
+
}
|
|
2075
|
+
|
|
1889
2076
|
/**
|
|
1890
2077
|
* Expand the ttsx runtime's selected module edges into the same exact and
|
|
1891
2078
|
* missing resolution inputs used by the direct isolated evaluator.
|
|
@@ -1957,6 +2144,15 @@ function readTtsxDescriptorInputs(
|
|
|
1957
2144
|
(signatures.has(resolved) &&
|
|
1958
2145
|
signatures.get(resolved) !== record.signature)
|
|
1959
2146
|
) {
|
|
2147
|
+
E2ETrace.capabilityResolution(
|
|
2148
|
+
"plugin-descriptor-input-signature-moved",
|
|
2149
|
+
{
|
|
2150
|
+
resolved,
|
|
2151
|
+
first: signatures.get(resolved),
|
|
2152
|
+
later:
|
|
2153
|
+
typeof record.signature === "string" ? record.signature : null,
|
|
2154
|
+
},
|
|
2155
|
+
);
|
|
1960
2156
|
hashes.delete(resolved);
|
|
1961
2157
|
realpaths.delete(resolved);
|
|
1962
2158
|
signatures.delete(resolved);
|
|
@@ -2034,10 +2230,13 @@ function errorMessage(error: unknown): string {
|
|
|
2034
2230
|
return error instanceof Error ? error.message : String(error);
|
|
2035
2231
|
}
|
|
2036
2232
|
|
|
2037
|
-
function withPluginLoaderEnv<T>(
|
|
2233
|
+
function withPluginLoaderEnv<T>(
|
|
2234
|
+
run: () => T,
|
|
2235
|
+
identities: PluginContentIdentities.Store | undefined,
|
|
2236
|
+
): T {
|
|
2038
2237
|
const previousNode = process.env.TTSC_NODE_BINARY;
|
|
2039
2238
|
const previousTtsx = process.env.TTSC_TTSX_BINARY;
|
|
2040
|
-
const node = resolveNodeBinary({}, process.cwd());
|
|
2239
|
+
const node = resolveNodeBinary({}, process.cwd(), identities);
|
|
2041
2240
|
if (process.env.TTSC_NODE_BINARY === undefined && node !== undefined) {
|
|
2042
2241
|
process.env.TTSC_NODE_BINARY = node;
|
|
2043
2242
|
}
|
|
@@ -2136,6 +2335,7 @@ function pluginBuildDirectories(
|
|
|
2136
2335
|
}[],
|
|
2137
2336
|
env: NodeJS.ProcessEnv,
|
|
2138
2337
|
replacements?: Map<string, readonly string[]>,
|
|
2338
|
+
readers?: Map<string, SourcePluginWorkspace.GoModReader>,
|
|
2139
2339
|
): string[] {
|
|
2140
2340
|
const directories = new Set<string>();
|
|
2141
2341
|
for (const record of records) {
|
|
@@ -2146,8 +2346,12 @@ function pluginBuildDirectories(
|
|
|
2146
2346
|
);
|
|
2147
2347
|
if (record.kind === "executable") {
|
|
2148
2348
|
for (const directory of pluginReplacementWatchDirectories(
|
|
2149
|
-
record.moduleRoot,
|
|
2150
|
-
|
|
2349
|
+
record.moduleRoot,
|
|
2350
|
+
env,
|
|
2351
|
+
replacements,
|
|
2352
|
+
readers,
|
|
2353
|
+
))
|
|
2354
|
+
directories.add(directory);
|
|
2151
2355
|
}
|
|
2152
2356
|
for (const contributor of record.contributors ?? [])
|
|
2153
2357
|
directories.add(path.resolve(contributor.source));
|
|
@@ -2164,13 +2368,19 @@ function pluginReplacementWatchDirectories(
|
|
|
2164
2368
|
moduleRoot: string,
|
|
2165
2369
|
env: NodeJS.ProcessEnv,
|
|
2166
2370
|
observed?: Map<string, readonly string[]>,
|
|
2371
|
+
readers?: Map<string, SourcePluginWorkspace.GoModReader>,
|
|
2167
2372
|
): readonly string[] {
|
|
2168
2373
|
const previous = observed?.get(moduleRoot);
|
|
2169
2374
|
if (previous !== undefined) return previous;
|
|
2170
2375
|
let directories: readonly string[];
|
|
2171
2376
|
try {
|
|
2172
|
-
directories = pluginModuleReplaceDirectories(
|
|
2173
|
-
|
|
2377
|
+
directories = pluginModuleReplaceDirectories(
|
|
2378
|
+
moduleRoot,
|
|
2379
|
+
env,
|
|
2380
|
+
undefined,
|
|
2381
|
+
undefined,
|
|
2382
|
+
readers,
|
|
2383
|
+
).map((replacement) => replacement.directory);
|
|
2174
2384
|
} catch {
|
|
2175
2385
|
// An unreadable manifest/tool is not valid metadata. The already observed
|
|
2176
2386
|
// module retains its repair path; actual proposal/build refusal propagates.
|