ttsc 0.19.2 → 0.20.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 +7 -5
- package/cmd/graphdump/main.go +2 -4
- package/cmd/ttsc/filter.go +12 -4
- package/cmd/ttsc/filter_resolves_flag_names_case_insensitively_test.go +53 -0
- package/cmd/ttsc/flags_gen.go +3 -3
- package/cmd/ttscgraph/dump.go +5 -7
- package/cmd/ttscgraph/run_dump_emits_only_checker_verified_member_relations_test.go +118 -0
- package/cmd/ttscgraph/serve.go +58 -308
- package/cmd/ttscgraph/serve_session_keeps_base_url_fallback_unchanged_test.go +49 -0
- package/cmd/ttscgraph/serve_session_keeps_esm_directory_candidate_unchanged_test.go +61 -0
- package/cmd/ttscgraph/serve_session_keeps_exports_blocked_file_candidates_unchanged_test.go +64 -0
- package/cmd/ttscgraph/serve_session_keeps_inactive_conditional_export_unchanged_test.go +66 -0
- package/cmd/ttscgraph/serve_session_keeps_lower_priority_module_candidate_unchanged_test.go +67 -0
- package/cmd/ttscgraph/serve_session_keeps_lower_priority_paths_pattern_unchanged_test.go +58 -0
- package/cmd/ttscgraph/serve_session_keeps_nonlongest_root_dirs_candidate_unchanged_test.go +54 -0
- package/cmd/ttscgraph/serve_session_reloads_commonjs_package_entry_for_esm_test.go +50 -0
- package/cmd/ttscgraph/serve_session_reloads_module_suffix_candidate_test.go +41 -0
- package/cmd/ttscgraph/serve_session_reloads_superseding_module_candidates_test.go +216 -0
- package/cmd/ttscgraph/serve_session_retries_failed_dump_test.go +103 -0
- package/driver/graph.go +12 -6
- package/driver/lsp.go +30 -0
- package/driver/program.go +37 -1
- package/driver/resolution_candidates.go +819 -0
- package/driver/windowsjunction/windowsjunction.go +40 -0
- package/go.mod +2 -0
- package/internal/graph/build.go +45 -11
- package/internal/graph/dump.go +312 -108
- package/internal/graph/dump_checkout_paths_are_stable_test.go +210 -0
- package/internal/graph/dump_diagnostics_ride_the_generation_that_built_it_test.go +9 -3
- package/internal/graph/dump_paths.go +172 -0
- package/internal/graph/dump_paths_are_portable_and_injective_test.go +93 -0
- package/internal/graph/dump_schema_version_matches_the_typescript_client_test.go +1 -1
- package/internal/graph/dump_uses_ecma_line_terminators_test.go +87 -0
- package/internal/graph/duplicate_variable_object_members_keep_first_declaration_test.go +61 -0
- package/internal/graph/edges.go +220 -5
- package/internal/graph/enum_members_carry_their_names_on_the_enum_node_test.go +131 -0
- package/internal/graph/graph.go +177 -5
- package/internal/graph/line_model.go +122 -0
- package/internal/graph/literals.go +175 -0
- package/internal/graph/literals_are_absent_when_the_type_admits_more_than_it_can_name_test.go +74 -0
- package/internal/graph/literals_cover_enum_members_the_graph_has_no_nodes_for_test.go +79 -0
- package/internal/graph/literals_do_not_depend_on_declaration_line_wrapping_test.go +84 -0
- package/internal/graph/literals_render_every_value_in_typescript_source_form_test.go +77 -0
- package/internal/graph/literals_resolve_through_alias_indirection_test.go +64 -0
- package/internal/graph/member_relation_edges_follow_checker_validity_test.go +85 -0
- package/internal/graph/member_relation_edges_preserve_checker_boundaries_test.go +191 -0
- package/internal/graph/member_relation_edges_reject_checker_invalid_pairs_test.go +119 -0
- package/internal/graph/node_ids_preserve_hash_bearing_components_test.go +41 -0
- package/internal/graph/node_modifiers_emit_union_strings_test.go +4 -1
- package/internal/graph/object_literal_members_ride_on_the_snapshot_test.go +192 -0
- package/internal/graph/object_member_signatures_preserve_literal_whitespace_test.go +67 -0
- package/internal/graph/object_members.go +229 -0
- package/internal/graph/provenance.go +88 -30
- package/internal/graph/source_texts_cover_every_resident_program_source_test.go +73 -0
- package/internal/graphsymbols/position_helpers_follow_ecma_line_terminators_test.go +66 -0
- package/internal/graphsymbols/provider.go +26 -91
- package/internal/lspserver/lsp_clean_didopen_refreshes_compiler_state_test.go +144 -0
- package/internal/lspserver/lsp_completion.go +109 -0
- package/internal/lspserver/lsp_completion_gate_never_refuses_a_matching_line_test.go +50 -0
- package/internal/lspserver/lsp_completion_hints_longest_trigger_wins_test.go +149 -0
- package/internal/lspserver/lsp_completion_hints_nearest_trigger_wins_test.go +37 -0
- package/internal/lspserver/lsp_completion_merges_into_upstream_response_test.go +149 -0
- package/internal/lspserver/lsp_completion_nearest_hint_replaces_nearest_filter_test.go +43 -0
- package/internal/lspserver/lsp_completion_preserves_completion_list_extensions_test.go +99 -0
- package/internal/lspserver/lsp_completion_refuses_hints_inside_a_string_literal_test.go +69 -0
- package/internal/lspserver/lsp_completion_replaces_full_filter_in_rank_order_test.go +85 -0
- package/internal/lspserver/lsp_completion_request.go +455 -0
- package/internal/lspserver/lsp_completion_scope.go +530 -0
- package/internal/lspserver/lsp_completion_scope_bench_test.go +41 -0
- package/internal/lspserver/lsp_completion_scope_classifies_regex_statement_and_operator_boundaries_test.go +39 -0
- package/internal/lspserver/lsp_completion_scope_ignores_jsdoc_bytes_in_literals_test.go +108 -0
- package/internal/lspserver/lsp_completion_scope_refuses_regex_hints_test.go +52 -0
- package/internal/lspserver/lsp_completion_trigger_uses_last_rune_test.go +24 -0
- package/internal/lspserver/lsp_deleted_watched_file_withdraws_plugin_diagnostics_test.go +110 -0
- package/internal/lspserver/lsp_didsave_keeps_the_incremental_changed_uri_path_test.go +78 -0
- package/internal/lspserver/lsp_hints_absence_is_not_an_error_test.go +46 -0
- package/internal/lspserver/lsp_hints_refresh_coalesces_concurrent_requests_test.go +82 -0
- package/internal/lspserver/lsp_hints_refresh_ignores_a_superseded_generation_test.go +40 -0
- package/internal/lspserver/lsp_hints_refresh_keeps_each_producer_isolated_test.go +64 -0
- package/internal/lspserver/lsp_hints_refresh_replaces_the_session_snapshot_test.go +66 -0
- package/internal/lspserver/lsp_hints_refresh_scheduled_by_editor_events_test.go +90 -0
- package/internal/lspserver/lsp_hints_refresh_serves_completion_while_running_test.go +91 -0
- package/internal/lspserver/lsp_index_byte_from_bounds_its_search_start_test.go +38 -0
- package/internal/lspserver/lsp_initialize_constrains_position_encoding_to_utf16_test.go +205 -0
- package/internal/lspserver/lsp_late_completion_trigger_is_reported_once_test.go +105 -0
- package/internal/lspserver/lsp_native_completion_hints_decode_flat_lint_wire_test.go +66 -0
- package/internal/lspserver/lsp_native_completion_hints_grouped_compatibility_boundary_test.go +60 -0
- package/internal/lspserver/lsp_native_plugin_source.go +315 -2
- package/internal/lspserver/lsp_native_resident.go +304 -0
- package/internal/lspserver/lsp_plugin.go +85 -8
- package/internal/lspserver/lsp_plugin_completion_resolve_stays_local_test.go +82 -0
- package/internal/lspserver/lsp_position_conversions_span_astral_and_combining_runes_test.go +119 -0
- package/internal/lspserver/lsp_proxy.go +601 -9
- package/internal/lspserver/lsp_refresh.go +70 -0
- package/internal/lspserver/lsp_resident_falls_back_when_serve_unsupported_test.go +43 -0
- package/internal/lspserver/lsp_resident_maps_verb_args_test.go +34 -0
- package/internal/lspserver/lsp_server.go +13 -1
- package/internal/lspserver/lsp_watched_file_changes_reach_compiler_caches_test.go +172 -0
- package/lib/TtscCompiler.d.ts +3 -1
- package/lib/TtscCompiler.js +5 -1
- package/lib/TtscCompiler.js.map +1 -1
- package/lib/TtscService.d.ts +13 -3
- package/lib/TtscService.js +6 -6
- package/lib/TtscService.js.map +1 -1
- package/lib/compiler/internal/project/readConfigJson.d.ts +30 -0
- package/lib/compiler/internal/project/readConfigJson.js +208 -0
- package/lib/compiler/internal/project/readConfigJson.js.map +1 -0
- package/lib/compiler/internal/project/readProjectConfig.js +53 -149
- package/lib/compiler/internal/project/readProjectConfig.js.map +1 -1
- package/lib/compiler/internal/residentTransformProcess.d.ts +15 -2
- package/lib/compiler/internal/residentTransformProcess.js +159 -39
- package/lib/compiler/internal/residentTransformProcess.js.map +1 -1
- package/lib/compiler/internal/runBuild.d.ts +6 -0
- package/lib/compiler/internal/runBuild.js +143 -44
- package/lib/compiler/internal/runBuild.js.map +1 -1
- package/lib/compiler/internal/startResidentTransform.d.ts +5 -1
- package/lib/compiler/internal/startResidentTransform.js +3 -1
- package/lib/compiler/internal/startResidentTransform.js.map +1 -1
- package/lib/compiler/internal/transformProjectInMemory.js +12 -2
- package/lib/compiler/internal/transformProjectInMemory.js.map +1 -1
- package/lib/flags/parser.d.ts +19 -0
- package/lib/flags/parser.js +78 -36
- package/lib/flags/parser.js.map +1 -1
- package/lib/flags/schema.d.ts +49 -11
- package/lib/flags/schema.js +94 -22
- package/lib/flags/schema.js.map +1 -1
- package/lib/internal/assertSafeExplicitCacheDirectory.d.ts +5 -0
- package/lib/internal/assertSafeExplicitCacheDirectory.js +26 -0
- package/lib/internal/assertSafeExplicitCacheDirectory.js.map +1 -0
- package/lib/launcher/internal/runTtsc.js +107 -69
- package/lib/launcher/internal/runTtsc.js.map +1 -1
- package/lib/launcher/internal/runTtsx.js +28 -41
- package/lib/launcher/internal/runTtsx.js.map +1 -1
- package/lib/launcher/internal/runtimeHooks.d.ts +15 -0
- package/lib/launcher/internal/runtimeHooks.js +18 -1
- package/lib/launcher/internal/runtimeHooks.js.map +1 -1
- package/lib/launcher/internal/watchTopology.d.ts +43 -0
- package/lib/launcher/internal/watchTopology.js +360 -0
- package/lib/launcher/internal/watchTopology.js.map +1 -0
- package/lib/plugin/internal/buildSourcePlugin.d.ts +14 -3
- package/lib/plugin/internal/buildSourcePlugin.js +247 -61
- package/lib/plugin/internal/buildSourcePlugin.js.map +1 -1
- package/lib/plugin/internal/loadProjectPlugins.js +63 -2
- package/lib/plugin/internal/loadProjectPlugins.js.map +1 -1
- package/lib/structures/ITtscCompilerTransformation.d.ts +16 -0
- package/lib/structures/internal/ITtscParsedProjectConfig.d.ts +2 -0
- package/package.json +8 -8
- package/shim/ast/shim.go +48 -3
- package/shim/astnav/go.mod +14 -0
- package/shim/astnav/go.sum +20 -0
- package/shim/astnav/shim.go +15 -0
- package/shim/checker/shim.go +113 -0
- package/shim/core/shim.go +47 -0
- package/shim/diagnosticwriter/lint.go +50 -0
- package/src/TtscCompiler.ts +5 -1
- package/src/TtscService.ts +37 -10
- package/src/compiler/internal/project/readConfigJson.ts +209 -0
- package/src/compiler/internal/project/readProjectConfig.ts +62 -158
- package/src/compiler/internal/residentTransformProcess.ts +197 -39
- package/src/compiler/internal/runBuild.ts +169 -47
- package/src/compiler/internal/startResidentTransform.ts +12 -1
- package/src/compiler/internal/transformProjectInMemory.ts +12 -1
- package/src/flags/parser.ts +113 -42
- package/src/flags/schema.ts +113 -31
- package/src/internal/assertSafeExplicitCacheDirectory.ts +29 -0
- package/src/launcher/internal/runTtsc.ts +117 -68
- package/src/launcher/internal/runTtsx.ts +29 -44
- package/src/launcher/internal/runtimeHooks.ts +30 -2
- package/src/launcher/internal/watchTopology.ts +466 -0
- package/src/plugin/internal/buildSourcePlugin.ts +326 -64
- package/src/plugin/internal/loadProjectPlugins.ts +80 -2
- package/src/structures/ITtscCompilerTransformation.ts +17 -0
- package/src/structures/internal/ITtscParsedProjectConfig.ts +2 -0
- package/tools/shim_audit/baseline.json +0 -3
- package/tools/shim_audit/main.go +42 -14
- package/tools/shim_audit/shim_dir_coverage_test.go +25 -0
- package/utility/flags_gen.go +3 -3
- package/utility/host.go +9 -3
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
package main
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"path/filepath"
|
|
5
|
+
"testing"
|
|
6
|
+
)
|
|
7
|
+
|
|
8
|
+
// TestServeSessionKeepsInactiveConditionalExportUnchanged verifies a
|
|
9
|
+
// condition the active TypeScript-Go lookup cannot select is not a graph
|
|
10
|
+
// freshness input.
|
|
11
|
+
//
|
|
12
|
+
// An inactive branch can be present ahead of the active `types` and `default`
|
|
13
|
+
// branches in package.json, but creating that target must not reload a
|
|
14
|
+
// resident ESM session. Creating the missing active `types` target still must.
|
|
15
|
+
func TestServeSessionKeepsInactiveConditionalExportUnchanged(t *testing.T) {
|
|
16
|
+
root := t.TempDir()
|
|
17
|
+
writeGraphFile(t, filepath.Join(root, "package.json"), `{"type":"module"}`)
|
|
18
|
+
writeGraphFile(t, filepath.Join(root, "tsconfig.json"), `{
|
|
19
|
+
"compilerOptions": {
|
|
20
|
+
"allowJs": true,
|
|
21
|
+
"module": "nodenext",
|
|
22
|
+
"moduleResolution": "nodenext",
|
|
23
|
+
"target": "ES2022"
|
|
24
|
+
},
|
|
25
|
+
"files": ["src/main.ts"]
|
|
26
|
+
}`)
|
|
27
|
+
writeGraphFile(t, filepath.Join(root, "src", "main.ts"), "import { winner } from 'fixture-package/feature';\nexport function main(): void { winner(); }\n")
|
|
28
|
+
writeGraphFile(t, filepath.Join(root, "node_modules", "fixture-package", "package.json"), `{
|
|
29
|
+
"name": "fixture-package",
|
|
30
|
+
"exports": {
|
|
31
|
+
"./feature": {
|
|
32
|
+
"browser": "./dist/browser.js",
|
|
33
|
+
"types": "./dist/types.d.ts",
|
|
34
|
+
"default": "./dist/fallback.js"
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}`)
|
|
38
|
+
writeGraphFile(t, filepath.Join(root, "node_modules", "fixture-package", "dist", "fallback.js"), "export function winner() {}\n")
|
|
39
|
+
|
|
40
|
+
session, err := newGraphSession(root, "tsconfig.json")
|
|
41
|
+
if err != nil {
|
|
42
|
+
t.Fatal(err)
|
|
43
|
+
}
|
|
44
|
+
defer session.Close()
|
|
45
|
+
if _, _, _, err := session.Snapshot(); err != nil {
|
|
46
|
+
t.Fatal(err)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
writeGraphFile(t, filepath.Join(root, "node_modules", "fixture-package", "dist", "browser.js"), "export function winner() {}\nexport function browserOnly() {}\n")
|
|
50
|
+
dump, mode, changed, err := session.Snapshot()
|
|
51
|
+
if err != nil {
|
|
52
|
+
t.Fatal(err)
|
|
53
|
+
}
|
|
54
|
+
if dump != nil || mode != serveModeUnchanged || changed {
|
|
55
|
+
t.Fatalf("inactive browser condition = dump:%v mode:%q changed:%v", dump != nil, mode, changed)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
writeGraphFile(t, filepath.Join(root, "node_modules", "fixture-package", "dist", "types.d.ts"), "export declare function winner(): void;\nexport declare function typesWinner(): void;\n")
|
|
59
|
+
dump, mode, changed, err = session.Snapshot()
|
|
60
|
+
if err != nil {
|
|
61
|
+
t.Fatal(err)
|
|
62
|
+
}
|
|
63
|
+
if dump == nil || mode != serveModeReload || !changed {
|
|
64
|
+
t.Fatalf("active types condition = dump:%v mode:%q changed:%v", dump != nil, mode, changed)
|
|
65
|
+
}
|
|
66
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
package main
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"os"
|
|
5
|
+
"path/filepath"
|
|
6
|
+
"testing"
|
|
7
|
+
)
|
|
8
|
+
|
|
9
|
+
// TestServeSessionKeepsLowerPriorityModuleCandidateUnchanged verifies a
|
|
10
|
+
// resident session does not reload when a candidate after its selected target
|
|
11
|
+
// appears.
|
|
12
|
+
//
|
|
13
|
+
// Directory index probes are lower priority than every direct-file probe. An
|
|
14
|
+
// interleaved candidate list would turn the creation of an irrelevant index
|
|
15
|
+
// file into a full program reload and erase the bounded-freshness guarantee.
|
|
16
|
+
//
|
|
17
|
+
// 1. Load an extensionless commonjs import that resolves directly to value.js.
|
|
18
|
+
// 2. Create only lower-priority value/index.ts and value.mts candidates.
|
|
19
|
+
// 3. Assert the resident session remains unchanged, then create value.ts and
|
|
20
|
+
// assert the strictly higher-priority candidate does reload it.
|
|
21
|
+
func TestServeSessionKeepsLowerPriorityModuleCandidateUnchanged(t *testing.T) {
|
|
22
|
+
root := t.TempDir()
|
|
23
|
+
writeGraphFile(t, filepath.Join(root, "tsconfig.json"), `{
|
|
24
|
+
"compilerOptions": { "allowJs": true, "module": "commonjs", "target": "ES2022" },
|
|
25
|
+
"files": ["src/main.ts"]
|
|
26
|
+
}`)
|
|
27
|
+
writeGraphFile(t, filepath.Join(root, "src", "main.ts"), "import { winner } from './value';\nexport function main(): void { winner(); }\n")
|
|
28
|
+
writeGraphFile(t, filepath.Join(root, "src", "value.js"), "export function winner() {}\n")
|
|
29
|
+
|
|
30
|
+
session, err := newGraphSession(root, "tsconfig.json")
|
|
31
|
+
if err != nil {
|
|
32
|
+
t.Fatal(err)
|
|
33
|
+
}
|
|
34
|
+
defer session.Close()
|
|
35
|
+
if _, _, _, err := session.Snapshot(); err != nil {
|
|
36
|
+
t.Fatal(err)
|
|
37
|
+
}
|
|
38
|
+
if err := os.MkdirAll(filepath.Join(root, "src", "value"), 0o755); err != nil {
|
|
39
|
+
t.Fatal(err)
|
|
40
|
+
}
|
|
41
|
+
writeGraphFile(t, filepath.Join(root, "src", "value", "index.ts"), "export function winner(): void {}\n")
|
|
42
|
+
dump, mode, changed, err := session.Snapshot()
|
|
43
|
+
if err != nil {
|
|
44
|
+
t.Fatal(err)
|
|
45
|
+
}
|
|
46
|
+
if dump != nil || mode != serveModeUnchanged || changed {
|
|
47
|
+
t.Fatalf("lower-priority index = dump:%v mode:%q changed:%v", dump != nil, mode, changed)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
writeGraphFile(t, filepath.Join(root, "src", "value.mts"), "export function winner(): void {}\n")
|
|
51
|
+
dump, mode, changed, err = session.Snapshot()
|
|
52
|
+
if err != nil {
|
|
53
|
+
t.Fatal(err)
|
|
54
|
+
}
|
|
55
|
+
if dump != nil || mode != serveModeUnchanged || changed {
|
|
56
|
+
t.Fatalf("commonjs-lower-priority .mts = dump:%v mode:%q changed:%v", dump != nil, mode, changed)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
writeGraphFile(t, filepath.Join(root, "src", "value.ts"), "export function winner(): void {}\nexport function typescriptWinner(): void {}\n")
|
|
60
|
+
dump, mode, changed, err = session.Snapshot()
|
|
61
|
+
if err != nil {
|
|
62
|
+
t.Fatal(err)
|
|
63
|
+
}
|
|
64
|
+
if dump == nil || mode != serveModeReload || !changed || !hasDumpNode(*dump, "typescriptWinner") {
|
|
65
|
+
t.Fatalf("higher-priority .ts = dump:%v mode:%q changed:%v", dump != nil, mode, changed)
|
|
66
|
+
}
|
|
67
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
package main
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"path/filepath"
|
|
5
|
+
"testing"
|
|
6
|
+
)
|
|
7
|
+
|
|
8
|
+
// TestServeSessionKeepsLowerPriorityPathsPatternUnchanged verifies only the
|
|
9
|
+
// most-specific TypeScript-Go paths pattern contributes freshness candidates.
|
|
10
|
+
//
|
|
11
|
+
// `@/special/*` outranks `@/*`; a file under the broad substitution never
|
|
12
|
+
// participates in this lookup, while a missing .ts sibling of the selected
|
|
13
|
+
// specific substitution does.
|
|
14
|
+
func TestServeSessionKeepsLowerPriorityPathsPatternUnchanged(t *testing.T) {
|
|
15
|
+
root := t.TempDir()
|
|
16
|
+
writeGraphFile(t, filepath.Join(root, "tsconfig.json"), `{
|
|
17
|
+
"compilerOptions": {
|
|
18
|
+
"allowJs": true,
|
|
19
|
+
"baseUrl": ".",
|
|
20
|
+
"module": "commonjs",
|
|
21
|
+
"paths": {
|
|
22
|
+
"@/*": ["broad/*"],
|
|
23
|
+
"@/special/*": ["specific/*"]
|
|
24
|
+
},
|
|
25
|
+
"target": "ES2022"
|
|
26
|
+
},
|
|
27
|
+
"files": ["src/main.ts"]
|
|
28
|
+
}`)
|
|
29
|
+
writeGraphFile(t, filepath.Join(root, "src", "main.ts"), "import { winner } from '@/special/value';\nexport function main(): void { winner(); }\n")
|
|
30
|
+
writeGraphFile(t, filepath.Join(root, "specific", "value.js"), "export function winner() {}\n")
|
|
31
|
+
|
|
32
|
+
session, err := newGraphSession(root, "tsconfig.json")
|
|
33
|
+
if err != nil {
|
|
34
|
+
t.Fatal(err)
|
|
35
|
+
}
|
|
36
|
+
defer session.Close()
|
|
37
|
+
if _, _, _, err := session.Snapshot(); err != nil {
|
|
38
|
+
t.Fatal(err)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
writeGraphFile(t, filepath.Join(root, "broad", "special", "value.ts"), "export function winner(): void {}\n")
|
|
42
|
+
dump, mode, changed, err := session.Snapshot()
|
|
43
|
+
if err != nil {
|
|
44
|
+
t.Fatal(err)
|
|
45
|
+
}
|
|
46
|
+
if dump != nil || mode != serveModeUnchanged || changed {
|
|
47
|
+
t.Fatalf("broad paths pattern = dump:%v mode:%q changed:%v", dump != nil, mode, changed)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
writeGraphFile(t, filepath.Join(root, "specific", "value.ts"), "export function winner(): void {}\nexport function specificPathsWinner(): void {}\n")
|
|
51
|
+
dump, mode, changed, err = session.Snapshot()
|
|
52
|
+
if err != nil {
|
|
53
|
+
t.Fatal(err)
|
|
54
|
+
}
|
|
55
|
+
if dump == nil || mode != serveModeReload || !changed || !hasDumpNode(*dump, "specificPathsWinner") {
|
|
56
|
+
t.Fatalf("specific paths pattern = dump:%v mode:%q changed:%v", dump != nil, mode, changed)
|
|
57
|
+
}
|
|
58
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
package main
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"path/filepath"
|
|
5
|
+
"testing"
|
|
6
|
+
)
|
|
7
|
+
|
|
8
|
+
// TestServeSessionKeepsNonLongestRootDirsCandidateUnchanged verifies rootDirs
|
|
9
|
+
// starts from TypeScript-Go's longest matching source root.
|
|
10
|
+
//
|
|
11
|
+
// The containing source lies under both src and src/generated. Only the
|
|
12
|
+
// longest root makes out/views/template a peer candidate; out/generated/views
|
|
13
|
+
// comes from the shorter root and is never tried by this resolution.
|
|
14
|
+
func TestServeSessionKeepsNonLongestRootDirsCandidateUnchanged(t *testing.T) {
|
|
15
|
+
root := t.TempDir()
|
|
16
|
+
writeGraphFile(t, filepath.Join(root, "tsconfig.json"), `{
|
|
17
|
+
"compilerOptions": {
|
|
18
|
+
"allowJs": true,
|
|
19
|
+
"module": "commonjs",
|
|
20
|
+
"rootDirs": ["src", "src/generated", "out"],
|
|
21
|
+
"target": "ES2022"
|
|
22
|
+
},
|
|
23
|
+
"files": ["src/generated/views/main.ts"]
|
|
24
|
+
}`)
|
|
25
|
+
writeGraphFile(t, filepath.Join(root, "src", "generated", "views", "main.ts"), "import { winner } from './template';\nexport function main(): void { winner(); }\n")
|
|
26
|
+
writeGraphFile(t, filepath.Join(root, "out", "views", "template.js"), "export function winner() {}\n")
|
|
27
|
+
|
|
28
|
+
session, err := newGraphSession(root, "tsconfig.json")
|
|
29
|
+
if err != nil {
|
|
30
|
+
t.Fatal(err)
|
|
31
|
+
}
|
|
32
|
+
defer session.Close()
|
|
33
|
+
if _, _, _, err := session.Snapshot(); err != nil {
|
|
34
|
+
t.Fatal(err)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
writeGraphFile(t, filepath.Join(root, "out", "generated", "views", "template.ts"), "export function winner(): void {}\n")
|
|
38
|
+
dump, mode, changed, err := session.Snapshot()
|
|
39
|
+
if err != nil {
|
|
40
|
+
t.Fatal(err)
|
|
41
|
+
}
|
|
42
|
+
if dump != nil || mode != serveModeUnchanged || changed {
|
|
43
|
+
t.Fatalf("non-longest rootDirs candidate = dump:%v mode:%q changed:%v", dump != nil, mode, changed)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
writeGraphFile(t, filepath.Join(root, "src", "views", "template.ts"), "export function winner(): void {}\nexport function rootDirsWinner(): void {}\n")
|
|
47
|
+
dump, mode, changed, err = session.Snapshot()
|
|
48
|
+
if err != nil {
|
|
49
|
+
t.Fatal(err)
|
|
50
|
+
}
|
|
51
|
+
if dump == nil || mode != serveModeReload || !changed || !hasDumpNode(*dump, "rootDirsWinner") {
|
|
52
|
+
t.Fatalf("longest-root peer candidate = dump:%v mode:%q changed:%v", dump != nil, mode, changed)
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
package main
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"path/filepath"
|
|
5
|
+
"testing"
|
|
6
|
+
)
|
|
7
|
+
|
|
8
|
+
// TestServeSessionReloadsCommonJSPackageEntryForESM verifies an ESM importer
|
|
9
|
+
// preserves the CommonJS fallback rules of a package's extensionless main.
|
|
10
|
+
//
|
|
11
|
+
// The importing source is ESM, but TypeScript-Go temporarily uses CommonJS
|
|
12
|
+
// lookup for a package without `type: module`. A missing main.ts therefore
|
|
13
|
+
// precedes main.js and must invalidate the resident session when it appears.
|
|
14
|
+
func TestServeSessionReloadsCommonJSPackageEntryForESM(t *testing.T) {
|
|
15
|
+
root := t.TempDir()
|
|
16
|
+
writeGraphFile(t, filepath.Join(root, "package.json"), `{"type":"module"}`)
|
|
17
|
+
writeGraphFile(t, filepath.Join(root, "tsconfig.json"), `{
|
|
18
|
+
"compilerOptions": {
|
|
19
|
+
"allowJs": true,
|
|
20
|
+
"module": "nodenext",
|
|
21
|
+
"moduleResolution": "nodenext",
|
|
22
|
+
"target": "ES2022"
|
|
23
|
+
},
|
|
24
|
+
"files": ["src/main.ts"]
|
|
25
|
+
}`)
|
|
26
|
+
writeGraphFile(t, filepath.Join(root, "src", "main.ts"), "import { winner } from 'fixture-package';\nexport function main(): void { winner(); }\n")
|
|
27
|
+
writeGraphFile(t, filepath.Join(root, "node_modules", "fixture-package", "package.json"), `{
|
|
28
|
+
"name": "fixture-package",
|
|
29
|
+
"main": "./dist/main"
|
|
30
|
+
}`)
|
|
31
|
+
writeGraphFile(t, filepath.Join(root, "node_modules", "fixture-package", "dist", "main.js"), "export function winner() {}\n")
|
|
32
|
+
|
|
33
|
+
session, err := newGraphSession(root, "tsconfig.json")
|
|
34
|
+
if err != nil {
|
|
35
|
+
t.Fatal(err)
|
|
36
|
+
}
|
|
37
|
+
defer session.Close()
|
|
38
|
+
if _, _, _, err := session.Snapshot(); err != nil {
|
|
39
|
+
t.Fatal(err)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
writeGraphFile(t, filepath.Join(root, "node_modules", "fixture-package", "dist", "main.ts"), "export function winner(): void {}\nexport function packageEntryWinner(): void {}\n")
|
|
43
|
+
dump, mode, changed, err := session.Snapshot()
|
|
44
|
+
if err != nil {
|
|
45
|
+
t.Fatal(err)
|
|
46
|
+
}
|
|
47
|
+
if dump == nil || mode != serveModeReload || !changed || !hasDumpNode(*dump, "packageEntryWinner") {
|
|
48
|
+
t.Fatalf("CommonJS package main.ts = dump:%v mode:%q changed:%v", dump != nil, mode, changed)
|
|
49
|
+
}
|
|
50
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
package main
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"path/filepath"
|
|
5
|
+
"testing"
|
|
6
|
+
)
|
|
7
|
+
|
|
8
|
+
// TestServeSessionReloadsModuleSuffixCandidate verifies a configured module
|
|
9
|
+
// suffix is considered before the unsuffixed extension candidate.
|
|
10
|
+
func TestServeSessionReloadsModuleSuffixCandidate(t *testing.T) {
|
|
11
|
+
root := t.TempDir()
|
|
12
|
+
writeGraphFile(t, filepath.Join(root, "tsconfig.json"), `{
|
|
13
|
+
"compilerOptions": {
|
|
14
|
+
"allowJs": true,
|
|
15
|
+
"module": "commonjs",
|
|
16
|
+
"moduleSuffixes": [".native", ""],
|
|
17
|
+
"target": "ES2022"
|
|
18
|
+
},
|
|
19
|
+
"files": ["src/main.ts"]
|
|
20
|
+
}`)
|
|
21
|
+
writeGraphFile(t, filepath.Join(root, "src", "main.ts"), "import { winner } from './value';\nexport function main(): void { winner(); }\n")
|
|
22
|
+
writeGraphFile(t, filepath.Join(root, "src", "value.js"), "export function winner() {}\n")
|
|
23
|
+
|
|
24
|
+
session, err := newGraphSession(root, "tsconfig.json")
|
|
25
|
+
if err != nil {
|
|
26
|
+
t.Fatal(err)
|
|
27
|
+
}
|
|
28
|
+
defer session.Close()
|
|
29
|
+
if _, _, _, err := session.Snapshot(); err != nil {
|
|
30
|
+
t.Fatal(err)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
writeGraphFile(t, filepath.Join(root, "src", "value.native.ts"), "export function winner(): void {}\nexport function nativeWinner(): void {}\n")
|
|
34
|
+
dump, mode, changed, err := session.Snapshot()
|
|
35
|
+
if err != nil {
|
|
36
|
+
t.Fatal(err)
|
|
37
|
+
}
|
|
38
|
+
if dump == nil || mode != serveModeReload || !changed || !hasDumpNode(*dump, "nativeWinner") {
|
|
39
|
+
t.Fatalf("module-suffix candidate = dump:%v mode:%q changed:%v", dump != nil, mode, changed)
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
package main
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"path/filepath"
|
|
5
|
+
"testing"
|
|
6
|
+
)
|
|
7
|
+
|
|
8
|
+
// TestServeSessionReloadsSupersedingModuleCandidates verifies a resident
|
|
9
|
+
// session reloads when an unchanged specifier gains a missing candidate that
|
|
10
|
+
// outranks the file TypeScript-Go selected for the first snapshot.
|
|
11
|
+
//
|
|
12
|
+
// A resident session cannot rely on a changed importer or tsconfig to notice a
|
|
13
|
+
// resolution precedence change. Each case pins a distinct resolver family while
|
|
14
|
+
// preserving both files between observations.
|
|
15
|
+
//
|
|
16
|
+
// 1. Load a project whose specifier resolves to the lower-priority target.
|
|
17
|
+
// 2. Create only the absent target that precedes it in that resolver's search.
|
|
18
|
+
// 3. Assert the resident snapshot reloads and exposes the new target when one
|
|
19
|
+
// carries a distinguishing declaration.
|
|
20
|
+
func TestServeSessionReloadsSupersedingModuleCandidates(t *testing.T) {
|
|
21
|
+
cases := []struct {
|
|
22
|
+
name string
|
|
23
|
+
setup func(*testing.T, string) string
|
|
24
|
+
add func(*testing.T, string)
|
|
25
|
+
}{
|
|
26
|
+
{
|
|
27
|
+
name: "relative_extension",
|
|
28
|
+
setup: func(t *testing.T, root string) string {
|
|
29
|
+
writeGraphFile(t, filepath.Join(root, "tsconfig.json"), `{
|
|
30
|
+
"compilerOptions": { "allowJs": true, "module": "commonjs", "target": "ES2022" },
|
|
31
|
+
"files": ["src/main.ts"]
|
|
32
|
+
}`)
|
|
33
|
+
writeGraphFile(t, filepath.Join(root, "src", "main.ts"), "import { winner } from './value';\nexport function main(): void { winner(); }\n")
|
|
34
|
+
writeGraphFile(t, filepath.Join(root, "src", "value.js"), "export function winner() {}\n")
|
|
35
|
+
return "typescriptWinner"
|
|
36
|
+
},
|
|
37
|
+
add: func(t *testing.T, root string) {
|
|
38
|
+
writeGraphFile(t, filepath.Join(root, "src", "value.ts"), "export function winner(): void {}\nexport function typescriptWinner(): void {}\n")
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
name: "ordered_paths",
|
|
43
|
+
setup: func(t *testing.T, root string) string {
|
|
44
|
+
writeGraphFile(t, filepath.Join(root, "tsconfig.json"), `{
|
|
45
|
+
"compilerOptions": {
|
|
46
|
+
"baseUrl": ".",
|
|
47
|
+
"module": "commonjs",
|
|
48
|
+
"paths": { "@generated/*": ["first/*", "fallback/*"] },
|
|
49
|
+
"target": "ES2022"
|
|
50
|
+
},
|
|
51
|
+
"files": ["src/main.ts"]
|
|
52
|
+
}`)
|
|
53
|
+
writeGraphFile(t, filepath.Join(root, "src", "main.ts"), "import { winner } from '@generated/value';\nexport function main(): void { winner(); }\n")
|
|
54
|
+
writeGraphFile(t, filepath.Join(root, "fallback", "value.ts"), "export function winner(): void {}\n")
|
|
55
|
+
return "firstPathsWinner"
|
|
56
|
+
},
|
|
57
|
+
add: func(t *testing.T, root string) {
|
|
58
|
+
writeGraphFile(t, filepath.Join(root, "first", "value.ts"), "export function winner(): void {}\nexport function firstPathsWinner(): void {}\n")
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
name: "root_dirs",
|
|
63
|
+
setup: func(t *testing.T, root string) string {
|
|
64
|
+
writeGraphFile(t, filepath.Join(root, "tsconfig.json"), `{
|
|
65
|
+
"compilerOptions": {
|
|
66
|
+
"module": "commonjs",
|
|
67
|
+
"rootDirs": ["src", "generated"],
|
|
68
|
+
"target": "ES2022"
|
|
69
|
+
},
|
|
70
|
+
"files": ["src/views/main.ts"]
|
|
71
|
+
}`)
|
|
72
|
+
writeGraphFile(t, filepath.Join(root, "src", "views", "main.ts"), "import { winner } from './template';\nexport function main(): void { winner(); }\n")
|
|
73
|
+
writeGraphFile(t, filepath.Join(root, "generated", "views", "template.ts"), "export function winner(): void {}\n")
|
|
74
|
+
return "rootDirsWinner"
|
|
75
|
+
},
|
|
76
|
+
add: func(t *testing.T, root string) {
|
|
77
|
+
writeGraphFile(t, filepath.Join(root, "src", "views", "template.ts"), "export function winner(): void {}\nexport function rootDirsWinner(): void {}\n")
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
name: "nearer_node_modules",
|
|
82
|
+
setup: func(t *testing.T, root string) string {
|
|
83
|
+
writeGraphFile(t, filepath.Join(root, "tsconfig.json"), `{
|
|
84
|
+
"compilerOptions": { "allowJs": true, "module": "commonjs", "target": "ES2022" },
|
|
85
|
+
"files": ["src/deep/main.ts"]
|
|
86
|
+
}`)
|
|
87
|
+
writeGraphFile(t, filepath.Join(root, "src", "deep", "main.ts"), "import { winner } from 'fixture-package';\nexport function main(): void { winner(); }\n")
|
|
88
|
+
writeGraphFile(t, filepath.Join(root, "node_modules", "fixture-package", "index.js"), "export function winner() {}\n")
|
|
89
|
+
return "nearerNodeModulesWinner"
|
|
90
|
+
},
|
|
91
|
+
add: func(t *testing.T, root string) {
|
|
92
|
+
writeGraphFile(t, filepath.Join(root, "src", "node_modules", "fixture-package", "index.ts"), "export function winner(): void {}\nexport function nearerNodeModulesWinner(): void {}\n")
|
|
93
|
+
},
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
name: "package_exports",
|
|
97
|
+
setup: func(t *testing.T, root string) string {
|
|
98
|
+
writeGraphFile(t, filepath.Join(root, "tsconfig.json"), `{
|
|
99
|
+
"compilerOptions": {
|
|
100
|
+
"allowJs": true,
|
|
101
|
+
"module": "nodenext",
|
|
102
|
+
"moduleResolution": "nodenext",
|
|
103
|
+
"target": "ES2022"
|
|
104
|
+
},
|
|
105
|
+
"files": ["src/main.ts"]
|
|
106
|
+
}`)
|
|
107
|
+
writeGraphFile(t, filepath.Join(root, "src", "main.ts"), "import { winner } from 'fixture-package/feature';\nexport function main(): void { winner(); }\n")
|
|
108
|
+
writeGraphFile(t, filepath.Join(root, "node_modules", "fixture-package", "package.json"), `{
|
|
109
|
+
"name": "fixture-package",
|
|
110
|
+
"exports": { "./feature": ["./dist/first.js", "./dist/fallback.js"] }
|
|
111
|
+
}`)
|
|
112
|
+
writeGraphFile(t, filepath.Join(root, "node_modules", "fixture-package", "dist", "fallback.js"), "export function winner() {}\n")
|
|
113
|
+
return ""
|
|
114
|
+
},
|
|
115
|
+
add: func(t *testing.T, root string) {
|
|
116
|
+
writeGraphFile(t, filepath.Join(root, "node_modules", "fixture-package", "dist", "first.js"), "export function winner() {}\nexport function exportsWinner() {}\n")
|
|
117
|
+
},
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
name: "conditional_package_exports",
|
|
121
|
+
setup: func(t *testing.T, root string) string {
|
|
122
|
+
writeGraphFile(t, filepath.Join(root, "tsconfig.json"), `{
|
|
123
|
+
"compilerOptions": {
|
|
124
|
+
"allowJs": true,
|
|
125
|
+
"module": "nodenext",
|
|
126
|
+
"moduleResolution": "nodenext",
|
|
127
|
+
"target": "ES2022"
|
|
128
|
+
},
|
|
129
|
+
"files": ["src/main.ts"]
|
|
130
|
+
}`)
|
|
131
|
+
writeGraphFile(t, filepath.Join(root, "src", "main.ts"), "import { winner } from 'fixture-package/feature';\nexport function main(): void { winner(); }\n")
|
|
132
|
+
writeGraphFile(t, filepath.Join(root, "node_modules", "fixture-package", "package.json"), `{
|
|
133
|
+
"name": "fixture-package",
|
|
134
|
+
"exports": {
|
|
135
|
+
"./feature": {
|
|
136
|
+
"types": "./dist/types.d.ts",
|
|
137
|
+
"default": "./dist/fallback.js"
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}`)
|
|
141
|
+
writeGraphFile(t, filepath.Join(root, "node_modules", "fixture-package", "dist", "fallback.js"), "export function winner() {}\n")
|
|
142
|
+
return ""
|
|
143
|
+
},
|
|
144
|
+
add: func(t *testing.T, root string) {
|
|
145
|
+
writeGraphFile(t, filepath.Join(root, "node_modules", "fixture-package", "dist", "types.d.ts"), "export declare function winner(): void;\n")
|
|
146
|
+
},
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
name: "conditional_package_imports",
|
|
150
|
+
setup: func(t *testing.T, root string) string {
|
|
151
|
+
writeGraphFile(t, filepath.Join(root, "package.json"), `{
|
|
152
|
+
"name": "fixture-project",
|
|
153
|
+
"imports": {
|
|
154
|
+
"#feature": {
|
|
155
|
+
"types": "./generated/types.d.ts",
|
|
156
|
+
"default": "./generated/fallback.js"
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}`)
|
|
160
|
+
writeGraphFile(t, filepath.Join(root, "tsconfig.json"), `{
|
|
161
|
+
"compilerOptions": {
|
|
162
|
+
"allowJs": true,
|
|
163
|
+
"module": "nodenext",
|
|
164
|
+
"moduleResolution": "nodenext",
|
|
165
|
+
"target": "ES2022"
|
|
166
|
+
},
|
|
167
|
+
"files": ["src/main.ts"]
|
|
168
|
+
}`)
|
|
169
|
+
writeGraphFile(t, filepath.Join(root, "src", "main.ts"), "import { winner } from '#feature';\nexport function main(): void { winner(); }\n")
|
|
170
|
+
writeGraphFile(t, filepath.Join(root, "generated", "fallback.js"), "export function winner() {}\n")
|
|
171
|
+
return ""
|
|
172
|
+
},
|
|
173
|
+
add: func(t *testing.T, root string) {
|
|
174
|
+
writeGraphFile(t, filepath.Join(root, "generated", "types.d.ts"), "export declare function winner(): void;\n")
|
|
175
|
+
},
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
name: "file_over_directory_index",
|
|
179
|
+
setup: func(t *testing.T, root string) string {
|
|
180
|
+
writeGraphFile(t, filepath.Join(root, "tsconfig.json"), `{
|
|
181
|
+
"compilerOptions": { "allowJs": true, "module": "commonjs", "target": "ES2022" },
|
|
182
|
+
"files": ["src/main.ts"]
|
|
183
|
+
}`)
|
|
184
|
+
writeGraphFile(t, filepath.Join(root, "src", "main.ts"), "import { winner } from './feature';\nexport function main(): void { winner(); }\n")
|
|
185
|
+
writeGraphFile(t, filepath.Join(root, "src", "feature", "index.js"), "export function winner() {}\n")
|
|
186
|
+
return "fileWinner"
|
|
187
|
+
},
|
|
188
|
+
add: func(t *testing.T, root string) {
|
|
189
|
+
writeGraphFile(t, filepath.Join(root, "src", "feature.js"), "export function winner() {}\nexport function fileWinner() {}\n")
|
|
190
|
+
},
|
|
191
|
+
},
|
|
192
|
+
}
|
|
193
|
+
for _, test := range cases {
|
|
194
|
+
t.Run(test.name, func(t *testing.T) {
|
|
195
|
+
root := t.TempDir()
|
|
196
|
+
want := test.setup(t, root)
|
|
197
|
+
session, err := newGraphSession(root, "tsconfig.json")
|
|
198
|
+
if err != nil {
|
|
199
|
+
t.Fatal(err)
|
|
200
|
+
}
|
|
201
|
+
defer session.Close()
|
|
202
|
+
if _, _, _, err := session.Snapshot(); err != nil {
|
|
203
|
+
t.Fatal(err)
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
test.add(t, root)
|
|
207
|
+
dump, mode, changed, err := session.Snapshot()
|
|
208
|
+
if err != nil {
|
|
209
|
+
t.Fatal(err)
|
|
210
|
+
}
|
|
211
|
+
if dump == nil || mode != serveModeReload || !changed || (want != "" && !hasDumpNode(*dump, want)) {
|
|
212
|
+
t.Fatalf("superseding candidate = dump:%v mode:%q changed:%v want-node:%q", dump != nil, mode, changed, want)
|
|
213
|
+
}
|
|
214
|
+
})
|
|
215
|
+
}
|
|
216
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
package main
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"strings"
|
|
5
|
+
"testing"
|
|
6
|
+
|
|
7
|
+
"github.com/samchon/ttsc/packages/ttsc/driver"
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
// TestServeSessionKeepsChangeDetectionLiveAfterInitialDumpError verifies a
|
|
11
|
+
// rejected first dump still advances the session into its change-detection
|
|
12
|
+
// state. The invalid relative cwd is a deterministic path-mapper failure; once
|
|
13
|
+
// corrected, the same captured generation is retried and can become the first
|
|
14
|
+
// published snapshot.
|
|
15
|
+
func TestServeSessionKeepsChangeDetectionLiveAfterInitialDumpError(t *testing.T) {
|
|
16
|
+
root := graphSessionFixture(t)
|
|
17
|
+
compiler, diags, err := driver.NewSession(root, "tsconfig.json", driver.LoadProgramOptions{})
|
|
18
|
+
if err != nil {
|
|
19
|
+
t.Fatal(err)
|
|
20
|
+
}
|
|
21
|
+
if compiler == nil {
|
|
22
|
+
t.Fatalf("NewSession returned nil session (diagnostics: %v)", diags)
|
|
23
|
+
}
|
|
24
|
+
session := &graphSession{
|
|
25
|
+
cwd: root,
|
|
26
|
+
tsconfig: "tsconfig.json",
|
|
27
|
+
compiler: compiler,
|
|
28
|
+
}
|
|
29
|
+
defer session.Close()
|
|
30
|
+
if err := session.captureState(); err != nil {
|
|
31
|
+
t.Fatal(err)
|
|
32
|
+
}
|
|
33
|
+
session.cwd = "relative-project"
|
|
34
|
+
|
|
35
|
+
dump, _, changed, err := session.Snapshot()
|
|
36
|
+
if err == nil || !strings.Contains(err.Error(), "project root") {
|
|
37
|
+
t.Fatalf("initial dump error = %v, want absolute-root rejection", err)
|
|
38
|
+
}
|
|
39
|
+
if dump != nil || changed || !session.initialized || session.pendingDumpMode != serveModeInitial {
|
|
40
|
+
t.Fatalf(
|
|
41
|
+
"failed initial state = dump:%v changed:%v initialized:%v pending:%q",
|
|
42
|
+
dump != nil,
|
|
43
|
+
changed,
|
|
44
|
+
session.initialized,
|
|
45
|
+
session.pendingDumpMode,
|
|
46
|
+
)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
session.cwd = root
|
|
50
|
+
dump, mode, changed, err := session.Snapshot()
|
|
51
|
+
if err != nil {
|
|
52
|
+
t.Fatal(err)
|
|
53
|
+
}
|
|
54
|
+
if dump == nil || mode != serveModeInitial || !changed {
|
|
55
|
+
t.Fatalf("repaired initial dump = dump:%v mode:%q changed:%v", dump != nil, mode, changed)
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// TestServeSessionRetriesAPendingDumpBeforeUnchanged pins the state boundary
|
|
60
|
+
// introduced by dump-time path validation. A failed dump may occur after the
|
|
61
|
+
// compiler generation and its hashes were captured; the next request must
|
|
62
|
+
// retry that generation instead of confirming the older client graph as
|
|
63
|
+
// unchanged.
|
|
64
|
+
func TestServeSessionRetriesAPendingDumpBeforeUnchanged(t *testing.T) {
|
|
65
|
+
root := graphSessionFixture(t)
|
|
66
|
+
compiler, diags, err := driver.NewSession(root, "tsconfig.json", driver.LoadProgramOptions{})
|
|
67
|
+
if err != nil {
|
|
68
|
+
t.Fatal(err)
|
|
69
|
+
}
|
|
70
|
+
if compiler == nil {
|
|
71
|
+
t.Fatalf("NewSession returned nil session (diagnostics: %v)", diags)
|
|
72
|
+
}
|
|
73
|
+
session := &graphSession{
|
|
74
|
+
cwd: root,
|
|
75
|
+
tsconfig: "tsconfig.json",
|
|
76
|
+
compiler: compiler,
|
|
77
|
+
initialized: true,
|
|
78
|
+
pendingDumpMode: serveModeReload,
|
|
79
|
+
}
|
|
80
|
+
defer session.Close()
|
|
81
|
+
if err := session.captureState(); err != nil {
|
|
82
|
+
t.Fatal(err)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
dump, mode, changed, err := session.Snapshot()
|
|
86
|
+
if err != nil {
|
|
87
|
+
t.Fatal(err)
|
|
88
|
+
}
|
|
89
|
+
if dump == nil || mode != serveModeReload || !changed {
|
|
90
|
+
t.Fatalf("pending dump retry = dump:%v mode:%q changed:%v", dump != nil, mode, changed)
|
|
91
|
+
}
|
|
92
|
+
if session.pendingDumpMode != "" {
|
|
93
|
+
t.Fatalf("successful retry left pending mode %q", session.pendingDumpMode)
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
dump, mode, changed, err = session.Snapshot()
|
|
97
|
+
if err != nil {
|
|
98
|
+
t.Fatal(err)
|
|
99
|
+
}
|
|
100
|
+
if dump != nil || mode != serveModeUnchanged || changed {
|
|
101
|
+
t.Fatalf("retry did not converge: dump:%v mode:%q changed:%v", dump != nil, mode, changed)
|
|
102
|
+
}
|
|
103
|
+
}
|