ttsc 0.32.0 → 0.32.1
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/lib/TtscCompiler.js +1 -1
- package/lib/TtscCompiler.js.map +1 -1
- package/lib/compiler/internal/ResidentCheckProcess.d.ts +74 -96
- package/lib/compiler/internal/ResidentCheckProcess.js +150 -335
- package/lib/compiler/internal/ResidentCheckProcess.js.map +1 -1
- package/lib/compiler/internal/ResidentCheckProcessHost.d.ts +127 -0
- package/lib/compiler/internal/ResidentCheckProcessHost.js +447 -0
- package/lib/compiler/internal/ResidentCheckProcessHost.js.map +1 -0
- package/lib/compiler/internal/ResidentCheckProcessProtocol.d.ts +64 -0
- package/lib/compiler/internal/ResidentCheckProcessProtocol.js +3 -0
- package/lib/compiler/internal/ResidentCheckProcessProtocol.js.map +1 -0
- package/lib/compiler/internal/build/BuildExecution.d.ts +103 -1
- package/lib/compiler/internal/build/BuildExecution.js +91 -11
- package/lib/compiler/internal/build/BuildExecution.js.map +1 -1
- package/lib/compiler/internal/build/ResidentCheckWatchSession.d.ts +16 -11
- package/lib/compiler/internal/build/ResidentCheckWatchSession.js +37 -21
- package/lib/compiler/internal/build/ResidentCheckWatchSession.js.map +1 -1
- package/lib/compiler/internal/build/RunBuildOptions.d.ts +6 -5
- package/lib/compiler/internal/build/WatchInputPublication.d.ts +59 -0
- package/lib/compiler/internal/build/WatchInputPublication.js +93 -0
- package/lib/compiler/internal/build/WatchInputPublication.js.map +1 -0
- package/lib/compiler/internal/build/runBuild.d.ts +29 -2
- package/lib/compiler/internal/build/runBuild.js +45 -19
- package/lib/compiler/internal/build/runBuild.js.map +1 -1
- package/lib/compiler/internal/buildNativeCompiler.d.ts +2 -0
- package/lib/compiler/internal/buildNativeCompiler.js +1 -0
- package/lib/compiler/internal/buildNativeCompiler.js.map +1 -1
- package/lib/compiler/internal/compileProjectInMemory.js +4 -2
- package/lib/compiler/internal/compileProjectInMemory.js.map +1 -1
- package/lib/compiler/internal/project/resolveOwningProjectConfig.d.ts +7 -2
- package/lib/compiler/internal/project/resolveOwningProjectConfig.js +6 -3
- package/lib/compiler/internal/project/resolveOwningProjectConfig.js.map +1 -1
- package/lib/compiler/internal/readEffectiveCompilerOptions.js +1 -1
- package/lib/compiler/internal/readEffectiveCompilerOptions.js.map +1 -1
- package/lib/compiler/internal/resolveBinary.d.ts +1 -0
- package/lib/compiler/internal/resolveBinary.js.map +1 -1
- package/lib/compiler/internal/resolveTsgo.d.ts +6 -0
- package/lib/compiler/internal/resolveTsgo.js.map +1 -1
- package/lib/compiler/internal/runSingleFileEmit.d.ts +28 -1
- package/lib/compiler/internal/runSingleFileEmit.js +120 -86
- package/lib/compiler/internal/runSingleFileEmit.js.map +1 -1
- package/lib/compiler/internal/startResidentTransform.js +8 -2
- package/lib/compiler/internal/startResidentTransform.js.map +1 -1
- package/lib/compiler/internal/transformProjectInMemory.js +11 -3
- package/lib/compiler/internal/transformProjectInMemory.js.map +1 -1
- package/lib/compiler/internal/transformProjectInWorker.d.ts +1 -1
- package/lib/compiler/internal/transformProjectInWorker.js +3 -2
- package/lib/compiler/internal/transformProjectInWorker.js.map +1 -1
- package/lib/internal/workerModuleUrl.d.ts +28 -0
- package/lib/internal/workerModuleUrl.js +40 -0
- package/lib/internal/workerModuleUrl.js.map +1 -0
- package/lib/launcher/internal/buildSingleRootProject.js +2 -1
- package/lib/launcher/internal/buildSingleRootProject.js.map +1 -1
- package/lib/launcher/internal/getCompilerVersionText.js +3 -2
- package/lib/launcher/internal/getCompilerVersionText.js.map +1 -1
- package/lib/launcher/internal/prepareExecution.js +2 -1
- package/lib/launcher/internal/prepareExecution.js.map +1 -1
- package/lib/launcher/internal/runTtsc.js +91 -41
- package/lib/launcher/internal/runTtsc.js.map +1 -1
- package/lib/launcher/internal/runtime/CommonJsRuntimeSource.d.ts +10 -6
- package/lib/launcher/internal/runtime/CommonJsRuntimeSource.js +11 -9
- package/lib/launcher/internal/runtime/CommonJsRuntimeSource.js.map +1 -1
- package/lib/launcher/internal/runtime/advertiseTypeScriptExtensions.d.ts +20 -0
- package/lib/launcher/internal/runtime/advertiseTypeScriptExtensions.js +27 -0
- package/lib/launcher/internal/runtime/advertiseTypeScriptExtensions.js.map +1 -0
- package/lib/launcher/internal/runtime/installRuntimeHooks.d.ts +5 -3
- package/lib/launcher/internal/runtime/installRuntimeHooks.js +7 -3
- package/lib/launcher/internal/runtime/installRuntimeHooks.js.map +1 -1
- package/lib/launcher/internal/watch/AsyncWatchTopology.d.ts +113 -0
- package/lib/launcher/internal/watch/AsyncWatchTopology.js +232 -0
- package/lib/launcher/internal/watch/AsyncWatchTopology.js.map +1 -0
- package/lib/launcher/internal/watch/WatchSettlement.d.ts +49 -0
- package/lib/launcher/internal/watch/WatchSettlement.js +70 -0
- package/lib/launcher/internal/watch/WatchSettlement.js.map +1 -0
- package/lib/launcher/internal/watch/WatchTopology.d.ts +29 -1
- package/lib/launcher/internal/watch/WatchTopology.js +86 -10
- package/lib/launcher/internal/watch/WatchTopology.js.map +1 -1
- package/lib/launcher/internal/watch/WatchTopologyWorkerProtocol.d.ts +121 -0
- package/lib/launcher/internal/watch/WatchTopologyWorkerProtocol.js +3 -0
- package/lib/launcher/internal/watch/WatchTopologyWorkerProtocol.js.map +1 -0
- package/lib/launcher/internal/watch/serveWatchTopologyWorker.d.ts +19 -0
- package/lib/launcher/internal/watch/serveWatchTopologyWorker.js +62 -0
- package/lib/launcher/internal/watch/serveWatchTopologyWorker.js.map +1 -0
- package/lib/launcher/internal/watch/watchTopologyWorker.d.ts +1 -0
- package/lib/launcher/internal/watch/watchTopologyWorker.js +22 -0
- package/lib/launcher/internal/watch/watchTopologyWorker.js.map +1 -0
- package/lib/plugin/CapabilityPluginResolver.d.ts +1 -1
- package/lib/plugin/CapabilityPluginResolver.js +3 -2
- package/lib/plugin/CapabilityPluginResolver.js.map +1 -1
- package/lib/plugin/internal/load/PluginDescriptorEvaluationCache.d.ts +15 -12
- package/lib/plugin/internal/load/PluginDescriptorEvaluationCache.js +13 -11
- package/lib/plugin/internal/load/PluginDescriptorEvaluationCache.js.map +1 -1
- package/lib/plugin/internal/load/PluginPackageResolution.d.ts +2 -2
- package/lib/plugin/internal/load/PluginPackageResolution.js +13 -7
- package/lib/plugin/internal/load/PluginPackageResolution.js.map +1 -1
- package/lib/plugin/internal/load/ProjectPluginEntries.d.ts +23 -7
- package/lib/plugin/internal/load/ProjectPluginEntries.js +36 -14
- package/lib/plugin/internal/load/ProjectPluginEntries.js.map +1 -1
- package/lib/plugin/internal/load/collectProjectHostInputs.d.ts +3 -1
- package/lib/plugin/internal/load/collectProjectHostInputs.js +5 -2
- package/lib/plugin/internal/load/collectProjectHostInputs.js.map +1 -1
- package/lib/plugin/internal/load/hasProjectPluginEntries.d.ts +3 -1
- package/lib/plugin/internal/load/hasProjectPluginEntries.js +4 -2
- package/lib/plugin/internal/load/hasProjectPluginEntries.js.map +1 -1
- package/lib/plugin/internal/load/loadProjectPlugins.d.ts +36 -5
- package/lib/plugin/internal/load/loadProjectPlugins.js +466 -416
- package/lib/plugin/internal/load/loadProjectPlugins.js.map +1 -1
- package/lib/plugin/internal/load/pluginResolutionFailure.d.ts +18 -0
- package/lib/plugin/internal/load/pluginResolutionFailure.js +32 -0
- package/lib/plugin/internal/load/pluginResolutionFailure.js.map +1 -0
- package/lib/plugin/internal/source/PluginBuildEnvironmentReadings.d.ts +1 -1
- package/lib/plugin/internal/source/PluginBuildEnvironmentReadings.js +3 -2
- package/lib/plugin/internal/source/PluginBuildEnvironmentReadings.js.map +1 -1
- package/lib/structures/ITtscCompilerContext.d.ts +12 -12
- package/lib/structures/ITtscPlugin.d.ts +7 -5
- package/lib/structures/ITtscPluginFactoryContext.d.ts +9 -8
- package/lib/structures/internal/TtscSingleFileEmitOptions.d.ts +12 -6
- package/package.json +9 -9
- package/src/TtscCompiler.ts +1 -1
- package/src/compiler/internal/ResidentCheckProcess.ts +159 -374
- package/src/compiler/internal/ResidentCheckProcessHost.ts +502 -0
- package/src/compiler/internal/ResidentCheckProcessProtocol.ts +53 -0
- package/src/compiler/internal/build/BuildExecution.ts +118 -9
- package/src/compiler/internal/build/ResidentCheckWatchSession.ts +41 -24
- package/src/compiler/internal/build/RunBuildOptions.ts +9 -5
- package/src/compiler/internal/build/WatchInputPublication.ts +106 -0
- package/src/compiler/internal/build/runBuild.ts +58 -34
- package/src/compiler/internal/buildNativeCompiler.ts +4 -0
- package/src/compiler/internal/compileProjectInMemory.ts +8 -2
- package/src/compiler/internal/project/resolveOwningProjectConfig.ts +16 -5
- package/src/compiler/internal/readEffectiveCompilerOptions.ts +1 -1
- package/src/compiler/internal/resolveBinary.ts +4 -1
- package/src/compiler/internal/resolveTsgo.ts +7 -0
- package/src/compiler/internal/runSingleFileEmit.ts +139 -99
- package/src/compiler/internal/startResidentTransform.ts +9 -2
- package/src/compiler/internal/transformProjectInMemory.ts +12 -3
- package/src/compiler/internal/transformProjectInWorker.ts +10 -2
- package/src/internal/workerModuleUrl.ts +34 -0
- package/src/launcher/internal/buildSingleRootProject.ts +2 -0
- package/src/launcher/internal/getCompilerVersionText.ts +3 -2
- package/src/launcher/internal/prepareExecution.ts +2 -0
- package/src/launcher/internal/runTtsc.ts +123 -45
- package/src/launcher/internal/runtime/CommonJsRuntimeSource.ts +11 -9
- package/src/launcher/internal/runtime/advertiseTypeScriptExtensions.ts +25 -0
- package/src/launcher/internal/runtime/installRuntimeHooks.ts +7 -3
- package/src/launcher/internal/watch/AsyncWatchTopology.ts +267 -0
- package/src/launcher/internal/watch/WatchSettlement.ts +67 -0
- package/src/launcher/internal/watch/WatchTopology.ts +84 -13
- package/src/launcher/internal/watch/WatchTopologyWorkerProtocol.ts +106 -0
- package/src/launcher/internal/watch/serveWatchTopologyWorker.ts +75 -0
- package/src/launcher/internal/watch/watchTopologyWorker.ts +29 -0
- package/src/plugin/CapabilityPluginResolver.ts +9 -2
- package/src/plugin/internal/load/PluginDescriptorEvaluationCache.ts +17 -12
- package/src/plugin/internal/load/PluginPackageResolution.ts +14 -9
- package/src/plugin/internal/load/ProjectPluginEntries.ts +40 -15
- package/src/plugin/internal/load/collectProjectHostInputs.ts +7 -1
- package/src/plugin/internal/load/hasProjectPluginEntries.ts +8 -3
- package/src/plugin/internal/load/loadProjectPlugins.ts +672 -594
- package/src/plugin/internal/load/pluginResolutionFailure.ts +37 -0
- package/src/plugin/internal/source/PluginBuildEnvironmentReadings.ts +8 -2
- package/src/structures/ITtscCompilerContext.ts +12 -12
- package/src/structures/ITtscPlugin.ts +7 -5
- package/src/structures/ITtscPluginFactoryContext.ts +9 -8
- package/src/structures/internal/TtscSingleFileEmitOptions.ts +22 -11
|
@@ -4,6 +4,7 @@ import { createRequire } from "node:module";
|
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
6
6
|
|
|
7
|
+
import { WatchInputPublication } from "../../../compiler/internal/build/WatchInputPublication";
|
|
7
8
|
import { readJsonFile } from "../../../compiler/internal/project/readJsonFile";
|
|
8
9
|
import { readProjectConfig } from "../../../compiler/internal/project/readProjectConfig";
|
|
9
10
|
import { SidecarEnvironment } from "../../../compiler/internal/sharedHost/SidecarEnvironment";
|
|
@@ -20,6 +21,7 @@ import type { ITtscPluginFactoryContext } from "../../../structures/ITtscPluginF
|
|
|
20
21
|
import type { ITtscProjectPluginConfig } from "../../../structures/ITtscProjectPluginConfig";
|
|
21
22
|
import type { ITtscLoadedNativePlugin } from "../../../structures/internal/ITtscLoadedNativePlugin";
|
|
22
23
|
import type { ITtscParsedProjectConfig } from "../../../structures/internal/ITtscParsedProjectConfig";
|
|
24
|
+
import type { TtscPluginSourceInputsHandler } from "../../../structures/internal/TtscSingleFileEmitOptions";
|
|
23
25
|
import { pluginDescriptorFailureReason } from "../pluginDescriptorFailureReason";
|
|
24
26
|
import { pluginDescriptorProcessFailure } from "../pluginDescriptorProcessFailure";
|
|
25
27
|
import { NativeSourcePackages } from "../source/NativeSourcePackages";
|
|
@@ -83,6 +85,9 @@ import { visitImportMappedCandidates } from "./visitImportMappedCandidates";
|
|
|
83
85
|
* declaration. Sequential content, metadata and physical-path observations are
|
|
84
86
|
* not an atomic snapshot or detection of every omitted read.
|
|
85
87
|
*
|
|
88
|
+
* Synchronous callers require synchronous watch-input handlers; use
|
|
89
|
+
* {@link loadProjectPlugins.async} to await a worker's baseline publication.
|
|
90
|
+
*
|
|
86
91
|
* @param options.binary - Absolute path to the ttsc native helper binary.
|
|
87
92
|
* @param options.cacheDir - Override the plugin binary cache directory.
|
|
88
93
|
* @param options.cwd - Working directory for resolving relative paths.
|
|
@@ -93,11 +98,12 @@ import { visitImportMappedCandidates } from "./visitImportMappedCandidates";
|
|
|
93
98
|
* native environment-name identity. Defaults to `process.env` for CLI
|
|
94
99
|
* callers, so ambient behavior is unchanged.
|
|
95
100
|
* @param options.file - Path to the tsconfig/jsconfig file.
|
|
96
|
-
* @param options.pluginConfigDir - Caller-declared
|
|
97
|
-
* config-file discovery
|
|
98
|
-
* @param options.projectRoot - Override the
|
|
101
|
+
* @param options.pluginConfigDir - Caller-declared consumer directory for
|
|
102
|
+
* plugin packages, factory contexts and config-file discovery.
|
|
103
|
+
* @param options.projectRoot - Override the source root, native working
|
|
104
|
+
* directory, cache anchor and returned relative Go-source base.
|
|
99
105
|
* @param options.tsconfig - Alias for `file`.
|
|
100
|
-
* @evidence contracts/common.md#principled-implementation The loader brackets
|
|
106
|
+
* @evidence contracts/common.md#principled-implementation The loader brackets discovery at the selected config or explicit pluginConfigDir and factories receive that consumer anchor, independently of the source root retained for descriptor/native process cwd, caches and relative Go sources. It validates declarations before publishing conservative source repair interests. Metadata refusal remains terminal; valid records narrow watch interests before final admission/build, while contradictory content or physical observations are omitted from proof rather than retroactively blessed.
|
|
101
107
|
* @evidence contracts/common.md#clear-and-simple-design The operation owns one ordered load generation; private helpers separate discovery, evaluation, validation, composition and proof merging, while package resolution and source building remain their own modules.
|
|
102
108
|
* @evidence contracts/common.md#prohibited-implementation-shortcuts Descriptor module caches are isolated rather than deleting application singletons. ttsx retry occurs only for explicit supported TypeScript loader incompatibility, with plugins disabled to avoid recursive self-hosting; arbitrary descriptor failures are not retried into false success.
|
|
103
109
|
* @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.
|
|
@@ -135,10 +141,7 @@ export function loadProjectPlugins(options: {
|
|
|
135
141
|
* Observe plugin build roots before building, including failed builds, with
|
|
136
142
|
* the record store that proves their states (#1728).
|
|
137
143
|
*/
|
|
138
|
-
onWatchInputs?:
|
|
139
|
-
inputs: readonly string[],
|
|
140
|
-
identities?: PluginContentIdentities.Store,
|
|
141
|
-
) => void;
|
|
144
|
+
onWatchInputs?: TtscPluginSourceInputsHandler;
|
|
142
145
|
|
|
143
146
|
/** Caller-selected anchor for plugin-owned configuration discovery. */
|
|
144
147
|
pluginConfigDir?: string;
|
|
@@ -199,617 +202,676 @@ export function loadProjectPlugins(options: {
|
|
|
199
202
|
/** Resolved project values and logical/physical configuration identity. */
|
|
200
203
|
project: ITtscParsedProjectConfig;
|
|
201
204
|
} {
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
205
|
+
return WatchInputPublication.run(loadProjectPlugins.steps(options));
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Keep synchronous loading and awaited watch handoffs on one load sequence.
|
|
210
|
+
*
|
|
211
|
+
* @evidence contracts/common.md#principled-implementation Both completion modes advance one ordered discovery, admission, publication and build sequence. Awaited stepping preserves baseline-before-read handoffs before package selection and source builds, including empty selection and conservative repair roots.
|
|
212
|
+
* @evidence contracts/common.md#clear-and-simple-design The namespace adds an awaited runner beside synchronous loading and exposes one generator to build orchestration; existing helpers retain discovery, validation and compilation responsibilities.
|
|
213
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts Publication suspension retains failed-build interests and source proof rather than rebuilding a baseline after compilation. Pending publication cannot establish observation; rejection enters the real load failure path without replacing admission or native builds.
|
|
214
|
+
* @evidence contracts/common.md#meaningful-documentation Entry prose distinguishes completion modes, baseline-before-read ordering and internal sequence completion/rejection duties; the primary loader documents input and result provenance.
|
|
215
|
+
* @evidence contracts/portability.md#os-neutral-implementation The shared sequence retains existing native resolution, paths, environment and argument-array handling; the namespace adds no independent boundary.
|
|
216
|
+
* @evidence contracts/performance.md#efficient-algorithms Discovery, source hashing, Go metadata, validation and builds retain their original input costs; each publication adds one suspension without repeating those phases.
|
|
217
|
+
* @evidence contracts/performance.md#reuse-equivalent-work Validated descriptor/source records and load-local digest/reader sharing remain available across suspension; the completion wrapper retains no reusable load or in-flight cache.
|
|
218
|
+
* @evidence contracts/performance.md#bound-retention-and-release-resources One load generation stays live while its current handoff settles; evaluator cleanup and returned-generation ownership remain with the sequence, and handler rejection enters generator cleanup.
|
|
219
|
+
*/
|
|
220
|
+
export namespace loadProjectPlugins {
|
|
221
|
+
/**
|
|
222
|
+
* Load plugins after each watch owner confirms its reported input baseline. A
|
|
223
|
+
* rejected handoff fails loading before the next source read or build.
|
|
224
|
+
*/
|
|
225
|
+
export function async(
|
|
226
|
+
options: Parameters<typeof loadProjectPlugins>[0],
|
|
227
|
+
): Promise<ReturnType<typeof loadProjectPlugins>> {
|
|
228
|
+
return WatchInputPublication.runAsync(steps(options));
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Produce one load, suspending at each watch-input handoff before continuing.
|
|
233
|
+
* Internal build orchestration consumes the whole sequence with its chosen
|
|
234
|
+
* completion runner; it must deliver rejection back into the sequence.
|
|
235
|
+
*/
|
|
236
|
+
export function* steps(
|
|
237
|
+
options: Parameters<typeof loadProjectPlugins>[0],
|
|
238
|
+
): WatchInputPublication.Sequence<ReturnType<typeof loadProjectPlugins>> {
|
|
239
|
+
// Snapshot the caller environment before `withPluginLoaderEnv` injects
|
|
240
|
+
// host-owned Node/ttsx locators into process.env. Under a Bun parent the
|
|
241
|
+
// direct descriptor evaluator must remain Bun unless the caller explicitly
|
|
242
|
+
// selected another runtime.
|
|
243
|
+
const effectiveEnv = SidecarEnvironment.merge(options.env ?? process.env);
|
|
244
|
+
const projectSnapshot = readProjectHostInputSnapshot({
|
|
245
|
+
cwd: options.cwd,
|
|
246
|
+
file: options.file,
|
|
247
|
+
includePluginDiscovery: options.entries === undefined,
|
|
248
|
+
pluginConfigDir: options.pluginConfigDir,
|
|
249
|
+
projectRoot: options.projectRoot,
|
|
250
|
+
tsconfig: options.tsconfig,
|
|
251
|
+
});
|
|
252
|
+
const { project } = projectSnapshot;
|
|
253
|
+
const projectHostInputs = projectSnapshot.hostInputs;
|
|
254
|
+
const projectHostInputHashes = projectSnapshot.hostInputHashes;
|
|
255
|
+
const projectHostInputRealpaths = projectSnapshot.hostInputRealpaths;
|
|
256
|
+
const entries: ProjectPluginEntries.ProjectPluginEntry[] =
|
|
257
|
+
options.entries === false
|
|
258
|
+
? []
|
|
259
|
+
: ProjectPluginEntries.resolvePluginEntries(
|
|
260
|
+
project,
|
|
261
|
+
options.entries,
|
|
262
|
+
options.pluginConfigDir,
|
|
263
|
+
).filter((entry) => entry.config.enabled !== false);
|
|
264
|
+
if (entries.length === 0) {
|
|
265
|
+
yield options.onWatchInputs?.([]);
|
|
266
|
+
return {
|
|
267
|
+
...collectHostInputSnapshot(
|
|
222
268
|
project,
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
if (entries.length === 0) {
|
|
226
|
-
options.onWatchInputs?.([]);
|
|
227
|
-
return {
|
|
228
|
-
...collectHostInputSnapshot(
|
|
229
|
-
project,
|
|
230
|
-
{},
|
|
231
|
-
[],
|
|
232
|
-
projectHostInputs,
|
|
233
|
-
revalidateHostInputHashes(projectHostInputHashes, projectHostInputs),
|
|
234
|
-
revalidateHostInputRealpaths(
|
|
235
|
-
projectHostInputRealpaths,
|
|
269
|
+
{},
|
|
270
|
+
[],
|
|
236
271
|
projectHostInputs,
|
|
272
|
+
revalidateHostInputHashes(projectHostInputHashes, projectHostInputs),
|
|
273
|
+
revalidateHostInputRealpaths(
|
|
274
|
+
projectHostInputRealpaths,
|
|
275
|
+
projectHostInputs,
|
|
276
|
+
),
|
|
237
277
|
),
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
}
|
|
245
|
-
}
|
|
278
|
+
descriptorReadsDeclared: true,
|
|
279
|
+
discoveryInputsComplete: project.configInputsComplete === true,
|
|
280
|
+
nativePlugins: [],
|
|
281
|
+
pluginSources: {},
|
|
282
|
+
project,
|
|
283
|
+
};
|
|
284
|
+
}
|
|
246
285
|
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
tsconfig: project.path,
|
|
256
|
-
};
|
|
257
|
-
// Where isolated descriptor evaluations keep their answers across launches
|
|
258
|
-
// (`PluginDescriptorEvaluationCache`).
|
|
259
|
-
// WARNING (#1721, #1722, #1723): a warm load must prove its unchanged inputs
|
|
260
|
-
// from this store, not re-read them. Every launch is a new process, so any
|
|
261
|
-
// module-level memo of this load's work dies with it; a 27 s warm typia
|
|
262
|
-
// launch whose native build took 0.28 s is what that looked like.
|
|
263
|
-
const identities =
|
|
264
|
-
options.identities ??
|
|
265
|
-
PluginContentIdentities.open({
|
|
286
|
+
const cwd = path.resolve(options.cwd ?? process.cwd());
|
|
287
|
+
const context = {
|
|
288
|
+
binary: options.binary,
|
|
289
|
+
cwd,
|
|
290
|
+
...(options.pluginConfigDir === undefined ||
|
|
291
|
+
options.pluginConfigDir === ""
|
|
292
|
+
? {}
|
|
293
|
+
: { pluginConfigDir: path.resolve(cwd, options.pluginConfigDir) }),
|
|
266
294
|
projectRoot: project.root,
|
|
295
|
+
tsconfig: project.path,
|
|
296
|
+
};
|
|
297
|
+
// Where isolated descriptor evaluations keep their answers across launches
|
|
298
|
+
// (`PluginDescriptorEvaluationCache`).
|
|
299
|
+
// WARNING (#1721, #1722, #1723): a warm load must prove its unchanged inputs
|
|
300
|
+
// from this store, not re-read them. Every launch is a new process, so any
|
|
301
|
+
// module-level memo of this load's work dies with it; a 27 s warm typia
|
|
302
|
+
// launch whose native build took 0.28 s is what that looked like.
|
|
303
|
+
const identities =
|
|
304
|
+
options.identities ??
|
|
305
|
+
PluginContentIdentities.open({
|
|
306
|
+
projectRoot: project.root,
|
|
307
|
+
cacheDir: options.cacheDir,
|
|
308
|
+
env: effectiveEnv,
|
|
309
|
+
});
|
|
310
|
+
const descriptorCache: DescriptorCacheOptions = {
|
|
267
311
|
cacheDir: options.cacheDir,
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
}
|
|
284
|
-
const entryParent = path.join(entry.baseDir, "package.json");
|
|
285
|
-
const probedCandidates = collectModuleResolutionCandidates(
|
|
286
|
-
specifier,
|
|
287
|
-
entryParent,
|
|
288
|
-
undefined,
|
|
289
|
-
);
|
|
290
|
-
// Capture every candidate before resolution chooses the descriptor entry.
|
|
291
|
-
// A post-resolution snapshot could bless a higher-priority file created
|
|
292
|
-
// after the resolver had already selected the old entry.
|
|
293
|
-
const probedCandidateHashes = hashHostInputPaths(probedCandidates);
|
|
294
|
-
const probedCandidateRealpaths =
|
|
295
|
-
realpathHostInputPaths(probedCandidates);
|
|
296
|
-
const request = PluginPackageResolution.resolvePluginRequest(
|
|
297
|
-
specifier,
|
|
298
|
-
entry.baseDir,
|
|
299
|
-
);
|
|
300
|
-
// Keep the candidates of the search roots up to the one the entry
|
|
301
|
-
// resolved in: the lookup never read the roots after it
|
|
302
|
-
// (`moduleResolutionBaseSelects`).
|
|
303
|
-
const read = new Set(
|
|
304
|
-
collectModuleResolutionCandidates(
|
|
312
|
+
identities,
|
|
313
|
+
projectRoot: project.root,
|
|
314
|
+
version: pluginBuildVersions(project.root).ttsc,
|
|
315
|
+
};
|
|
316
|
+
const loadedEntries = withPluginLoaderEnv(
|
|
317
|
+
() =>
|
|
318
|
+
entries.map((entry) => {
|
|
319
|
+
const specifier = entry.config.transform;
|
|
320
|
+
if (typeof specifier !== "string" || specifier.length === 0) {
|
|
321
|
+
throw new Error(
|
|
322
|
+
`ttsc: plugin entry is missing a string "transform" field`,
|
|
323
|
+
);
|
|
324
|
+
}
|
|
325
|
+
const entryParent = path.join(entry.baseDir, "package.json");
|
|
326
|
+
const probedCandidates = collectModuleResolutionCandidates(
|
|
305
327
|
specifier,
|
|
306
328
|
entryParent,
|
|
329
|
+
undefined,
|
|
330
|
+
);
|
|
331
|
+
// Capture every candidate before resolution chooses the descriptor entry.
|
|
332
|
+
// A post-resolution snapshot could bless a higher-priority file created
|
|
333
|
+
// after the resolver had already selected the old entry.
|
|
334
|
+
const probedCandidateHashes = hashHostInputPaths(probedCandidates);
|
|
335
|
+
const probedCandidateRealpaths =
|
|
336
|
+
realpathHostInputPaths(probedCandidates);
|
|
337
|
+
const request = PluginPackageResolution.resolvePluginRequest(
|
|
338
|
+
specifier,
|
|
339
|
+
entry.baseDir,
|
|
340
|
+
);
|
|
341
|
+
// Keep the candidates of the search roots up to the one the entry
|
|
342
|
+
// resolved in: the lookup never read the roots after it
|
|
343
|
+
// (`moduleResolutionBaseSelects`).
|
|
344
|
+
const read = new Set(
|
|
345
|
+
collectModuleResolutionCandidates(
|
|
346
|
+
specifier,
|
|
347
|
+
entryParent,
|
|
348
|
+
request,
|
|
349
|
+
).map((candidate) => path.resolve(candidate)),
|
|
350
|
+
);
|
|
351
|
+
const entryCandidates = probedCandidates.filter((candidate) =>
|
|
352
|
+
read.has(path.resolve(candidate)),
|
|
353
|
+
);
|
|
354
|
+
const entryCandidateHashes = pickHostInputEntries(
|
|
355
|
+
probedCandidateHashes,
|
|
356
|
+
entryCandidates,
|
|
357
|
+
);
|
|
358
|
+
const entryCandidateRealpaths = pickHostInputEntries(
|
|
359
|
+
probedCandidateRealpaths,
|
|
360
|
+
entryCandidates,
|
|
361
|
+
);
|
|
362
|
+
const loaded = loadPluginEntry(
|
|
363
|
+
entry.config,
|
|
364
|
+
{
|
|
365
|
+
...context,
|
|
366
|
+
plugin: entry.config,
|
|
367
|
+
// Package factories such as typia resolve their own package from
|
|
368
|
+
// this consumer anchor. Keep the compiler source root below for
|
|
369
|
+
// native cwd, cache ownership and returned relative Go sources.
|
|
370
|
+
projectRoot: ProjectPluginEntries.resolvePluginBaseDir(
|
|
371
|
+
project,
|
|
372
|
+
options.pluginConfigDir,
|
|
373
|
+
),
|
|
374
|
+
},
|
|
307
375
|
request,
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
entryCandidateHashes,
|
|
338
|
-
loadedHostInputHashes,
|
|
339
|
-
);
|
|
340
|
-
const hostInputRealpaths = mergeObservedHostInputRealpaths(
|
|
341
|
-
entryCandidateRealpaths,
|
|
342
|
-
loadedHostInputRealpaths,
|
|
343
|
-
);
|
|
344
|
-
for (const input of loaded.hostInputs) {
|
|
345
|
-
const absolute = path.resolve(input);
|
|
346
|
-
if (
|
|
347
|
-
!Object.prototype.hasOwnProperty.call(
|
|
348
|
-
loadedHostInputHashes,
|
|
349
|
-
absolute,
|
|
350
|
-
)
|
|
351
|
-
) {
|
|
352
|
-
delete hostInputHashes[absolute];
|
|
376
|
+
effectiveEnv,
|
|
377
|
+
descriptorCache,
|
|
378
|
+
);
|
|
379
|
+
const loadedHostInputHashes = mergeObservedHostInputHashes(
|
|
380
|
+
loaded.hostInputHashes,
|
|
381
|
+
hashHostInputPaths(Object.keys(loaded.hostInputHashes)),
|
|
382
|
+
);
|
|
383
|
+
const loadedHostInputRealpaths = mergeObservedHostInputRealpaths(
|
|
384
|
+
loaded.hostInputRealpaths,
|
|
385
|
+
realpathHostInputPaths(Object.keys(loaded.hostInputRealpaths)),
|
|
386
|
+
);
|
|
387
|
+
const hostInputHashes = mergeObservedHostInputHashes(
|
|
388
|
+
entryCandidateHashes,
|
|
389
|
+
loadedHostInputHashes,
|
|
390
|
+
);
|
|
391
|
+
const hostInputRealpaths = mergeObservedHostInputRealpaths(
|
|
392
|
+
entryCandidateRealpaths,
|
|
393
|
+
loadedHostInputRealpaths,
|
|
394
|
+
);
|
|
395
|
+
for (const input of loaded.hostInputs) {
|
|
396
|
+
const absolute = path.resolve(input);
|
|
397
|
+
if (
|
|
398
|
+
!Object.prototype.hasOwnProperty.call(
|
|
399
|
+
loadedHostInputHashes,
|
|
400
|
+
absolute,
|
|
401
|
+
)
|
|
402
|
+
) {
|
|
403
|
+
delete hostInputHashes[absolute];
|
|
404
|
+
}
|
|
353
405
|
}
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
);
|
|
406
|
+
return {
|
|
407
|
+
...loaded,
|
|
408
|
+
hostInputHashes,
|
|
409
|
+
hostInputRealpaths,
|
|
410
|
+
hostInputs: [...loaded.hostInputs, ...entryCandidates],
|
|
411
|
+
request,
|
|
412
|
+
};
|
|
413
|
+
}),
|
|
414
|
+
identities,
|
|
415
|
+
);
|
|
416
|
+
const plugins = composePluginSources(
|
|
417
|
+
entries,
|
|
418
|
+
loadedEntries.map((entry) => entry.plugin),
|
|
419
|
+
);
|
|
369
420
|
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
);
|
|
373
|
-
const candidates = plugins
|
|
374
|
-
.map((plugin, index) => {
|
|
375
|
-
const stage = PluginDescriptorAdmission.stage(plugin);
|
|
376
|
-
validatePluginSource(plugin);
|
|
377
|
-
const contributors = validatePluginContributors(plugin);
|
|
378
|
-
const source = resolvePluginSource(plugin.source, context.projectRoot);
|
|
379
|
-
const label = pluginLabel(plugin, entries[index]!.config, index);
|
|
380
|
-
requirePluginSource(source, label);
|
|
381
|
-
return { plugin, index, stage, contributors, source, label };
|
|
382
|
-
})
|
|
383
|
-
.map((candidate) => ({
|
|
384
|
-
...candidate,
|
|
385
|
-
...resolvePluginGoModule(candidate.source, candidate.label),
|
|
386
|
-
}));
|
|
387
|
-
// One reading of each source directory, shared by package selection and
|
|
388
|
-
// every build below and reported as the state the binaries were keyed on.
|
|
389
|
-
const sourceDigests = new Map<string, string>();
|
|
390
|
-
// And one reading of the environment each build directory is keyed on, which
|
|
391
|
-
// a plugin module root's state reports as it is.
|
|
392
|
-
const environmentDigests = new Map<string, string>();
|
|
393
|
-
// With the witness of each such reading, so a build of a directory package
|
|
394
|
-
// selection already read keys on that reading instead of probing Go again.
|
|
395
|
-
const environmentWitnesses = new Map<
|
|
396
|
-
string,
|
|
397
|
-
PluginBuildEnvironmentWitness.Record
|
|
398
|
-
>();
|
|
399
|
-
const readings = {
|
|
400
|
-
sources: sourceDigests,
|
|
401
|
-
environments: environmentDigests,
|
|
402
|
-
witnesses: environmentWitnesses,
|
|
403
|
-
};
|
|
404
|
-
// Records describing sources must never land inside one, so the store is
|
|
405
|
-
// admitted for source proofs only once every source of the load is known.
|
|
406
|
-
const sourceIdentities = PluginContentIdentities.outside(identities, [
|
|
407
|
-
...candidates.flatMap((candidate) => [
|
|
408
|
-
candidate.moduleRoot,
|
|
409
|
-
candidate.packageDir,
|
|
410
|
-
...(candidate.contributors ?? []).map((input) => input.source),
|
|
411
|
-
]),
|
|
412
|
-
...SourcePluginWorkspace.findTtscOverlayDirs(),
|
|
413
|
-
]);
|
|
414
|
-
// One fixed-effective-environment load owns manifest syntax sharing from the
|
|
415
|
-
// first watch query through metadata and builds. Do not allocate this after
|
|
416
|
-
// watch projection: that silently repeats selected-Go work (#1712).
|
|
417
|
-
const packageReaders = new Map<string, SourcePluginWorkspace.GoModReader>();
|
|
418
|
-
const watchReplacements =
|
|
419
|
-
options.onWatchInputs === undefined
|
|
420
|
-
? undefined
|
|
421
|
-
: new Map<string, readonly string[]>();
|
|
422
|
-
if (options.onWatchInputs !== undefined) {
|
|
423
|
-
// The prospective context reads the admitted module layout and anchors its
|
|
424
|
-
// tool there before kind exists. Keep both possible final-root baselines:
|
|
425
|
-
// a linked package keeps packageDir, and an executable keeps moduleRoot.
|
|
426
|
-
const interests = new Set(
|
|
427
|
-
candidates
|
|
428
|
-
.flatMap((candidate) => [
|
|
429
|
-
candidate.moduleRoot,
|
|
430
|
-
candidate.packageDir,
|
|
431
|
-
...(candidate.contributors ?? []).map((input) => input.source),
|
|
432
|
-
])
|
|
433
|
-
.filter(reportsPluginSource),
|
|
421
|
+
const { ttsc: ttscVersion, tsgo: tsgoVersion } = pluginBuildVersions(
|
|
422
|
+
context.projectRoot,
|
|
434
423
|
);
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
424
|
+
const candidates = plugins
|
|
425
|
+
.map((plugin, index) => {
|
|
426
|
+
const stage = PluginDescriptorAdmission.stage(plugin);
|
|
427
|
+
validatePluginSource(plugin);
|
|
428
|
+
const contributors = validatePluginContributors(plugin);
|
|
429
|
+
const source = resolvePluginSource(plugin.source, context.projectRoot);
|
|
430
|
+
const label = pluginLabel(plugin, entries[index]!.config, index);
|
|
431
|
+
requirePluginSource(source, label);
|
|
432
|
+
return { plugin, index, stage, contributors, source, label };
|
|
433
|
+
})
|
|
434
|
+
.map((candidate) => ({
|
|
435
|
+
...candidate,
|
|
436
|
+
...resolvePluginGoModule(candidate.source, candidate.label),
|
|
437
|
+
}));
|
|
438
|
+
// One reading of each source directory, shared by package selection and
|
|
439
|
+
// every build below and reported as the state the binaries were keyed on.
|
|
440
|
+
const sourceDigests = new Map<string, string>();
|
|
441
|
+
// And one reading of the environment each build directory is keyed on, which
|
|
442
|
+
// a plugin module root's state reports as it is.
|
|
443
|
+
const environmentDigests = new Map<string, string>();
|
|
444
|
+
// With the witness of each such reading, so a build of a directory package
|
|
445
|
+
// selection already read keys on that reading instead of probing Go again.
|
|
446
|
+
const environmentWitnesses = new Map<
|
|
447
|
+
string,
|
|
448
|
+
PluginBuildEnvironmentWitness.Record
|
|
449
|
+
>();
|
|
450
|
+
const readings = {
|
|
451
|
+
sources: sourceDigests,
|
|
452
|
+
environments: environmentDigests,
|
|
453
|
+
witnesses: environmentWitnesses,
|
|
454
|
+
};
|
|
455
|
+
// Records describing sources must never land inside one, so the store is
|
|
456
|
+
// admitted for source proofs only once every source of the load is known.
|
|
457
|
+
const sourceIdentities = PluginContentIdentities.outside(identities, [
|
|
458
|
+
...candidates.flatMap((candidate) => [
|
|
445
459
|
candidate.moduleRoot,
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
entries[index]!.config,
|
|
472
|
-
index,
|
|
473
|
-
{
|
|
474
|
-
env: effectiveEnv,
|
|
475
|
-
observation: proposals[index]!.observation,
|
|
476
|
-
},
|
|
460
|
+
candidate.packageDir,
|
|
461
|
+
...(candidate.contributors ?? []).map((input) => input.source),
|
|
462
|
+
]),
|
|
463
|
+
...SourcePluginWorkspace.findTtscOverlayDirs(),
|
|
464
|
+
]);
|
|
465
|
+
// One fixed-effective-environment load owns manifest syntax sharing from the
|
|
466
|
+
// first watch query through metadata and builds. Do not allocate this after
|
|
467
|
+
// watch projection: that silently repeats selected-Go work (#1712).
|
|
468
|
+
const packageReaders = new Map<string, SourcePluginWorkspace.GoModReader>();
|
|
469
|
+
const watchReplacements =
|
|
470
|
+
options.onWatchInputs === undefined
|
|
471
|
+
? undefined
|
|
472
|
+
: new Map<string, readonly string[]>();
|
|
473
|
+
if (options.onWatchInputs !== undefined) {
|
|
474
|
+
// The prospective context reads the admitted module layout and anchors its
|
|
475
|
+
// tool there before kind exists. Keep both possible final-root baselines:
|
|
476
|
+
// a linked package keeps packageDir, and an executable keeps moduleRoot.
|
|
477
|
+
const interests = new Set(
|
|
478
|
+
candidates
|
|
479
|
+
.flatMap((candidate) => [
|
|
480
|
+
candidate.moduleRoot,
|
|
481
|
+
candidate.packageDir,
|
|
482
|
+
...(candidate.contributors ?? []).map((input) => input.source),
|
|
483
|
+
])
|
|
484
|
+
.filter(reportsPluginSource),
|
|
477
485
|
);
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
486
|
+
// WARNING (#1728): hand the watch owner this load's store with the roots.
|
|
487
|
+
// It baselines each root before any build reads it; without the store it
|
|
488
|
+
// read every source the load proves from records a moment later.
|
|
489
|
+
// A worker owns the watch baseline now. Complete this handoff before Go
|
|
490
|
+
// metadata or source proof consumes the roots, preserving #1728 (#1758).
|
|
491
|
+
yield options.onWatchInputs([...interests].sort(), sourceIdentities);
|
|
492
|
+
const initialSize = interests.size;
|
|
493
|
+
for (const candidate of candidates) {
|
|
494
|
+
// Nested source-only proposals replace the outer root manifests. Do not
|
|
495
|
+
// activate their irrelevant module graph just to discover watch inputs.
|
|
496
|
+
if (candidate.stage === "transform" && candidate.entry !== ".")
|
|
497
|
+
continue;
|
|
498
|
+
for (const directory of pluginReplacementWatchDirectories(
|
|
499
|
+
candidate.moduleRoot,
|
|
500
|
+
effectiveEnv,
|
|
501
|
+
watchReplacements,
|
|
502
|
+
packageReaders,
|
|
503
|
+
sourceIdentities,
|
|
504
|
+
))
|
|
505
|
+
if (reportsPluginSource(directory)) interests.add(directory);
|
|
482
506
|
}
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
)
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
507
|
+
if (interests.size !== initialSize)
|
|
508
|
+
yield options.onWatchInputs([...interests].sort(), sourceIdentities);
|
|
509
|
+
}
|
|
510
|
+
const proposals = NativeSourcePackages.propose(
|
|
511
|
+
candidates.map((candidate) => ({
|
|
512
|
+
...candidate,
|
|
513
|
+
ownModule: candidate.stage !== "transform",
|
|
514
|
+
})),
|
|
515
|
+
effectiveEnv,
|
|
516
|
+
packageReaders,
|
|
517
|
+
sourceIdentities,
|
|
518
|
+
readings,
|
|
519
|
+
);
|
|
520
|
+
const records = candidates.map(
|
|
521
|
+
({ plugin, index, stage, contributors, source, packageDir }) => {
|
|
522
|
+
const { kind, moduleRoot } = resolveNativeSource(
|
|
523
|
+
source,
|
|
524
|
+
plugin,
|
|
525
|
+
entries[index]!.config,
|
|
526
|
+
index,
|
|
527
|
+
{
|
|
528
|
+
env: effectiveEnv,
|
|
529
|
+
observation: proposals[index]!.observation,
|
|
530
|
+
},
|
|
531
|
+
);
|
|
532
|
+
if (kind === "linked" && stage !== "transform") {
|
|
533
|
+
throw new Error(
|
|
534
|
+
`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`,
|
|
535
|
+
);
|
|
536
|
+
}
|
|
537
|
+
const linkedContributorName =
|
|
538
|
+
kind === "linked"
|
|
539
|
+
? `linked_${String(index).padStart(6, "0")}`
|
|
540
|
+
: undefined;
|
|
541
|
+
const hostInputs = validatePluginHostInputs(plugin, index);
|
|
542
|
+
const pluginHostInputHashes = validatePluginHostInputHashes(
|
|
543
|
+
plugin,
|
|
544
|
+
index,
|
|
513
545
|
hostInputs,
|
|
514
|
-
)
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
loadedEntries[index]!.hostInputs,
|
|
546
|
+
);
|
|
547
|
+
const pluginHostInputRealpaths = validatePluginHostInputRealpaths(
|
|
548
|
+
plugin,
|
|
549
|
+
index,
|
|
519
550
|
hostInputs,
|
|
520
|
-
)
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
+
);
|
|
552
|
+
return {
|
|
553
|
+
capabilities: plugin.capabilities,
|
|
554
|
+
contributors,
|
|
555
|
+
config: entries[index]!.config,
|
|
556
|
+
kind,
|
|
557
|
+
label: pluginLabel(plugin, entries[index]!.config, index),
|
|
558
|
+
linkedContributorName,
|
|
559
|
+
name: plugin.name,
|
|
560
|
+
reportsTypeScriptDiagnostics:
|
|
561
|
+
plugin.reportsTypeScriptDiagnostics === true,
|
|
562
|
+
request: loadedEntries[index]!.request,
|
|
563
|
+
hostInputHashes: mergePluginHostInputHashes(
|
|
564
|
+
loadedEntries[index]!.hostInputHashes,
|
|
565
|
+
pluginHostInputHashes,
|
|
566
|
+
loadedEntries[index]!.hostInputs,
|
|
567
|
+
hostInputs,
|
|
568
|
+
),
|
|
569
|
+
hostInputRealpaths: mergePluginHostInputHashes(
|
|
570
|
+
loadedEntries[index]!.hostInputRealpaths,
|
|
571
|
+
pluginHostInputRealpaths,
|
|
572
|
+
loadedEntries[index]!.hostInputs,
|
|
573
|
+
hostInputs,
|
|
574
|
+
),
|
|
575
|
+
hostInputs: [...loadedEntries[index]!.hostInputs, ...hostInputs],
|
|
576
|
+
moduleRoot,
|
|
577
|
+
packageDir,
|
|
578
|
+
source,
|
|
579
|
+
stage,
|
|
580
|
+
};
|
|
581
|
+
},
|
|
551
582
|
);
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
583
|
+
const executableCandidates = candidates.filter(
|
|
584
|
+
(candidate) =>
|
|
585
|
+
records[candidate.index]!.kind === "executable" &&
|
|
586
|
+
!proposals[candidate.index]!.ownModule,
|
|
587
|
+
);
|
|
588
|
+
const buildDirectories = pluginBuildDirectories(
|
|
589
|
+
records,
|
|
590
|
+
effectiveEnv,
|
|
591
|
+
watchReplacements,
|
|
592
|
+
packageReaders,
|
|
593
|
+
sourceIdentities,
|
|
594
|
+
);
|
|
595
|
+
// Admission can now narrow the provisional interests without restamping the
|
|
596
|
+
// retained package/module baselines. Final host errors still keep these roots.
|
|
597
|
+
yield options.onWatchInputs?.(buildDirectories, sourceIdentities);
|
|
598
|
+
const keyedDirectories = new Set(buildDirectories);
|
|
599
|
+
const linkedContributors = records
|
|
600
|
+
.filter((record) => record.stage === "transform")
|
|
601
|
+
.flatMap((record) =>
|
|
602
|
+
record.kind === "linked"
|
|
603
|
+
? [{ name: record.linkedContributorName!, source: record.source }]
|
|
604
|
+
: [],
|
|
605
|
+
);
|
|
606
|
+
const transformHosts = records.filter(
|
|
607
|
+
(record) => record.stage === "transform" && record.kind === "executable",
|
|
608
|
+
);
|
|
609
|
+
const hostContributors =
|
|
610
|
+
linkedContributors.length === 0 ? undefined : linkedContributors;
|
|
611
|
+
// Every host compiles the linked sources under its own module/tool context.
|
|
612
|
+
// Equivalent entries in one module share this metadata command and reader;
|
|
613
|
+
// a second executable host can select a genuinely different Go context.
|
|
614
|
+
const admittedExecutables = new Set<string>();
|
|
615
|
+
if (linkedContributors.length !== 0) {
|
|
616
|
+
const hosts =
|
|
617
|
+
transformHosts.length === 0
|
|
618
|
+
? [
|
|
619
|
+
{
|
|
620
|
+
source: path.join(ttscPackageRoot(), "cmd", "utility-host"),
|
|
621
|
+
label: "linked-plugin-host",
|
|
622
|
+
},
|
|
623
|
+
]
|
|
624
|
+
: transformHosts;
|
|
625
|
+
const contexts = new Map<
|
|
626
|
+
string,
|
|
627
|
+
{ source: string; label: string; records: typeof transformHosts }
|
|
628
|
+
>();
|
|
629
|
+
for (const host of hosts) {
|
|
630
|
+
const moduleRoot = resolvePluginGoModule(
|
|
631
|
+
host.source,
|
|
632
|
+
host.label,
|
|
633
|
+
).moduleRoot;
|
|
634
|
+
let context = contexts.get(moduleRoot);
|
|
635
|
+
if (context === undefined) {
|
|
636
|
+
context = { source: host.source, label: host.label, records: [] };
|
|
637
|
+
contexts.set(moduleRoot, context);
|
|
638
|
+
}
|
|
639
|
+
}
|
|
640
|
+
for (const record of transformHosts)
|
|
641
|
+
contexts.get(record.moduleRoot)!.records.push(record);
|
|
642
|
+
for (const host of contexts.values()) {
|
|
643
|
+
const moduleHosts = host.records;
|
|
644
|
+
const hostEntries = moduleHosts.map((record) => ({
|
|
645
|
+
entry: resolvePluginGoModule(record.source, record.label).entry,
|
|
646
|
+
}));
|
|
647
|
+
const observations = NativeSourcePackages.inspect({
|
|
648
|
+
source: host.source,
|
|
649
|
+
pluginName: host.label,
|
|
650
|
+
env: effectiveEnv,
|
|
651
|
+
readers: packageReaders,
|
|
652
|
+
identities: sourceIdentities,
|
|
653
|
+
readings,
|
|
654
|
+
packages: [
|
|
655
|
+
...hostEntries,
|
|
656
|
+
...linkedContributors.map((input) => ({
|
|
657
|
+
...input,
|
|
658
|
+
entry: `./contrib/${input.name}`,
|
|
659
|
+
})),
|
|
660
|
+
],
|
|
661
|
+
});
|
|
662
|
+
moduleHosts.forEach((record, index) => {
|
|
663
|
+
NativeSourcePackages.kind(
|
|
664
|
+
observations[index]!,
|
|
665
|
+
record.label,
|
|
666
|
+
"executable",
|
|
667
|
+
);
|
|
668
|
+
admittedExecutables.add(record.source);
|
|
669
|
+
});
|
|
670
|
+
linkedContributors.forEach((input, index) => {
|
|
671
|
+
NativeSourcePackages.kind(
|
|
672
|
+
observations[hostEntries.length + index]!,
|
|
673
|
+
`${input.name} inside host ${host.label}`,
|
|
674
|
+
"linked",
|
|
675
|
+
);
|
|
676
|
+
});
|
|
584
677
|
}
|
|
585
678
|
}
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
entry: resolvePluginGoModule(record.source, record.label).entry,
|
|
592
|
-
}));
|
|
593
|
-
const observations = NativeSourcePackages.inspect({
|
|
594
|
-
source: host.source,
|
|
595
|
-
pluginName: host.label,
|
|
596
|
-
env: effectiveEnv,
|
|
597
|
-
readers: packageReaders,
|
|
598
|
-
identities: sourceIdentities,
|
|
599
|
-
readings,
|
|
600
|
-
packages: [
|
|
601
|
-
...hostEntries,
|
|
602
|
-
...linkedContributors.map((input) => ({
|
|
603
|
-
...input,
|
|
604
|
-
entry: `./contrib/${input.name}`,
|
|
605
|
-
})),
|
|
606
|
-
],
|
|
607
|
-
});
|
|
608
|
-
moduleHosts.forEach((record, index) => {
|
|
609
|
-
NativeSourcePackages.kind(
|
|
610
|
-
observations[index]!,
|
|
611
|
-
record.label,
|
|
612
|
-
"executable",
|
|
613
|
-
);
|
|
614
|
-
admittedExecutables.add(record.source);
|
|
615
|
-
});
|
|
616
|
-
linkedContributors.forEach((input, index) => {
|
|
617
|
-
NativeSourcePackages.kind(
|
|
618
|
-
observations[hostEntries.length + index]!,
|
|
619
|
-
`${input.name} inside host ${host.label}`,
|
|
620
|
-
"linked",
|
|
621
|
-
);
|
|
622
|
-
});
|
|
623
|
-
}
|
|
624
|
-
}
|
|
625
|
-
// A nested main proposal still needs its actual owning manifests. Hosts
|
|
626
|
-
// with linked contributors were admitted together above; other equivalent
|
|
627
|
-
// entries share one standalone observation, with no repeated host copy.
|
|
628
|
-
const standaloneCandidates = executableCandidates.filter(
|
|
629
|
-
(candidate) => !admittedExecutables.has(candidate.source),
|
|
630
|
-
);
|
|
631
|
-
const executablePackages = NativeSourcePackages.ownPackages(
|
|
632
|
-
standaloneCandidates,
|
|
633
|
-
effectiveEnv,
|
|
634
|
-
packageReaders,
|
|
635
|
-
sourceIdentities,
|
|
636
|
-
readings,
|
|
637
|
-
);
|
|
638
|
-
standaloneCandidates.forEach((candidate, index) => {
|
|
639
|
-
NativeSourcePackages.kind(
|
|
640
|
-
executablePackages[index]!,
|
|
641
|
-
candidate.label,
|
|
642
|
-
"executable",
|
|
679
|
+
// A nested main proposal still needs its actual owning manifests. Hosts
|
|
680
|
+
// with linked contributors were admitted together above; other equivalent
|
|
681
|
+
// entries share one standalone observation, with no repeated host copy.
|
|
682
|
+
const standaloneCandidates = executableCandidates.filter(
|
|
683
|
+
(candidate) => !admittedExecutables.has(candidate.source),
|
|
643
684
|
);
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
...(linked
|
|
651
|
-
? linkedContributors.map((input) => ({
|
|
652
|
-
entry: `./contrib/${input.name}`,
|
|
653
|
-
kind: "linked" as const,
|
|
654
|
-
}))
|
|
655
|
-
: []),
|
|
656
|
-
];
|
|
657
|
-
const builtTransformHosts = new Map<object, string>();
|
|
658
|
-
for (const record of transformHosts) {
|
|
659
|
-
builtTransformHosts.set(
|
|
660
|
-
record,
|
|
661
|
-
buildSourcePlugin({
|
|
662
|
-
baseDir: context.projectRoot,
|
|
663
|
-
cacheDir: options.cacheDir,
|
|
664
|
-
contributors: mergeContributors(record.contributors, hostContributors),
|
|
665
|
-
env: effectiveEnv,
|
|
666
|
-
goModReaders: packageReaders,
|
|
667
|
-
identities: sourceIdentities,
|
|
668
|
-
pluginName: record.label,
|
|
669
|
-
packageOwnership: packageOwnership(record.source, record.label, true),
|
|
670
|
-
source: record.source,
|
|
671
|
-
environmentDigests,
|
|
672
|
-
environmentWitnesses,
|
|
673
|
-
sourceDigests,
|
|
674
|
-
ttscVersion,
|
|
675
|
-
tsgoVersion,
|
|
676
|
-
}),
|
|
685
|
+
const executablePackages = NativeSourcePackages.ownPackages(
|
|
686
|
+
standaloneCandidates,
|
|
687
|
+
effectiveEnv,
|
|
688
|
+
packageReaders,
|
|
689
|
+
sourceIdentities,
|
|
690
|
+
readings,
|
|
677
691
|
);
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
692
|
+
standaloneCandidates.forEach((candidate, index) => {
|
|
693
|
+
NativeSourcePackages.kind(
|
|
694
|
+
executablePackages[index]!,
|
|
695
|
+
candidate.label,
|
|
696
|
+
"executable",
|
|
697
|
+
);
|
|
698
|
+
});
|
|
699
|
+
const packageOwnership = (
|
|
700
|
+
source: string,
|
|
701
|
+
label: string,
|
|
702
|
+
linked: boolean,
|
|
703
|
+
) => [
|
|
704
|
+
{
|
|
705
|
+
entry: resolvePluginGoModule(source, label).entry,
|
|
706
|
+
kind: "executable" as const,
|
|
707
|
+
},
|
|
708
|
+
...(linked
|
|
709
|
+
? linkedContributors.map((input) => ({
|
|
710
|
+
entry: `./contrib/${input.name}`,
|
|
711
|
+
kind: "linked" as const,
|
|
712
|
+
}))
|
|
713
|
+
: []),
|
|
714
|
+
];
|
|
715
|
+
const builtTransformHosts = new Map<object, string>();
|
|
716
|
+
for (const record of transformHosts) {
|
|
717
|
+
builtTransformHosts.set(
|
|
718
|
+
record,
|
|
719
|
+
buildSourcePlugin({
|
|
682
720
|
baseDir: context.projectRoot,
|
|
683
721
|
cacheDir: options.cacheDir,
|
|
684
|
-
contributors:
|
|
722
|
+
contributors: mergeContributors(
|
|
723
|
+
record.contributors,
|
|
724
|
+
hostContributors,
|
|
725
|
+
),
|
|
685
726
|
env: effectiveEnv,
|
|
686
727
|
goModReaders: packageReaders,
|
|
687
728
|
identities: sourceIdentities,
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
source:
|
|
691
|
-
packageOwnership: packageOwnership(
|
|
692
|
-
path.join(ttscPackageRoot(), "cmd", "utility-host"),
|
|
693
|
-
"linked-plugin-host",
|
|
694
|
-
true,
|
|
695
|
-
),
|
|
729
|
+
pluginName: record.label,
|
|
730
|
+
packageOwnership: packageOwnership(record.source, record.label, true),
|
|
731
|
+
source: record.source,
|
|
696
732
|
environmentDigests,
|
|
697
733
|
environmentWitnesses,
|
|
698
734
|
sourceDigests,
|
|
699
735
|
ttscVersion,
|
|
700
736
|
tsgoVersion,
|
|
701
|
-
})
|
|
702
|
-
: undefined;
|
|
703
|
-
const selectedTransformHost =
|
|
704
|
-
transformHosts.length === 0
|
|
705
|
-
? fallbackDriverHost
|
|
706
|
-
: builtTransformHosts.get(transformHosts[0]!);
|
|
707
|
-
const nativePlugins: ITtscLoadedNativePlugin[] = records.map((record) => {
|
|
708
|
-
const binary =
|
|
709
|
-
record.stage === "transform" && record.kind === "linked"
|
|
710
|
-
? selectedTransformHost
|
|
711
|
-
: record.stage === "transform"
|
|
712
|
-
? builtTransformHosts.get(record)
|
|
713
|
-
: buildSourcePlugin({
|
|
714
|
-
baseDir: context.projectRoot,
|
|
715
|
-
cacheDir: options.cacheDir,
|
|
716
|
-
contributors: record.contributors,
|
|
717
|
-
env: effectiveEnv,
|
|
718
|
-
goModReaders: packageReaders,
|
|
719
|
-
identities: sourceIdentities,
|
|
720
|
-
pluginName: record.label,
|
|
721
|
-
packageOwnership: packageOwnership(
|
|
722
|
-
record.source,
|
|
723
|
-
record.label,
|
|
724
|
-
false,
|
|
725
|
-
),
|
|
726
|
-
source: record.source,
|
|
727
|
-
environmentDigests,
|
|
728
|
-
environmentWitnesses,
|
|
729
|
-
sourceDigests,
|
|
730
|
-
ttscVersion,
|
|
731
|
-
tsgoVersion,
|
|
732
|
-
});
|
|
733
|
-
if (binary === undefined) {
|
|
734
|
-
throw new Error(
|
|
735
|
-
`ttsc: plugin "${record.label}" is a linked Go package, but no compiler host is available`,
|
|
737
|
+
}),
|
|
736
738
|
);
|
|
737
739
|
}
|
|
740
|
+
const fallbackDriverHost =
|
|
741
|
+
transformHosts.length === 0 && linkedContributors.length !== 0
|
|
742
|
+
? buildSourcePlugin({
|
|
743
|
+
baseDir: context.projectRoot,
|
|
744
|
+
cacheDir: options.cacheDir,
|
|
745
|
+
contributors: linkedContributors,
|
|
746
|
+
env: effectiveEnv,
|
|
747
|
+
goModReaders: packageReaders,
|
|
748
|
+
identities: sourceIdentities,
|
|
749
|
+
label: "linked plugin host",
|
|
750
|
+
pluginName: "linked-plugin-host",
|
|
751
|
+
source: path.join(ttscPackageRoot(), "cmd", "utility-host"),
|
|
752
|
+
packageOwnership: packageOwnership(
|
|
753
|
+
path.join(ttscPackageRoot(), "cmd", "utility-host"),
|
|
754
|
+
"linked-plugin-host",
|
|
755
|
+
true,
|
|
756
|
+
),
|
|
757
|
+
environmentDigests,
|
|
758
|
+
environmentWitnesses,
|
|
759
|
+
sourceDigests,
|
|
760
|
+
ttscVersion,
|
|
761
|
+
tsgoVersion,
|
|
762
|
+
})
|
|
763
|
+
: undefined;
|
|
764
|
+
const selectedTransformHost =
|
|
765
|
+
transformHosts.length === 0
|
|
766
|
+
? fallbackDriverHost
|
|
767
|
+
: builtTransformHosts.get(transformHosts[0]!);
|
|
768
|
+
const nativePlugins: ITtscLoadedNativePlugin[] = records.map((record) => {
|
|
769
|
+
const binary =
|
|
770
|
+
record.stage === "transform" && record.kind === "linked"
|
|
771
|
+
? selectedTransformHost
|
|
772
|
+
: record.stage === "transform"
|
|
773
|
+
? builtTransformHosts.get(record)
|
|
774
|
+
: buildSourcePlugin({
|
|
775
|
+
baseDir: context.projectRoot,
|
|
776
|
+
cacheDir: options.cacheDir,
|
|
777
|
+
contributors: record.contributors,
|
|
778
|
+
env: effectiveEnv,
|
|
779
|
+
goModReaders: packageReaders,
|
|
780
|
+
identities: sourceIdentities,
|
|
781
|
+
pluginName: record.label,
|
|
782
|
+
packageOwnership: packageOwnership(
|
|
783
|
+
record.source,
|
|
784
|
+
record.label,
|
|
785
|
+
false,
|
|
786
|
+
),
|
|
787
|
+
source: record.source,
|
|
788
|
+
environmentDigests,
|
|
789
|
+
environmentWitnesses,
|
|
790
|
+
sourceDigests,
|
|
791
|
+
ttscVersion,
|
|
792
|
+
tsgoVersion,
|
|
793
|
+
});
|
|
794
|
+
if (binary === undefined) {
|
|
795
|
+
throw new Error(
|
|
796
|
+
`ttsc: plugin "${record.label}" is a linked Go package, but no compiler host is available`,
|
|
797
|
+
);
|
|
798
|
+
}
|
|
799
|
+
return {
|
|
800
|
+
binary,
|
|
801
|
+
// This fallback is compiled from our utility-host, whose actual writer
|
|
802
|
+
// publishes provenance and supports a separate compiler argument cwd.
|
|
803
|
+
// A separately selected executable host must opt in itself; a linked
|
|
804
|
+
// library cannot certify that foreign host. An undeclared capability
|
|
805
|
+
// only withholds the optional protocol: build execution still runs such
|
|
806
|
+
// a host and observes it from outside, never rejecting it.
|
|
807
|
+
capabilities:
|
|
808
|
+
record.stage === "transform" &&
|
|
809
|
+
record.kind === "linked" &&
|
|
810
|
+
fallbackDriverHost !== undefined
|
|
811
|
+
? {
|
|
812
|
+
...record.capabilities,
|
|
813
|
+
compilerArgsCwd: true,
|
|
814
|
+
emitProvenance: true,
|
|
815
|
+
}
|
|
816
|
+
: record.capabilities,
|
|
817
|
+
config: record.config,
|
|
818
|
+
contributors: record.contributors,
|
|
819
|
+
kind: record.kind,
|
|
820
|
+
name: record.name,
|
|
821
|
+
reportsTypeScriptDiagnostics: record.reportsTypeScriptDiagnostics,
|
|
822
|
+
source: record.source,
|
|
823
|
+
stage: record.stage,
|
|
824
|
+
};
|
|
825
|
+
});
|
|
738
826
|
return {
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
// library cannot certify that foreign host. An undeclared capability
|
|
744
|
-
// only withholds the optional protocol: build execution still runs such
|
|
745
|
-
// a host and observes it from outside, never rejecting it.
|
|
746
|
-
capabilities:
|
|
747
|
-
record.stage === "transform" &&
|
|
748
|
-
record.kind === "linked" &&
|
|
749
|
-
fallbackDriverHost !== undefined
|
|
750
|
-
? {
|
|
751
|
-
...record.capabilities,
|
|
752
|
-
compilerArgsCwd: true,
|
|
753
|
-
emitProvenance: true,
|
|
754
|
-
}
|
|
755
|
-
: record.capabilities,
|
|
756
|
-
config: record.config,
|
|
757
|
-
contributors: record.contributors,
|
|
758
|
-
kind: record.kind,
|
|
759
|
-
name: record.name,
|
|
760
|
-
reportsTypeScriptDiagnostics: record.reportsTypeScriptDiagnostics,
|
|
761
|
-
source: record.source,
|
|
762
|
-
stage: record.stage,
|
|
763
|
-
};
|
|
764
|
-
});
|
|
765
|
-
return {
|
|
766
|
-
...collectHostInputSnapshot(
|
|
767
|
-
project,
|
|
768
|
-
context,
|
|
769
|
-
records,
|
|
770
|
-
projectHostInputs,
|
|
771
|
-
revalidateHostInputHashes(projectHostInputHashes, projectHostInputs),
|
|
772
|
-
revalidateHostInputRealpaths(
|
|
773
|
-
projectHostInputRealpaths,
|
|
827
|
+
...collectHostInputSnapshot(
|
|
828
|
+
project,
|
|
829
|
+
context,
|
|
830
|
+
records,
|
|
774
831
|
projectHostInputs,
|
|
832
|
+
revalidateHostInputHashes(projectHostInputHashes, projectHostInputs),
|
|
833
|
+
revalidateHostInputRealpaths(
|
|
834
|
+
projectHostInputRealpaths,
|
|
835
|
+
projectHostInputs,
|
|
836
|
+
),
|
|
775
837
|
),
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
}
|
|
838
|
+
descriptorReadsDeclared: loadedEntries.every(
|
|
839
|
+
(entry) =>
|
|
840
|
+
entry.observationsComplete && declaresHostInputReads(entry.plugin),
|
|
841
|
+
),
|
|
842
|
+
discoveryInputsComplete: project.configInputsComplete === true,
|
|
843
|
+
...(identities === undefined ? {} : { identities }),
|
|
844
|
+
nativePlugins: orderNativePlugins(nativePlugins),
|
|
845
|
+
...(loadedEntries.some((entry) => !entry.observationsComplete)
|
|
846
|
+
? { observationsComplete: false as const }
|
|
847
|
+
: {}),
|
|
848
|
+
// The directories the watch inputs named before the builds, as the builds
|
|
849
|
+
// read them. Package selection shares these readings and also reads a
|
|
850
|
+
// linked plugin's module root, which no build keys on, so only the build
|
|
851
|
+
// directories are reported.
|
|
852
|
+
pluginSources: Object.fromEntries(
|
|
853
|
+
[...sourceDigests]
|
|
854
|
+
.filter(([directory]) => keyedDirectories.has(directory))
|
|
855
|
+
.sort(([left], [right]) => (left < right ? -1 : left > right ? 1 : 0))
|
|
856
|
+
.map(([directory, sourceDigest]) => [
|
|
857
|
+
directory,
|
|
858
|
+
pluginSourceState(directory, {
|
|
859
|
+
env: effectiveEnv,
|
|
860
|
+
sourceDigest,
|
|
861
|
+
environment:
|
|
862
|
+
environmentDigests.get(directory) ??
|
|
863
|
+
pluginBuildEnvironment(
|
|
864
|
+
directory,
|
|
865
|
+
effectiveEnv,
|
|
866
|
+
undefined,
|
|
867
|
+
sourceIdentities,
|
|
868
|
+
),
|
|
869
|
+
}),
|
|
870
|
+
]),
|
|
871
|
+
),
|
|
872
|
+
project,
|
|
873
|
+
};
|
|
874
|
+
}
|
|
813
875
|
}
|
|
814
876
|
|
|
815
877
|
type ProjectHostInputSnapshot = {
|
|
@@ -948,12 +1010,18 @@ function readProjectHostInputSnapshot(options: {
|
|
|
948
1010
|
cwd?: string;
|
|
949
1011
|
file?: string;
|
|
950
1012
|
includePluginDiscovery: boolean;
|
|
1013
|
+
pluginConfigDir?: string;
|
|
951
1014
|
projectRoot?: string;
|
|
952
1015
|
tsconfig?: string;
|
|
953
1016
|
}): ProjectHostInputSnapshot {
|
|
954
|
-
const { includePluginDiscovery, ...projectOptions } =
|
|
1017
|
+
const { includePluginDiscovery, pluginConfigDir, ...projectOptions } =
|
|
1018
|
+
options;
|
|
955
1019
|
let project = readProjectConfig(projectOptions);
|
|
956
|
-
let hostInputs = collectProjectHostInputs(
|
|
1020
|
+
let hostInputs = collectProjectHostInputs(
|
|
1021
|
+
project,
|
|
1022
|
+
includePluginDiscovery,
|
|
1023
|
+
pluginConfigDir,
|
|
1024
|
+
);
|
|
957
1025
|
const observedInputs = new Set(hostInputs);
|
|
958
1026
|
for (let attempt = 0; attempt < 3; attempt++) {
|
|
959
1027
|
const before = hashHostInputPaths(hostInputs);
|
|
@@ -963,6 +1031,7 @@ function readProjectHostInputSnapshot(options: {
|
|
|
963
1031
|
const candidateInputs = collectProjectHostInputs(
|
|
964
1032
|
candidateProject,
|
|
965
1033
|
includePluginDiscovery,
|
|
1034
|
+
pluginConfigDir,
|
|
966
1035
|
);
|
|
967
1036
|
for (const input of candidateInputs) observedInputs.add(input);
|
|
968
1037
|
const after = hashHostInputPaths(candidateInputs);
|
|
@@ -1384,7 +1453,7 @@ function loadPluginDescriptor(
|
|
|
1384
1453
|
request,
|
|
1385
1454
|
context,
|
|
1386
1455
|
effectiveEnv,
|
|
1387
|
-
descriptorCache
|
|
1456
|
+
descriptorCache,
|
|
1388
1457
|
);
|
|
1389
1458
|
if (loaded === undefined) {
|
|
1390
1459
|
throw error;
|
|
@@ -1401,6 +1470,9 @@ interface DescriptorCacheOptions {
|
|
|
1401
1470
|
/** Record store that proves the evaluating runtimes from metadata (#1723). */
|
|
1402
1471
|
identities: PluginContentIdentities.Store | undefined;
|
|
1403
1472
|
|
|
1473
|
+
/** Source-project cache anchor, independent of descriptor consumer context. */
|
|
1474
|
+
projectRoot: string;
|
|
1475
|
+
|
|
1404
1476
|
/** This ttsc build's version. */
|
|
1405
1477
|
version: string;
|
|
1406
1478
|
}
|
|
@@ -1453,7 +1525,7 @@ function loadCommonJsDescriptor(
|
|
|
1453
1525
|
const runtimeCapabilities = javascriptRuntimeCapabilities(
|
|
1454
1526
|
runtime,
|
|
1455
1527
|
effectiveEnv,
|
|
1456
|
-
|
|
1528
|
+
descriptorCache.projectRoot,
|
|
1457
1529
|
descriptorCache.identities,
|
|
1458
1530
|
);
|
|
1459
1531
|
const node =
|
|
@@ -1463,7 +1535,7 @@ function loadCommonJsDescriptor(
|
|
|
1463
1535
|
? runtimeCapabilities.executable
|
|
1464
1536
|
: resolveNodeBinary(
|
|
1465
1537
|
effectiveEnv,
|
|
1466
|
-
|
|
1538
|
+
descriptorCache.projectRoot,
|
|
1467
1539
|
descriptorCache.identities,
|
|
1468
1540
|
);
|
|
1469
1541
|
const cacheAuthority = {
|
|
@@ -1471,6 +1543,8 @@ function loadCommonJsDescriptor(
|
|
|
1471
1543
|
cacheDir: descriptorCache.cacheDir,
|
|
1472
1544
|
identities: descriptorCache.identities,
|
|
1473
1545
|
context,
|
|
1546
|
+
// Factory context anchors the consumer; the evaluator runs at the source root.
|
|
1547
|
+
cwd: descriptorCache.projectRoot,
|
|
1474
1548
|
// Everything the child receives besides the per-evaluation output paths.
|
|
1475
1549
|
env: {
|
|
1476
1550
|
...effectiveEnv,
|
|
@@ -1478,7 +1552,7 @@ function loadCommonJsDescriptor(
|
|
|
1478
1552
|
...descriptorRecordRoot(descriptorCache.identities),
|
|
1479
1553
|
TTSC_TTSX_BINARY: ttsx,
|
|
1480
1554
|
},
|
|
1481
|
-
projectRoot:
|
|
1555
|
+
projectRoot: descriptorCache.projectRoot,
|
|
1482
1556
|
request,
|
|
1483
1557
|
runtime,
|
|
1484
1558
|
version: descriptorCache.version,
|
|
@@ -1559,7 +1633,7 @@ function loadCommonJsDescriptor(
|
|
|
1559
1633
|
shim,
|
|
1560
1634
|
],
|
|
1561
1635
|
{
|
|
1562
|
-
cwd:
|
|
1636
|
+
cwd: descriptorCache.projectRoot,
|
|
1563
1637
|
env: {
|
|
1564
1638
|
...effectiveEnv,
|
|
1565
1639
|
// The direct evaluator may be Bun, but ttsx and native config
|
|
@@ -1950,12 +2024,16 @@ function loadDescriptorViaTtsx(
|
|
|
1950
2024
|
request: string,
|
|
1951
2025
|
context: ITtscPluginFactoryContext,
|
|
1952
2026
|
effectiveEnv: NodeJS.ProcessEnv,
|
|
1953
|
-
|
|
2027
|
+
descriptorCache: DescriptorCacheOptions,
|
|
1954
2028
|
): IsolatedPluginDescriptor | undefined {
|
|
1955
2029
|
// Binary discovery prefers the instance environment, then the ambient
|
|
1956
2030
|
// process.env (where `withPluginLoaderEnv` injects ttsc's own node/ttsx paths
|
|
1957
2031
|
// just before this runs), then the running interpreter.
|
|
1958
|
-
const node = resolveNodeBinary(
|
|
2032
|
+
const node = resolveNodeBinary(
|
|
2033
|
+
effectiveEnv,
|
|
2034
|
+
descriptorCache.projectRoot,
|
|
2035
|
+
descriptorCache.identities,
|
|
2036
|
+
);
|
|
1959
2037
|
const ttsx = effectiveEnv.TTSC_TTSX_BINARY ?? process.env.TTSC_TTSX_BINARY;
|
|
1960
2038
|
if (node === undefined || ttsx === undefined || ttsx.length === 0) {
|
|
1961
2039
|
return undefined;
|
|
@@ -1982,11 +2060,11 @@ function loadDescriptorViaTtsx(
|
|
|
1982
2060
|
const trace = E2ETrace.begin(
|
|
1983
2061
|
node,
|
|
1984
2062
|
[ttsx, "--no-plugins", shim],
|
|
1985
|
-
{ cwd:
|
|
2063
|
+
{ cwd: descriptorCache.projectRoot },
|
|
1986
2064
|
"plugin-descriptor",
|
|
1987
2065
|
);
|
|
1988
2066
|
const result = spawnOwnedDescriptor(node, [ttsx, "--no-plugins", shim], {
|
|
1989
|
-
cwd:
|
|
2067
|
+
cwd: descriptorCache.projectRoot,
|
|
1990
2068
|
encoding: "utf8",
|
|
1991
2069
|
env: {
|
|
1992
2070
|
...effectiveEnv,
|
|
@@ -1994,7 +2072,7 @@ function loadDescriptorViaTtsx(
|
|
|
1994
2072
|
// may recurse into further descriptor loads) finds them even when the
|
|
1995
2073
|
// instance-env snapshot predates `withPluginLoaderEnv`.
|
|
1996
2074
|
TTSC_NODE_BINARY: node,
|
|
1997
|
-
...descriptorRecordRoot(identities),
|
|
2075
|
+
...descriptorRecordRoot(descriptorCache.identities),
|
|
1998
2076
|
TTSC_TTSX_BINARY: ttsx,
|
|
1999
2077
|
TTSC_PLUGIN_CONTEXT: JSON.stringify({
|
|
2000
2078
|
binary: context.binary,
|