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
|
@@ -39,6 +39,7 @@ import { PassthroughFlags } from "./PassthroughFlags";
|
|
|
39
39
|
import { PluginFailureDiagnostics } from "./PluginFailureDiagnostics";
|
|
40
40
|
import type { RunBuildOptions } from "./RunBuildOptions";
|
|
41
41
|
import { TsgoArguments } from "./TsgoArguments";
|
|
42
|
+
import { WatchInputPublication } from "./WatchInputPublication";
|
|
42
43
|
import { appendBuildOutput } from "./appendBuildOutput";
|
|
43
44
|
import { isAbsoluteLocalProjectInputPath } from "./isAbsoluteLocalProjectInputPath";
|
|
44
45
|
import { mergeProjectInputSnapshots } from "./mergeProjectInputSnapshots";
|
|
@@ -260,6 +261,52 @@ export namespace BuildExecution {
|
|
|
260
261
|
execution: ReturnType<typeof resolveExecutionContext>,
|
|
261
262
|
setupStartedAt: bigint,
|
|
262
263
|
): { buildOptions: RunBuildOptions; result?: TtscBuildResult } {
|
|
264
|
+
return WatchInputPublication.run(
|
|
265
|
+
prepareBuildExecutionSteps(options, timing, execution, setupStartedAt),
|
|
266
|
+
);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
/**
|
|
270
|
+
* Await project-input publication before handing a prepared build to its
|
|
271
|
+
* compiler or resident check owner. Publication rejection propagates.
|
|
272
|
+
*
|
|
273
|
+
* @evidence contracts/common.md#principled-implementation The asynchronous runner joins the same preparation sequence's project-input handoff before its result becomes available.
|
|
274
|
+
* @evidence contracts/common.md#clear-and-simple-design The companion changes completion mode while keeping diagnostic recovery, emit policy and discovery in one sequence.
|
|
275
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts An unsettled or rejected publication cannot become successful preparation.
|
|
276
|
+
* @evidence contracts/common.md#meaningful-documentation Native prose identifies the publication barrier and propagated failure.
|
|
277
|
+
* @evidence contracts/portability.md#os-neutral-implementation Native discovery and selected paths remain with the shared preparation sequence.
|
|
278
|
+
* @evidence contracts/performance.md#efficient-algorithms One runner advances the preparation handoff once, retaining the shared discovery and diagnostic work costs.
|
|
279
|
+
* @evidence contracts/performance.md#reuse-equivalent-work The supplied resolved context remains authoritative throughout preparation and its awaited handoff.
|
|
280
|
+
* @evidence contracts/performance.md#bound-retention-and-release-resources The current preparation state survives only until the callback settles or fails; resident handles belong to the caller.
|
|
281
|
+
*/
|
|
282
|
+
export function prepareBuildExecutionAsync(
|
|
283
|
+
...args: Parameters<typeof prepareBuildExecution>
|
|
284
|
+
): Promise<ReturnType<typeof prepareBuildExecution>> {
|
|
285
|
+
return WatchInputPublication.runAsync(prepareBuildExecutionSteps(...args));
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* Prepare one selected execution, yielding its discovered project topology
|
|
290
|
+
* before the caller may begin compilation.
|
|
291
|
+
*
|
|
292
|
+
* @evidence contracts/common.md#principled-implementation Setup failures retain their existing recovery policy; successful discovery suspends at the owning watch handoff before returning build options.
|
|
293
|
+
* @evidence contracts/common.md#clear-and-simple-design One preparation sequence serves synchronous, asynchronous and composed build entries.
|
|
294
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts The sequence publishes actual native discovery and preserves failure results instead of fabricating completed registration.
|
|
295
|
+
* @evidence contracts/common.md#meaningful-documentation Native prose states selection ownership and the barrier before compilation.
|
|
296
|
+
* @evidence contracts/portability.md#os-neutral-implementation Project-input discovery delegates native processes and path reconciliation to their existing boundaries.
|
|
297
|
+
* @evidence contracts/performance.md#efficient-algorithms Preparation retains one timing update, option projection and optional native discovery; callback completion adds one suspension rather than repeated discovery.
|
|
298
|
+
* @evidence contracts/performance.md#reuse-equivalent-work The resolved context and setup result are passed to the next phase without another plugin load.
|
|
299
|
+
* @evidence contracts/performance.md#bound-retention-and-release-resources Build-local options and discovered snapshot remain live during publication; the sequence acquires no resident handle.
|
|
300
|
+
*/
|
|
301
|
+
export function* prepareBuildExecutionSteps(
|
|
302
|
+
options: RunBuildOptions,
|
|
303
|
+
timing: BuildTiming.BuildTiming,
|
|
304
|
+
execution: ReturnType<typeof resolveExecutionContext>,
|
|
305
|
+
setupStartedAt: bigint,
|
|
306
|
+
): WatchInputPublication.Sequence<{
|
|
307
|
+
buildOptions: RunBuildOptions;
|
|
308
|
+
result?: TtscBuildResult;
|
|
309
|
+
}> {
|
|
263
310
|
if (
|
|
264
311
|
execution.nativePlugins.length > 0 ||
|
|
265
312
|
execution.pluginSetupFailure !== undefined
|
|
@@ -282,7 +329,9 @@ export namespace BuildExecution {
|
|
|
282
329
|
};
|
|
283
330
|
}
|
|
284
331
|
if (options.onProjectInputs !== undefined) {
|
|
285
|
-
options.onProjectInputs(
|
|
332
|
+
yield options.onProjectInputs(
|
|
333
|
+
discoverNativeProjectInputs(options, execution),
|
|
334
|
+
);
|
|
286
335
|
}
|
|
287
336
|
return { buildOptions };
|
|
288
337
|
}
|
|
@@ -506,7 +555,11 @@ export namespace BuildExecution {
|
|
|
506
555
|
// beside the point for a flag whose meaning does not presuppose a project.
|
|
507
556
|
// Forward it to tsgo from the invocation directory instead of failing.
|
|
508
557
|
}
|
|
509
|
-
const tsgo = resolveTsgo({
|
|
558
|
+
const tsgo = resolveTsgo({
|
|
559
|
+
...options,
|
|
560
|
+
cwd,
|
|
561
|
+
env: compilerEnv(options.env),
|
|
562
|
+
});
|
|
510
563
|
const res = spawnNative(tsgo.binary, [...(options.passthrough ?? [])], {
|
|
511
564
|
cwd,
|
|
512
565
|
env: compilerEnv(options.env),
|
|
@@ -1212,7 +1265,8 @@ export namespace BuildExecution {
|
|
|
1212
1265
|
* Plugin admission, loading and watch-input callbacks inside the guarded
|
|
1213
1266
|
* acquisition branch become setup-failure results on error. Initial project/
|
|
1214
1267
|
* compiler resolution and final config-anchor resolution outside it may
|
|
1215
|
-
* throw.
|
|
1268
|
+
* throw. A synchronous call requires synchronous watch-input handlers; use
|
|
1269
|
+
* resolveExecutionContextAsync when registration returns a promise.
|
|
1216
1270
|
*
|
|
1217
1271
|
* @evidence contracts/common.md#principled-implementation One selected project supplies root, config and compiler policy; explicit resolvedProject preserves prior selection, and the guarded plugin admission/loading/watch-input callback branch is converted to a setup failure.
|
|
1218
1272
|
* @evidence contracts/common.md#clear-and-simple-design A single context carries compiler/project/plugin selection to all phases, with plugin acquisition isolated from project and executable resolution.
|
|
@@ -1231,13 +1285,64 @@ export namespace BuildExecution {
|
|
|
1231
1285
|
resolvedProject?: ITtscParsedProjectConfig;
|
|
1232
1286
|
tsconfig?: string;
|
|
1233
1287
|
},
|
|
1288
|
+
) {
|
|
1289
|
+
return WatchInputPublication.run(resolveExecutionContextSteps(options));
|
|
1290
|
+
}
|
|
1291
|
+
|
|
1292
|
+
/**
|
|
1293
|
+
* Resolve the selected execution after its plugin watch owner completes every
|
|
1294
|
+
* source-baseline handoff. Rejection keeps the setup-failure policy.
|
|
1295
|
+
*
|
|
1296
|
+
* @evidence contracts/common.md#principled-implementation Awaited stepping shares project/compiler selection and the guarded acquisition branch while retaining each pre-read publication barrier.
|
|
1297
|
+
* @evidence contracts/common.md#clear-and-simple-design The companion delegates to the same resolution sequence as the synchronous entry.
|
|
1298
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts Plugin or watch publication failure remains an explicit setup failure rather than successful empty selection.
|
|
1299
|
+
* @evidence contracts/common.md#meaningful-documentation Native prose distinguishes awaited source baselines and the existing returned setup-failure boundary.
|
|
1300
|
+
* @evidence contracts/portability.md#os-neutral-implementation Selected native paths, compiler executable and effective environment retain the resolution sequence's platform boundaries.
|
|
1301
|
+
* @evidence contracts/performance.md#efficient-algorithms Each publication is advanced once without repeating project resolution, plugin selection or source builds.
|
|
1302
|
+
* @evidence contracts/performance.md#reuse-equivalent-work One returned selected context serves all following phases; loader records retain their own validity conditions.
|
|
1303
|
+
* @evidence contracts/performance.md#bound-retention-and-release-resources The current selection and loader generation remain retained until a handoff settles; resident children remain separately owned.
|
|
1304
|
+
*/
|
|
1305
|
+
export function resolveExecutionContextAsync(
|
|
1306
|
+
options: Parameters<typeof resolveExecutionContext>[0],
|
|
1307
|
+
): Promise<ReturnType<typeof resolveExecutionContext>> {
|
|
1308
|
+
return WatchInputPublication.runAsync(
|
|
1309
|
+
resolveExecutionContextSteps(options),
|
|
1310
|
+
);
|
|
1311
|
+
}
|
|
1312
|
+
|
|
1313
|
+
/**
|
|
1314
|
+
* Select one execution and suspend its plugin producer at watch handoffs. The
|
|
1315
|
+
* no-plugin path also publishes its empty selection before returning.
|
|
1316
|
+
*
|
|
1317
|
+
* @evidence contracts/common.md#principled-implementation The existing guarded acquisition sequence yields the loader's pre-read barriers and converts thrown handoff failures into the same setup-failure result as loading errors.
|
|
1318
|
+
* @evidence contracts/common.md#clear-and-simple-design Selection and final context assembly remain in one sequence for both completion modes.
|
|
1319
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts Empty plugin selection is published explicitly; rejected acquisition never becomes successful empty admission.
|
|
1320
|
+
* @evidence contracts/common.md#meaningful-documentation Native prose states suspension and empty-selection behavior; the synchronous entry documents context and error ownership.
|
|
1321
|
+
* @evidence contracts/portability.md#os-neutral-implementation Native resolution, effective environment identity and config-anchor selection use their existing owners without changing path spellings.
|
|
1322
|
+
* @evidence contracts/performance.md#efficient-algorithms Initial project/compiler selection precedes optional plugin loading once; suspension does not add another discovery or source scan.
|
|
1323
|
+
* @evidence contracts/performance.md#reuse-equivalent-work The resolved project, opened record store and acquired plugin list stay in the same invocation across publication.
|
|
1324
|
+
* @evidence contracts/performance.md#bound-retention-and-release-resources Selection metadata is build-owned and loader caches keep their existing ownership; a suspended handoff retains only the current acquisition generation here.
|
|
1325
|
+
*/
|
|
1326
|
+
export function* resolveExecutionContextSteps(
|
|
1327
|
+
options: TtscCommonOptions & {
|
|
1328
|
+
emit?: boolean;
|
|
1329
|
+
onWatchInputs?: TtscPluginSourceInputsHandler;
|
|
1330
|
+
resolvedProject?: ITtscParsedProjectConfig;
|
|
1331
|
+
tsconfig?: string;
|
|
1332
|
+
},
|
|
1234
1333
|
) {
|
|
1235
1334
|
const cwd = path.resolve(options.cwd ?? process.cwd());
|
|
1236
1335
|
const compilerSelection = CompilerProjectSelection.read(options);
|
|
1237
1336
|
const project = compilerSelection.project;
|
|
1238
1337
|
const tsconfig = project.path;
|
|
1239
1338
|
const projectRoot = project.root;
|
|
1240
|
-
const tsgo = resolveTsgo({
|
|
1339
|
+
const tsgo = resolveTsgo({
|
|
1340
|
+
...options,
|
|
1341
|
+
cwd: projectRoot,
|
|
1342
|
+
// Public options carry overrides; resolver env is a complete snapshot.
|
|
1343
|
+
// Keep the original overrides for per-invocation channel ownership.
|
|
1344
|
+
env: compilerEnv(options.env),
|
|
1345
|
+
});
|
|
1241
1346
|
let pluginSetupFailure: TtscBuildResult | undefined;
|
|
1242
1347
|
let nativePlugins: ITtscLoadedNativePlugin[] = [];
|
|
1243
1348
|
// Opened only for an invocation that loads plugins, so a project without
|
|
@@ -1247,7 +1352,11 @@ export namespace BuildExecution {
|
|
|
1247
1352
|
try {
|
|
1248
1353
|
if (
|
|
1249
1354
|
compilerSelection.inspectionError === undefined &&
|
|
1250
|
-
hasProjectPluginEntries(
|
|
1355
|
+
hasProjectPluginEntries(
|
|
1356
|
+
project,
|
|
1357
|
+
options.plugins,
|
|
1358
|
+
options.pluginConfigDir,
|
|
1359
|
+
)
|
|
1251
1360
|
) {
|
|
1252
1361
|
const cacheDir =
|
|
1253
1362
|
options.cacheDir ??
|
|
@@ -1258,8 +1367,8 @@ export namespace BuildExecution {
|
|
|
1258
1367
|
cacheDir,
|
|
1259
1368
|
env,
|
|
1260
1369
|
});
|
|
1261
|
-
nativePlugins = loadProjectPlugins({
|
|
1262
|
-
binary: resolveBinary(
|
|
1370
|
+
nativePlugins = (yield* loadProjectPlugins.steps({
|
|
1371
|
+
binary: resolveBinary({ env }) ?? "",
|
|
1263
1372
|
cacheDir,
|
|
1264
1373
|
cwd,
|
|
1265
1374
|
entries: options.plugins,
|
|
@@ -1269,9 +1378,9 @@ export namespace BuildExecution {
|
|
|
1269
1378
|
pluginConfigDir: options.pluginConfigDir,
|
|
1270
1379
|
projectRoot,
|
|
1271
1380
|
tsconfig,
|
|
1272
|
-
}).nativePlugins;
|
|
1381
|
+
})).nativePlugins;
|
|
1273
1382
|
} else {
|
|
1274
|
-
options.onWatchInputs?.([]);
|
|
1383
|
+
yield options.onWatchInputs?.([]);
|
|
1275
1384
|
}
|
|
1276
1385
|
} catch (error) {
|
|
1277
1386
|
pluginSetupFailure = {
|
|
@@ -34,14 +34,14 @@ import { takeResidentCheckEntryRequest } from "./takeResidentCheckEntryRequest";
|
|
|
34
34
|
* `TTSC_WATCH_DEBUG_INPUTS` reports why selection is reset and the active
|
|
35
35
|
* sidecar count being retired, and distinguishes a failed resident transport.
|
|
36
36
|
*
|
|
37
|
-
* @evidence contracts/common.md#principled-implementation Stable invocation selection and serialized cycles let compatible analysis-only checks retain their Program; explicit reload and observed input-topology changes reset selection before another cycle.
|
|
38
|
-
* @evidence contracts/common.md#clear-and-simple-design The session owns selected execution, dependency snapshot, process identities and per-entry delivery buffers while shared BuildExecution owns one-shot phase and failure policy.
|
|
39
|
-
* @evidence contracts/common.md#prohibited-implementation-shortcuts Capability-aware residency
|
|
40
|
-
* @evidence contracts/common.md#meaningful-documentation Native paragraphs state supported lanes, reset causes and the caller's serialization/stable-invocation premise; run and dispose document lifecycle effects.
|
|
41
|
-
* @evidence contracts/portability.md#os-neutral-implementation Native filesystem checks
|
|
42
|
-
* @evidence contracts/performance.md#efficient-algorithms Per-cycle command planning, key serialization and buffer unions process configured checks and pending path text; sorting/comparison bytes, native cache observations, subscribed input discovery and delegated checks add work.
|
|
43
|
-
* @evidence contracts/performance.md#reuse-equivalent-work Process keys include binary/name/argv/compiler payload, while stable invocation context and reload guard the remaining startup inputs
|
|
44
|
-
* @evidence contracts/performance.md#bound-retention-and-release-resources Reset clears active maps, execution and snapshots while retiring children and join promises remain separately retained. Unknown joins
|
|
37
|
+
* @evidence contracts/common.md#principled-implementation Stable invocation selection and serialized cycles let compatible analysis-only checks retain their Program; explicit reload and observed input-topology changes reset selection before another cycle. Initial capture and warm refresh await the watch owner's publication before retaining topology; warm refresh compares physical dependency identity while publishing every declared-alias update.
|
|
38
|
+
* @evidence contracts/common.md#clear-and-simple-design The session owns selected execution, dependency snapshot, process identities and per-entry delivery buffers while shared BuildExecution owns one-shot phase and failure policy. Initial capture wraps the existing discovery callback, and warm refresh joins discovery, comparison and watch registration without another topology owner.
|
|
39
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts Capability-aware residency retains the actual transport-failure one-shot path and distinct configured check positions. Pending or rejected registration cannot restamp topology, and unchanged physical dependencies cannot bypass declared-alias publication.
|
|
40
|
+
* @evidence contracts/common.md#meaningful-documentation Native paragraphs state supported lanes, reset causes and the caller's serialization/stable-invocation premise; private capture and refresh prose distinguish committed topology, physical comparison and declared-alias publication, while run and dispose document lifecycle effects.
|
|
41
|
+
* @evidence contracts/portability.md#os-neutral-implementation Native filesystem checks, cache touch helpers and child creation retain selected binary paths and delegated executable/argv/environment handling. BuildExecution owns native discovery and path normalization; initial capture forwards its snapshot without native operations and warm comparison preserves physical and declared representations.
|
|
42
|
+
* @evidence contracts/performance.md#efficient-algorithms Per-cycle command planning, key serialization and buffer unions process configured checks and pending path text; sorting/comparison bytes, native cache observations, subscribed input discovery and delegated checks add work. Initial capture adds one shallow options copy and one awaited callback; warm refresh adds one native discovery, linear normalized comparison and callback, avoiding reset when topology is unchanged. Accumulated output can repeatedly copy earlier phase text.
|
|
43
|
+
* @evidence contracts/performance.md#reuse-equivalent-work Process keys include binary/name/argv/compiler payload, while stable invocation context and reload guard the remaining startup inputs. Accepted snapshots serve warm topology comparison only after watch registration completes; execution reuse also requires equal physical dependency topology.
|
|
44
|
+
* @evidence contracts/performance.md#bound-retention-and-release-resources Initial capture closes over the session and caller for its build; warm handoff retains the previous and next snapshots until successful registration replaces the accepted population, while rejection preserves it. Reset clears active maps, execution and snapshots while retiring children and join promises remain separately retained. Unknown joins retain rejection and prevent replacement; delegated termination is not descendant settlement. Stable options bound active process keys by configured checks, but pending unique paths and repeated disposal chains have no independent historical ceiling.
|
|
45
45
|
*/
|
|
46
46
|
export class ResidentCheckWatchSession {
|
|
47
47
|
private execution:
|
|
@@ -70,7 +70,9 @@ export class ResidentCheckWatchSession {
|
|
|
70
70
|
* and plugins and starts resident check processes for compatible entries.
|
|
71
71
|
* Later cycles reuse them and forward `change` as an incremental request. A
|
|
72
72
|
* resident process that fails is retired and its entry falls back to the
|
|
73
|
-
* one-shot check for that cycle.
|
|
73
|
+
* one-shot check for that cycle. Plugin and project watch handoffs complete
|
|
74
|
+
* before checks begin; reused topology is republished through the same
|
|
75
|
+
* completion boundary.
|
|
74
76
|
*
|
|
75
77
|
* @evidence contracts/common.md#principled-implementation Compatible no-emit check-only selection uses the same diagnostic/failure policy as one-shot execution; reload, missing binaries and changed normalized dependency topology cold-resolve the next execution.
|
|
76
78
|
* @evidence contracts/common.md#clear-and-simple-design The cycle separates setup/reuse, topology refresh, ordered checks and final diagnostics/timing, delegating each phase to its owning shared operation.
|
|
@@ -103,14 +105,16 @@ export class ResidentCheckWatchSession {
|
|
|
103
105
|
let buildOptions: RunBuildOptions;
|
|
104
106
|
if (execution === undefined) {
|
|
105
107
|
const setupStartedAt = process.hrtime.bigint();
|
|
106
|
-
execution = BuildExecution.
|
|
108
|
+
execution = await BuildExecution.resolveExecutionContextAsync(options);
|
|
109
|
+
this.assertOpen(generation);
|
|
107
110
|
const discoveryOptions = this.captureProjectInputs(options);
|
|
108
|
-
const prepared = BuildExecution.
|
|
111
|
+
const prepared = await BuildExecution.prepareBuildExecutionAsync(
|
|
109
112
|
discoveryOptions,
|
|
110
113
|
timing,
|
|
111
114
|
execution,
|
|
112
115
|
setupStartedAt,
|
|
113
116
|
);
|
|
117
|
+
this.assertOpen(generation);
|
|
114
118
|
buildOptions = prepared.buildOptions;
|
|
115
119
|
if (prepared.result !== undefined) {
|
|
116
120
|
await this.resetForRun("preparation-result");
|
|
@@ -145,12 +149,16 @@ export class ResidentCheckWatchSession {
|
|
|
145
149
|
touchPluginCacheEntryInUse(plugin.binary);
|
|
146
150
|
buildOptions = BuildExecution.applyProjectNoEmit(options, execution);
|
|
147
151
|
}
|
|
148
|
-
if (
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
152
|
+
if (reusedExecution) {
|
|
153
|
+
const topologyChanged = await this.refreshProjectInputTopology(
|
|
154
|
+
options,
|
|
155
|
+
execution,
|
|
156
|
+
);
|
|
157
|
+
this.assertOpen(generation);
|
|
158
|
+
if (topologyChanged) {
|
|
159
|
+
await this.resetForRun("project-input-topology");
|
|
160
|
+
return this.run(options);
|
|
161
|
+
}
|
|
154
162
|
}
|
|
155
163
|
|
|
156
164
|
const checked = await this.runCheckPlugins(
|
|
@@ -294,15 +302,20 @@ export class ResidentCheckWatchSession {
|
|
|
294
302
|
return joined;
|
|
295
303
|
}
|
|
296
304
|
|
|
297
|
-
/**
|
|
305
|
+
/**
|
|
306
|
+
* Retain discovered project topology after its watch owner confirms the
|
|
307
|
+
* publication; rejected registration leaves the previous snapshot intact.
|
|
308
|
+
*/
|
|
298
309
|
private captureProjectInputs(options: RunBuildOptions): RunBuildOptions {
|
|
299
310
|
const onProjectInputs = options.onProjectInputs;
|
|
300
311
|
if (onProjectInputs === undefined) return options;
|
|
312
|
+
const generation = this.generation;
|
|
301
313
|
return {
|
|
302
314
|
...options,
|
|
303
|
-
onProjectInputs: (snapshot) => {
|
|
315
|
+
onProjectInputs: async (snapshot) => {
|
|
316
|
+
await onProjectInputs(snapshot);
|
|
317
|
+
this.assertOpen(generation);
|
|
304
318
|
this.projectInputs = snapshot;
|
|
305
|
-
onProjectInputs(snapshot);
|
|
306
319
|
},
|
|
307
320
|
};
|
|
308
321
|
}
|
|
@@ -310,19 +323,23 @@ export class ResidentCheckWatchSession {
|
|
|
310
323
|
/**
|
|
311
324
|
* Refresh normalized Program topology while always publishing declared alias
|
|
312
325
|
* updates to the watcher, even when physical dependency identity is
|
|
313
|
-
* unchanged.
|
|
326
|
+
* unchanged. Await registration before checks reuse the selected execution.
|
|
314
327
|
*/
|
|
315
|
-
private refreshProjectInputTopology(
|
|
328
|
+
private async refreshProjectInputTopology(
|
|
316
329
|
options: RunBuildOptions,
|
|
317
330
|
execution: ReturnType<typeof BuildExecution.resolveExecutionContext>,
|
|
318
|
-
): boolean {
|
|
331
|
+
): Promise<boolean> {
|
|
319
332
|
if (options.onProjectInputs === undefined) return false;
|
|
333
|
+
const generation = this.generation;
|
|
320
334
|
const next = BuildExecution.discoverNativeProjectInputs(options, execution);
|
|
321
335
|
const changed =
|
|
322
336
|
this.projectInputs !== undefined &&
|
|
323
337
|
!projectInputSnapshotsEqual(this.projectInputs, next);
|
|
338
|
+
// Replaying an unchanged population still crosses the worker's publication
|
|
339
|
+
// barrier. Starting checks first would accept edits before registration.
|
|
340
|
+
await options.onProjectInputs(next);
|
|
341
|
+
this.assertOpen(generation);
|
|
324
342
|
this.projectInputs = next;
|
|
325
|
-
options.onProjectInputs(next);
|
|
326
343
|
return changed;
|
|
327
344
|
}
|
|
328
345
|
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import type { ITtscParsedProjectConfig } from "../../../structures/internal/ITtscParsedProjectConfig";
|
|
2
|
-
import type { ITtscProjectInputSnapshot } from "../../../structures/internal/ITtscProjectInputSnapshot";
|
|
3
2
|
import type { TtscBuildOptions } from "../../../structures/internal/TtscBuildOptions";
|
|
4
|
-
import type {
|
|
3
|
+
import type {
|
|
4
|
+
TtscPluginSourceInputsHandler,
|
|
5
|
+
TtscProjectInputsHandler,
|
|
6
|
+
} from "../../../structures/internal/TtscSingleFileEmitOptions";
|
|
5
7
|
|
|
6
8
|
/**
|
|
7
9
|
* Options of one {@link runBuild} call: the public build options plus the knobs
|
|
@@ -119,7 +121,8 @@ export type RunBuildOptions = TtscBuildOptions & {
|
|
|
119
121
|
/**
|
|
120
122
|
* Receives selected native-plugin source roots after the project resolves.
|
|
121
123
|
* The watch launcher uses these roots to invalidate a sidecar when its Go
|
|
122
|
-
* implementation changes between rebuilds.
|
|
124
|
+
* implementation changes between rebuilds. Asynchronous entries await a
|
|
125
|
+
* returned promise; synchronous entries require a synchronous handler.
|
|
123
126
|
*/
|
|
124
127
|
onWatchInputs?: TtscPluginSourceInputsHandler;
|
|
125
128
|
|
|
@@ -127,9 +130,10 @@ export type RunBuildOptions = TtscBuildOptions & {
|
|
|
127
130
|
* Receives the reconciled project-rule filesystem dependency snapshot. Called
|
|
128
131
|
* when this internal callback is supplied, normally by watch launchers;
|
|
129
132
|
* ordinary calls without the callback do not probe the optional sidecar
|
|
130
|
-
* command.
|
|
133
|
+
* command. Asynchronous entries await a returned promise before compilation;
|
|
134
|
+
* synchronous entries require a synchronous handler.
|
|
131
135
|
*/
|
|
132
|
-
onProjectInputs?:
|
|
136
|
+
onProjectInputs?: TtscProjectInputsHandler;
|
|
133
137
|
|
|
134
138
|
/**
|
|
135
139
|
* Request an external source map in an emitting direct tsgo lane even when
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Complete each watch-input handoff before resuming its producer.
|
|
3
|
+
*
|
|
4
|
+
* Synchronous compiler APIs retain their return types and require synchronous
|
|
5
|
+
* handlers. Watch callers use the asynchronous runner so a worker establishes
|
|
6
|
+
* its baseline before the producer reads or builds the reported inputs.
|
|
7
|
+
*
|
|
8
|
+
* @evidence contracts/common.md#principled-implementation Generator suspension preserves ordered publication checkpoints; rejected handoffs return to the producer's failure policy and finally blocks. The synchronous guard recognizes callable then members across realms and observes an already-started promise's rejection before refusing asynchronous completion.
|
|
9
|
+
* @evidence contracts/common.md#clear-and-simple-design Two runners share one producer sequence; the synchronous guard owns promise recognition and refusal, and its caller delivers that failure to the producer.
|
|
10
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts A synchronous entry refuses asynchronous work instead of reporting completion or blocking; neither runner changes watcher or filesystem internals.
|
|
11
|
+
* @evidence contracts/common.md#meaningful-documentation Native prose identifies publication ordering, synchronous restrictions, cross-realm recognition and already-started handler ownership; each runner documents failure delivery.
|
|
12
|
+
* @evidenceExclude contracts/portability.md#os-neutral-implementation Promise recognition and publication stepping introduce no native filesystem, path identity or process boundary.
|
|
13
|
+
* @evidence contracts/performance.md#efficient-algorithms Each runner advances each handoff once with constant state; the synchronous guard adds one then-member observation and one rejection observer. Callback work and retained producer state remain owner costs.
|
|
14
|
+
* @evidenceExclude contracts/performance.md#reuse-equivalent-work Publication and completion validation belong to each current producer handoff and are never memoized or shared away.
|
|
15
|
+
* @evidence contracts/performance.md#bound-retention-and-release-resources One suspended sequence remains until completion or failure, and rejected handoffs enter its cleanup path. The rejection observer lasts until the already-started handler settles; the synchronous runner cannot join or cancel it. Handler duration and retained producer bytes have no independent bound.
|
|
16
|
+
*/
|
|
17
|
+
export namespace WatchInputPublication {
|
|
18
|
+
/**
|
|
19
|
+
* A producer suspends only at a watch owner's completion boundary.
|
|
20
|
+
*
|
|
21
|
+
* @evidence contracts/common.md#principled-implementation Yielded values describe handler completion, and the final return preserves the producer's result type.
|
|
22
|
+
* @evidence contracts/common.md#clear-and-simple-design One generator shape serves both completion runners without changing the producer's return contract.
|
|
23
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts The type models real callback completion without injecting watcher or filesystem behavior.
|
|
24
|
+
* @evidence contracts/common.md#meaningful-documentation Native prose identifies the suspension boundary.
|
|
25
|
+
* @evidenceExclude contracts/portability.md#os-neutral-implementation This type has no native representation or process boundary.
|
|
26
|
+
* @evidenceExclude contracts/performance.md#efficient-algorithms A type declaration chooses no processing strategy.
|
|
27
|
+
* @evidenceExclude contracts/performance.md#reuse-equivalent-work A type declaration computes no reusable work.
|
|
28
|
+
* @evidenceExclude contracts/performance.md#bound-retention-and-release-resources A type declaration acquires no resource.
|
|
29
|
+
*/
|
|
30
|
+
export type Sequence<Result> = Generator<void | Promise<void>, Result, void>;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Finish a synchronous producer, refusing a handler that returns a promise.
|
|
34
|
+
* The refusal enters the producer's ordinary exception and cleanup path.
|
|
35
|
+
*
|
|
36
|
+
* @evidence contracts/common.md#principled-implementation Each yielded completion is checked before advancing; asynchronous completion becomes an exception delivered into the producer.
|
|
37
|
+
* @evidence contracts/common.md#clear-and-simple-design The runner owns synchronous completion while the sequence owns operation policy and cleanup.
|
|
38
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts Promise rejection is observed and synchronous success cannot precede its completion.
|
|
39
|
+
* @evidence contracts/common.md#meaningful-documentation Native prose states promise refusal and the producer-owned exception path.
|
|
40
|
+
* @evidenceExclude contracts/portability.md#os-neutral-implementation Sequence stepping performs no native operation.
|
|
41
|
+
* @evidence contracts/performance.md#efficient-algorithms The runner visits each handoff once and retains one iterator result at a time.
|
|
42
|
+
* @evidenceExclude contracts/performance.md#reuse-equivalent-work Ordered effectful publications are not cached or shared.
|
|
43
|
+
* @evidence contracts/performance.md#bound-retention-and-release-resources Refusal enters generator cleanup and observes the already-started promise's rejection; its unfinished handler remains handler-owned rather than joined by this synchronous API.
|
|
44
|
+
*/
|
|
45
|
+
export function run<Result>(sequence: Sequence<Result>): Result {
|
|
46
|
+
let step = sequence.next();
|
|
47
|
+
while (!step.done) {
|
|
48
|
+
try {
|
|
49
|
+
assertSynchronous(step.value);
|
|
50
|
+
} catch (error) {
|
|
51
|
+
step = sequence.throw(error);
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
step = sequence.next();
|
|
55
|
+
}
|
|
56
|
+
return step.value;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Join every handoff before continuing, delivering rejection to the producer
|
|
61
|
+
* rather than bypassing its error handling or temporary-resource cleanup.
|
|
62
|
+
*
|
|
63
|
+
* @evidence contracts/common.md#principled-implementation Await settles each yielded handoff and throws rejection back into the same suspended generator before advancing.
|
|
64
|
+
* @evidence contracts/common.md#clear-and-simple-design The runner owns asynchronous completion while producer policy remains inside the shared sequence.
|
|
65
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts No pending or rejected publication is silently treated as completed registration.
|
|
66
|
+
* @evidence contracts/common.md#meaningful-documentation Native prose states ordered joining, rejection delivery and cleanup ownership.
|
|
67
|
+
* @evidenceExclude contracts/portability.md#os-neutral-implementation Promise and generator stepping introduce no native boundary.
|
|
68
|
+
* @evidence contracts/performance.md#efficient-algorithms Each yielded handoff is awaited once with constant runner state.
|
|
69
|
+
* @evidenceExclude contracts/performance.md#reuse-equivalent-work Each effectful publication belongs to its current producer and is not cached.
|
|
70
|
+
* @evidence contracts/performance.md#bound-retention-and-release-resources One suspended sequence remains live until the handler settles; rejection enters its cleanup path, with no independent callback deadline imposed here.
|
|
71
|
+
*/
|
|
72
|
+
export async function runAsync<Result>(
|
|
73
|
+
sequence: Sequence<Result>,
|
|
74
|
+
): Promise<Result> {
|
|
75
|
+
let step = sequence.next();
|
|
76
|
+
while (!step.done) {
|
|
77
|
+
try {
|
|
78
|
+
await step.value;
|
|
79
|
+
} catch (error) {
|
|
80
|
+
step = sequence.throw(error);
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
step = sequence.next();
|
|
84
|
+
}
|
|
85
|
+
return step.value;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Refuse cross-realm promises and thenables through the producer's failure
|
|
90
|
+
* path, observing rejection from a handler that has already started.
|
|
91
|
+
*/
|
|
92
|
+
function assertSynchronous(value: unknown): void {
|
|
93
|
+
if (
|
|
94
|
+
value !== null &&
|
|
95
|
+
(typeof value === "object" || typeof value === "function") &&
|
|
96
|
+
typeof (value as { then?: unknown }).then === "function"
|
|
97
|
+
) {
|
|
98
|
+
// The handler has already started; observe its rejection even though
|
|
99
|
+
// this synchronous caller cannot join it and must fail the operation.
|
|
100
|
+
void Promise.resolve(value).catch(() => {});
|
|
101
|
+
throw new TypeError(
|
|
102
|
+
"ttsc: asynchronous watch input publication requires an asynchronous build entry",
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
@@ -2,6 +2,7 @@ import type { TtscBuildResult } from "../../../structures/internal/TtscBuildResu
|
|
|
2
2
|
import { BuildExecution } from "./BuildExecution";
|
|
3
3
|
import { BuildTiming } from "./BuildTiming";
|
|
4
4
|
import type { RunBuildOptions } from "./RunBuildOptions";
|
|
5
|
+
import { WatchInputPublication } from "./WatchInputPublication";
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* Run `ttsc` against a tsconfig. Returns once the binary exits so the CLI can
|
|
@@ -10,8 +11,9 @@ import type { RunBuildOptions } from "./RunBuildOptions";
|
|
|
10
11
|
*
|
|
11
12
|
* Project-free terminal flags bypass project/plugin setup when applicable.
|
|
12
13
|
* Required emit provenance preserves compiler selection and exposes unknown
|
|
13
|
-
* ownership when the selected producer cannot establish the requested
|
|
14
|
-
*
|
|
14
|
+
* ownership when the selected producer cannot establish the requested relation.
|
|
15
|
+
* Watch-input handlers must complete synchronously; use {@link runBuild.async}
|
|
16
|
+
* when a handler returns a promise.
|
|
15
17
|
*
|
|
16
18
|
* @evidence contracts/common.md#principled-implementation Shared preparation selects project and plugins before execution, while project-free terminal requests take their supported direct compiler path; timing is appended after the resulting build phase.
|
|
17
19
|
* @evidence contracts/common.md#clear-and-simple-design The public synchronous entry owns timing and delegates setup/execution to BuildExecution, keeping the same build policy available to watch sessions.
|
|
@@ -23,39 +25,61 @@ import type { RunBuildOptions } from "./RunBuildOptions";
|
|
|
23
25
|
* @evidence contracts/performance.md#bound-retention-and-release-resources The ledger and execution state are build-owned, while returned output/proof/diagnostic records transfer to the caller; no resident handle or historical build is stored here. Delegated native/probe/artifact acquisition and cleanup may be best effort, and thrown setup can precede some cleanup boundaries. This wrapper supplies no duration/output bound or descendant-release certification.
|
|
24
26
|
*/
|
|
25
27
|
export function runBuild(options: RunBuildOptions = {}): TtscBuildResult {
|
|
26
|
-
|
|
27
|
-
const result = runBuildTimed(options, timing);
|
|
28
|
-
return BuildTiming.appendTimingOutput(result, timing);
|
|
28
|
+
return WatchInputPublication.run(runBuild.steps(options));
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
31
|
+
/**
|
|
32
|
+
* Share one build sequence between synchronous APIs and awaited watch cycles.
|
|
33
|
+
*
|
|
34
|
+
* @evidence contracts/common.md#principled-implementation Both completion modes use the same timed terminal selection, context acquisition, preparation and compile sequence. The asynchronous runner joins every plugin and project publication before native compilation; composing callers must deliver callback rejection into that sequence.
|
|
35
|
+
* @evidence contracts/common.md#clear-and-simple-design The namespace keeps awaited completion beside its synchronous entry and exposes one timing and phase sequence to single-file orchestration; BuildExecution retains build policy.
|
|
36
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts Awaiting changes only publication completion, preserves compiler/plugin selection and project-free terminal behavior, and sends publication failure through existing setup and cleanup rather than bypassing a pending baseline.
|
|
37
|
+
* @evidence contracts/common.md#meaningful-documentation Entry prose states the publication barrier, order before compilation and internal callers' obligation to complete the sequence and deliver rejection.
|
|
38
|
+
* @evidence contracts/portability.md#os-neutral-implementation BuildExecution retains native cwd, path identity and argument-array ownership across suspension; the namespace adds no independent native boundary.
|
|
39
|
+
* @evidence contracts/performance.md#efficient-algorithms Each selected terminal, context, discovery, preparation and compile phase runs once; each publication adds one await and constant sequence state.
|
|
40
|
+
* @evidence contracts/performance.md#reuse-equivalent-work One resolved execution context serves preparation and compilation without reloading plugins; the namespace retains no completed build or in-flight cache.
|
|
41
|
+
* @evidence contracts/performance.md#bound-retention-and-release-resources The invocation owns its sequence, ledger, context and current handoff while callbacks settle. Selected results transfer to the caller, delegated resource ownership and cleanup stay unchanged, and no resident history is retained.
|
|
42
|
+
*/
|
|
43
|
+
export namespace runBuild {
|
|
44
|
+
/**
|
|
45
|
+
* Run a build after each watch-input handler's returned promise settles.
|
|
46
|
+
* Compilation starts only after both plugin and project baselines complete.
|
|
47
|
+
*/
|
|
48
|
+
export function async(
|
|
49
|
+
options: RunBuildOptions = {},
|
|
50
|
+
): Promise<TtscBuildResult> {
|
|
51
|
+
return WatchInputPublication.runAsync(steps(options));
|
|
52
|
+
}
|
|
41
53
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
timing
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
54
|
+
/**
|
|
55
|
+
* Produce one timed build, yielding watch handoffs before native work.
|
|
56
|
+
* Composing owners must complete the sequence and deliver callback rejection
|
|
57
|
+
* back into it so the existing setup and cleanup policies apply.
|
|
58
|
+
*/
|
|
59
|
+
export function* steps(
|
|
60
|
+
options: RunBuildOptions,
|
|
61
|
+
): WatchInputPublication.Sequence<TtscBuildResult> {
|
|
62
|
+
const timing = BuildTiming.createBuildTiming(options);
|
|
63
|
+
const projectFree = BuildExecution.runProjectFreeTerminalFlag(options);
|
|
64
|
+
if (projectFree !== null)
|
|
65
|
+
return BuildTiming.appendTimingOutput(projectFree, timing);
|
|
66
|
+
const setupStartedAt = process.hrtime.bigint();
|
|
67
|
+
const execution =
|
|
68
|
+
yield* BuildExecution.resolveExecutionContextSteps(options);
|
|
69
|
+
const prepared = yield* BuildExecution.prepareBuildExecutionSteps(
|
|
70
|
+
options,
|
|
71
|
+
timing,
|
|
72
|
+
execution,
|
|
73
|
+
setupStartedAt,
|
|
74
|
+
);
|
|
75
|
+
const result =
|
|
76
|
+
prepared.result ??
|
|
77
|
+
BuildExecution.runPreparedBuild(
|
|
78
|
+
options,
|
|
79
|
+
timing,
|
|
80
|
+
execution,
|
|
81
|
+
prepared.buildOptions,
|
|
82
|
+
);
|
|
83
|
+
return BuildTiming.appendTimingOutput(result, timing);
|
|
84
|
+
}
|
|
61
85
|
}
|
|
@@ -33,12 +33,16 @@ export function buildNativeCompiler(options: {
|
|
|
33
33
|
/** Optional explicit cache directory, interpreted by the artifact builder. */
|
|
34
34
|
cacheDir?: string;
|
|
35
35
|
|
|
36
|
+
/** Complete environment used to select and key the native host build. */
|
|
37
|
+
env?: NodeJS.ProcessEnv;
|
|
38
|
+
|
|
36
39
|
/** Installed ttsc package containing cmd/ttsc and its module metadata. */
|
|
37
40
|
packageRoot: string;
|
|
38
41
|
}): string {
|
|
39
42
|
return buildSourcePlugin({
|
|
40
43
|
baseDir: options.cacheBaseDir,
|
|
41
44
|
cacheDir: options.cacheDir,
|
|
45
|
+
env: options.env,
|
|
42
46
|
label: "compiler host",
|
|
43
47
|
overlayDirs: [],
|
|
44
48
|
pluginName: "ttsc",
|
|
@@ -68,11 +68,13 @@ export function compileProjectInMemory(options: ITtscCompilerContext): {
|
|
|
68
68
|
return compileProjectWithPlugins(options, cwd, project);
|
|
69
69
|
}
|
|
70
70
|
const tsconfig = project.path;
|
|
71
|
+
const env = inheritedSidecarEnv(options.env, options.binary);
|
|
71
72
|
const binary = buildNativeCompiler({
|
|
72
73
|
cacheBaseDir: project.root,
|
|
73
74
|
cacheDir:
|
|
74
75
|
options.cacheDir ??
|
|
75
76
|
SidecarEnvironment.read(options.env, "TTSC_CACHE_DIR"),
|
|
77
|
+
env,
|
|
76
78
|
packageRoot: packageRootDir(),
|
|
77
79
|
});
|
|
78
80
|
const res = spawnNative(
|
|
@@ -80,7 +82,7 @@ export function compileProjectInMemory(options: ITtscCompilerContext): {
|
|
|
80
82
|
["api-compile", "--cwd", project.root, "--tsconfig", tsconfig],
|
|
81
83
|
{
|
|
82
84
|
cwd: project.root,
|
|
83
|
-
env
|
|
85
|
+
env,
|
|
84
86
|
},
|
|
85
87
|
);
|
|
86
88
|
if (res.error) {
|
|
@@ -110,7 +112,11 @@ function hasConfiguredPlugins(
|
|
|
110
112
|
options: ITtscCompilerContext,
|
|
111
113
|
project: ITtscParsedProjectConfig,
|
|
112
114
|
): boolean {
|
|
113
|
-
return hasProjectPluginEntries(
|
|
115
|
+
return hasProjectPluginEntries(
|
|
116
|
+
project,
|
|
117
|
+
options.plugins,
|
|
118
|
+
options.pluginConfigDir,
|
|
119
|
+
);
|
|
114
120
|
}
|
|
115
121
|
|
|
116
122
|
/**
|