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
|
@@ -5,12 +5,27 @@
|
|
|
5
5
|
// tsgo's Program.Emit has no hook to inject a custom transformer, so ttsc's
|
|
6
6
|
// driver assembles the per-file emit pipeline by hand (see GetSourceFilesToEmit
|
|
7
7
|
// / GetScriptTransformers / GetOutputPathsFor). That hand-assembly must also
|
|
8
|
-
// reproduce
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
// `
|
|
12
|
-
//
|
|
13
|
-
//
|
|
8
|
+
// reproduce every step the emitter would otherwise run: building the printer's
|
|
9
|
+
// options from the compiler options, the source-map branch a bare printer.Write
|
|
10
|
+
// with a nil generator drops entirely, the `emitBOM` byte-order mark, and the
|
|
11
|
+
// `WriteFileData` the emitter hands its writeFile callback. This file ports
|
|
12
|
+
// internal/compiler/emitter.go's `emitJSFile` PrinterOptions construction and
|
|
13
|
+
// the whole of its `printSourceFile` so a build that goes through a plugin
|
|
14
|
+
// transform honors the same compiler options — and produces the same map (and
|
|
15
|
+
// `//# sourceMappingURL=` trailer, and the same first bytes) — a plain build
|
|
16
|
+
// does.
|
|
17
|
+
//
|
|
18
|
+
// Keep it in sync with that emitter source when the pin is bumped. Anything
|
|
19
|
+
// `emitJSFile` sets and this file omits takes the Go zero value, which silently
|
|
20
|
+
// turns the option off for every project that emits through a plugin transform,
|
|
21
|
+
// and anything `printSourceFile` does around the printer that this file omits
|
|
22
|
+
// is missing from the plugin lane's output even when the option set matches.
|
|
23
|
+
// `printer_options_field_set_matches_pinned_emitter_test.go` fails when the pin
|
|
24
|
+
// changes the PrinterOptions field set,
|
|
25
|
+
// `write_file_data_field_set_matches_pinned_emitter_test.go` fails when it
|
|
26
|
+
// changes the WriteFileData field set, and
|
|
27
|
+
// `emit_plugin_transform_matches_plain_emit_for_printer_options_test.go` fails
|
|
28
|
+
// when a forwarded option stops matching the plain emit.
|
|
14
29
|
package compiler
|
|
15
30
|
|
|
16
31
|
import (
|
|
@@ -25,24 +40,43 @@ import (
|
|
|
25
40
|
|
|
26
41
|
// PrintedFile is the rendered output of one source file in the plugin-transform
|
|
27
42
|
// emit path. JS is the JavaScript text, already carrying a trailing
|
|
28
|
-
// `//# sourceMappingURL=` comment when a map was produced
|
|
29
|
-
//
|
|
30
|
-
//
|
|
43
|
+
// `//# sourceMappingURL=` comment when a map was produced and a leading UTF-8
|
|
44
|
+
// byte order mark when `emitBOM` is on. MapText/MapPath are the external
|
|
45
|
+
// source-map file and its path; both are empty when no external map is written
|
|
46
|
+
// (source maps disabled, or an inline map encoded into the JS).
|
|
31
47
|
type PrintedFile struct {
|
|
32
48
|
JS string
|
|
33
49
|
MapText string
|
|
34
50
|
MapPath string
|
|
51
|
+
// SourceMapUrlPos is the offset of the `//# sourceMappingURL=` trailer in JS,
|
|
52
|
+
// or -1 when no trailer was written — the value tsgo's emitter reports as
|
|
53
|
+
// WriteFileData.SourceMapUrlPos so a caller can locate and rewrite the
|
|
54
|
+
// trailer without re-scanning the text. Like the emitter's, it is the printer
|
|
55
|
+
// writer's text position, taken BEFORE the `emitBOM` mark is prepended, so a
|
|
56
|
+
// BOM build's offset is three bytes short of the trailer's position in the
|
|
57
|
+
// written file. That is the pinned emitter's own behavior
|
|
58
|
+
// (internal/compiler/emitter.go::printSourceFile computes sourceMapUrlPos
|
|
59
|
+
// from the writer and only then calls AddUTF8ByteOrderMark), and this lane
|
|
60
|
+
// exists to match it: "correcting" the offset here would make a plugin build
|
|
61
|
+
// disagree with the plain build of the same project.
|
|
62
|
+
SourceMapUrlPos int
|
|
35
63
|
}
|
|
36
64
|
|
|
37
65
|
// PrintFileWithSourceMap renders sourceFile through a printer built from options
|
|
38
66
|
// and emitContext, optionally generating a source map, mirroring
|
|
39
|
-
// emitter.printSourceFile for the single-file
|
|
67
|
+
// emitter.emitJSFile and emitter.printSourceFile for the single-file
|
|
68
|
+
// plugin-transform path. The PrinterOptions below are emitJSFile's, field for
|
|
69
|
+
// field: `removeComments`, `newLine`, `noEmitHelpers`, `sourceMap`,
|
|
70
|
+
// `inlineSourceMap`, `inlineSources`, and `target`. When
|
|
40
71
|
// `sourceMap`/`inlineSourceMap` is enabled (and the file is not JSON) it builds a
|
|
41
72
|
// sourcemap.Generator, feeds it to the printer so positions are recorded,
|
|
42
|
-
// appends the sourceMappingURL trailer, and returns the
|
|
43
|
-
// (or encodes the map inline).
|
|
44
|
-
//
|
|
45
|
-
//
|
|
73
|
+
// appends the sourceMappingURL trailer, records its offset, and returns the
|
|
74
|
+
// external map text/path (or encodes the map inline). `emitBOM` prepends the
|
|
75
|
+
// UTF-8 byte order mark to the JavaScript afterwards, exactly where
|
|
76
|
+
// printSourceFile does it — outside PrinterOptions, which is why forwarding the
|
|
77
|
+
// whole options struct never reached it. The external map is written without a
|
|
78
|
+
// mark, matching the emitter's own `writeText(sourceMapFilePath, ..., nil)`.
|
|
79
|
+
// host supplies the same directory/casing context tsgo's emitter reads.
|
|
46
80
|
func PrintFileWithSourceMap(
|
|
47
81
|
emitContext *innerprinter.EmitContext,
|
|
48
82
|
node *innerast.Node,
|
|
@@ -53,10 +87,13 @@ func PrintFileWithSourceMap(
|
|
|
53
87
|
sourceMapFilePath string,
|
|
54
88
|
) PrintedFile {
|
|
55
89
|
printer := innerprinter.NewPrinter(innerprinter.PrinterOptions{
|
|
90
|
+
RemoveComments: options.RemoveComments.IsTrue(),
|
|
56
91
|
NewLine: options.NewLine,
|
|
92
|
+
NoEmitHelpers: options.NoEmitHelpers.IsTrue(),
|
|
57
93
|
SourceMap: options.SourceMap.IsTrue(),
|
|
58
94
|
InlineSourceMap: options.InlineSourceMap.IsTrue(),
|
|
59
95
|
InlineSources: options.InlineSources.IsTrue(),
|
|
96
|
+
Target: options.Target,
|
|
60
97
|
}, innerprinter.PrintHandlers{}, emitContext)
|
|
61
98
|
writer := innerprinter.NewTextWriter(options.NewLine.GetNewLineCharacter(), 0)
|
|
62
99
|
|
|
@@ -78,7 +115,7 @@ func PrintFileWithSourceMap(
|
|
|
78
115
|
|
|
79
116
|
printer.Write(node, sourceFile, writer, generator)
|
|
80
117
|
|
|
81
|
-
result := PrintedFile{}
|
|
118
|
+
result := PrintedFile{SourceMapUrlPos: -1}
|
|
82
119
|
if generator != nil {
|
|
83
120
|
url := sourceMappingURL(options, generator, host, jsFilePath, sourceMapFilePath, sourceFile)
|
|
84
121
|
if len(url) > 0 {
|
|
@@ -89,6 +126,7 @@ func PrintFileWithSourceMap(
|
|
|
89
126
|
writer.RawWrite("\n")
|
|
90
127
|
}
|
|
91
128
|
}
|
|
129
|
+
result.SourceMapUrlPos = writer.GetTextPos()
|
|
92
130
|
writer.WriteComment("//# sourceMappingURL=")
|
|
93
131
|
writer.WriteComment(url)
|
|
94
132
|
}
|
|
@@ -100,6 +138,9 @@ func PrintFileWithSourceMap(
|
|
|
100
138
|
writer.WriteLine()
|
|
101
139
|
}
|
|
102
140
|
result.JS = writer.String()
|
|
141
|
+
if options.EmitBOM.IsTrue() {
|
|
142
|
+
result.JS = innerstringutil.AddUTF8ByteOrderMark(result.JS)
|
|
143
|
+
}
|
|
103
144
|
return result
|
|
104
145
|
}
|
|
105
146
|
|
|
@@ -1,13 +1,20 @@
|
|
|
1
1
|
// gen_shims:hand-maintained
|
|
2
2
|
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
3
|
+
// Parts of tsgo's own incremental engine (`tsc --incremental` semantics),
|
|
4
|
+
// exposed from internal/execute/incremental for the two things a ttsc host
|
|
5
|
+
// needs from it:
|
|
6
|
+
//
|
|
7
|
+
// - the reference graph, so transform envelopes can carry the same
|
|
8
|
+
// language-semantic input bound the compiler itself uses for invalidation:
|
|
9
|
+
// per-file direct resolved references and the files that contribute to the
|
|
10
|
+
// global scope;
|
|
11
|
+
// - the build-information emit, so a host that constructs its Program
|
|
12
|
+
// in-process still writes the `.tsbuildinfo` an `incremental` or
|
|
13
|
+
// `composite` project asked for.
|
|
8
14
|
package compiler
|
|
9
15
|
|
|
10
16
|
import (
|
|
17
|
+
"context"
|
|
11
18
|
_ "unsafe"
|
|
12
19
|
|
|
13
20
|
innerast "github.com/microsoft/typescript-go/internal/ast"
|
|
@@ -15,11 +22,41 @@ import (
|
|
|
15
22
|
innercompiler "github.com/microsoft/typescript-go/internal/compiler"
|
|
16
23
|
"github.com/microsoft/typescript-go/internal/tspath"
|
|
17
24
|
|
|
18
|
-
//
|
|
19
|
-
//
|
|
20
|
-
|
|
25
|
+
// Imported for EmitFreshWithBuildInfo below, and for the linknamed symbols
|
|
26
|
+
// further down: compiling the package into every shim consumer is what makes
|
|
27
|
+
// those references resolve.
|
|
28
|
+
"github.com/microsoft/typescript-go/internal/execute/incremental"
|
|
21
29
|
)
|
|
22
30
|
|
|
31
|
+
// EmitFreshWithBuildInfo runs a full emit through tsgo's own incremental
|
|
32
|
+
// program, so an `incremental` or `composite` project gets the `.tsbuildinfo`
|
|
33
|
+
// tsgo would have written, in the exact format and location
|
|
34
|
+
// `outputpaths.GetBuildInfoFileName` resolves from the compiler options.
|
|
35
|
+
//
|
|
36
|
+
// This is the emit half of `tsc.go::performIncrementalCompilation`, which the
|
|
37
|
+
// tsgo CLI takes whenever `CompilerOptions.IsIncremental()`. A host that builds
|
|
38
|
+
// its Program in-process (ttsc's driver, and therefore every plugin sidecar
|
|
39
|
+
// emitting through it) never reaches that CLI path, so without this the build
|
|
40
|
+
// information is silently dropped even though the options parsed cleanly.
|
|
41
|
+
//
|
|
42
|
+
// "Fresh" is the load-bearing word: no previous snapshot is supplied, so
|
|
43
|
+
// `programToSnapshot` marks every file changed and this emits the whole program
|
|
44
|
+
// exactly as `Program.Emit` does, then writes the build info. A ttsc plugin's
|
|
45
|
+
// output is not a pure function of the source text a build info records — it
|
|
46
|
+
// also depends on the plugin binary, its config file, and its contributors —
|
|
47
|
+
// so reusing a previous snapshot to skip a file would serve stale transformed
|
|
48
|
+
// output. Producing the record is sound; consuming it needs plugin identity in
|
|
49
|
+
// the invalidation key first.
|
|
50
|
+
func EmitFreshWithBuildInfo(ctx context.Context, program *Program, options EmitOptions) *EmitResult {
|
|
51
|
+
incrementalProgram := incremental.NewProgram(
|
|
52
|
+
program,
|
|
53
|
+
nil,
|
|
54
|
+
incremental.CreateHost(program.Host()),
|
|
55
|
+
false,
|
|
56
|
+
)
|
|
57
|
+
return incrementalProgram.Emit(ctx, options)
|
|
58
|
+
}
|
|
59
|
+
|
|
23
60
|
//go:linkname incrementalGetReferencedFiles github.com/microsoft/typescript-go/internal/execute/incremental.getReferencedFiles
|
|
24
61
|
func incrementalGetReferencedFiles(program *innercompiler.Program, file *innerast.SourceFile) *collections.Set[tspath.Path]
|
|
25
62
|
|
package/src/TtscCompiler.ts
CHANGED
|
@@ -6,7 +6,10 @@ import { resolveProjectConfig } from "./compiler/internal/project/resolveProject
|
|
|
6
6
|
import { resolveBinary } from "./compiler/internal/resolveBinary";
|
|
7
7
|
import { createProcessDiagnostic } from "./compiler/internal/runBuild";
|
|
8
8
|
import { transformProjectInMemory } from "./compiler/internal/transformProjectInMemory";
|
|
9
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
type SafeCacheCleanupTarget,
|
|
11
|
+
resolveSafeCacheCleanupTargets,
|
|
12
|
+
} from "./internal/resolveSafeCacheCleanupTargets";
|
|
10
13
|
import { resolveCleanTargets } from "./plugin/internal/buildSourcePlugin";
|
|
11
14
|
import { loadProjectPlugins } from "./plugin/internal/loadProjectPlugins";
|
|
12
15
|
import type { ITtscCompilerContext } from "./structures/ITtscCompilerContext";
|
|
@@ -86,15 +89,16 @@ export class TtscCompiler {
|
|
|
86
89
|
/**
|
|
87
90
|
* Remove compiled cache artifacts for this compiler instance.
|
|
88
91
|
*
|
|
89
|
-
* Removes
|
|
90
|
-
*
|
|
91
|
-
*
|
|
92
|
-
* project-local caches. A user-provided `GOCACHE` is never removed.
|
|
92
|
+
* Removes an explicit `cacheDir` wholesale. Otherwise removes the plugin
|
|
93
|
+
* binary subdirectory, a safely identified ttsc-owned Go build cache
|
|
94
|
+
* (including an external `TTSC_GO_CACHE_DIR`), and the two legacy
|
|
95
|
+
* project-local caches. A user-provided `GOCACHE` is never removed. Every
|
|
96
|
+
* resolved deletion target is validated before the first removal. The cache
|
|
93
97
|
* location comes from this instance's `cacheDir` and environment
|
|
94
98
|
* (`TTSC_CACHE_DIR` / `TTSC_GO_CACHE_DIR`), defaulting to
|
|
95
|
-
* `<workspaceRoot>/node_modules/.cache/ttsc`.
|
|
96
|
-
*
|
|
97
|
-
*
|
|
99
|
+
* `<workspaceRoot>/node_modules/.cache/ttsc`. Any resolved cache target that
|
|
100
|
+
* equals or contains the project, or names a filesystem root, is rejected
|
|
101
|
+
* before any directory is removed.
|
|
98
102
|
*
|
|
99
103
|
* @returns Cache directories that were removed.
|
|
100
104
|
*/
|
|
@@ -105,31 +109,35 @@ export class TtscCompiler {
|
|
|
105
109
|
path.join(projectRoot, ".ttsc"),
|
|
106
110
|
];
|
|
107
111
|
const explicitCacheDir = this.resolveCacheDir();
|
|
112
|
+
let targets: string[];
|
|
108
113
|
if (explicitCacheDir !== undefined) {
|
|
109
|
-
assertSafeExplicitCacheDirectory(projectRoot, explicitCacheDir);
|
|
110
114
|
// An explicit constructor `cacheDir` names the cache directory for this
|
|
111
115
|
// instance — exactly like `ttsc clean --cache-dir X` on the CLI — so
|
|
112
116
|
// remove it wholesale plus the legacy project-local caches. This keeps
|
|
113
117
|
// the programmatic and CLI clean contracts identical for an explicit
|
|
114
118
|
// cache dir.
|
|
115
|
-
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
resolveCleanTargets(
|
|
119
|
+
targets = [explicitCacheDir, ...legacyTargets];
|
|
120
|
+
} else {
|
|
121
|
+
// Default / `context.env.TTSC_CACHE_DIR`: resolve the cache root and the Go
|
|
122
|
+
// build cache (`TTSC_GO_CACHE_DIR`) from this instance's effective
|
|
123
|
+
// environment — the same `{ ...process.env, ...context.env }` that
|
|
124
|
+
// prepare()/compile()/transform() build with — then remove only the
|
|
125
|
+
// ttsc-owned subdirectories, so a possibly-shared root is never deleted and
|
|
126
|
+
// a user-provided `GOCACHE` is never touched. Using the effective env (not
|
|
127
|
+
// ambient `process.env`) makes clean() remove exactly the artifacts this
|
|
128
|
+
// instance owns, including a `TTSC_GO_CACHE_DIR` supplied only in
|
|
129
|
+
// `context.env`.
|
|
130
|
+
targets = resolveCleanTargets(
|
|
128
131
|
projectRoot,
|
|
129
132
|
this.resolvePluginCacheDir(),
|
|
130
133
|
this.resolveEffectiveEnv(),
|
|
131
|
-
)
|
|
132
|
-
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
// Validate the complete deletion set before removing the first directory.
|
|
137
|
+
// This includes an environment-selected TTSC_GO_CACHE_DIR and project-local
|
|
138
|
+
// legacy locations, not only an explicit constructor cacheDir.
|
|
139
|
+
const safeTargets = resolveSafeCacheCleanupTargets(projectRoot, targets);
|
|
140
|
+
return removeExistingDirectories(safeTargets);
|
|
133
141
|
}
|
|
134
142
|
|
|
135
143
|
/**
|
|
@@ -234,24 +242,29 @@ export class TtscCompiler {
|
|
|
234
242
|
* The effective environment for this instance's source-plugin builds and
|
|
235
243
|
* clean targets: `context.env` merged over `process.env`, matching the
|
|
236
244
|
* documented {@link ITtscCompilerContext.env} contract that child compiler,
|
|
237
|
-
* native-plugin,
|
|
238
|
-
* fresh object so callers never mutate the shared
|
|
239
|
-
* `context.env` was supplied this is a plain copy of
|
|
240
|
-
* default behavior is unchanged.
|
|
245
|
+
* native-plugin, native-host, and isolated descriptor processes already
|
|
246
|
+
* receive. Returned as a fresh object so callers never mutate the shared
|
|
247
|
+
* `process.env`; when no `context.env` was supplied this is a plain copy of
|
|
248
|
+
* `process.env`, so CLI / default behavior is unchanged.
|
|
241
249
|
*/
|
|
242
250
|
private resolveEffectiveEnv(): NodeJS.ProcessEnv {
|
|
243
251
|
return { ...process.env, ...this.context.env };
|
|
244
252
|
}
|
|
245
253
|
}
|
|
246
254
|
|
|
247
|
-
function removeExistingDirectories(
|
|
255
|
+
function removeExistingDirectories(
|
|
256
|
+
directories: readonly SafeCacheCleanupTarget[],
|
|
257
|
+
): string[] {
|
|
248
258
|
const removed: string[] = [];
|
|
249
|
-
|
|
250
|
-
|
|
259
|
+
const visited = new Set<string>();
|
|
260
|
+
for (const directory of directories) {
|
|
261
|
+
if (visited.has(directory.path)) continue;
|
|
262
|
+
visited.add(directory.path);
|
|
263
|
+
if (!directory.exists || !fs.existsSync(directory.path)) {
|
|
251
264
|
continue;
|
|
252
265
|
}
|
|
253
|
-
fs.rmSync(directory, { recursive: true, force: true });
|
|
254
|
-
removed.push(directory);
|
|
266
|
+
fs.rmSync(directory.path, { recursive: true, force: true });
|
|
267
|
+
removed.push(directory.requestedPath);
|
|
255
268
|
}
|
|
256
269
|
return removed;
|
|
257
270
|
}
|
|
@@ -265,6 +278,9 @@ interface ProjectTransformation {
|
|
|
265
278
|
dependencies?: Record<string, string[]>;
|
|
266
279
|
dependenciesComplete?: string[];
|
|
267
280
|
graph?: ITtscCompilerTransformation.IReferenceGraph;
|
|
281
|
+
hostInputHashes?: Record<string, string | null>;
|
|
282
|
+
hostInputRealpaths?: Record<string, string | null>;
|
|
283
|
+
hostInputs?: string[];
|
|
268
284
|
result: TtscBuildResult;
|
|
269
285
|
typescript: Record<string, string>;
|
|
270
286
|
volatile?: string[];
|
|
@@ -382,6 +398,9 @@ function toCompilerTransformation(
|
|
|
382
398
|
dependencies,
|
|
383
399
|
dependenciesComplete,
|
|
384
400
|
graph,
|
|
401
|
+
hostInputHashes,
|
|
402
|
+
hostInputRealpaths,
|
|
403
|
+
hostInputs,
|
|
385
404
|
result,
|
|
386
405
|
typescript,
|
|
387
406
|
volatile,
|
|
@@ -390,6 +409,9 @@ function toCompilerTransformation(
|
|
|
390
409
|
...(dependencies === undefined ? {} : { dependencies }),
|
|
391
410
|
...(dependenciesComplete === undefined ? {} : { dependenciesComplete }),
|
|
392
411
|
...(graph === undefined ? {} : { graph }),
|
|
412
|
+
...(hostInputHashes === undefined ? {} : { hostInputHashes }),
|
|
413
|
+
...(hostInputRealpaths === undefined ? {} : { hostInputRealpaths }),
|
|
414
|
+
...(hostInputs === undefined ? {} : { hostInputs }),
|
|
393
415
|
...(volatile === undefined ? {} : { volatile }),
|
|
394
416
|
};
|
|
395
417
|
if (result.status === 0 && !hasErrorDiagnostics(result.diagnostics)) {
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
|
-
import os from "node:os";
|
|
3
2
|
import path from "node:path";
|
|
4
3
|
|
|
4
|
+
import { createCanonicalTempDirectory } from "../../internal/createCanonicalTempDirectory";
|
|
5
|
+
|
|
5
6
|
export interface CapturedProcessOutput {
|
|
6
7
|
/** Close the descriptors and remove the backing files. */
|
|
7
8
|
dispose(): void;
|
|
@@ -32,7 +33,7 @@ export interface CapturedProcessOutput {
|
|
|
32
33
|
* bytes.
|
|
33
34
|
*/
|
|
34
35
|
export function captureProcessOutput(): CapturedProcessOutput {
|
|
35
|
-
const directory =
|
|
36
|
+
const directory = createCanonicalTempDirectory("ttsc-spawn-");
|
|
36
37
|
const stdoutPath = path.join(directory, "stdout");
|
|
37
38
|
const stderrPath = path.join(directory, "stderr");
|
|
38
39
|
const stdoutFd = fs.openSync(stdoutPath, "w+");
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
|
-
import os from "node:os";
|
|
3
2
|
import path from "node:path";
|
|
4
3
|
|
|
4
|
+
import { createCanonicalTempDirectory } from "../../internal/createCanonicalTempDirectory";
|
|
5
5
|
import { hasProjectPluginEntries } from "../../plugin/internal/loadProjectPlugins";
|
|
6
6
|
import type { ITtscCompilerContext } from "../../structures/ITtscCompilerContext";
|
|
7
7
|
import type { ITtscCompilerDiagnostic } from "../../structures/ITtscCompilerDiagnostic";
|
|
@@ -11,6 +11,7 @@ import { buildNativeCompiler } from "./buildNativeCompiler";
|
|
|
11
11
|
import { isOutsideRelativePath, packageRootDir } from "./paths";
|
|
12
12
|
import { readProjectConfig } from "./project/readProjectConfig";
|
|
13
13
|
import { runBuild } from "./runBuild";
|
|
14
|
+
import { inheritedSidecarEnv } from "./sharedHostHelpers";
|
|
14
15
|
import { outputText, spawnNative } from "./spawnNative";
|
|
15
16
|
|
|
16
17
|
/**
|
|
@@ -50,7 +51,7 @@ export function compileProjectInMemory(options: ITtscCompilerContext): {
|
|
|
50
51
|
["api-compile", "--cwd", project.root, "--tsconfig", tsconfig],
|
|
51
52
|
{
|
|
52
53
|
cwd: project.root,
|
|
53
|
-
env:
|
|
54
|
+
env: inheritedSidecarEnv(options.env),
|
|
54
55
|
},
|
|
55
56
|
);
|
|
56
57
|
if (res.error) {
|
|
@@ -110,7 +111,7 @@ function compileProjectWithPlugins(
|
|
|
110
111
|
output: Record<string, string>;
|
|
111
112
|
result: TtscBuildResult;
|
|
112
113
|
} {
|
|
113
|
-
const tempRoot =
|
|
114
|
+
const tempRoot = createCanonicalTempDirectory("ttsc-api-output-");
|
|
114
115
|
const tempOutDir = path.join(tempRoot, "out");
|
|
115
116
|
try {
|
|
116
117
|
const result = runBuild({
|
|
@@ -119,6 +120,13 @@ function compileProjectWithPlugins(
|
|
|
119
120
|
emit: true,
|
|
120
121
|
forceListEmittedFiles: true,
|
|
121
122
|
outDir: tempOutDir,
|
|
123
|
+
// The temp directory is an `outDir` this lane injected so the emit can be
|
|
124
|
+
// read back as strings; the project need not declare one at all. tsgo
|
|
125
|
+
// answers an inferred common source directory with TS5011 as soon as any
|
|
126
|
+
// `outDir` is in play, so pin the root it would infer. The keys
|
|
127
|
+
// `outputKeyMapper` builds are unchanged by it — that root is exactly the
|
|
128
|
+
// layout tsgo already lays the emit out against (issue #1172).
|
|
129
|
+
pinInferredRootDir: true,
|
|
122
130
|
quiet: true,
|
|
123
131
|
resolvedProject: project,
|
|
124
132
|
structuredDiagnostics: true,
|
|
@@ -20,6 +20,8 @@ import { isOutsideRelativePath } from "./paths";
|
|
|
20
20
|
* Returns `null` when no matching output file is found on disk.
|
|
21
21
|
*/
|
|
22
22
|
export function resolveEmittedJavaScript(options: {
|
|
23
|
+
/** Skip trailing-stem recovery when exact source ownership is required. */
|
|
24
|
+
allowStemFallback?: boolean;
|
|
23
25
|
/** Pre-computed list of emitted paths; when absent `outDir` is scanned. */
|
|
24
26
|
emittedFiles?: readonly string[];
|
|
25
27
|
outDir: string;
|
|
@@ -45,6 +47,10 @@ export function resolveEmittedJavaScript(options: {
|
|
|
45
47
|
}
|
|
46
48
|
}
|
|
47
49
|
|
|
50
|
+
if (options.allowStemFallback === false) {
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
|
|
48
54
|
// Score the pre-computed emit list first (cheap). When it yields nothing —
|
|
49
55
|
// because the list is incomplete (a native transform host such as typia emits
|
|
50
56
|
// without printing the `--listEmittedFiles` lines) or because the emit landed
|