@ttsc/wasm 0.30.4 → 0.31.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.
Files changed (174) hide show
  1. package/README.md +3 -3
  2. package/build/build-wasm.cjs +5 -4
  3. package/build/go-build-cache.cjs +347 -0
  4. package/build/pack-prepare.cjs +3 -2
  5. package/cmd/ttsc-wasm/main.go +22 -10
  6. package/cmd/ttsc-wasm/main_wasm.go +2 -2
  7. package/dist/.ttsc-wasm-build.json +138 -58
  8. package/dist/go.mod +7 -5
  9. package/dist/ttsc.wasm +2 -2
  10. package/go.mod +7 -5
  11. package/go.sum +10 -10
  12. package/host/api.go +34 -41
  13. package/host/doc.go +7 -6
  14. package/host/expose.go +42 -0
  15. package/host/fountain.go +192 -22
  16. package/host/host.go +10 -25
  17. package/host/host_native.go +3 -5
  18. package/host/invoke.go +133 -0
  19. package/host/plugin.go +37 -72
  20. package/host/result.go +108 -0
  21. package/lib/src/BootTtscWorkerTerminationError.d.ts +20 -0
  22. package/lib/src/BootTtscWorkerTerminationError.js +20 -0
  23. package/lib/src/BootTtscWorkerTerminationError.js.map +1 -1
  24. package/lib/src/MemFSError.d.ts +21 -2
  25. package/lib/src/MemFSError.js +25 -2
  26. package/lib/src/MemFSError.js.map +1 -1
  27. package/lib/src/bootTtsc.d.ts +49 -2
  28. package/lib/src/bootTtsc.js +89 -23
  29. package/lib/src/bootTtsc.js.map +1 -1
  30. package/lib/src/createMemFS.d.ts +45 -0
  31. package/lib/src/createMemFS.js +269 -66
  32. package/lib/src/createMemFS.js.map +1 -1
  33. package/lib/src/parseResult.d.ts +19 -0
  34. package/lib/src/parseResult.js +19 -0
  35. package/lib/src/parseResult.js.map +1 -1
  36. package/lib/src/structures/IBootResult.d.ts +20 -2
  37. package/lib/src/structures/IBootTtscOptions.d.ts +28 -6
  38. package/lib/src/structures/IFileStats.d.ts +51 -0
  39. package/lib/src/structures/IMemFSHost.d.ts +89 -0
  40. package/lib/src/structures/ITtscApi.d.ts +154 -9
  41. package/lib/src/structures/ITtscBuildOpts.d.ts +18 -1
  42. package/lib/src/structures/ITtscCompileResult.d.ts +20 -2
  43. package/lib/src/structures/ITtscDiagnostic.d.ts +25 -1
  44. package/lib/src/structures/ITtscFileQuery.d.ts +19 -1
  45. package/lib/src/structures/ITtscFountainDiagnosticsResult.d.ts +20 -1
  46. package/lib/src/structures/ITtscNodeAtPositionResult.d.ts +18 -1
  47. package/lib/src/structures/ITtscNodeInfo.d.ts +23 -2
  48. package/lib/src/structures/ITtscPluginOpts.d.ts +24 -3
  49. package/lib/src/structures/ITtscPositionQuery.d.ts +21 -4
  50. package/lib/src/structures/ITtscReleaseSnapshotResult.d.ts +22 -2
  51. package/lib/src/structures/ITtscResult.d.ts +31 -5
  52. package/lib/src/structures/ITtscSnapshotHandle.d.ts +19 -1
  53. package/lib/src/structures/ITtscSnapshotResult.d.ts +22 -1
  54. package/lib/src/structures/ITtscSnapshotsResult.d.ts +19 -1
  55. package/lib/src/structures/ITtscSourceFileTextResult.d.ts +19 -1
  56. package/lib/src/structures/ITtscSourceFilesResult.d.ts +23 -2
  57. package/lib/src/structures/ITtscSymbolAtPositionResult.d.ts +18 -1
  58. package/lib/src/structures/ITtscSymbolDeclaration.d.ts +25 -2
  59. package/lib/src/structures/ITtscSymbolInfo.d.ts +19 -1
  60. package/lib/src/structures/ITtscTransformResult.d.ts +21 -3
  61. package/lib/src/structures/ITtscTypeAtPositionResult.d.ts +18 -1
  62. package/lib/src/structures/ITtscTypeInfo.d.ts +19 -1
  63. package/lib/src/structures/ITtscVersion.d.ts +28 -1
  64. package/lib/src/structures/IWasmExecFS.d.ts +310 -0
  65. package/package.json +4 -2
  66. package/shim-vendor/shim/ast/enums_gen.go +4 -2
  67. package/shim-vendor/shim/ast/go.mod +5 -5
  68. package/shim-vendor/shim/ast/go.sum +10 -10
  69. package/shim-vendor/shim/ast/lint.go +1088 -20
  70. package/shim-vendor/shim/ast/parent.go +38 -22
  71. package/shim-vendor/shim/ast/safe_text.go +48 -26
  72. package/shim-vendor/shim/ast/shim.go +1307 -20
  73. package/shim-vendor/shim/ast/test/next_jsdoc_comment_location_reaches_variable_statement_test.go +51 -0
  74. package/shim-vendor/shim/ast/test/node_text_joins_multi_hop_qualified_name_test.go +24 -9
  75. package/shim-vendor/shim/ast/test/node_text_joins_one_hop_qualified_name_test.go +9 -5
  76. package/shim-vendor/shim/ast/test/node_text_returns_empty_for_nil_test.go +13 -5
  77. package/shim-vendor/shim/ast/test/node_text_returns_identifier_text_test.go +12 -5
  78. package/shim-vendor/shim/ast/test/node_text_skips_empty_qualified_left_test.go +35 -5
  79. package/shim-vendor/shim/astnav/go.mod +5 -5
  80. package/shim-vendor/shim/astnav/go.sum +12 -10
  81. package/shim-vendor/shim/astnav/shim.go +9 -0
  82. package/shim-vendor/shim/bundled/go.mod +7 -1
  83. package/shim-vendor/shim/bundled/go.sum +12 -0
  84. package/shim-vendor/shim/checker/enums_gen.go +4 -2
  85. package/shim-vendor/shim/checker/extra-shim.json +6 -0
  86. package/shim-vendor/shim/checker/go.mod +5 -5
  87. package/shim-vendor/shim/checker/go.sum +10 -10
  88. package/shim-vendor/shim/checker/node_builder_fields_gen.go +19 -0
  89. package/shim-vendor/shim/checker/shim.go +827 -114
  90. package/shim-vendor/shim/compiler/emit_sourcemap.go +68 -29
  91. package/shim-vendor/shim/compiler/emitassemble.go +36 -2
  92. package/shim-vendor/shim/compiler/emithook.go +13 -3
  93. package/shim-vendor/shim/compiler/go.mod +5 -5
  94. package/shim-vendor/shim/compiler/go.sum +10 -10
  95. package/shim-vendor/shim/compiler/incremental.go +56 -20
  96. package/shim-vendor/shim/compiler/resolution.go +92 -9
  97. package/shim-vendor/shim/core/enums_gen.go +2 -2
  98. package/shim-vendor/shim/core/go.mod +6 -1
  99. package/shim-vendor/shim/core/go.sum +10 -0
  100. package/shim-vendor/shim/core/modulekind.go +9 -0
  101. package/shim-vendor/shim/core/shim.go +157 -6
  102. package/shim-vendor/shim/diagnosticwriter/go.mod +10 -1
  103. package/shim-vendor/shim/diagnosticwriter/go.sum +20 -0
  104. package/shim-vendor/shim/diagnosticwriter/lint.go +188 -10
  105. package/shim-vendor/shim/diagnosticwriter/shim.go +14 -0
  106. package/shim-vendor/shim/lsp/go.mod +5 -5
  107. package/shim-vendor/shim/lsp/go.sum +10 -10
  108. package/shim-vendor/shim/lsp/shim.go +78 -2
  109. package/shim-vendor/shim/parser/go.mod +10 -1
  110. package/shim-vendor/shim/parser/go.sum +22 -0
  111. package/shim-vendor/shim/printer/emithost.go +46 -1
  112. package/shim-vendor/shim/printer/go.mod +5 -5
  113. package/shim-vendor/shim/printer/go.sum +10 -10
  114. package/shim-vendor/shim/printer/shim.go +114 -7
  115. package/shim-vendor/shim/printer/sourcemap.go +55 -0
  116. package/shim-vendor/shim/scanner/go.mod +10 -1
  117. package/shim-vendor/shim/scanner/go.sum +20 -0
  118. package/shim-vendor/shim/scanner/regexp.go +19 -4
  119. package/shim-vendor/shim/scanner/shim.go +3 -0
  120. package/shim-vendor/shim/stringutil/extra-shim.json +1 -0
  121. package/shim-vendor/shim/stringutil/go.mod +5 -0
  122. package/shim-vendor/shim/stringutil/go.sum +2 -0
  123. package/shim-vendor/shim/stringutil/shim.go +119 -0
  124. package/shim-vendor/shim/transformers/go.mod +5 -5
  125. package/shim-vendor/shim/transformers/go.sum +12 -10
  126. package/shim-vendor/shim/transformers/shim.go +12 -3
  127. package/shim-vendor/shim/tsoptions/command_line_raw.go +44 -0
  128. package/shim-vendor/shim/tsoptions/go.mod +10 -1
  129. package/shim-vendor/shim/tsoptions/go.sum +22 -0
  130. package/shim-vendor/shim/tsoptions/shim.go +1 -1
  131. package/shim-vendor/shim/tspath/go.mod +1 -1
  132. package/shim-vendor/shim/tspath/go.sum +6 -0
  133. package/shim-vendor/shim/vfs/cachedvfs/go.mod +3 -1
  134. package/shim-vendor/shim/vfs/cachedvfs/go.sum +12 -0
  135. package/shim-vendor/shim/vfs/decode.go +26 -0
  136. package/shim-vendor/shim/vfs/decode_test.go +42 -0
  137. package/shim-vendor/shim/vfs/go.mod +7 -1
  138. package/shim-vendor/shim/vfs/go.sum +12 -0
  139. package/shim-vendor/shim/vfs/osvfs/go.mod +7 -1
  140. package/shim-vendor/shim/vfs/osvfs/go.sum +12 -0
  141. package/src/BootTtscWorkerTerminationError.ts +22 -0
  142. package/src/MemFSError.ts +29 -2
  143. package/src/bootTtsc.ts +104 -28
  144. package/src/createMemFS.ts +291 -64
  145. package/src/parseResult.ts +19 -0
  146. package/src/structures/IBootResult.ts +21 -2
  147. package/src/structures/IBootTtscOptions.ts +32 -6
  148. package/src/structures/IFileStats.ts +65 -0
  149. package/src/structures/IMemFSHost.ts +97 -0
  150. package/src/structures/ITtscApi.ts +154 -9
  151. package/src/structures/ITtscBuildOpts.ts +19 -1
  152. package/src/structures/ITtscCompileResult.ts +21 -2
  153. package/src/structures/ITtscDiagnostic.ts +32 -1
  154. package/src/structures/ITtscFileQuery.ts +19 -1
  155. package/src/structures/ITtscFountainDiagnosticsResult.ts +20 -1
  156. package/src/structures/ITtscNodeAtPositionResult.ts +18 -1
  157. package/src/structures/ITtscNodeInfo.ts +27 -2
  158. package/src/structures/ITtscPluginOpts.ts +28 -3
  159. package/src/structures/ITtscPositionQuery.ts +21 -4
  160. package/src/structures/ITtscReleaseSnapshotResult.ts +22 -2
  161. package/src/structures/ITtscResult.ts +34 -5
  162. package/src/structures/ITtscSnapshotHandle.ts +19 -1
  163. package/src/structures/ITtscSnapshotResult.ts +22 -1
  164. package/src/structures/ITtscSnapshotsResult.ts +19 -1
  165. package/src/structures/ITtscSourceFileTextResult.ts +19 -1
  166. package/src/structures/ITtscSourceFilesResult.ts +23 -2
  167. package/src/structures/ITtscSymbolAtPositionResult.ts +18 -1
  168. package/src/structures/ITtscSymbolDeclaration.ts +27 -2
  169. package/src/structures/ITtscSymbolInfo.ts +23 -1
  170. package/src/structures/ITtscTransformResult.ts +22 -3
  171. package/src/structures/ITtscTypeAtPositionResult.ts +18 -1
  172. package/src/structures/ITtscTypeInfo.ts +20 -1
  173. package/src/structures/ITtscVersion.ts +33 -1
  174. package/src/structures/IWasmExecFS.ts +336 -0
@@ -5,25 +5,21 @@
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 every step the emitter would otherwise run: building the printer's
8
+ // reproduce the selected text/map assembly steps: building the printer's
9
9
  // options from the compiler options, the source-map branch a bare printer.Write
10
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
11
+ // trailer position the emitter places in WriteFileData. This file ports
12
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.
13
+ // its printing, source-map and BOM assembly policy. The driver owns writing
14
+ // returned artifacts and its metadata; upstream diagnostic/write-result and
15
+ // SourceMaps receipt machinery is not reproduced by this helper. Byte and map
16
+ // compatibility depends on the actual transformed nodes and retained provenance.
17
17
  //
18
18
  // Keep it in sync with that emitter source when the pin is bumped. Anything
19
19
  // `emitJSFile` sets and this file omits takes the Go zero value, which silently
20
20
  // turns the option off for every project that emits through a plugin transform,
21
21
  // and anything `printSourceFile` does around the printer that this file omits
22
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
23
  // `emit_plugin_transform_matches_plain_emit_for_printer_options_test.go` fails
28
24
  // when a forwarded option stops matching the plain emit.
29
25
  package compiler
@@ -39,17 +35,32 @@ import (
39
35
  )
40
36
 
41
37
  // PrintedFile is the rendered output of one source file in the plugin-transform
42
- // emit path. JS is the JavaScript text, already carrying a trailing
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).
38
+ // emit path. JS is the script text, carrying a sourceMappingURL trailer when
39
+ // its selected URL is nonempty and a leading UTF-8 BOM when emitBOM is on.
40
+ // MapText/MapPath contain external map text and its selected destination only
41
+ // when mapping is enabled, maps are not inline and that destination is nonempty.
42
+ // They are otherwise empty. These are returned artifacts, not write receipts.
43
+ //
44
+ // @evidence contracts/common.md#principled-implementation The record separates emitted script, optional external map and map destination, retaining the pinned emitter's pre-BOM trailer coordinate rather than mixing file bytes with writer positions.
45
+ // @evidence contracts/common.md#clear-and-simple-design One per-file result carries related output artifacts; absent external maps use empty values and absent trailers use the documented negative sentinel.
46
+ // @evidence contracts/common.md#prohibited-implementation-shortcuts The sentinel and pre-BOM coordinate are compiler protocol values, not patched expected answers; no foreign state or consumer-specific output is introduced.
47
+ // @evidence contracts/common.md#meaningful-documentation Native prose explains map absence, inline output and BOM coordinate effects; every member has native documentation separated by blank source lines.
48
+ // @evidence contracts/portability.md#os-neutral-implementation MapPath preserves the host-resolved native output destination while JS contains URI trailer spelling; the fields keep those distinct rather than equating URL and filesystem identity.
49
+ // @evidenceExclude contracts/performance.md#efficient-algorithms This record represents output and does not choose the printing algorithm.
50
+ // @evidenceExclude contracts/performance.md#reuse-equivalent-work This output record does not coordinate computation across consumers.
51
+ // @evidenceExclude contracts/performance.md#bound-retention-and-release-resources Storage lifetime belongs to the printing operation and its caller, not independently to the result declaration.
47
52
  type PrintedFile struct {
48
- JS string
53
+ // JS contains emitted script text, optional map trailer and optional BOM.
54
+ JS string
55
+
56
+ // MapText contains the external map JSON, or empty text for inline or absent maps.
49
57
  MapText string
58
+
59
+ // MapPath is the destination for MapText, or empty when no external map is emitted.
50
60
  MapPath string
61
+
51
62
  // 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
63
+ // or -1 when no trailer was written, the value tsgo's emitter reports as
53
64
  // WriteFileData.SourceMapUrlPos so a caller can locate and rewrite the
54
65
  // trailer without re-scanning the text. Like the emitter's, it is the printer
55
66
  // writer's text position, taken BEFORE the `emitBOM` mark is prepended, so a
@@ -62,10 +73,11 @@ type PrintedFile struct {
62
73
  SourceMapUrlPos int
63
74
  }
64
75
 
65
- // PrintFileWithSourceMap renders sourceFile through a printer built from options
66
- // and emitContext, optionally generating a source map, mirroring
67
- // emitter.emitJSFile and emitter.printSourceFile for the single-file
68
- // plugin-transform path. The PrinterOptions below are emitJSFile's, field for
76
+ // PrintFileWithSourceMap renders node from sourceFile through a printer built
77
+ // from options and emitContext, optionally generating a source map, mirroring
78
+ // their text/map assembly for the single-file plugin-transform path. It returns
79
+ // artifacts; it does not reproduce upstream writes, diagnostics, SourceMaps
80
+ // receipts or complete WriteFileData. The PrinterOptions below are emitJSFile's, field for
69
81
  // field: `removeComments`, `newLine`, `noEmitHelpers`, `sourceMap`,
70
82
  // `inlineSourceMap`, `inlineSources`, and `target`. When
71
83
  // `sourceMap`/`inlineSourceMap` is enabled (and the file is not JSON) it builds a
@@ -73,10 +85,22 @@ type PrintedFile struct {
73
85
  // appends the sourceMappingURL trailer, records its offset, and returns the
74
86
  // external map text/path (or encodes the map inline). `emitBOM` prepends the
75
87
  // 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)`.
88
+ // printSourceFile does it, outside PrinterOptions, which is why forwarding the
89
+ // whole options struct never reached it. Returned external map text has no BOM,
90
+ // matching the text supplied to upstream's map write.
79
91
  // host supplies the same directory/casing context tsgo's emitter reads.
92
+ //
93
+ // The source file, compiler options and host must be nonnil. Original node
94
+ // positions and emitContext provenance determine source-map accuracy.
95
+ //
96
+ // @evidence contracts/common.md#principled-implementation The maintained port follows the pinned emitter's printer options, map eligibility, URI encoding, newline/trailer handling and post-print BOM ordering; upstream printer traversal derives mappings from retained node provenance.
97
+ // @evidence contracts/common.md#clear-and-simple-design One per-file printer/writer/generator owns output assembly, while focused helpers separate source-root, shared map-directory and trailer-URL policy without duplicating output state.
98
+ // @evidence contracts/common.md#prohibited-implementation-shortcuts JSON map suppression, inline maps and pre-BOM offsets implement actual compiler options and output protocol; they do not select fixtures or patch upstream printer behavior.
99
+ // @evidence contracts/common.md#meaningful-documentation Native paragraphs distinguish printer settings from post-print BOM effects, external from inline maps, path context and provenance requirements; the result documents its coordinate convention explicitly.
100
+ // @evidence contracts/portability.md#os-neutral-implementation Compiler path helpers normalize native output paths, host-provided case sensitivity governs relative identity, and trailer paths are separately URI-encoded; URL spelling is not treated as filesystem casing.
101
+ // @evidence contracts/performance.md#efficient-algorithms Text and mapping collection share one printer invocation; upstream printing can also consult node provenance, semantic helpers, source positions and path text, so this is not a strict one-pass bound over input or output bytes. Map-table copies and JSON serialization, optional base64, trailer writes and a BOM text copy add their own work. The writer's recorded position avoids rescanning emitted text just to locate the trailer.
102
+ // @evidence contracts/performance.md#reuse-equivalent-work Text and source mappings share the printer traversal and EmitContext provenance; no cross-file printer source-index state is reused, and compiler options and transformed nodes determine each output.
103
+ // @evidence contracts/performance.md#bound-retention-and-release-resources Per-call printer, writer and generator hold output buffers, source/name indexes, mapping segments and optional borrowed source text. Map serialization/base64 and BOM assembly can temporarily coexist with those buffers; result strings retain their backing bytes after return. EmitContext and source/semantic graphs remain caller-owned, and this function adds no historical result registry or spawned task. No fixed byte cap is imposed here.
80
104
  func PrintFileWithSourceMap(
81
105
  emitContext *innerprinter.EmitContext,
82
106
  node *innerast.Node,
@@ -105,7 +129,7 @@ func PrintFileWithSourceMap(
105
129
  generator = innersourcemap.NewGenerator(
106
130
  innertspath.GetBaseFileName(innertspath.NormalizeSlashes(jsFilePath)),
107
131
  sourceMapSourceRoot(options),
108
- sourceMapDirectory(options, host, jsFilePath, sourceFile),
132
+ SourceMapDirectory(options, host, jsFilePath, sourceFile),
109
133
  innertspath.ComparePathsOptions{
110
134
  UseCaseSensitiveFileNames: host.UseCaseSensitiveFileNames(),
111
135
  CurrentDirectory: host.GetCurrentDirectory(),
@@ -154,10 +178,25 @@ func sourceMapSourceRoot(options *innercore.CompilerOptions) string {
154
178
  return root
155
179
  }
156
180
 
157
- // sourceMapDirectory mirrors emitter.getSourceMapDirectory: the directory the
158
- // sourcemap generator resolves source paths against, honoring sourceRoot/mapRoot
159
- // and falling back to the .js output directory.
160
- func sourceMapDirectory(options *innercore.CompilerOptions, host innerprinter.EmitHost, filePath string, sourceFile *innerast.SourceFile) string {
181
+ // SourceMapDirectory returns the directory the pinned compiler's source-map
182
+ // generator uses to resolve source paths. This is the generator's internal
183
+ // directory context, not the map's published sourceRoot field.
184
+ //
185
+ // A nonempty sourceRoot selects the host's common source directory. Otherwise
186
+ // mapRoot selects the map directory, projecting sourceFile's path into that
187
+ // root when sourceFile is present; a relative mapRoot is based on the common
188
+ // source directory. Without either option, the output file's directory is used.
189
+ // The options and host must be nonnil; sourceFile may be nil.
190
+ //
191
+ // @evidence contracts/common.md#principled-implementation The maintained helper follows pinned emitter.getSourceMapDirectory's sourceRoot precedence, per-source mapRoot projection and relative-root anchoring, returning the exact generator base instead of assuming maps are based on an emitted file directory.
192
+ // @evidence contracts/common.md#clear-and-simple-design One supported public helper owns generator-directory policy for printing and downstream map consumers, avoiding independently implemented path-base rules.
193
+ // @evidence contracts/common.md#prohibited-implementation-shortcuts Directory selection follows real compiler options and host context, including URL and relative roots, without a consumer-specific map repair or filesystem guessing.
194
+ // @evidence contracts/common.md#meaningful-documentation Native paragraphs distinguish internal generator context from published sourceRoot, describe option precedence and path projection, and state nonnil versus optional inputs.
195
+ // @evidence contracts/portability.md#os-neutral-implementation Compiler path helpers handle native roots and URL spelling separately, while per-source projection uses the host's actual current/common directories and case policy rather than an OS-name assumption.
196
+ // @evidence contracts/performance.md#efficient-algorithms Branching applies sourceRoot/mapRoot precedence and compiler path normalization/remapping over path text. Host CommonSourceDirectory/current-directory/case queries are delegated work and may compute or reuse source metadata; the absence of a local file loop does not bound those host costs. Centralizing this policy avoids separate consumer implementations, not all repeated path work.
197
+ // @evidenceExclude contracts/performance.md#reuse-equivalent-work This pure path-context calculation does not coordinate completed or in-flight work across requests; map consumers own any per-file index of its results.
198
+ // @evidence contracts/performance.md#bound-retention-and-release-resources Intermediate normalized/remapped path strings are invocation-local, and the returned directory string can retain newly allocated or borrowed backing bytes. Host-owned common-directory/source metadata remains with that host. This helper keeps no independent historical result cache, native handle or running task; callers determine the returned string's retention.
199
+ func SourceMapDirectory(options *innercore.CompilerOptions, host innerprinter.EmitHost, filePath string, sourceFile *innerast.SourceFile) string {
161
200
  if len(options.SourceRoot) > 0 {
162
201
  return host.CommonSourceDirectory()
163
202
  }
@@ -17,14 +17,48 @@ import (
17
17
  // GetSourceFilesToEmit returns the source files tsgo would emit for the program
18
18
  // (excludes .d.ts and external-library files), linked from the internal package.
19
19
  //
20
+ // @evidence contracts/common.md#principled-implementation Linking the pinned compiler's own selection helper preserves its target-file, declaration and compiler-option eligibility decisions rather than recreating emit selection.
21
+ // @evidence contracts/common.md#clear-and-simple-design The direct declaration exposes selection independently of output writing, allowing the driver to insert transformers while retaining compiler ownership of eligible files.
22
+ // @evidence contracts/common.md#prohibited-implementation-shortcuts The symbol bridge exposes upstream behavior without replacing it; forceDtsEmit is an actual compiler control, not a fixture exception.
23
+ // @evidence contracts/common.md#meaningful-documentation Native prose describes emitted-file selection and internal linkage, with the acknowledgment separated from the Go linkage directive.
24
+ // @evidenceExclude contracts/portability.md#os-neutral-implementation This exposes upstream emit eligibility and does not choose native path identity or perform filesystem access.
25
+ // @evidenceExclude contracts/performance.md#bound-retention-and-release-resources GetSourceFilesToEmit declares a signature only; the implementation owns acquisition and release of resources.
26
+ // @evidenceExclude contracts/performance.md#efficient-algorithms GetSourceFilesToEmit declares a signature only; the implementation owns the processing strategy.
27
+ // @evidenceExclude contracts/performance.md#reuse-equivalent-work GetSourceFilesToEmit declares a signature only; the implementation owns any shared work.
28
+ //
20
29
  //go:linkname GetSourceFilesToEmit github.com/microsoft/typescript-go/internal/compiler.getSourceFilesToEmit
21
30
  func GetSourceFilesToEmit(host innercompiler.SourceFileMayBeEmittedHost, targetSourceFile *innerast.SourceFile, forceDtsEmit bool) []*innerast.SourceFile
22
31
 
23
32
  // OutputPaths holds the resolved output file paths for one source file.
33
+ // Empty fields represent outputs disabled or suppressed by upstream policy,
34
+ // such as a JSON script destination identical to its source location. Resolved
35
+ // destinations do not certify that later emit or writing succeeds.
36
+ //
37
+ // @evidence contracts/common.md#principled-implementation The exact upstream output-path alias preserves separate script, declaration and map destinations, including absent outputs, without losing compiler-resolved path distinctions.
38
+ // @evidence contracts/common.md#clear-and-simple-design One compiler-owned result groups related outputs for a source file, avoiding independently recomputed paths at each sink.
39
+ // @evidence contracts/common.md#prohibited-implementation-shortcuts The alias does not insert consumer-specific filenames or alter output policy.
40
+ // @evidence contracts/common.md#meaningful-documentation Native prose states per-file output ownership and the meaning of empty destinations.
41
+ // @evidence contracts/portability.md#os-neutral-implementation Output fields preserve the compiler's host-resolved native destinations, including absent outputs, rather than imposing URL spelling or an OS-derived case policy.
42
+ // @evidenceExclude contracts/performance.md#bound-retention-and-release-resources A type declaration acquires and holds no runtime resource.
43
+ // @evidenceExclude contracts/performance.md#efficient-algorithms A type declaration chooses no processing strategy.
44
+ // @evidenceExclude contracts/performance.md#reuse-equivalent-work A type declaration computes nothing, so there is no work to share.
24
45
  type OutputPaths = inneroutputpaths.OutputPaths
25
46
 
26
- // GetOutputPathsFor resolves the .js / .d.ts / map output paths for a source
27
- // file (honoring rootDir/outDir), the same call tsgo's emitter makes.
47
+ // GetOutputPathsFor resolves script, declaration and map destinations using
48
+ // upstream extension and output-directory policy. The script extension can
49
+ // also be .jsx, .mjs, .cjs or .json; disabled or suppressed outputs are empty.
50
+ // The host supplies the common source directory, current directory and case
51
+ // policy. This is path selection, not proof that emit writes every destination.
52
+ // sourceFile, options and host must satisfy the upstream resolver's premises.
53
+ //
54
+ // @evidence contracts/common.md#principled-implementation The wrapper delegates the same source file, options, host and declaration-emission control to the compiler's output-path algorithm, preserving root and output directory semantics.
55
+ // @evidence contracts/common.md#clear-and-simple-design Output placement remains in upstream's owning helper; this adapter only exposes that boundary to the driver.
56
+ // @evidence contracts/common.md#prohibited-implementation-shortcuts No path is fabricated from a consumer or fixture name, and the upstream output resolver is neither copied nor patched.
57
+ // @evidence contracts/common.md#meaningful-documentation Native prose names the output classes, relevant directory options and host context, with a separate acknowledgment section.
58
+ // @evidence contracts/portability.md#os-neutral-implementation Upstream's output resolver receives the actual host directory and path-identity policy; the shim does not guess separators, drive roots or case sensitivity from an OS name.
59
+ // @evidence contracts/performance.md#bound-retention-and-release-resources Upstream allocates a returned OutputPaths object and constructs or borrows destination strings; their backing storage survives with the caller's result. Host-owned directory and case-policy state remains with the host. This bridge acquires no independent file handle or persistent result registry.
60
+ // @evidenceExclude contracts/performance.md#efficient-algorithms Upstream owns extension selection, path normalization, comparison and directory remapping, including work proportional to path text and any host directory lookup. This direct adapter chooses no separate output-path algorithm.
61
+ // @evidenceExclude contracts/performance.md#reuse-equivalent-work Output-path computation and any reusable common-directory or host metadata belong to the upstream resolver and host. This bridge coordinates no independent cache or cross-call producer.
28
62
  func GetOutputPathsFor(sourceFile *innerast.SourceFile, options *innercore.CompilerOptions, host inneroutputpaths.OutputPathsHost, forceDtsEmit bool) *inneroutputpaths.OutputPaths {
29
63
  return inneroutputpaths.GetOutputPathsFor(sourceFile, options, host, forceDtsEmit)
30
64
  }
@@ -20,13 +20,23 @@ import (
20
20
  //
21
21
  // `sourceFile` is the marking target, not the file that gets transformed.
22
22
  // Upstream reads it for two per-file constants (in-JS-file, JSX language
23
- // variant) and then hands it to emitResolver.MarkLinkedReferencesRecursively,
24
- // whose marks the import-elision transformer later reads back through
25
- // EmitContext.ParseNode. A caller that runs a plugin pass first must therefore
23
+ // variant) and, unless isolated modules without import elision, JSX transform
24
+ // or decorator metadata makes marking unnecessary, hands it to
25
+ // emitResolver.MarkLinkedReferencesRecursively, whose marks the import-elision
26
+ // transformer later reads back through EmitContext.ParseNode. A caller that runs a plugin pass first must therefore
26
27
  // pass the PARSE tree here and the transformed tree to TransformSourceFile;
27
28
  // upstream's own emitter passes one file to both only because it has nothing in
28
29
  // between. Re-check this when the pin moves: a new use of the parameter inside
29
30
  // getScriptTransformers could make the two roles diverge further.
30
31
  //
32
+ // @evidence contracts/common.md#principled-implementation Linking the pinned builtin chain preserves compiler transform ordering; the parse-tree argument supplies stable linked-reference marks that transformed nodes retrieve through EmitContext provenance.
33
+ // @evidence contracts/common.md#clear-and-simple-design The helper exposes chain assembly without running transforms, keeping plugin insertion in the driver and builtin ordering in the compiler.
34
+ // @evidence contracts/common.md#prohibited-implementation-shortcuts The source-file distinction follows the pinned helper's marking semantics rather than masking an arbitrary transform failure; linkage exposes the function without replacing its implementation.
35
+ // @evidence contracts/common.md#meaningful-documentation Native paragraphs explain chain contents, marking versus transformation roles and the version-pin premise, with Go linkage retained outside the prose section.
36
+ // @evidenceExclude contracts/performance.md#bound-retention-and-release-resources GetScriptTransformers declares a signature only; the implementation owns acquisition and release of resources.
37
+ // @evidenceExclude contracts/performance.md#efficient-algorithms GetScriptTransformers declares a signature only; the implementation owns the processing strategy.
38
+ // @evidenceExclude contracts/performance.md#reuse-equivalent-work GetScriptTransformers declares a signature only; the implementation owns any shared work.
39
+ // @evidenceExclude contracts/portability.md#os-neutral-implementation GetScriptTransformers is a signature without a body here; path and platform behavior belongs to the implementation that supplies it.
40
+ //
31
41
  //go:linkname GetScriptTransformers github.com/microsoft/typescript-go/internal/compiler.getScriptTransformers
32
42
  func GetScriptTransformers(emitContext *innerprinter.EmitContext, host innerprinter.EmitHost, sourceFile *innerast.SourceFile) []*innertransformers.Transformer
@@ -2,13 +2,13 @@ module github.com/microsoft/typescript-go/shim/compiler
2
2
 
3
3
  go 1.26
4
4
 
5
- require github.com/microsoft/typescript-go v0.0.0-20260429010842-56ab4af42157
5
+ require github.com/microsoft/typescript-go v0.0.0-20260610182825-7fc57c005063
6
6
 
7
7
  require (
8
- github.com/go-json-experiment/json v0.0.0-20260214004413-d219187c3433 // indirect
8
+ github.com/go-json-experiment/json v0.0.0-20260601182631-00ed12fed2a6 // indirect
9
9
  github.com/klauspost/cpuid/v2 v2.2.10 // indirect
10
10
  github.com/zeebo/xxh3 v1.1.0 // indirect
11
- golang.org/x/sync v0.20.0 // indirect
12
- golang.org/x/sys v0.43.0 // indirect
13
- golang.org/x/text v0.36.0 // indirect
11
+ golang.org/x/sync v0.21.0 // indirect
12
+ golang.org/x/sys v0.46.0 // indirect
13
+ golang.org/x/text v0.38.0 // indirect
14
14
  )
@@ -1,22 +1,22 @@
1
- github.com/go-json-experiment/json v0.0.0-20260214004413-d219187c3433 h1:vymEbVwYFP/L05h5TKQxvkXoKxNvTpjxYKdF1Nlwuao=
2
- github.com/go-json-experiment/json v0.0.0-20260214004413-d219187c3433/go.mod h1:tphK2c80bpPhMOI4v6bIc2xWywPfbqi1Z06+RcrMkDg=
1
+ github.com/go-json-experiment/json v0.0.0-20260601182631-00ed12fed2a6 h1:nxP4pPoyqOAgX8lYDFCfl3DyKeXErCvSvhcyzwGV9CE=
2
+ github.com/go-json-experiment/json v0.0.0-20260601182631-00ed12fed2a6/go.mod h1:tphK2c80bpPhMOI4v6bIc2xWywPfbqi1Z06+RcrMkDg=
3
3
  github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
4
4
  github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
5
5
  github.com/klauspost/cpuid/v2 v2.2.10 h1:tBs3QSyvjDyFTq3uoc/9xFpCuOsJQFNPiAhYdw2skhE=
6
6
  github.com/klauspost/cpuid/v2 v2.2.10/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
7
- github.com/microsoft/typescript-go v0.0.0-20260429010842-56ab4af42157 h1:llOMPhKDiQ+UEJiAaQuuWaJOTg5V7tNNTEf9JPWoYSY=
8
- github.com/microsoft/typescript-go v0.0.0-20260429010842-56ab4af42157/go.mod h1:m8YA0PMC7ti0GW0RI05D6fEcjQeu98XVS+FWF+VDW2k=
7
+ github.com/microsoft/typescript-go v0.0.0-20260610182825-7fc57c005063 h1:UUVrjTrD+7nkVvkJTjxwA5+SaZ5n1uyAffm2zX2gn+o=
8
+ github.com/microsoft/typescript-go v0.0.0-20260610182825-7fc57c005063/go.mod h1:s3yhRRZ7nzSZaiKicku520Tj9Mvewr9y2UtrvpwOmDE=
9
9
  github.com/peter-evans/patience v0.3.0 h1:rX0JdJeepqdQl1Sk9c9uvorjYYzL2TfgLX1adqYm9cA=
10
10
  github.com/peter-evans/patience v0.3.0/go.mod h1:Kmxu5sY1NmBLFSStvXjX1wS9mIv7wMcP/ubucyMOAu0=
11
11
  github.com/zeebo/assert v1.3.0 h1:g7C04CbJuIDKNPFHmsk4hwZDO5O+kntRxzaUoNXj+IQ=
12
12
  github.com/zeebo/assert v1.3.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0=
13
13
  github.com/zeebo/xxh3 v1.1.0 h1:s7DLGDK45Dyfg7++yxI0khrfwq9661w9EN78eP/UZVs=
14
14
  github.com/zeebo/xxh3 v1.1.0/go.mod h1:IisAie1LELR4xhVinxWS5+zf1lA4p0MW4T+w+W07F5s=
15
- golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=
16
- golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
17
- golang.org/x/sys v0.43.0 h1:Rlag2XtaFTxp19wS8MXlJwTvoh8ArU6ezoyFsMyCTNI=
18
- golang.org/x/sys v0.43.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
19
- golang.org/x/text v0.36.0 h1:JfKh3XmcRPqZPKevfXVpI1wXPTqbkE5f7JA92a55Yxg=
20
- golang.org/x/text v0.36.0/go.mod h1:NIdBknypM8iqVmPiuco0Dh6P5Jcdk8lJL0CUebqK164=
15
+ golang.org/x/sync v0.21.0 h1:HLII4xRRTtCRkxYp4HNFF0Js/Og6q2i++KXbg0gHCwM=
16
+ golang.org/x/sync v0.21.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
17
+ golang.org/x/sys v0.46.0 h1:noSf2Fq6F8DBgS+LysIkx7rIExoNHJsxOAtPp4rthXw=
18
+ golang.org/x/sys v0.46.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
19
+ golang.org/x/text v0.38.0 h1:sXmwo9DwP3OK9EZ7PqAdaooSGozfl/3a6/xJcbzPRhE=
20
+ golang.org/x/text v0.38.0/go.mod h1:YXZt3QhHUKYT53r2lLKFIVi6Ao1jdzrTR/KQ09qyxF4=
21
21
  gotest.tools/v3 v3.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q=
22
22
  gotest.tools/v3 v3.5.2/go.mod h1:LtdLGcnqToBH83WByAAi/wiwSFCArdFIUV/xxN4pcjA=
@@ -29,10 +29,10 @@ import (
29
29
  "github.com/microsoft/typescript-go/internal/execute/incremental"
30
30
  )
31
31
 
32
- // EmitFreshWithBuildInfo runs a full emit through tsgo's own incremental
33
- // program, so an `incremental` or `composite` project gets the `.tsbuildinfo`
34
- // tsgo would have written, in the exact format and location
35
- // `outputpaths.GetBuildInfoFileName` resolves from the compiler options.
32
+ // EmitFreshWithBuildInfo emits through a new upstream incremental wrapper
33
+ // around the supplied checked Program, with no previous wrapper/snapshot.
34
+ // Its build-information format and candidate location come from upstream
35
+ // snapshot serialization and outputpaths.GetBuildInfoFileName.
36
36
  //
37
37
  // This is the emit half of `tsc.go::performIncrementalCompilation`, which the
38
38
  // tsgo CLI takes whenever `CompilerOptions.IsIncremental()`. A host that builds
@@ -40,14 +40,28 @@ import (
40
40
  // emitting through it) never reaches that CLI path, so without this the build
41
41
  // information is silently dropped even though the options parsed cleanly.
42
42
  //
43
- // "Fresh" is the load-bearing word: no previous snapshot is supplied, so
44
- // `programToSnapshot` marks every file changed and this emits the whole program
45
- // exactly as `Program.Emit` does, then writes the build info. A ttsc plugin's
43
+ // "Fresh" in EmitFreshWithBuildInfo means no previous snapshot is supplied.
44
+ // When upstream incremental-state tracking is enabled, initial construction
45
+ // tracks loaded files and makes their applicable output pending rather than
46
+ // reusing prior emit signatures or diagnostics. TargetSourceFile still selects
47
+ // single-file emission; noEmit/noEmitOnError, cancellation, blocked output and
48
+ // write failure retain their upstream behavior. A whole-program eligible emit
49
+ // attempts pending build info, but a record is not guaranteed on every call.
50
+ // The supplied Program and context must be valid for this emit round. A plugin's
46
51
  // output is not a pure function of the source text a build info records — it
47
52
  // also depends on the plugin binary, its config file, and its contributors —
48
53
  // so reusing a previous snapshot to skip a file would serve stale transformed
49
- // output. Producing the record is sound; consuming it needs plugin identity in
50
- // the invalidation key first.
54
+ // output. Using a record to skip plugin effects requires a reuse identity that
55
+ // covers every relevant input and effect, not source text alone.
56
+ //
57
+ // @evidence contracts/common.md#principled-implementation A nil previous wrapper prevents reuse of old snapshot emit signatures/diagnostics and initializes applicable pending output under upstream emit controls; source-only prior state cannot establish plugin-effect equivalence.
58
+ // @evidence contracts/common.md#clear-and-simple-design One upstream incremental-program construction owns full emit and build-info output, avoiding a separate record serializer or a partially reused emit path.
59
+ // @evidence contracts/common.md#prohibited-implementation-shortcuts Fresh emission is grounded in absent plugin identity in the snapshot key, not a blanket retry masking stale output; no fake build-info or consumer-specific cache key is introduced.
60
+ // @evidence contracts/common.md#meaningful-documentation Native paragraphs explain the in-process build-info connection, fresh pending state, emit/cancellation/write limits and plugin-effect invalidation rather than unconditional output or incremental reuse.
61
+ // @evidenceExclude contracts/portability.md#os-neutral-implementation This wrapper chooses snapshot reuse, while Program.Host and the upstream incremental emitter own native output-path and filesystem decisions.
62
+ // @evidence contracts/performance.md#efficient-algorithms The fresh wrapper reuses the checked Program but builds snapshot file hashes, references and semantic metadata; eligible output then incurs emission and additional build-info table traversal/JSON serialization. File, reference, source/output-byte and diagnostic populations drive this work. Delegating the actual engine avoids a separate record implementation, not those traversals; prior snapshot skipping is unsafe without plugin-equivalent inputs/effects.
63
+ // @evidence contracts/performance.md#reuse-equivalent-work The supplied checked Program is reused, while no previous incremental wrapper is admitted. Skipping effectful emission requires identity and invalidation covering all plugin/runtime/configuration/contributor dependencies and effects; quiet source text alone cannot authorize it.
64
+ // @evidence contracts/performance.md#bound-retention-and-release-resources The invocation acquires an incremental snapshot with file/reference/pending/diagnostic state plus temporary emission and build-info serialization storage. It retains the supplied Program while upstream work runs; returned results and WriteFile callback data may retain output or semantic references afterward. This adapter keeps no historical snapshot registry or independent running-task owner, and caller/host/upstream own result, callback and Program lifetimes on success, error or cancellation.
51
65
  func EmitFreshWithBuildInfo(ctx context.Context, program *Program, options EmitOptions) *EmitResult {
52
66
  incrementalProgram := incremental.NewProgram(
53
67
  program,
@@ -64,13 +78,12 @@ func incrementalGetReferencedFiles(program *innercompiler.Program, file *inneras
64
78
  //go:linkname incrementalFileAffectsGlobalScope github.com/microsoft/typescript-go/internal/execute/incremental.fileAffectsGlobalScope
65
79
  func incrementalFileAffectsGlobalScope(file *innerast.SourceFile) bool
66
80
 
67
- // GetReferencedFilePaths returns the canonical paths of every file that `file`
68
- // directly references in `program`: resolved imports and re-exports (type-only
69
- // included), `/// <reference>` targets, resolved type reference directives,
70
- // module augmentations, and ambient-module declaration files. This is exactly
71
- // the per-file `referencedMap` entry tsgo's incremental engine stores in
72
- // `tsbuildinfo`, so the result is the sound language-semantic upper bound on
73
- // which program files a symbol in `file` can resolve through.
81
+ // GetReferencedFilePaths adapts the upstream incremental reference set:
82
+ // import/re-export and string module-augmentation symbols' declaration files,
83
+ // path directives, resolved type directives and ambient-module declarations.
84
+ // It is not a transitive symbol-reachability closure or proof that every path
85
+ // is a loaded source. Extensionless path-directive adaptation below can also
86
+ // differ from the raw upstream build-info entry.
74
87
  //
75
88
  // The returned strings are tspath.Path values (case-canonicalized on
76
89
  // case-insensitive filesystems); map them back to real file names through
@@ -78,6 +91,17 @@ func incrementalFileAffectsGlobalScope(file *innerast.SourceFile) bool
78
91
  // Extensionless path references are replaced with the source file Program
79
92
  // actually loaded because the upstream incremental helper retains their raw
80
93
  // directive path instead of the selected extension-bearing path.
94
+ // Program and file must be nonnil and belong to the same loaded program.
95
+ // Returned order follows the compiler's reference set; it is not sorted.
96
+ //
97
+ // @evidence contracts/common.md#principled-implementation Upstream's semantic reference set is combined with the same program's resolved path directives, replacing extensionless raw paths with loaded source identities and deduplicating canonical paths; project-reference redirects use the program's actual declaration-to-source mapping.
98
+ // @evidence contracts/common.md#clear-and-simple-design The exported function owns reference-set adaptation while a private helper resolves resident and virtual declaration sources through one program context.
99
+ // @evidence contracts/common.md#prohibited-implementation-shortcuts The extra project-reference lookup addresses supported unbuilt declaration outputs using compiler redirects and supported extensions, rather than guessing filenames or special-casing projects.
100
+ // @evidence contracts/common.md#meaningful-documentation Native paragraphs identify reference categories, canonical spelling, extension replacement, same-program premises and unsorted output with descriptive text separate from tags.
101
+ // @evidence contracts/portability.md#os-neutral-implementation Path identity uses Program.UseCaseSensitiveFileNames and compiler path helpers, while project-reference redirects recover the loaded filename rather than inferring native case behavior from the OS.
102
+ // @evidence contracts/performance.md#efficient-algorithms Adaptation uses expected linear map/set processing in upstream reference count plus path-directive count, with path-text hashing/canonicalization and a bounded supported-extension search per unresolved directive. Before that, upstream obtains a checker and visits import/augmentation symbols, their declarations and ambient modules; semantic lookup, declaration parent walks and host/project-reference queries are additional delegated work, not bounded by the returned path count alone.
103
+ // @evidence contracts/performance.md#reuse-equivalent-work Loaded Program resolutions, sources and checker state are reused, while the reference set and adaptation maps are rebuilt per invocation. Upstream checker queries may populate semantic caches; this adapter coordinates no cross-Program cache or separate resolver producer.
104
+ // @evidence contracts/performance.md#bound-retention-and-release-resources Upstream acquires a file checker with a deferred release callback and may retain semantic state under its Program/checker owner. Reference, replacement and deduplication sets are invocation-local; returned slice/string ownership transfers to the caller and may share existing path backing storage. The bridge keeps no historical result registry.
81
105
  func GetReferencedFilePaths(program *Program, file *innerast.SourceFile) []string {
82
106
  set := incrementalGetReferencedFiles(program, file)
83
107
  if set == nil {
@@ -138,10 +162,22 @@ func getSourceFileFromReference(program *Program, file *innerast.SourceFile, ref
138
162
  return nil
139
163
  }
140
164
 
141
- // FileAffectsGlobalScope reports whether editing `file` can change the global
142
- // scope: global-scope module augmentations, ambient declaration files, and
143
- // script (non-module) files. Mirrors the predicate tsgo's incremental engine
144
- // uses to decide that a change must invalidate every file in the program.
165
+ // FileAffectsGlobalScope reports the upstream incremental engine's global
166
+ // impact classification, first ensuring the source file is bound. A global
167
+ // augmentation is true; otherwise external/CommonJS modules and JSON are false.
168
+ // A remaining script is true only when it has a statement other than a
169
+ // string-literal-named module declaration. Empty or ambient-external-only
170
+ // scripts are not automatically global-impact files.
171
+ // file must be a nonnil compiler source file.
172
+ //
173
+ // @evidence contracts/common.md#principled-implementation The wrapper delegates the pinned incremental engine's global-scope predicate, preserving the same distinction used for program-wide semantic invalidation.
174
+ // @evidence contracts/common.md#clear-and-simple-design One predicate exposes compiler-owned classification without an independent global-scope analysis.
175
+ // @evidence contracts/common.md#prohibited-implementation-shortcuts No path, project name or expected invalidation result is special-cased; the foreign predicate remains unchanged.
176
+ // @evidence contracts/common.md#meaningful-documentation Native prose states binding, augmentation/module/JSON/script distinctions, empty/ambient-only limits and the nonnil source-file premise without certifying every edit's runtime invalidation result.
177
+ // @evidenceExclude contracts/portability.md#os-neutral-implementation Global-scope syntax classification has no native filesystem or process boundary.
178
+ // @evidenceExclude contracts/performance.md#efficient-algorithms Upstream binding and global-impact classification own their algorithms: an unbound file can incur AST binding, then augmentation/statement scans short-circuit according to the classification. This direct bridge chooses no independent traversal or impact analysis.
179
+ // @evidenceExclude contracts/performance.md#reuse-equivalent-work Upstream IsBound/BindOnce and its binder pool own binding reuse; this bridge coordinates no separate impact-result cache or cross-generation producer/invalidation policy.
180
+ // @evidence contracts/performance.md#bound-retention-and-release-resources Binding can acquire a pooled binder and populate source-owned symbols, flow and classification state; its defer returns and resets the binder while that bound AST state survives under the file owner. The bridge returns only a boolean and keeps no independent state registry or handle, but does not equate that with absence of delegated retention.
145
181
  func FileAffectsGlobalScope(file *innerast.SourceFile) bool {
146
182
  return incrementalFileAffectsGlobalScope(file)
147
183
  }
@@ -18,6 +18,15 @@ import (
18
18
  )
19
19
 
20
20
  // ProgramResolutionKind distinguishes module and type-reference resolution.
21
+ //
22
+ // @evidence contracts/common.md#principled-implementation The two discriminants select the compiler's distinct module-name and type-directive algorithms, retaining their different result semantics.
23
+ // @evidence contracts/common.md#clear-and-simple-design One small enum selects the replay operation without encoding the distinction in task names or separate task containers.
24
+ // @evidence contracts/common.md#prohibited-implementation-shortcuts The constants identify actual resolver operations rather than expected results or consumer-specific behavior.
25
+ // @evidence contracts/common.md#meaningful-documentation Native prose identifies both resolution categories before the acknowledgment block.
26
+ // @evidenceExclude contracts/portability.md#os-neutral-implementation The enum selects a semantic operation and carries no native path or platform capability.
27
+ // @evidenceExclude contracts/performance.md#efficient-algorithms The discriminant representation does not own resolution processing.
28
+ // @evidenceExclude contracts/performance.md#reuse-equivalent-work The enum does not coordinate shared computation.
29
+ // @evidenceExclude contracts/performance.md#bound-retention-and-release-resources The enum owns no retained state or running resource.
21
30
  type ProgramResolutionKind uint8
22
31
 
23
32
  const (
@@ -26,17 +35,47 @@ const (
26
35
  )
27
36
 
28
37
  // ProgramResolutionTask is one resolution already performed by a resident
29
- // Program. The exported fields provide deterministic host ordering while the
38
+ // Program. Exported fields let a host explicitly sort and group tasks; the
39
+ // record itself imposes no order. The
30
40
  // unexported fields retain the exact compiler context needed for replay.
41
+ // Keep tasks with their originating Program options and project-reference
42
+ // metadata unchanged; ReplayProgramResolutions accepts one coherent source's
43
+ // task group, not arbitrary tasks from different programs.
44
+ //
45
+ // @evidence contracts/common.md#principled-implementation The record retains name, resolution mode, lexical containing path, expected target and originating options/project redirects, preserving the inputs needed to compare compiler resolution rather than only resolved filenames.
46
+ // @evidence contracts/common.md#clear-and-simple-design Public ordering/provenance fields are distinct from private replay context, allowing hosts to group tasks without manufacturing the compiler state used for semantic replay.
47
+ // @evidence contracts/common.md#prohibited-implementation-shortcuts Expected results preserve actual package and symlink identities; task construction does not synthesize answers for consumer names.
48
+ // @evidence contracts/common.md#meaningful-documentation Native paragraphs state resident-program provenance and coherent-group ownership; documented public fields have blank source lines between them.
49
+ // @evidence contracts/portability.md#os-neutral-implementation Lexical containing and resolved filenames remain distinct from loaded source/target filenames and canonical cache keys, preserving casing and project-reference spelling needed by native resolution.
50
+ // @evidenceExclude contracts/performance.md#efficient-algorithms This task record represents work selected by its producer, not the resolution algorithm owner.
51
+ // @evidenceExclude contracts/performance.md#reuse-equivalent-work The task type does not independently validate or coordinate reuse.
52
+ // @evidenceExclude contracts/performance.md#bound-retention-and-release-resources Retention of task arrays and referenced Program metadata belongs to producer and caller operations, not independently to the record declaration.
31
53
  type ProgramResolutionTask struct {
54
+ // ContainingFile is recovered source/config context when available, otherwise
55
+ // the resident canonical cache-key spelling used for replay.
32
56
  ContainingFile string
33
- Kind ProgramResolutionKind
34
- Mode core.ResolutionMode
35
- Name string
36
- ResolvedFile string
37
- SourceFile string
38
- TargetFile string
39
- Universal bool
57
+
58
+ // Kind selects module or type-reference resolution.
59
+ Kind ProgramResolutionKind
60
+
61
+ // Mode carries the compiler's import-versus-require resolution mode.
62
+ Mode core.ResolutionMode
63
+
64
+ // Name is the original module or type-directive specifier.
65
+ Name string
66
+
67
+ // ResolvedFile is the resident resolver's target spelling, or empty if unresolved.
68
+ ResolvedFile string
69
+
70
+ // SourceFile names the loaded containing source, or is empty when none was
71
+ // found, including automatic directives.
72
+ SourceFile string
73
+
74
+ // TargetFile names the loaded target after project-reference substitution, if available.
75
+ TargetFile string
76
+
77
+ // Universal marks automatic directives whose containing context is synthetic.
78
+ Universal bool
40
79
 
41
80
  compilerOptions *core.CompilerOptions
42
81
  currentDirectory string
@@ -47,6 +86,21 @@ type ProgramResolutionTask struct {
47
86
 
48
87
  // ProgramResolutionTasks returns every cached module and type-reference
49
88
  // resolution, including unresolved entries and automatic type directives.
89
+ // A nil Program returns nil. Returned tasks retain Program option and redirect
90
+ // pointers; the caller owns their storage and must preserve that context.
91
+ // Enumeration order follows compiler maps and is not sorted. TargetFile is
92
+ // populated only when the target resolves to a loaded source. Extraction may
93
+ // initialize referenced configs' input/output maps and query a native realpath
94
+ // for a preserved symlink redirect; it does not replay module resolution.
95
+ //
96
+ // @evidence contracts/common.md#principled-implementation Enumerating the resident compiler's module and type-directive caches retains both successes and failures; containing paths recover loaded-source or semantic-config spelling, and expected results include package, target and link identity.
97
+ // @evidence contracts/common.md#clear-and-simple-design One append closure shares task construction across both compiler cache traversals, while private helpers own source-redirect and project-reference context reconstruction.
98
+ // @evidence contracts/common.md#prohibited-implementation-shortcuts The inferred-types filename is the compiler's automatic-directive context, and recovering its lexical directory addresses actual case-canonical cache keys without relaxing result comparison.
99
+ // @evidence contracts/common.md#meaningful-documentation Native prose states cache coverage, nil behavior and retained Program-pointer lifetime; task fields document the lexical-versus-loaded path distinctions.
100
+ // @evidence contracts/portability.md#os-neutral-implementation Compiler canonical cache keys are not replayed as lexical filenames: source/config context restores spelling, and redirects use actual filesystem Realpath plus Program case policy rather than OS guesses.
101
+ // @evidence contracts/performance.md#efficient-algorithms Two cache traversals append one task per resolution and share one reference-context snapshot. Additional work includes reference-graph traversal, source/output map scans and first-use output-path construction, path hashing/canonicalization and selected native Realpath queries for symlink context. Map/string backing and referenced config/source population matter beyond just the returned task count; extraction does not independently replay imports.
102
+ // @evidence contracts/performance.md#reuse-equivalent-work Cached resident resolutions and one shared project-reference context are reused across tasks from the same Program, preserving their option and redirect identity rather than sharing across changed programs.
103
+ // @evidence contracts/performance.md#bound-retention-and-release-resources The returned task slice retains option, expected-result strings and redirect metadata, plus a shared context's directory set and output-to-reference map when present. These pointers can keep parsed project/config/source graphs reachable beyond the shallow map size. First-use input/output maps remain owned by referenced configs; invocation-local traversal/snapshot containers add no independent historical registry or running task, and callers bound how long they retain the result.
50
104
  func ProgramResolutionTasks(program *Program) []ProgramResolutionTask {
51
105
  if program == nil {
52
106
  return nil
@@ -69,7 +123,7 @@ func ProgramResolutionTasks(program *Program) []ProgramResolutionTask {
69
123
  // their containing directory, falling back to cwd for configless hosts.
70
124
  // Secondary lookup (package subpaths and relative types) preserves this
71
125
  // spelling in resolvedFileName or a symlink's originalPath. Replaying a
72
- // lowercased key falsely rejected unchanged programs in #1353. Restore
126
+ // lowercased key would falsely reject unchanged programs. Restore
73
127
  // the input context here; keep the strict result comparison below so
74
128
  // actual target, package and link changes still invalidate the program.
75
129
  containingDirectory := program.GetCurrentDirectory()
@@ -136,6 +190,20 @@ func programResolutionContext(program *Program, source ast.HasFileName) (module.
136
190
 
137
191
  // ReplayProgramResolutions resolves one source's tasks with one fresh upstream
138
192
  // resolver and reports whether every result still matches the resident Program.
193
+ // Tasks must share compiler options, current directory and project-reference
194
+ // context. An empty group, nil filesystem or missing options returns false.
195
+ // Every supported task is submitted even after a mismatch; group-local caches
196
+ // can satisfy equivalent lookups without repeating native reads. Equality is
197
+ // over the projected result fields, not a complete filesystem snapshot proof.
198
+ //
199
+ // @evidence contracts/common.md#principled-implementation A fresh upstream resolver replays each kind with its original name, mode, lexical containing file and redirect, then compares the complete projected result including unresolved, package and symlink identity; tasks require one coherent originating context.
200
+ // @evidence contracts/common.md#clear-and-simple-design One resolver and project-reference filesystem view belong to a group, while result projection centralizes equality and the loop continues submitting tasks after a mismatch instead of stopping at the first changed result.
201
+ // @evidence contracts/common.md#prohibited-implementation-shortcuts Virtual declaration existence follows actual project-reference source mappings; unsupported resolver write operations panic rather than silently fabricating effects, and full result equality is not weakened to hide changed identities.
202
+ // @evidence contracts/common.md#meaningful-documentation Native prose explains coherent-group premises, invalid-input refusal and why replay continues after a mismatch, with separate descriptive and acknowledgment sections.
203
+ // @evidence contracts/portability.md#os-neutral-implementation The supplied filesystem determines case sensitivity, existence and realpaths; the virtual declaration view uses canonical compiler paths and tracks native symlinks while preserving lexical resolver inputs.
204
+ // @evidence contracts/performance.md#efficient-algorithms Each supported task makes one resolver call and compares projected string/scalar fields, with group-local caches sharing eligible lookups. Actual resolver work includes ancestor/package probing, manifest bytes and path processing; tracing can bypass result-cache hits. Virtual declaration and known-link fallback scans can multiply directory/link population across existence queries, with native source-existence and realpath work in addition to map membership.
205
+ // @evidence contracts/performance.md#reuse-equivalent-work One fresh resolver and cached virtual filesystem share equivalent lookups within a coherent group; a new replay filesystem prevents prior observation results from hiding changed native inputs.
206
+ // @evidence contracts/performance.md#bound-retention-and-release-resources Fresh resolver and optional virtual/cached filesystem state retain entries, manifest buffers, projected results and known links for the synchronous group. This adapter keeps no historical registry or spawned task after return, making otherwise-unreferenced local state eligible for collection without promising immediate reclamation. Borrowed task/config graphs and observations retained by the supplied filesystem stay under their owners, with no fixed population or byte cap imposed here.
139
207
  func ReplayProgramResolutions(tasks []ProgramResolutionTask, filesystem vfs.FS) bool {
140
208
  if len(tasks) == 0 || filesystem == nil || tasks[0].compilerOptions == nil {
141
209
  return false
@@ -392,6 +460,21 @@ func (fs *projectReferenceResolutionFS) directoryExistsIfProjectReferenceDeclara
392
460
 
393
461
  // ReplayAutomaticTypeDirectiveDiscovery repeats the compiler's exact wildcard
394
462
  // type-root enumeration over filesystem so a host can observe its inputs.
463
+ // Nil program, filesystem or compiler options performs no discovery.
464
+ // Explicit non-wildcard types can return without filesystem enumeration.
465
+ // Wildcard discovery also reads package manifests to omit typings-null packages;
466
+ // this function discards the returned names, not filesystem observation state.
467
+ // Default wildcard roots require a config path or nonempty resident cwd, as
468
+ // required by the upstream effective-root helper.
469
+ //
470
+ // @evidence contracts/common.md#principled-implementation The compiler's automatic-type directive enumeration receives the resident options and current directory over the observation filesystem, reproducing wildcard discovery inputs rather than inferring them from only previously resolved targets.
471
+ // @evidence contracts/common.md#clear-and-simple-design A minimal resolution host exposes filesystem and cwd directly to the owning discovery helper; enumeration results need not be retained because observation is the required effect.
472
+ // @evidence contracts/common.md#prohibited-implementation-shortcuts Replay preserves real enumeration effects through a supported host instead of injecting assumed type-package names or patching the compiler's cache.
473
+ // @evidence contracts/common.md#meaningful-documentation Native prose states wildcard discovery's observation purpose and nil-input no-op behavior, with separate tags.
474
+ // @evidence contracts/portability.md#os-neutral-implementation Discovery obtains directories and entries from the caller's filesystem and resident cwd through the compiler host, without inferring type-root availability or casing from the OS.
475
+ // @evidenceExclude contracts/performance.md#efficient-algorithms Upstream owns effective-root construction, directory enumeration, package-manifest reads/parsing, wildcard substitution and name deduplication. Costs include ancestor/path text, entries, manifest bytes and selected type-name population; this direct adapter chooses no separate discovery algorithm and discards only the returned names.
476
+ // @evidence contracts/performance.md#reuse-equivalent-work Enumeration itself is the input-observation effect, so a resident list cannot replace traversal on a new filesystem observation; callers may share the resulting observation proof only when its filesystem snapshot is equivalent.
477
+ // @evidence contracts/performance.md#bound-retention-and-release-resources Upstream discovery can allocate root/name lists, package buffers and parsed manifest state during the synchronous call. The result is discarded here, while compiler options and any filesystem caches or collected observation entries remain under their existing owners. This adapter keeps no independent historical name registry or running task and imposes no bound on caller-owned observation retention.
395
478
  func ReplayAutomaticTypeDirectiveDiscovery(program *Program, filesystem vfs.FS) {
396
479
  if program == nil || filesystem == nil || program.Options() == nil {
397
480
  return
@@ -2,8 +2,8 @@
2
2
  //
3
3
  // Completes every exposed enum family: re-exports each member not already
4
4
  // re-exported elsewhere in the shim package, so a plugin that can name the
5
- // enum type can name all of its values. Prevents the #230 class (a sibling
6
- // const silently missing). Regenerate after a typescript-go bump with
5
+ // enum type can name all of its values. Prevents a partially re-exported
6
+ // family (a sibling const silently missing). Regenerate after a typescript-go bump with
7
7
  // `pnpm --filter ttsc shim:audit -fix`.
8
8
 
9
9
  package core