ttsc 0.18.3 → 0.19.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.
Files changed (173) hide show
  1. package/README.md +5 -6
  2. package/cmd/graphbench/main.go +1 -1
  3. package/cmd/platform/main.go +1 -48
  4. package/cmd/ttsc/build_branches_test.go +5 -1
  5. package/cmd/ttsc/main.go +0 -50
  6. package/cmd/ttsc/main_alias_branches_test.go +6 -12
  7. package/cmd/ttscgraph/dump.go +13 -3
  8. package/cmd/ttscgraph/main.go +18 -12
  9. package/cmd/ttscgraph/run_help_version_and_bad_flags_exit_codes_test.go +23 -5
  10. package/cmd/ttscgraph/serve.go +863 -0
  11. package/cmd/ttscgraph/serve_protocol_rejects_invalid_request_line_test.go +43 -0
  12. package/cmd/ttscgraph/serve_protocol_retries_session_creation_test.go +83 -0
  13. package/cmd/ttscgraph/serve_protocol_reuses_session_test.go +35 -0
  14. package/cmd/ttscgraph/serve_session_applies_source_edit_incrementally_test.go +55 -0
  15. package/cmd/ttscgraph/serve_session_fails_closed_on_deleted_config_test.go +68 -0
  16. package/cmd/ttscgraph/serve_session_fails_closed_on_invalid_config_test.go +50 -0
  17. package/cmd/ttscgraph/serve_session_keeps_missing_literal_root_unchanged_test.go +46 -0
  18. package/cmd/ttscgraph/serve_session_rebuilds_import_graph_change_test.go +60 -0
  19. package/cmd/ttscgraph/serve_session_reloads_created_literal_root_test.go +44 -0
  20. package/cmd/ttscgraph/serve_session_reloads_extended_config_change_test.go +45 -0
  21. package/cmd/ttscgraph/serve_session_reloads_newly_resolved_conditional_export_test.go +60 -0
  22. package/cmd/ttscgraph/serve_session_reloads_newly_resolved_config_types_test.go +44 -0
  23. package/cmd/ttscgraph/serve_session_reloads_newly_resolved_excluded_import_test.go +62 -0
  24. package/cmd/ttscgraph/serve_session_reloads_newly_resolved_package_export_test.go +46 -0
  25. package/cmd/ttscgraph/serve_session_reloads_newly_resolved_package_import_test.go +46 -0
  26. package/cmd/ttscgraph/serve_session_reloads_newly_resolved_path_alias_test.go +47 -0
  27. package/cmd/ttscgraph/serve_session_reloads_newly_resolved_reference_path_test.go +42 -0
  28. package/cmd/ttscgraph/serve_session_reloads_newly_resolved_root_dirs_target_test.go +46 -0
  29. package/cmd/ttscgraph/serve_session_reloads_newly_resolved_type_reference_test.go +42 -0
  30. package/cmd/ttscgraph/serve_session_reloads_root_file_set_test.go +52 -0
  31. package/cmd/ttscgraph/serve_session_reloads_source_deleted_during_load_test.go +60 -0
  32. package/cmd/ttscgraph/serve_session_reloads_transitive_project_reference_test.go +55 -0
  33. package/cmd/ttscgraph/serve_session_reloads_when_program_plugin_linked_test.go +53 -0
  34. package/cmd/ttscgraph/serve_session_reuses_unchanged_preamble_source_test.go +45 -0
  35. package/cmd/ttscgraph/serve_session_reuses_unchanged_snapshot_test.go +52 -0
  36. package/cmd/ttscgraph/serve_session_revisits_source_edited_during_load_test.go +61 -0
  37. package/cmd/ttscgraph/serve_session_tolerates_os_invalid_resolution_candidate_test.go +56 -0
  38. package/cmd/ttscgraph/serve_session_tracks_all_module_specifier_forms_test.go +41 -0
  39. package/cmd/ttscgraph/serve_session_tracks_diamond_project_references_once_test.go +61 -0
  40. package/cmd/ttscserver/main.go +5 -3
  41. package/driver/lsp.go +13 -1
  42. package/driver/plugins.go +56 -5
  43. package/driver/program.go +25 -10
  44. package/driver/rewrite.go +381 -21
  45. package/driver/session.go +11 -3
  46. package/go.mod +1 -0
  47. package/internal/graph/build.go +297 -3
  48. package/internal/graph/build_records_a_node_per_top_level_declaration_test.go +16 -2
  49. package/internal/graph/diagnostics.go +5 -4
  50. package/internal/graph/dump.go +60 -4
  51. package/internal/graph/dump_is_a_function_of_the_source_test.go +71 -0
  52. package/internal/graph/dump_serializes_the_full_graph_test.go +16 -4
  53. package/internal/graph/edges.go +122 -11
  54. package/internal/graph/exports.go +74 -17
  55. package/internal/graph/graph.go +33 -1
  56. package/internal/graph/node_identity_is_position_invariant_test.go +4 -2
  57. package/internal/graph/resolve.go +24 -0
  58. package/internal/graphsymbols/provider.go +50 -14
  59. package/internal/lspserver/lsp_native_plugin_source.go +77 -23
  60. package/internal/lspserver/lsp_plugin.go +19 -2
  61. package/internal/lspserver/lsp_proxy.go +244 -52
  62. package/internal/lspserver/lsp_server.go +35 -27
  63. package/internal/lspserver/lsp_symbols.go +25 -16
  64. package/lib/TtscCompiler.d.ts +13 -2
  65. package/lib/TtscCompiler.js +30 -20
  66. package/lib/TtscCompiler.js.map +1 -1
  67. package/lib/TtscService.js +9 -7
  68. package/lib/TtscService.js.map +1 -1
  69. package/lib/compiler/internal/compileProjectInMemory.js +15 -1
  70. package/lib/compiler/internal/compileProjectInMemory.js.map +1 -1
  71. package/lib/compiler/internal/project/createNativeProjectContextArgs.d.ts +3 -0
  72. package/lib/compiler/internal/project/createNativeProjectContextArgs.js +14 -0
  73. package/lib/compiler/internal/project/createNativeProjectContextArgs.js.map +1 -0
  74. package/lib/compiler/internal/project/readProjectConfig.js +53 -4
  75. package/lib/compiler/internal/project/readProjectConfig.js.map +1 -1
  76. package/lib/compiler/internal/project/resolveProjectConfig.d.ts +9 -2
  77. package/lib/compiler/internal/project/resolveProjectConfig.js +45 -16
  78. package/lib/compiler/internal/project/resolveProjectConfig.js.map +1 -1
  79. package/lib/compiler/internal/residentTransformProcess.d.ts +16 -5
  80. package/lib/compiler/internal/residentTransformProcess.js +68 -20
  81. package/lib/compiler/internal/residentTransformProcess.js.map +1 -1
  82. package/lib/compiler/internal/runBuild.d.ts +18 -0
  83. package/lib/compiler/internal/runBuild.js +220 -24
  84. package/lib/compiler/internal/runBuild.js.map +1 -1
  85. package/lib/compiler/internal/runSingleFileEmit.js +7 -4
  86. package/lib/compiler/internal/runSingleFileEmit.js.map +1 -1
  87. package/lib/compiler/internal/sharedHostHelpers.d.ts +16 -0
  88. package/lib/compiler/internal/sharedHostHelpers.js +23 -0
  89. package/lib/compiler/internal/sharedHostHelpers.js.map +1 -1
  90. package/lib/compiler/internal/startResidentTransform.js +18 -1
  91. package/lib/compiler/internal/startResidentTransform.js.map +1 -1
  92. package/lib/compiler/internal/transformProjectInMemory.js +34 -8
  93. package/lib/compiler/internal/transformProjectInMemory.js.map +1 -1
  94. package/lib/flags/parser.d.ts +17 -0
  95. package/lib/flags/parser.js +11 -1
  96. package/lib/flags/parser.js.map +1 -1
  97. package/lib/flags/schema.js +7 -0
  98. package/lib/flags/schema.js.map +1 -1
  99. package/lib/launcher/internal/prepareExecution.js +21 -2
  100. package/lib/launcher/internal/prepareExecution.js.map +1 -1
  101. package/lib/launcher/internal/runTtsc.js +13 -53
  102. package/lib/launcher/internal/runTtsc.js.map +1 -1
  103. package/lib/launcher/internal/runTtscserver.js +11 -0
  104. package/lib/launcher/internal/runTtscserver.js.map +1 -1
  105. package/lib/launcher/internal/runTtsx.js +27 -11
  106. package/lib/launcher/internal/runTtsx.js.map +1 -1
  107. package/lib/launcher/internal/runtimeHooks.d.ts +81 -0
  108. package/lib/launcher/internal/runtimeHooks.js +632 -43
  109. package/lib/launcher/internal/runtimeHooks.js.map +1 -1
  110. package/lib/launcher/internal/servedSourceMap.d.ts +25 -0
  111. package/lib/launcher/internal/servedSourceMap.js +164 -0
  112. package/lib/launcher/internal/servedSourceMap.js.map +1 -0
  113. package/lib/plugin/internal/buildSourcePlugin.d.ts +146 -2
  114. package/lib/plugin/internal/buildSourcePlugin.js +651 -113
  115. package/lib/plugin/internal/buildSourcePlugin.js.map +1 -1
  116. package/lib/plugin/internal/loadProjectPlugins.d.ts +7 -0
  117. package/lib/plugin/internal/loadProjectPlugins.js +33 -10
  118. package/lib/plugin/internal/loadProjectPlugins.js.map +1 -1
  119. package/lib/structures/ITtscCompilerContext.d.ts +16 -2
  120. package/lib/structures/ITtscCompilerResult.d.ts +8 -5
  121. package/lib/structures/ITtscPluginCapabilities.d.ts +8 -0
  122. package/lib/structures/ITtscPluginFactoryContext.d.ts +14 -0
  123. package/lib/structures/internal/ITtscParsedProjectConfig.d.ts +3 -0
  124. package/lib/structures/internal/ITtscProjectIdentity.d.ts +17 -0
  125. package/lib/structures/internal/ITtscProjectIdentity.js +3 -0
  126. package/lib/structures/internal/ITtscProjectIdentity.js.map +1 -0
  127. package/lib/structures/internal/TtscCommonOptions.d.ts +8 -0
  128. package/package.json +11 -8
  129. package/shim/ast/lint.go +10 -0
  130. package/shim/ast/shim.go +44 -0
  131. package/shim/checker/enums_gen.go +19 -0
  132. package/shim/checker/shim.go +130 -0
  133. package/shim/diagnosticwriter/lint.go +30 -3
  134. package/shim/printer/shim.go +22 -4
  135. package/shim/scanner/regexp.go +27 -0
  136. package/src/TtscCompiler.ts +29 -22
  137. package/src/TtscService.ts +15 -7
  138. package/src/compiler/internal/compileProjectInMemory.ts +18 -1
  139. package/src/compiler/internal/project/createNativeProjectContextArgs.ts +15 -0
  140. package/src/compiler/internal/project/readProjectConfig.ts +61 -5
  141. package/src/compiler/internal/project/resolveProjectConfig.ts +51 -21
  142. package/src/compiler/internal/residentTransformProcess.ts +95 -21
  143. package/src/compiler/internal/runBuild.ts +313 -32
  144. package/src/compiler/internal/runSingleFileEmit.ts +7 -4
  145. package/src/compiler/internal/sharedHostHelpers.ts +24 -0
  146. package/src/compiler/internal/startResidentTransform.ts +21 -1
  147. package/src/compiler/internal/transformProjectInMemory.ts +49 -6
  148. package/src/flags/parser.ts +28 -1
  149. package/src/flags/schema.ts +8 -0
  150. package/src/launcher/internal/prepareExecution.ts +22 -2
  151. package/src/launcher/internal/runTtsc.ts +13 -61
  152. package/src/launcher/internal/runTtscserver.ts +14 -0
  153. package/src/launcher/internal/runTtsx.ts +28 -13
  154. package/src/launcher/internal/runtimeHooks.ts +771 -53
  155. package/src/launcher/internal/servedSourceMap.ts +183 -0
  156. package/src/plugin/internal/buildSourcePlugin.ts +859 -122
  157. package/src/plugin/internal/loadProjectPlugins.ts +36 -6
  158. package/src/structures/ITtscCompilerContext.ts +17 -2
  159. package/src/structures/ITtscCompilerResult.ts +8 -5
  160. package/src/structures/ITtscPluginCapabilities.ts +9 -0
  161. package/src/structures/ITtscPluginFactoryContext.ts +15 -0
  162. package/src/structures/internal/ITtscParsedProjectConfig.ts +3 -0
  163. package/src/structures/internal/ITtscProjectIdentity.ts +17 -0
  164. package/src/structures/internal/TtscCommonOptions.ts +8 -0
  165. package/tools/shim_audit/baseline.json +16 -7
  166. package/tools/shim_audit/main.go +777 -71
  167. package/tools/shim_audit/main_test.go +28 -1
  168. package/tools/shim_audit/producer_exemptions_require_rationale_test.go +42 -0
  169. package/tools/shim_audit/producer_surface_includes_exposed_methods_test.go +154 -0
  170. package/tools/shim_audit/producer_surface_rejects_unproducible_reference_test.go +142 -0
  171. package/utility/host.go +46 -20
  172. package/utility/serve.go +1 -1
  173. package/shim/checker/signature_api_completeness.go +0 -58
@@ -0,0 +1,183 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import { pathToFileURL } from "node:url";
4
+
5
+ /** Rewritten served text keyed by emitted file, so the work runs once per run. */
6
+ const inlineCache = new Map<string, string>();
7
+
8
+ /**
9
+ * Trailing `//# sourceMappingURL=<url>` (or legacy `//@`) magic comment.
10
+ * Anchored at end of text through any trailing whitespace, so it matches the
11
+ * last comment whether tsgo emitted it with a newline, none, or a CRLF line
12
+ * ending.
13
+ */
14
+ const SOURCE_MAPPING_URL = /\/\/[#@] sourceMappingURL=([^\r\n]*)[ \t\r\n]*$/;
15
+
16
+ /**
17
+ * Replace a served emit's trailing external `//# sourceMappingURL=<relative>`
18
+ * comment with an inline `data:` URL whose `sources` are absolute `file://`
19
+ * URLs of the true on-disk source files.
20
+ *
21
+ * Ttsx runs tsgo-built JavaScript under the ORIGINAL `.ts` source URL. When the
22
+ * owning tsconfig emits external maps, the served text ends with a relative
23
+ * `sourceMappingURL` that Node resolves against the `.ts` script URL — where no
24
+ * `.js.map` exists — and that the per-run emit directory deletes at process
25
+ * exit anyway. Node's V8 coverage then caches the script with `data: null` and
26
+ * c8 misattributes lines (false 100%, issue #353); `--enable-source-maps`
27
+ * cannot map stack frames. Inlining the map into the served text (which V8
28
+ * captures at compile time) survives both the wrong resolution base and the
29
+ * post-exit cleanup, and absolutizing `sources` fixes the mis-rooted paths that
30
+ * mapped stack frames, debuggers, and IDE links would otherwise print.
31
+ *
32
+ * Idempotent: re-running it on already-inlined text (whose `sources` are
33
+ * already absolute `file://` URLs) reproduces the same bytes, which keeps the
34
+ * shared cross-process dependency cache deterministic.
35
+ *
36
+ * @param source - The emitted JavaScript text served under the source URL.
37
+ * @param emittedFile - On-disk path of the emitted `.js`, beside its `.map`.
38
+ * @param sourceFile - Real path of the `.ts` source the emit was built from.
39
+ */
40
+ export function inlineServedSourceMap(
41
+ source: string,
42
+ emittedFile: string | undefined,
43
+ sourceFile: string | undefined,
44
+ ): string {
45
+ if (emittedFile === undefined) {
46
+ return source;
47
+ }
48
+ const cached = inlineCache.get(emittedFile);
49
+ if (cached !== undefined) {
50
+ return cached;
51
+ }
52
+ const rewritten = rewrite(source, emittedFile, sourceFile);
53
+ inlineCache.set(emittedFile, rewritten);
54
+ return rewritten;
55
+ }
56
+
57
+ function rewrite(
58
+ source: string,
59
+ emittedFile: string,
60
+ sourceFile: string | undefined,
61
+ ): string {
62
+ const match = SOURCE_MAPPING_URL.exec(source);
63
+ if (match === null) {
64
+ return source;
65
+ }
66
+ const url = match[1]!.trim();
67
+ if (url.length === 0) {
68
+ return source;
69
+ }
70
+ const json = readMapJson(url, emittedFile);
71
+ if (json === null) {
72
+ // The referenced map cannot be read (an external ref whose sibling is
73
+ // missing). Strip the dangling comment so Node does not cache the script
74
+ // with `data: null` and misattribute coverage; leave an already-inline
75
+ // `data:` map untouched since it is self-contained.
76
+ return url.startsWith("data:")
77
+ ? source
78
+ : source.slice(0, match.index).replace(/\r?\n$/, "");
79
+ }
80
+ const inlined = inlineComment(json, emittedFile, sourceFile);
81
+ if (inlined === null) {
82
+ return source;
83
+ }
84
+ return source.slice(0, match.index) + inlined;
85
+ }
86
+
87
+ /** Read the raw map JSON from a `data:` URI or a sibling map file. */
88
+ function readMapJson(url: string, emittedFile: string): string | null {
89
+ if (url.startsWith("data:")) {
90
+ return decodeDataUri(url);
91
+ }
92
+ const direct = path.resolve(path.dirname(emittedFile), url);
93
+ const fromRef = readFileOrNull(direct);
94
+ if (fromRef !== null) {
95
+ return fromRef;
96
+ }
97
+ // tsgo names the comment after the emit basename; fall back to the canonical
98
+ // sibling path when the comment's relative form does not resolve on disk.
99
+ return readFileOrNull(`${emittedFile}.map`);
100
+ }
101
+
102
+ /** Decode a `data:application/json[;base64],...` source-map URI to its JSON. */
103
+ function decodeDataUri(url: string): string | null {
104
+ const comma = url.indexOf(",");
105
+ if (comma === -1) {
106
+ return null;
107
+ }
108
+ const meta = url.slice(0, comma);
109
+ if (!meta.includes("application/json")) {
110
+ return null;
111
+ }
112
+ const payload = url.slice(comma + 1);
113
+ try {
114
+ return meta.includes(";base64")
115
+ ? Buffer.from(payload, "base64").toString("utf8")
116
+ : decodeURIComponent(payload);
117
+ } catch {
118
+ return null;
119
+ }
120
+ }
121
+
122
+ /** Parse the map, absolutize its `sources`, and re-encode it as a `data:` URI. */
123
+ function inlineComment(
124
+ json: string,
125
+ emittedFile: string,
126
+ sourceFile: string | undefined,
127
+ ): string | null {
128
+ let map: {
129
+ sources?: unknown;
130
+ sourceRoot?: unknown;
131
+ [key: string]: unknown;
132
+ };
133
+ try {
134
+ map = JSON.parse(json) as typeof map;
135
+ } catch {
136
+ return null;
137
+ }
138
+ map.sources = absolutizeSources(map, path.dirname(emittedFile), sourceFile);
139
+ // `sources` are now absolute `file://` URLs, so any `sourceRoot` prefix would
140
+ // corrupt them — drop it.
141
+ delete map.sourceRoot;
142
+ const encoded = Buffer.from(JSON.stringify(map), "utf8").toString("base64");
143
+ return `//# sourceMappingURL=data:application/json;charset=utf-8;base64,${encoded}`;
144
+ }
145
+
146
+ /**
147
+ * Map each entry of the source map's `sources` to an absolute `file://` URL.
148
+ *
149
+ * Tsgo's per-file emit is 1:1, so a single source is the served file itself and
150
+ * resolves to the real on-disk `sourceFile` the serve path already knows — the
151
+ * most reliable anchor. A map that somehow carries several sources (or is
152
+ * consumed without a known source file) has each relative entry resolved
153
+ * against the map's own directory and `sourceRoot`, exactly where tsgo computed
154
+ * them from; entries that are already absolute URLs pass through unchanged.
155
+ */
156
+ function absolutizeSources(
157
+ map: { sources?: unknown; sourceRoot?: unknown },
158
+ mapDir: string,
159
+ sourceFile: string | undefined,
160
+ ): string[] {
161
+ const sources = Array.isArray(map.sources) ? map.sources : [];
162
+ if (sources.length === 1 && sourceFile !== undefined) {
163
+ return [pathToFileURL(sourceFile).href];
164
+ }
165
+ const sourceRoot = typeof map.sourceRoot === "string" ? map.sourceRoot : "";
166
+ return sources.map((entry) => {
167
+ if (typeof entry !== "string") {
168
+ return String(entry);
169
+ }
170
+ if (/^[a-zA-Z][a-zA-Z0-9+.-]*:/.test(entry)) {
171
+ return entry;
172
+ }
173
+ return pathToFileURL(path.resolve(mapDir, sourceRoot, entry)).href;
174
+ });
175
+ }
176
+
177
+ function readFileOrNull(file: string): string | null {
178
+ try {
179
+ return fs.readFileSync(file, "utf8");
180
+ } catch {
181
+ return null;
182
+ }
183
+ }