ttsc 0.26.1 → 0.27.0
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/README.md +10 -1
- package/cmd/ttsc/api_transform.go +17 -3
- package/cmd/ttscgraph/auxiliary_identity_state_tracks_retargets_not_source_contents_test.go +85 -0
- package/cmd/ttscgraph/disk_realpath_other.go +16 -0
- package/cmd/ttscgraph/disk_realpath_windows.go +56 -0
- package/cmd/ttscgraph/serve.go +104 -35
- package/driver/diagnostics_preamble.go +284 -0
- package/driver/emit_plugin.go +71 -19
- package/driver/graph.go +64 -11
- package/driver/input_observation.go +273 -0
- package/driver/input_observation_test.go +149 -0
- package/driver/plugins.go +384 -4
- package/driver/program.go +81 -15
- package/driver/resolution_candidates.go +13 -5
- package/driver/rewrite.go +47 -4
- package/internal/graph/diagnostics.go +4 -3
- package/internal/graph/provenance.go +10 -1
- package/lib/TtscCompiler.d.ts +12 -11
- package/lib/TtscCompiler.js +44 -29
- package/lib/TtscCompiler.js.map +1 -1
- package/lib/compiler/internal/captureProcessOutput.js +2 -2
- package/lib/compiler/internal/captureProcessOutput.js.map +1 -1
- package/lib/compiler/internal/compileProjectInMemory.js +11 -3
- package/lib/compiler/internal/compileProjectInMemory.js.map +1 -1
- package/lib/compiler/internal/resolveEmittedJavaScript.d.ts +2 -0
- package/lib/compiler/internal/resolveEmittedJavaScript.js +3 -0
- package/lib/compiler/internal/resolveEmittedJavaScript.js.map +1 -1
- package/lib/compiler/internal/runBuild.d.ts +29 -1
- package/lib/compiler/internal/runBuild.js +117 -32
- package/lib/compiler/internal/runBuild.js.map +1 -1
- package/lib/compiler/internal/runSingleFileEmit.js +9 -2
- package/lib/compiler/internal/runSingleFileEmit.js.map +1 -1
- package/lib/compiler/internal/sharedHostHelpers.d.ts +28 -0
- package/lib/compiler/internal/sharedHostHelpers.js +39 -0
- package/lib/compiler/internal/sharedHostHelpers.js.map +1 -1
- package/lib/compiler/internal/startResidentTransform.js +12 -4
- package/lib/compiler/internal/startResidentTransform.js.map +1 -1
- package/lib/compiler/internal/transformProjectInMemory.d.ts +3 -0
- package/lib/compiler/internal/transformProjectInMemory.js +239 -35
- package/lib/compiler/internal/transformProjectInMemory.js.map +1 -1
- package/lib/flags/schema.js +33 -5
- package/lib/flags/schema.js.map +1 -1
- package/lib/internal/createCanonicalTempDirectory.d.ts +17 -0
- package/lib/internal/createCanonicalTempDirectory.js +42 -0
- package/lib/internal/createCanonicalTempDirectory.js.map +1 -0
- package/lib/internal/projectInputPathIdentity.d.ts +3 -0
- package/lib/internal/projectInputPathIdentity.js +11 -5
- package/lib/internal/projectInputPathIdentity.js.map +1 -1
- package/lib/internal/resolveNodeBinary.d.ts +14 -0
- package/lib/internal/resolveNodeBinary.js +150 -0
- package/lib/internal/resolveNodeBinary.js.map +1 -0
- package/lib/internal/resolveSafeCacheCleanupTargets.d.ts +15 -0
- package/lib/internal/resolveSafeCacheCleanupTargets.js +61 -0
- package/lib/internal/resolveSafeCacheCleanupTargets.js.map +1 -0
- package/lib/launcher/internal/assertNoSolutionBuild.d.ts +31 -0
- package/lib/launcher/internal/assertNoSolutionBuild.js +38 -0
- package/lib/launcher/internal/assertNoSolutionBuild.js.map +1 -0
- package/lib/launcher/internal/prepareExecution.d.ts +3 -0
- package/lib/launcher/internal/prepareExecution.js +73 -26
- package/lib/launcher/internal/prepareExecution.js.map +1 -1
- package/lib/launcher/internal/runTtsc.js +27 -13
- package/lib/launcher/internal/runTtsc.js.map +1 -1
- package/lib/launcher/internal/runTtscserver.js +18 -3
- package/lib/launcher/internal/runTtscserver.js.map +1 -1
- package/lib/launcher/internal/runTtsx.js +4 -0
- package/lib/launcher/internal/runTtsx.js.map +1 -1
- package/lib/launcher/internal/runtimeHooks.d.ts +37 -1
- package/lib/launcher/internal/runtimeHooks.js +660 -62
- package/lib/launcher/internal/runtimeHooks.js.map +1 -1
- package/lib/plugin/internal/buildSourcePlugin.d.ts +62 -8
- package/lib/plugin/internal/buildSourcePlugin.js +754 -72
- package/lib/plugin/internal/buildSourcePlugin.js.map +1 -1
- package/lib/plugin/internal/loadProjectPlugins.d.ts +17 -5
- package/lib/plugin/internal/loadProjectPlugins.js +1339 -77
- package/lib/plugin/internal/loadProjectPlugins.js.map +1 -1
- package/lib/register.d.ts +1 -0
- package/lib/register.js +46 -0
- package/lib/register.js.map +1 -0
- package/lib/structures/ITtscCompilerContext.d.ts +6 -3
- package/lib/structures/ITtscCompilerTransformation.d.ts +31 -0
- package/lib/structures/ITtscPlugin.d.ts +33 -0
- package/package.json +16 -9
- package/shim/checker/go.mod +9 -0
- package/shim/checker/go.sum +22 -0
- package/shim/checker/shim.go +75 -0
- package/shim/compiler/emit_sourcemap.go +56 -15
- package/shim/compiler/incremental.go +45 -8
- package/src/TtscCompiler.ts +55 -33
- package/src/compiler/internal/captureProcessOutput.ts +3 -2
- package/src/compiler/internal/compileProjectInMemory.ts +11 -3
- package/src/compiler/internal/resolveEmittedJavaScript.ts +6 -0
- package/src/compiler/internal/runBuild.ts +172 -36
- package/src/compiler/internal/runSingleFileEmit.ts +9 -2
- package/src/compiler/internal/sharedHostHelpers.ts +44 -0
- package/src/compiler/internal/startResidentTransform.ts +12 -3
- package/src/compiler/internal/transformProjectInMemory.ts +410 -39
- package/src/flags/schema.ts +35 -5
- package/src/internal/createCanonicalTempDirectory.ts +53 -0
- package/src/internal/projectInputPathIdentity.ts +17 -4
- package/src/internal/resolveNodeBinary.ts +173 -0
- package/src/internal/resolveSafeCacheCleanupTargets.ts +85 -0
- package/src/launcher/internal/assertNoSolutionBuild.ts +40 -0
- package/src/launcher/internal/prepareExecution.ts +78 -26
- package/src/launcher/internal/runTtsc.ts +26 -13
- package/src/launcher/internal/runTtscserver.ts +18 -3
- package/src/launcher/internal/runTtsx.ts +4 -0
- package/src/launcher/internal/runtimeHooks.ts +830 -66
- package/src/plugin/internal/buildSourcePlugin.ts +984 -79
- package/src/plugin/internal/loadProjectPlugins.ts +1718 -104
- package/src/register.ts +47 -0
- package/src/structures/ITtscCompilerContext.ts +6 -3
- package/src/structures/ITtscCompilerTransformation.ts +39 -0
- package/src/structures/ITtscPlugin.ts +36 -0
- package/tools/shim_audit/baseline.json +0 -1
- package/utility/host.go +9 -3
- package/lib/internal/assertSafeExplicitCacheDirectory.d.ts +0 -5
- package/lib/internal/assertSafeExplicitCacheDirectory.js +0 -26
- package/lib/internal/assertSafeExplicitCacheDirectory.js.map +0 -1
- package/src/internal/assertSafeExplicitCacheDirectory.ts +0 -29
|
@@ -10,8 +10,6 @@ import { createFilesystemPathIdentityContext } from "../../internal/projectInput
|
|
|
10
10
|
import type { TtscCommonOptions } from "../../structures/internal/TtscCommonOptions";
|
|
11
11
|
import { type OwningModuleOptions, projectModuleOptions } from "./runtimeHooks";
|
|
12
12
|
|
|
13
|
-
/** Subdirectory name that isolates concurrent ttsx processes by PID. */
|
|
14
|
-
const PROCESS_CACHE_KEY = String(process.pid);
|
|
15
13
|
/**
|
|
16
14
|
* Maximum number of ancestor directories above the project root that the
|
|
17
15
|
* virtual filesystem overlay mirrors. Three levels covers the common monorepo
|
|
@@ -32,12 +30,15 @@ export function prepareExecution(
|
|
|
32
30
|
options: TtscCommonOptions & {
|
|
33
31
|
cacheDir?: string;
|
|
34
32
|
project?: string;
|
|
33
|
+
/** Internal cache key for more than one checked entry in this process. */
|
|
34
|
+
runtimeCacheKey?: string;
|
|
35
35
|
} = {},
|
|
36
36
|
): {
|
|
37
37
|
cleanupDir: string;
|
|
38
38
|
emitDir: string;
|
|
39
39
|
emittedFiles?: readonly string[];
|
|
40
40
|
entryFile: string;
|
|
41
|
+
entrySource: string;
|
|
41
42
|
moduleOptions: OwningModuleOptions;
|
|
42
43
|
projectRoot: string;
|
|
43
44
|
rootDir: string;
|
|
@@ -57,7 +58,6 @@ export function prepareExecution(
|
|
|
57
58
|
const context = createProjectContext(
|
|
58
59
|
cwd,
|
|
59
60
|
path.resolve(cwd, entryFile),
|
|
60
|
-
entry,
|
|
61
61
|
options,
|
|
62
62
|
);
|
|
63
63
|
try {
|
|
@@ -75,6 +75,7 @@ export function prepareExecution(
|
|
|
75
75
|
emitDir: context.emitDir,
|
|
76
76
|
emittedFiles: context.emittedFiles ?? undefined,
|
|
77
77
|
entryFile: emittedEntry,
|
|
78
|
+
entrySource: entry,
|
|
78
79
|
moduleOptions: context.moduleOptions,
|
|
79
80
|
projectRoot: context.root,
|
|
80
81
|
rootDir: context.runtimeRootDir,
|
|
@@ -148,16 +149,26 @@ function resolveEntrySpelling(cwd: string, entryFile: string): string {
|
|
|
148
149
|
return identities.resolve(path.resolve(cwd, entryFile)).path;
|
|
149
150
|
}
|
|
150
151
|
|
|
152
|
+
/**
|
|
153
|
+
* Directory-safe identity for one prepared runtime. Direct `ttsx` retains its
|
|
154
|
+
* historical PID directory; the public preload supplies a distinct key for
|
|
155
|
+
* every late TypeScript root so one preparation cannot erase another's emit.
|
|
156
|
+
*/
|
|
157
|
+
function resolveRuntimeCacheKey(runtimeCacheKey: string | undefined): string {
|
|
158
|
+
const key = runtimeCacheKey ?? String(process.pid);
|
|
159
|
+
if (!/^[A-Za-z0-9._-]+$/.test(key) || key === "." || key === "..") {
|
|
160
|
+
throw new Error(`ttsx: invalid runtime cache key ${JSON.stringify(key)}`);
|
|
161
|
+
}
|
|
162
|
+
return key;
|
|
163
|
+
}
|
|
164
|
+
|
|
151
165
|
/**
|
|
152
166
|
* @param discoveryFile - The entry as the user named it. Project discovery
|
|
153
167
|
* walks up from here, so it must not be retargeted through a symlink.
|
|
154
|
-
* @param entry - The entry in its physical spelling, which is what the emit
|
|
155
|
-
* layout and the runtime hooks both speak.
|
|
156
168
|
*/
|
|
157
169
|
function createProjectContext(
|
|
158
170
|
cwd: string,
|
|
159
171
|
discoveryFile: string,
|
|
160
|
-
entry: string,
|
|
161
172
|
options: NonNullable<Parameters<typeof prepareExecution>[1]>,
|
|
162
173
|
) {
|
|
163
174
|
const project = readProjectConfig(
|
|
@@ -172,21 +183,30 @@ function createProjectContext(
|
|
|
172
183
|
const tsconfig = project.path;
|
|
173
184
|
const root = project.root;
|
|
174
185
|
const explicitCacheDir = resolveCacheDir(cwd, options.cacheDir);
|
|
175
|
-
const
|
|
186
|
+
const cacheDirSpelling =
|
|
176
187
|
explicitCacheDir ??
|
|
177
188
|
path.join(root, "node_modules", ".cache", "ttsc", "ttsx");
|
|
178
|
-
const
|
|
179
|
-
const virtualRoot = path.join(processDir, "fs");
|
|
189
|
+
const runtimeCacheKey = resolveRuntimeCacheKey(options.runtimeCacheKey);
|
|
180
190
|
// Resolved once: it now costs a realpath (and, for a missing directory on
|
|
181
191
|
// Windows, a case-sensitivity probe) rather than a string join.
|
|
182
|
-
const runtimeRootDir = resolveRuntimeSourceRoot(project
|
|
192
|
+
const runtimeRootDir = resolveRuntimeSourceRoot(project);
|
|
193
|
+
fs.mkdirSync(cacheDirSpelling, { recursive: true });
|
|
194
|
+
// Pin the cache parent before deriving a generation path. Descriptors run
|
|
195
|
+
// after this point and may retarget a caller-controlled symlink or junction;
|
|
196
|
+
// every later runtime write and recursive cleanup must remain below the
|
|
197
|
+
// physical parent selected here.
|
|
198
|
+
const cacheDir =
|
|
199
|
+
createFilesystemPathIdentityContext().resolve(cacheDirSpelling).path;
|
|
200
|
+
const processDir = path.join(cacheDir, "project", runtimeCacheKey);
|
|
201
|
+
const virtualRoot = path.join(processDir, "fs");
|
|
183
202
|
return {
|
|
184
203
|
project,
|
|
185
204
|
tsconfig,
|
|
186
205
|
root,
|
|
187
206
|
cacheDir,
|
|
207
|
+
runtimeCacheKey,
|
|
188
208
|
processDir,
|
|
189
|
-
pluginCacheDir: explicitCacheDir,
|
|
209
|
+
pluginCacheDir: explicitCacheDir === undefined ? undefined : cacheDir,
|
|
190
210
|
virtualRoot,
|
|
191
211
|
emitDir: project.compilerOptions.outDir
|
|
192
212
|
? virtualPath(virtualRoot, project.compilerOptions.outDir)
|
|
@@ -217,6 +237,16 @@ function createProjectContext(
|
|
|
217
237
|
* The source-tree root the emit mirrors, in the same physical spelling as the
|
|
218
238
|
* entry it will be compared against.
|
|
219
239
|
*
|
|
240
|
+
* Undeclared, the root is the project's own directory, because that is the one
|
|
241
|
+
* tsgo uses: with a config file in play `GetCommonSourceDirectory` answers that
|
|
242
|
+
* file's directory and never computes a common directory of the input files.
|
|
243
|
+
* The entry's directory is not that root — it is only the same directory when
|
|
244
|
+
* the entry happens to sit beside the tsconfig, which is precisely why a
|
|
245
|
+
* `src/`-shaped project mislaid its emit here (issue #1172) while a flat one
|
|
246
|
+
* worked. `runtimeHooks.ts::resolveDependencySourceRoot` and
|
|
247
|
+
* `watchTopology.ts::inferPerSourceCompilerOutputs` already model the same
|
|
248
|
+
* rule, and `runBuild.ts::pinnedRootDirArgs` pins it for tsgo itself.
|
|
249
|
+
*
|
|
220
250
|
* Resolving it is the other half of `resolveEntrySpelling`, and skipping it
|
|
221
251
|
* leaves the comparison mixed rather than merely imprecise. `project.root`
|
|
222
252
|
* arrives through plain `fs.realpathSync`, which resolves reparse points but
|
|
@@ -227,22 +257,25 @@ function createProjectContext(
|
|
|
227
257
|
* way the gate reads an in-project entry as outside its own root, pays a second
|
|
228
258
|
* whole build for it, and publishes a wider root than the project has.
|
|
229
259
|
*
|
|
230
|
-
*
|
|
231
|
-
* the
|
|
260
|
+
* The pass costs nothing in agreement with the root tsgo was pinned to, which
|
|
261
|
+
* stays unresolved on purpose so it matches the spelling tsgo gives the input
|
|
262
|
+
* file names it compares against it. Only the prefix differs between the two;
|
|
263
|
+
* each side strips its own, so the relative path below the root — the part that
|
|
264
|
+
* decides where the emit lands and where the lookup reads — is identical.
|
|
232
265
|
*/
|
|
233
266
|
function resolveRuntimeSourceRoot(
|
|
234
267
|
project: ReturnType<typeof readProjectConfig>,
|
|
235
|
-
entry: string,
|
|
236
268
|
): string {
|
|
237
269
|
const rootDir = project.compilerOptions.rootDir;
|
|
238
|
-
if (typeof rootDir !== "string") {
|
|
239
|
-
return path.dirname(entry);
|
|
240
|
-
}
|
|
241
270
|
const identities = createFilesystemPathIdentityContext({
|
|
242
271
|
throwOnRealpathError: false,
|
|
243
272
|
});
|
|
244
273
|
return identities.resolve(
|
|
245
|
-
|
|
274
|
+
typeof rootDir !== "string"
|
|
275
|
+
? project.root
|
|
276
|
+
: path.isAbsolute(rootDir)
|
|
277
|
+
? rootDir
|
|
278
|
+
: path.resolve(project.root, rootDir),
|
|
246
279
|
).path;
|
|
247
280
|
}
|
|
248
281
|
|
|
@@ -265,6 +298,13 @@ function buildProject(
|
|
|
265
298
|
cacheDir: context.pluginCacheDir,
|
|
266
299
|
outDir: context.emitDir,
|
|
267
300
|
passthrough: options.passthrough,
|
|
301
|
+
// `context.emitDir` is ttsx's own temp directory, not an output the project
|
|
302
|
+
// asked for, and tsgo demands an explicit `rootDir` (TS5011) as soon as any
|
|
303
|
+
// `outDir` is in play. Pinning the root tsgo would infer keeps a check-only
|
|
304
|
+
// project runnable without moving its emit (issue #1172); a project that
|
|
305
|
+
// declares `rootDir` is left exactly as it is, which is also the root
|
|
306
|
+
// `resolveRuntimeSourceRoot` published above.
|
|
307
|
+
pinInferredRootDir: true,
|
|
268
308
|
// Emit a source map on the transient entry emit (a PID-isolated temp dir,
|
|
269
309
|
// never the consumer's `outDir`) so the serve path can inline it under the
|
|
270
310
|
// source URL. Routed as a dedicated build option, not a forwarded tsgo
|
|
@@ -345,7 +385,7 @@ function buildEntryProject(
|
|
|
345
385
|
const rootDir = commonAncestorDirectory(path.dirname(entry), context.root);
|
|
346
386
|
const tsconfig = path.join(
|
|
347
387
|
context.root,
|
|
348
|
-
`.ttsx-entry.${
|
|
388
|
+
`.ttsx-entry.${context.runtimeCacheKey}.tsconfig.json`,
|
|
349
389
|
);
|
|
350
390
|
fs.writeFileSync(
|
|
351
391
|
tsconfig,
|
|
@@ -414,8 +454,8 @@ function buildEntryProject(
|
|
|
414
454
|
fs.rmSync(tsconfig, { force: true });
|
|
415
455
|
} catch {
|
|
416
456
|
// Best effort: a leftover synthesized tsconfig must not mask a build
|
|
417
|
-
// failure, and it is
|
|
418
|
-
// project config.
|
|
457
|
+
// failure, and it is runtime-scoped so it can never be mistaken for a
|
|
458
|
+
// real project config.
|
|
419
459
|
}
|
|
420
460
|
}
|
|
421
461
|
}
|
|
@@ -559,6 +599,9 @@ function isDirectorySymlinkTarget(realEntry: string): boolean {
|
|
|
559
599
|
*/
|
|
560
600
|
function collectLinkDirectories(projectRoot: string): string[] {
|
|
561
601
|
const out: string[] = [];
|
|
602
|
+
const identities = createFilesystemPathIdentityContext({
|
|
603
|
+
throwOnRealpathError: false,
|
|
604
|
+
});
|
|
562
605
|
let current = projectRoot;
|
|
563
606
|
for (let depth = 0; depth <= MAX_VIRTUAL_PARENT_DEPTH; depth += 1) {
|
|
564
607
|
out.push(current);
|
|
@@ -570,7 +613,7 @@ function collectLinkDirectories(projectRoot: string): string[] {
|
|
|
570
613
|
break;
|
|
571
614
|
}
|
|
572
615
|
const parent = path.dirname(current);
|
|
573
|
-
if (parent === current || isUnsafeVirtualParent(parent)) {
|
|
616
|
+
if (parent === current || isUnsafeVirtualParent(parent, identities)) {
|
|
574
617
|
break;
|
|
575
618
|
}
|
|
576
619
|
current = parent;
|
|
@@ -578,10 +621,19 @@ function collectLinkDirectories(projectRoot: string): string[] {
|
|
|
578
621
|
return out.reverse();
|
|
579
622
|
}
|
|
580
623
|
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
624
|
+
/**
|
|
625
|
+
* Whether mirroring `directory` would reach a filesystem or temporary root.
|
|
626
|
+
* Identity comparison is required on Windows, where `os.tmpdir()` can carry an
|
|
627
|
+
* 8.3 component while a project created below it is returned in long spelling.
|
|
628
|
+
*/
|
|
629
|
+
function isUnsafeVirtualParent(
|
|
630
|
+
directory: string,
|
|
631
|
+
identities: ReturnType<typeof createFilesystemPathIdentityContext>,
|
|
632
|
+
): boolean {
|
|
633
|
+
const resolved = identities.resolve(directory);
|
|
634
|
+
const root = identities.resolve(path.parse(resolved.path).root);
|
|
635
|
+
const temporaryRoot = identities.resolve(os.tmpdir());
|
|
636
|
+
return resolved.key === root.key || resolved.key === temporaryRoot.key;
|
|
585
637
|
}
|
|
586
638
|
|
|
587
639
|
/**
|
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
parseFlags,
|
|
18
18
|
} from "../../flags/parser";
|
|
19
19
|
import { resolveFlagSpec } from "../../flags/schema";
|
|
20
|
-
import {
|
|
20
|
+
import { resolveSafeCacheCleanupTargets } from "../../internal/resolveSafeCacheCleanupTargets";
|
|
21
21
|
import {
|
|
22
22
|
isPathWithin,
|
|
23
23
|
legacyGlobalCacheTargets,
|
|
@@ -27,6 +27,7 @@ import {
|
|
|
27
27
|
import type { ITtscProjectInputSnapshot } from "../../structures/internal/ITtscProjectInputSnapshot";
|
|
28
28
|
import type { TtscBuildOptions } from "../../structures/internal/TtscBuildOptions";
|
|
29
29
|
import type { TtscSingleFileEmitOptions } from "../../structures/internal/TtscSingleFileEmitOptions";
|
|
30
|
+
import { assertNoSolutionBuild } from "./assertNoSolutionBuild";
|
|
30
31
|
import { getCompilerVersionText } from "./getCompilerVersionText";
|
|
31
32
|
import { resolveCacheDir } from "./resolveCacheDir";
|
|
32
33
|
import { resolveSingleFileOutput } from "./singleFileOutput";
|
|
@@ -206,9 +207,6 @@ function runClean(argv: readonly string[]): number {
|
|
|
206
207
|
const explicitCacheDir = options.cacheDir
|
|
207
208
|
? path.resolve(cwd, options.cacheDir)
|
|
208
209
|
: undefined;
|
|
209
|
-
if (explicitCacheDir !== undefined) {
|
|
210
|
-
assertSafeExplicitCacheDirectory(projectRoot, explicitCacheDir);
|
|
211
|
-
}
|
|
212
210
|
const targets = explicitCacheDir
|
|
213
211
|
? // Explicit `ttsc clean --cache-dir X`: the user names X as the cache to
|
|
214
212
|
// remove for this command, so remove it wholesale plus the legacy
|
|
@@ -222,11 +220,19 @@ function runClean(argv: readonly string[]): number {
|
|
|
222
220
|
// possibly-shared root is never deleted) plus the pre-0.17 machine-global
|
|
223
221
|
// cache so upgraders reclaim that disk.
|
|
224
222
|
[...resolveCleanTargets(projectRoot), ...legacyGlobalCacheTargets()];
|
|
223
|
+
// Check the complete deletion set before removing the first directory. An
|
|
224
|
+
// environment-selected TTSC_GO_CACHE_DIR and a legacy-global cache can be as
|
|
225
|
+
// destructive as an explicit --cache-dir when either equals or contains the
|
|
226
|
+
// project through its lexical spelling or a filesystem alias.
|
|
227
|
+
const safeTargets = resolveSafeCacheCleanupTargets(projectRoot, targets);
|
|
225
228
|
const removed: string[] = [];
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
229
|
+
const visited = new Set<string>();
|
|
230
|
+
for (const target of safeTargets) {
|
|
231
|
+
if (visited.has(target.path)) continue;
|
|
232
|
+
visited.add(target.path);
|
|
233
|
+
if (!target.exists || !fs.existsSync(target.path)) continue;
|
|
234
|
+
fs.rmSync(target.path, { recursive: true, force: true });
|
|
235
|
+
removed.push(target.requestedPath);
|
|
230
236
|
}
|
|
231
237
|
if (removed.length === 0) {
|
|
232
238
|
process.stdout.write(
|
|
@@ -268,24 +274,28 @@ function runCachePaths(argv: readonly string[]): number {
|
|
|
268
274
|
const cacheDir = resolveCacheDir(cwd, options.cacheDir);
|
|
269
275
|
const projectRoot = resolveCleanProjectRoot(cwd, options.tsconfig);
|
|
270
276
|
const paths = resolveSourceBuildCachePaths(projectRoot, cacheDir);
|
|
271
|
-
//
|
|
272
|
-
//
|
|
273
|
-
//
|
|
277
|
+
// Legacy combined roots retained for JSON compatibility. `requiredRoots`
|
|
278
|
+
// identifies the compiled binaries that skip cold builds;
|
|
279
|
+
// `acceleratorRoots` separately identifies the optional Go object cache.
|
|
274
280
|
const cacheableRoots = [
|
|
275
281
|
paths.root,
|
|
276
282
|
...(isPathWithin(paths.goBuildRoot, paths.root) ? [] : [paths.goBuildRoot]),
|
|
277
283
|
];
|
|
284
|
+
const requiredRoots = [paths.pluginRoot];
|
|
285
|
+
const acceleratorRoots = [paths.goBuildRoot];
|
|
278
286
|
if (options.json) {
|
|
279
287
|
process.stdout.write(
|
|
280
288
|
`${JSON.stringify(
|
|
281
289
|
{
|
|
282
290
|
cacheRoot: paths.root,
|
|
291
|
+
acceleratorRoots,
|
|
283
292
|
cacheableRoots,
|
|
284
293
|
cwd,
|
|
285
294
|
goBuildCacheRoot: paths.goBuildRoot,
|
|
286
295
|
goBuildCacheSource: paths.goBuildRootSource,
|
|
287
296
|
pluginCacheRoot: paths.pluginRoot,
|
|
288
297
|
projectRoot,
|
|
298
|
+
requiredRoots,
|
|
289
299
|
},
|
|
290
300
|
null,
|
|
291
301
|
2,
|
|
@@ -300,8 +310,10 @@ function runCachePaths(argv: readonly string[]): number {
|
|
|
300
310
|
` plugin binaries ${paths.pluginRoot}`,
|
|
301
311
|
` go build cache ${paths.goBuildRoot} (${paths.goBuildRootSource})`,
|
|
302
312
|
"",
|
|
303
|
-
"Persist
|
|
304
|
-
...
|
|
313
|
+
"Persist this required cache to skip cold plugin rebuilds:",
|
|
314
|
+
...requiredRoots.map((root) => ` ${root}`),
|
|
315
|
+
"Optionally persist this Go object accelerator for future cache misses:",
|
|
316
|
+
...acceleratorRoots.map((root) => ` ${root}`),
|
|
305
317
|
"",
|
|
306
318
|
].join("\n"),
|
|
307
319
|
);
|
|
@@ -441,6 +453,7 @@ function parseBuildArgs(argv: readonly string[]) {
|
|
|
441
453
|
isPositional: looksLikeInputFile,
|
|
442
454
|
subcommand: "build",
|
|
443
455
|
});
|
|
456
|
+
assertNoSolutionBuild(result, "ttsc:");
|
|
444
457
|
// Defaults: pinned by the previous hand-parser. `quiet` defaults true,
|
|
445
458
|
// `--verbose` flips it to false; `emit` defaults `undefined` so the resolved
|
|
446
459
|
// project controls ordinary build mode. `runCompatibleBuild` applies the
|
|
@@ -9,11 +9,13 @@ import { readProjectConfig } from "../../compiler/internal/project/readProjectCo
|
|
|
9
9
|
import { resolveBinary } from "../../compiler/internal/resolveBinary";
|
|
10
10
|
import { resolveTsgo } from "../../compiler/internal/resolveTsgo";
|
|
11
11
|
import { outputText, spawnNative } from "../../compiler/internal/spawnNative";
|
|
12
|
+
import { createCanonicalTempDirectory } from "../../internal/createCanonicalTempDirectory";
|
|
12
13
|
import {
|
|
13
14
|
type ProjectInputPathIdentityContext,
|
|
14
15
|
createProjectInputPathIdentityContext,
|
|
15
16
|
resolveProjectInputPath,
|
|
16
17
|
} from "../../internal/projectInputPathIdentity";
|
|
18
|
+
import { resolveNodeBinary } from "../../internal/resolveNodeBinary";
|
|
17
19
|
import {
|
|
18
20
|
hasProjectPluginEntries,
|
|
19
21
|
loadProjectPlugins,
|
|
@@ -127,6 +129,9 @@ function resolveTtscserverEnv(argv: readonly string[]): TtscserverEnvironment {
|
|
|
127
129
|
}
|
|
128
130
|
const context = resolveLspExecutionContext(argv);
|
|
129
131
|
const env = lspSidecarEnvironment({
|
|
132
|
+
cwd:
|
|
133
|
+
context.projectContext?.logicalProjectRoot ??
|
|
134
|
+
path.resolve(optionValue(argv, "--cwd") ?? process.cwd()),
|
|
130
135
|
pluginConfigOrigin: context.projectContext?.pluginConfigOrigin,
|
|
131
136
|
tsgoBinary: context.tsgoBinary,
|
|
132
137
|
});
|
|
@@ -170,7 +175,7 @@ export function materializeLSPPluginManifest(manifest: unknown): {
|
|
|
170
175
|
dispose(): void;
|
|
171
176
|
path: string;
|
|
172
177
|
} {
|
|
173
|
-
const directory =
|
|
178
|
+
const directory = createCanonicalTempDirectory("ttsc-lsp-");
|
|
174
179
|
const location = path.join(directory, "plugins.json");
|
|
175
180
|
try {
|
|
176
181
|
fs.writeFileSync(location, JSON.stringify(manifest), {
|
|
@@ -194,17 +199,20 @@ export function materializeLSPPluginManifest(manifest: unknown): {
|
|
|
194
199
|
}
|
|
195
200
|
|
|
196
201
|
function lspSidecarEnvironment(options: {
|
|
202
|
+
cwd: string;
|
|
197
203
|
pluginConfigOrigin: string | undefined;
|
|
198
204
|
tsgoBinary: string;
|
|
199
205
|
}): NodeJS.ProcessEnv {
|
|
200
206
|
const env: NodeJS.ProcessEnv = {
|
|
201
207
|
...process.env,
|
|
202
|
-
TTSC_NODE_BINARY: process.env.TTSC_NODE_BINARY ?? process.execPath,
|
|
203
208
|
TTSC_TSGO_BINARY: options.tsgoBinary,
|
|
204
209
|
TTSC_TTSX_BINARY:
|
|
205
210
|
process.env.TTSC_TTSX_BINARY ??
|
|
206
211
|
path.join(__dirname, "..", "..", "launcher", "ttsx.js"),
|
|
207
212
|
};
|
|
213
|
+
const node = resolveNodeBinary(env, options.cwd);
|
|
214
|
+
if (node === undefined) delete env.TTSC_NODE_BINARY;
|
|
215
|
+
else env.TTSC_NODE_BINARY = node;
|
|
208
216
|
if (options.pluginConfigOrigin === undefined) {
|
|
209
217
|
delete env.TTSC_PLUGIN_CONFIG_DIR;
|
|
210
218
|
} else {
|
|
@@ -318,7 +326,13 @@ function loadLSPProjectPlugins(
|
|
|
318
326
|
pluginConfigDir: pluginConfigOrigin,
|
|
319
327
|
tsconfig: project.identity.logicalConfigPath,
|
|
320
328
|
})
|
|
321
|
-
: {
|
|
329
|
+
: {
|
|
330
|
+
hostInputHashes: {},
|
|
331
|
+
hostInputRealpaths: {},
|
|
332
|
+
hostInputs: [...project.configPaths],
|
|
333
|
+
nativePlugins: [],
|
|
334
|
+
project,
|
|
335
|
+
};
|
|
322
336
|
}
|
|
323
337
|
|
|
324
338
|
function captureInitialLSPProjectInputs(options: {
|
|
@@ -355,6 +369,7 @@ function captureInitialLSPProjectInputs(options: {
|
|
|
355
369
|
);
|
|
356
370
|
}
|
|
357
371
|
const env = lspSidecarEnvironment({
|
|
372
|
+
cwd: options.project.root,
|
|
358
373
|
pluginConfigOrigin: options.pluginConfigOrigin,
|
|
359
374
|
tsgoBinary: options.tsgoBinary,
|
|
360
375
|
});
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
parseFlags,
|
|
12
12
|
} from "../../flags/parser";
|
|
13
13
|
import { resolveFlagSpec } from "../../flags/schema";
|
|
14
|
+
import { assertNoSolutionBuild } from "./assertNoSolutionBuild";
|
|
14
15
|
import { getCompilerVersionText } from "./getCompilerVersionText";
|
|
15
16
|
import { prepareExecution } from "./prepareExecution";
|
|
16
17
|
import { resolveCacheDir } from "./resolveCacheDir";
|
|
@@ -130,6 +131,7 @@ function parseCLI(argv: readonly string[]) {
|
|
|
130
131
|
isPositional: looksLikeEntryFile,
|
|
131
132
|
subcommand: "ttsx",
|
|
132
133
|
});
|
|
134
|
+
assertNoSolutionBuild(result, "ttsx:");
|
|
133
135
|
|
|
134
136
|
const entry = result.positional.find(looksLikeEntryFile);
|
|
135
137
|
if (entry === undefined) {
|
|
@@ -276,6 +278,8 @@ function runPreparedEntry(
|
|
|
276
278
|
depCacheDir,
|
|
277
279
|
emitDir: execution.emitDir,
|
|
278
280
|
emittedFiles: execution.emittedFiles,
|
|
281
|
+
entryFile: execution.entryFile,
|
|
282
|
+
entrySource: execution.entrySource,
|
|
279
283
|
moduleOptions: execution.moduleOptions,
|
|
280
284
|
projectRoot: execution.projectRoot,
|
|
281
285
|
rootDir: execution.rootDir,
|