ttsc 0.33.0 → 0.34.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 +2 -0
- package/cmd/ttsc/api_compile.go +3 -2
- package/cmd/ttsc/api_transform.go +1 -1
- package/cmd/ttsc/build.go +5 -4
- package/cmd/ttsc-cache/account.go +16 -0
- package/cmd/ttsc-cache/account_test.go +91 -0
- package/cmd/ttsc-cache/main.go +1 -1
- package/cmd/ttsc-cache/protocol_test.go +2 -2
- package/cmd/ttsc-cache/publisher_seal_test.go +1 -1
- package/cmd/ttsc-cache/stock_go_failure_test.go +1 -1
- package/cmd/ttsc-cache/stock_go_test.go +2 -2
- package/cmd/ttsc-cache/store.go +5 -0
- package/cmd/ttsc-cache/tuple.go +6 -2
- package/cmd/ttsc-cache/tuple_test.go +1 -1
- package/cmd/ttscgraph/main.go +6 -1
- package/cmd/ttscgraph/run_help_version_and_bad_flags_exit_codes_test.go +6 -1
- package/cmd/ttscgraph/serve.go +22 -20
- package/cmd/ttscgraph/serve_alternative_members_and_reads_refresh_test.go +95 -0
- package/cmd/ttscgraph/serve_shards.go +26 -15
- package/cmd/ttscgraph/serve_shards_abandoned_generation_converges_on_retry_test.go +2 -2
- package/cmd/ttscgraph/serve_shards_delete_removed_source_test.go +3 -3
- package/cmd/ttscgraph/serve_shards_prune_unreferenced_external_endpoints_test.go +1 -1
- package/cmd/ttscgraph/serve_shards_publish_created_source_test.go +3 -3
- package/cmd/ttscgraph/serve_shards_refresh_cross_file_implementation_test.go +2 -2
- package/cmd/ttscgraph/serve_shards_refresh_dependent_diagnostics_test.go +3 -3
- package/cmd/ttscgraph/serve_shards_rename_moves_source_identity_test.go +5 -5
- package/cmd/ttscgraph/serve_shards_reuse_unaffected_sources_test.go +8 -8
- package/cmd/ttscgraph/serve_source_encoding_test.go +2 -2
- package/driver/build_information_uses_selected_output_identity_test.go +5 -4
- package/driver/check_observations.go +1 -1
- package/driver/config_discovery.go +5 -1
- package/driver/declaration_shape.go +15 -21
- package/driver/diagnostics_preamble.go +2 -2
- package/driver/emit_containment.go +11 -14
- package/driver/emit_plugin.go +51 -43
- package/driver/emit_plugin_output.go +6 -5
- package/driver/emit_provenance.go +12 -15
- package/driver/graph.go +8 -8
- package/driver/host.go +15 -5
- package/driver/input_observation.go +22 -21
- package/driver/input_observation_test.go +11 -10
- package/driver/overlay.go +11 -11
- package/driver/program.go +102 -51
- package/driver/resolution_candidates.go +50 -32
- package/driver/resolution_candidates_test.go +18 -5
- package/driver/rewrite.go +11 -13
- package/driver/session.go +13 -7
- package/driver/target_ts70.go +85 -0
- package/driver/target_ts71.go +97 -0
- package/driver/transform_dependencies.go +1 -1
- package/driver/transform_source_map.go +21 -20
- package/go.mod +3 -3
- package/go.sum +4 -4
- package/internal/graph/alternative_member_declarations_resolve_uses_test.go +145 -0
- package/internal/graph/assigned_implementations_of_declaration_file_symbols_leave_no_edge_source_test.go +2 -2
- package/internal/graph/assigned_implementations_of_node_modules_symbols_leave_no_edge_source_test.go +2 -2
- package/internal/graph/build.go +75 -33
- package/internal/graph/build_files_reuses_committed_cross_file_endpoints_test.go +4 -4
- package/internal/graph/build_records_a_node_per_top_level_declaration_test.go +1 -1
- package/internal/graph/declaration_members.go +143 -0
- package/internal/graph/decorators_capture_name_and_literal_arguments_test.go +3 -3
- package/internal/graph/doc_tags.go +2 -2
- package/internal/graph/dump_paths.go +6 -5
- package/internal/graph/duplicate_variable_object_members_keep_first_declaration_test.go +1 -1
- package/internal/graph/edges.go +151 -68
- package/internal/graph/edges_cover_class_level_references_test.go +5 -5
- package/internal/graph/enum_initializer_calls_are_edges_test.go +2 -2
- package/internal/graph/enum_members_carry_their_names_on_the_enum_node_test.go +6 -6
- package/internal/graph/exports.go +6 -6
- package/internal/graph/file_diagnostics_match_tsgo_code_and_location_test.go +2 -2
- package/internal/graph/file_diagnostics_report_code_column_and_message_test.go +1 -1
- package/internal/graph/function_locals_do_not_collide_test.go +3 -3
- package/internal/graph/heritage_edges_cover_implements_and_interface_extends_test.go +5 -5
- package/internal/graph/heritage_edges_keep_extends_and_implements_to_same_base_test.go +2 -2
- package/internal/graph/heritage_edges_record_extends_versus_implements_origin_test.go +3 -3
- package/internal/graph/heritage_edges_traverse_barrels_and_stop_at_external_leaves_test.go +3 -3
- package/internal/graph/literals.go +3 -3
- package/internal/graph/literals_are_absent_when_the_type_admits_more_than_it_can_name_test.go +2 -2
- package/internal/graph/literals_cover_enum_members_the_graph_has_no_nodes_for_test.go +4 -4
- package/internal/graph/literals_do_not_depend_on_declaration_line_wrapping_test.go +2 -2
- package/internal/graph/literals_render_every_value_in_typescript_source_form_test.go +1 -1
- package/internal/graph/literals_resolve_through_alias_indirection_test.go +3 -3
- package/internal/graph/member_relation_edges_follow_checker_validity_test.go +7 -7
- package/internal/graph/member_relation_edges_preserve_checker_boundaries_test.go +19 -19
- package/internal/graph/member_relation_edges_reject_checker_invalid_pairs_test.go +11 -11
- package/internal/graph/namespace_dotted_form_qualifies_deeply_test.go +2 -2
- package/internal/graph/namespace_members_become_qualified_nodes_and_edges_test.go +7 -7
- package/internal/graph/namespace_private_declarations_keep_lexical_identity_test.go +85 -0
- package/internal/graph/nodes_are_marked_exported_through_the_export_table_test.go +2 -2
- package/internal/graph/object_literal_declarations_resolve_calls_test.go +9 -9
- package/internal/graph/object_literal_members_ride_on_the_snapshot_test.go +1 -1
- package/internal/graph/overload_implementation_replaces_signature_test.go +2 -2
- package/internal/graph/property_member_edges_remain_owner_visible_test.go +6 -6
- package/internal/graph/resolve.go +37 -12
- package/internal/graph/resolve_unwraps_barrel_reexport_to_real_declaration_test.go +6 -6
- package/internal/graph/source.go +1 -1
- package/internal/graph/type_ref_edges_cover_typeof_as_satisfies_test.go +7 -7
- package/internal/graph/type_ref_edges_resolve_named_types_across_files_test.go +2 -2
- package/internal/graph/value_access_edges_cover_properties_test.go +5 -5
- package/internal/graph/value_call_edges_attribute_function_assignments_to_members_test.go +3 -3
- package/internal/graph/value_call_edges_cover_jsx_components_test.go +2 -2
- package/internal/graph/value_call_edges_cover_methods_and_constructors_test.go +3 -3
- package/internal/graph/value_call_edges_cover_variable_bound_callables_test.go +2 -2
- package/internal/graph/value_call_edges_do_not_double_record_invoked_member_access_test.go +4 -4
- package/internal/graph/value_call_edges_record_construct_versus_call_origin_test.go +3 -3
- package/internal/graph/value_call_edges_resolve_across_files_and_dedupe_test.go +2 -2
- package/internal/graph/value_call_edges_skip_self_and_unresolved_test.go +4 -4
- package/internal/graph/value_reads_cover_expression_positions_test.go +88 -0
- package/lib/compiler/internal/buildNativeCompiler.d.ts +5 -2
- package/lib/compiler/internal/buildNativeCompiler.js +12 -4
- package/lib/compiler/internal/buildNativeCompiler.js.map +1 -1
- package/lib/flags/COMPILER_ENUM_WHITESPACE.js +1 -1
- package/lib/flags/COMPILER_ENUM_WHITESPACE.js.map +1 -1
- package/lib/flags/COMPILER_OPTIONS.js +1079 -149
- package/lib/flags/COMPILER_OPTIONS.js.map +1 -1
- package/lib/flags/COMPILER_OPTION_ASCII_FOLDS.js +1 -1
- package/lib/flags/COMPILER_OPTION_ASCII_FOLDS.js.map +1 -1
- package/lib/flags/COMPILER_OPTION_KINDS.js +1 -1
- package/lib/flags/COMPILER_OPTION_KINDS.js.map +1 -1
- package/lib/flags/CompilerOptionSpec.d.ts +9 -2
- package/lib/internal/pluginSource.d.ts +1 -0
- package/lib/internal/pluginSource.js +1 -0
- package/lib/internal/pluginSource.js.map +1 -1
- package/lib/launcher/internal/TypeScriptSyncApi.d.ts +140 -0
- package/lib/launcher/internal/TypeScriptSyncApi.js +99 -0
- package/lib/launcher/internal/TypeScriptSyncApi.js.map +1 -0
- package/lib/launcher/internal/buildSingleRootInMemory.d.ts +80 -0
- package/lib/launcher/internal/buildSingleRootInMemory.js +253 -0
- package/lib/launcher/internal/buildSingleRootInMemory.js.map +1 -0
- package/lib/launcher/internal/buildSingleRootProject.d.ts +22 -18
- package/lib/launcher/internal/buildSingleRootProject.js +27 -18
- package/lib/launcher/internal/buildSingleRootProject.js.map +1 -1
- package/lib/launcher/internal/compilerArgsAsConfigOptions.d.ts +39 -0
- package/lib/launcher/internal/compilerArgsAsConfigOptions.js +115 -0
- package/lib/launcher/internal/compilerArgsAsConfigOptions.js.map +1 -0
- package/lib/plugin/CapabilityPluginResolver.js +3 -0
- package/lib/plugin/CapabilityPluginResolver.js.map +1 -1
- package/lib/plugin/internal/load/loadProjectPlugins.js +6 -2
- package/lib/plugin/internal/load/loadProjectPlugins.js.map +1 -1
- package/lib/plugin/internal/source/CompilerTarget.d.ts +127 -0
- package/lib/plugin/internal/source/CompilerTarget.js +231 -0
- package/lib/plugin/internal/source/CompilerTarget.js.map +1 -0
- package/lib/plugin/internal/source/NativeSourcePackages.js +6 -5
- package/lib/plugin/internal/source/NativeSourcePackages.js.map +1 -1
- package/lib/plugin/internal/source/SourcePluginAdmission.d.ts +18 -1
- package/lib/plugin/internal/source/SourcePluginAdmission.js +24 -2
- package/lib/plugin/internal/source/SourcePluginAdmission.js.map +1 -1
- package/lib/plugin/internal/source/SourcePluginWorkspace.d.ts +6 -3
- package/lib/plugin/internal/source/SourcePluginWorkspace.js +31 -13
- package/lib/plugin/internal/source/SourcePluginWorkspace.js.map +1 -1
- package/lib/plugin/internal/source/buildSourcePlugin.js +3 -1
- package/lib/plugin/internal/source/buildSourcePlugin.js.map +1 -1
- package/lib/plugin/internal/source/hashPluginBuildEnvironment.d.ts +1 -1
- package/lib/plugin/internal/source/hashPluginBuildEnvironment.js +9 -1
- package/lib/plugin/internal/source/hashPluginBuildEnvironment.js.map +1 -1
- package/package.json +14 -9
- package/shim/ast/enums_gen.go +1 -0
- package/shim/ast/go.mod +2 -2
- package/shim/ast/go.sum +4 -4
- package/shim/ast/neutral.go +141 -0
- package/shim/astnav/go.mod +2 -2
- package/shim/astnav/go.sum +4 -4
- package/shim/bundled/go.mod +2 -2
- package/shim/bundled/go.sum +4 -4
- package/shim/checker/go.mod +2 -2
- package/shim/checker/go.sum +4 -4
- package/shim/compiler/go.mod +2 -2
- package/shim/compiler/go.sum +4 -4
- package/shim/compiler/neutral.go +213 -0
- package/shim/core/go.mod +2 -2
- package/shim/core/go.sum +4 -4
- package/shim/diagnosticwriter/go.mod +2 -2
- package/shim/diagnosticwriter/go.sum +4 -4
- package/shim/lsp/go.mod +2 -2
- package/shim/lsp/go.sum +4 -4
- package/shim/parser/go.mod +2 -2
- package/shim/parser/go.sum +4 -4
- package/shim/printer/go.mod +2 -2
- package/shim/printer/go.sum +4 -4
- package/shim/scanner/go.mod +2 -2
- package/shim/scanner/go.sum +4 -4
- package/shim/stringutil/go.mod +1 -1
- package/shim/stringutil/go.sum +2 -2
- package/shim/stringutil/shim.go +15 -0
- package/shim/transformers/go.mod +2 -2
- package/shim/transformers/go.sum +4 -4
- package/shim/tsoptions/go.mod +2 -2
- package/shim/tsoptions/go.sum +4 -4
- package/shim/tsoptions/neutral.go +56 -0
- package/shim/tspath/go.mod +1 -1
- package/shim/tspath/go.sum +2 -2
- package/shim/tspath/neutral.go +150 -0
- package/shim/tspath/typed_paths.go +266 -0
- package/shim/vfs/cachedvfs/go.mod +2 -2
- package/shim/vfs/cachedvfs/go.sum +4 -4
- package/shim/vfs/go.mod +2 -2
- package/shim/vfs/go.sum +4 -4
- package/shim/vfs/neutral.go +20 -0
- package/shim/vfs/osvfs/go.mod +2 -2
- package/shim/vfs/osvfs/go.sum +4 -4
- package/src/compiler/internal/buildNativeCompiler.ts +13 -4
- package/src/flags/COMPILER_ENUM_WHITESPACE.ts +1 -1
- package/src/flags/COMPILER_OPTIONS.ts +1080 -150
- package/src/flags/COMPILER_OPTION_ASCII_FOLDS.ts +1 -1
- package/src/flags/COMPILER_OPTION_KINDS.ts +1 -1
- package/src/flags/CompilerOptionSpec.ts +11 -2
- package/src/internal/pluginSource.ts +1 -0
- package/src/launcher/internal/TypeScriptSyncApi.ts +186 -0
- package/src/launcher/internal/buildSingleRootInMemory.ts +319 -0
- package/src/launcher/internal/buildSingleRootProject.ts +26 -18
- package/src/launcher/internal/compilerArgsAsConfigOptions.ts +112 -0
- package/src/plugin/CapabilityPluginResolver.ts +4 -1
- package/src/plugin/internal/load/loadProjectPlugins.ts +12 -2
- package/src/plugin/internal/source/CompilerTarget.ts +249 -0
- package/src/plugin/internal/source/NativeSourcePackages.ts +10 -4
- package/src/plugin/internal/source/SourcePluginAdmission.ts +28 -2
- package/src/plugin/internal/source/SourcePluginWorkspace.ts +45 -19
- package/src/plugin/internal/source/buildSourcePlugin.ts +3 -1
- package/src/plugin/internal/source/hashPluginBuildEnvironment.ts +9 -1
- package/targets/7.1/bridge/ast/enums_gen.go +174 -0
- package/targets/7.1/bridge/ast/extra-shim.json +4 -0
- package/targets/7.1/bridge/ast/go.mod +14 -0
- package/targets/7.1/bridge/ast/go.sum +20 -0
- package/targets/7.1/bridge/ast/lint.go +1412 -0
- package/targets/7.1/bridge/ast/neutral.go +141 -0
- package/targets/7.1/bridge/ast/parent.go +60 -0
- package/targets/7.1/bridge/ast/safe_text.go +108 -0
- package/targets/7.1/bridge/ast/shim.go +1656 -0
- package/targets/7.1/bridge/ast/surface.go +686 -0
- package/targets/7.1/bridge/ast/test/next_jsdoc_comment_location_reaches_variable_statement_test.go +51 -0
- package/targets/7.1/bridge/ast/test/node_text_joins_multi_hop_qualified_name_test.go +47 -0
- package/targets/7.1/bridge/ast/test/node_text_joins_one_hop_qualified_name_test.go +35 -0
- package/targets/7.1/bridge/ast/test/node_text_returns_empty_for_nil_test.go +31 -0
- package/targets/7.1/bridge/ast/test/node_text_returns_identifier_text_test.go +34 -0
- package/targets/7.1/bridge/ast/test/node_text_skips_empty_qualified_left_test.go +60 -0
- package/targets/7.1/bridge/astnav/go.mod +14 -0
- package/targets/7.1/bridge/astnav/go.sum +22 -0
- package/targets/7.1/bridge/astnav/shim.go +24 -0
- package/targets/7.1/bridge/bundled/extra-shim.json +1 -0
- package/targets/7.1/bridge/bundled/go.mod +10 -0
- package/targets/7.1/bridge/bundled/go.sum +10 -0
- package/targets/7.1/bridge/bundled/shim.go +24 -0
- package/targets/7.1/bridge/checker/enums_gen.go +150 -0
- package/targets/7.1/bridge/checker/extra-shim.json +37 -0
- package/targets/7.1/bridge/checker/go.mod +15 -0
- package/targets/7.1/bridge/checker/go.sum +24 -0
- package/targets/7.1/bridge/checker/node_builder_fields_gen.go +19 -0
- package/targets/7.1/bridge/checker/shim.go +1390 -0
- package/targets/7.1/bridge/compiler/contentmapper_process.go +70 -0
- package/targets/7.1/bridge/compiler/emit_sourcemap.go +296 -0
- package/targets/7.1/bridge/compiler/emitassemble.go +81 -0
- package/targets/7.1/bridge/compiler/emithook.go +44 -0
- package/targets/7.1/bridge/compiler/extra-shim.json +4 -0
- package/targets/7.1/bridge/compiler/go.mod +15 -0
- package/targets/7.1/bridge/compiler/go.sum +24 -0
- package/targets/7.1/bridge/compiler/incremental.go +185 -0
- package/targets/7.1/bridge/compiler/neutral.go +256 -0
- package/targets/7.1/bridge/compiler/resolution.go +571 -0
- package/targets/7.1/bridge/compiler/shim.go +70 -0
- package/targets/7.1/bridge/core/enums_gen.go +15 -0
- package/targets/7.1/bridge/core/extra-shim.json +4 -0
- package/targets/7.1/bridge/core/go.mod +7 -0
- package/targets/7.1/bridge/core/go.sum +8 -0
- package/targets/7.1/bridge/core/modulekind.go +19 -0
- package/targets/7.1/bridge/core/shim.go +272 -0
- package/targets/7.1/bridge/diagnosticwriter/go.mod +14 -0
- package/targets/7.1/bridge/diagnosticwriter/go.sum +20 -0
- package/targets/7.1/bridge/diagnosticwriter/lint.go +411 -0
- package/targets/7.1/bridge/diagnosticwriter/shim.go +56 -0
- package/targets/7.1/bridge/lsp/extra-shim.json +4 -0
- package/targets/7.1/bridge/lsp/go.mod +16 -0
- package/targets/7.1/bridge/lsp/go.sum +26 -0
- package/targets/7.1/bridge/lsp/shim.go +112 -0
- package/targets/7.1/bridge/parser/extra-shim.json +4 -0
- package/targets/7.1/bridge/parser/go.mod +14 -0
- package/targets/7.1/bridge/parser/go.sum +24 -0
- package/targets/7.1/bridge/parser/shim.go +61 -0
- package/targets/7.1/bridge/printer/emithost.go +69 -0
- package/targets/7.1/bridge/printer/go.mod +15 -0
- package/targets/7.1/bridge/printer/go.sum +24 -0
- package/targets/7.1/bridge/printer/shim.go +168 -0
- package/targets/7.1/bridge/printer/sourcemap.go +49 -0
- package/targets/7.1/bridge/scanner/extra-shim.json +4 -0
- package/targets/7.1/bridge/scanner/go.mod +14 -0
- package/targets/7.1/bridge/scanner/go.sum +20 -0
- package/targets/7.1/bridge/scanner/regexp.go +42 -0
- package/targets/7.1/bridge/scanner/shim.go +137 -0
- package/targets/7.1/bridge/stringutil/extra-shim.json +1 -0
- package/targets/7.1/bridge/stringutil/go.mod +5 -0
- package/targets/7.1/bridge/stringutil/go.sum +2 -0
- package/targets/7.1/bridge/stringutil/shim.go +131 -0
- package/targets/7.1/bridge/transformers/go.mod +15 -0
- package/targets/7.1/bridge/transformers/go.sum +24 -0
- package/targets/7.1/bridge/transformers/shim.go +24 -0
- package/targets/7.1/bridge/tsoptions/command_line_raw.go +44 -0
- package/targets/7.1/bridge/tsoptions/extra-shim.json +4 -0
- package/targets/7.1/bridge/tsoptions/go.mod +15 -0
- package/targets/7.1/bridge/tsoptions/go.sum +24 -0
- package/targets/7.1/bridge/tsoptions/neutral.go +47 -0
- package/targets/7.1/bridge/tsoptions/shim.go +193 -0
- package/targets/7.1/bridge/tspath/extra-shim.json +4 -0
- package/targets/7.1/bridge/tspath/go.mod +5 -0
- package/targets/7.1/bridge/tspath/go.sum +6 -0
- package/targets/7.1/bridge/tspath/neutral.go +142 -0
- package/targets/7.1/bridge/tspath/shim.go +382 -0
- package/targets/7.1/bridge/vfs/cachedvfs/extra-shim.json +4 -0
- package/targets/7.1/bridge/vfs/cachedvfs/go.mod +5 -0
- package/targets/7.1/bridge/vfs/cachedvfs/go.sum +10 -0
- package/targets/7.1/bridge/vfs/cachedvfs/shim.go +12 -0
- package/targets/7.1/bridge/vfs/decode.go +26 -0
- package/targets/7.1/bridge/vfs/decode_test.go +42 -0
- package/targets/7.1/bridge/vfs/extra-shim.json +4 -0
- package/targets/7.1/bridge/vfs/go.mod +10 -0
- package/targets/7.1/bridge/vfs/go.sum +10 -0
- package/targets/7.1/bridge/vfs/neutral.go +23 -0
- package/targets/7.1/bridge/vfs/osvfs/extra-shim.json +4 -0
- package/targets/7.1/bridge/vfs/osvfs/go.mod +10 -0
- package/targets/7.1/bridge/vfs/osvfs/go.sum +10 -0
- package/targets/7.1/bridge/vfs/osvfs/shim.go +14 -0
- package/targets/7.1/bridge/vfs/shim.go +27 -0
- package/targets/7.1/facade/ast/facade_gen.go +2691 -0
- package/targets/7.1/facade/ast/go.mod +20 -0
- package/targets/7.1/facade/ast/go.sum +20 -0
- package/targets/7.1/facade/astnav/facade_gen.go +15 -0
- package/targets/7.1/facade/astnav/go.mod +22 -0
- package/targets/7.1/facade/astnav/go.sum +22 -0
- package/targets/7.1/facade/bundled/facade_gen.go +32 -0
- package/targets/7.1/facade/bundled/go.mod +21 -0
- package/targets/7.1/facade/bundled/go.sum +10 -0
- package/targets/7.1/facade/checker/facade_gen.go +563 -0
- package/targets/7.1/facade/checker/go.mod +26 -0
- package/targets/7.1/facade/checker/go.sum +24 -0
- package/targets/7.1/facade/compiler/facade_gen.go +198 -0
- package/targets/7.1/facade/compiler/go.mod +41 -0
- package/targets/7.1/facade/compiler/go.sum +24 -0
- package/targets/7.1/facade/core/facade_gen.go +130 -0
- package/targets/7.1/facade/core/go.mod +12 -0
- package/targets/7.1/facade/core/go.sum +8 -0
- package/targets/7.1/facade/diagnosticwriter/facade_gen.go +36 -0
- package/targets/7.1/facade/diagnosticwriter/go.mod +22 -0
- package/targets/7.1/facade/diagnosticwriter/go.sum +20 -0
- package/targets/7.1/facade/lsp/facade_gen.go +31 -0
- package/targets/7.1/facade/lsp/go.mod +19 -0
- package/targets/7.1/facade/lsp/go.sum +26 -0
- package/targets/7.1/facade/parser/facade_gen.go +102 -0
- package/targets/7.1/facade/parser/go.mod +25 -0
- package/targets/7.1/facade/parser/go.sum +24 -0
- package/targets/7.1/facade/printer/facade_gen.go +74 -0
- package/targets/7.1/facade/printer/go.mod +26 -0
- package/targets/7.1/facade/printer/go.sum +24 -0
- package/targets/7.1/facade/scanner/facade_gen.go +191 -0
- package/targets/7.1/facade/scanner/go.mod +25 -0
- package/targets/7.1/facade/scanner/go.sum +20 -0
- package/targets/7.1/facade/stringutil/facade_gen.go +176 -0
- package/targets/7.1/facade/stringutil/go.mod +9 -0
- package/targets/7.1/facade/stringutil/go.sum +2 -0
- package/targets/7.1/facade/transformers/facade_gen.go +12 -0
- package/targets/7.1/facade/transformers/go.mod +18 -0
- package/targets/7.1/facade/transformers/go.sum +24 -0
- package/targets/7.1/facade/tsoptions/facade_gen.go +274 -0
- package/targets/7.1/facade/tsoptions/go.mod +32 -0
- package/targets/7.1/facade/tsoptions/go.sum +24 -0
- package/targets/7.1/facade/tspath/facade_gen.go +550 -0
- package/targets/7.1/facade/tspath/go.mod +9 -0
- package/targets/7.1/facade/tspath/go.sum +6 -0
- package/targets/7.1/facade/vfs/cachedvfs/facade_gen.go +17 -0
- package/targets/7.1/facade/vfs/cachedvfs/go.mod +18 -0
- package/targets/7.1/facade/vfs/cachedvfs/go.sum +10 -0
- package/targets/7.1/facade/vfs/facade_gen.go +47 -0
- package/targets/7.1/facade/vfs/go.mod +18 -0
- package/targets/7.1/facade/vfs/go.sum +10 -0
- package/targets/7.1/facade/vfs/osvfs/facade_gen.go +20 -0
- package/targets/7.1/facade/vfs/osvfs/go.mod +21 -0
- package/targets/7.1/facade/vfs/osvfs/go.sum +10 -0
- package/tools/gen_facade/committed_facades_match_their_bridges_test.go +57 -0
- package/tools/gen_facade/facade_manifest_points_into_the_bridge_root_test.go +75 -0
- package/tools/gen_facade/facade_spells_internal_types_through_bridge_aliases_test.go +75 -0
- package/tools/gen_facade/facade_types_are_their_bridge_types_test.go +99 -0
- package/tools/gen_facade/go.mod +10 -0
- package/tools/gen_facade/go.sum +8 -0
- package/tools/gen_facade/main.go +734 -0
- package/tools/gen_shims/go.mod +4 -4
- package/tools/gen_shims/go.sum +6 -6
- package/tools/gen_shims/main.go +124 -66
- package/tools/gen_shims/mirror_structs_terminate_on_unexported_cycles_test.go +101 -0
- package/tools/shim_audit/baseline-7.1.json +720 -0
- package/tools/shim_audit/baseline.json +5 -4
- package/tools/shim_audit/go.mod +4 -4
- package/tools/shim_audit/go.sum +6 -6
- package/tools/shim_audit/linkname_signatures.go +178 -0
- package/tools/shim_audit/linkname_signatures_match_their_targets_test.go +64 -0
- package/tools/shim_audit/linkname_targets_follow_the_audited_compiler_test.go +38 -0
- package/tools/shim_audit/main.go +29 -4
- package/tools/shim_audit/neutral_api.go +160 -0
- package/tools/shim_audit/neutral_api_must_match_across_targets_test.go +74 -0
- package/utility/host.go +5 -4
- package/utility/preamble_output.go +15 -15
- package/utility/serve.go +1 -1
|
@@ -15,10 +15,9 @@
|
|
|
15
15
|
"ESCAPE|checker|IntrinsicType",
|
|
16
16
|
"ESCAPE|checker|LiteralType",
|
|
17
17
|
"ESCAPE|checker|MappedType",
|
|
18
|
-
"ESCAPE|checker|NodeBuilder",
|
|
19
|
-
"ESCAPE|checker|NodeBuilderContext",
|
|
20
18
|
"ESCAPE|checker|ObjectType",
|
|
21
19
|
"ESCAPE|checker|ReverseMappedType",
|
|
20
|
+
"ESCAPE|checker|SignatureId",
|
|
22
21
|
"ESCAPE|checker|StringMappingType",
|
|
23
22
|
"ESCAPE|checker|StructuredType",
|
|
24
23
|
"ESCAPE|checker|SubstitutionType",
|
|
@@ -35,7 +34,7 @@
|
|
|
35
34
|
"ESCAPE|checker|UnionReduction",
|
|
36
35
|
"ESCAPE|checker|UnionType",
|
|
37
36
|
"ESCAPE|checker|UniqueESSymbolType",
|
|
38
|
-
"ESCAPE|
|
|
37
|
+
"ESCAPE|core|CheckerLifetime",
|
|
39
38
|
"ESCAPE|core|LimitedSemaphore",
|
|
40
39
|
"ESCAPE|core|ModuleDetectionKind",
|
|
41
40
|
"ESCAPE|core|NewLineKind",
|
|
@@ -75,6 +74,8 @@
|
|
|
75
74
|
"FUNC|ast|EqualDiagnostics",
|
|
76
75
|
"FUNC|ast|EqualDiagnosticsNoRelatedInfo",
|
|
77
76
|
"FUNC|ast|EscapeAllInternalSymbolNames",
|
|
77
|
+
"FUNC|ast|EscapeInternalSymbolName",
|
|
78
|
+
"FUNC|ast|EscapeSymbolName",
|
|
78
79
|
"FUNC|ast|ExpressionIsAlias",
|
|
79
80
|
"FUNC|ast|FindAncestor",
|
|
80
81
|
"FUNC|ast|FindAncestorKind",
|
|
@@ -302,7 +303,6 @@
|
|
|
302
303
|
"FUNC|ast|IsIdentifier",
|
|
303
304
|
"FUNC|ast|IsIdentifierName",
|
|
304
305
|
"FUNC|ast|IsIfStatement",
|
|
305
|
-
"FUNC|ast|IsImplicitlyExportedJSTypeAlias",
|
|
306
306
|
"FUNC|ast|IsImportAttribute",
|
|
307
307
|
"FUNC|ast|IsImportAttributes",
|
|
308
308
|
"FUNC|ast|IsImportCall",
|
|
@@ -665,6 +665,7 @@
|
|
|
665
665
|
"FUNC|diagnosticwriter|WriteFormatDiagnostics",
|
|
666
666
|
"FUNC|execute/incremental|ComputeHash",
|
|
667
667
|
"FUNC|execute/incremental|GetMTime",
|
|
668
|
+
"FUNC|execute/incremental|IsBuildInfoFileNameDefaultLibrary",
|
|
668
669
|
"FUNC|printer|FormatGeneratedName",
|
|
669
670
|
"FUNC|printer|GetDefaultIndentSize",
|
|
670
671
|
"FUNC|printer|GetEmitContext",
|
package/tools/shim_audit/go.mod
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
module github.com/samchon/ttsc/packages/ttsc/tools/shim_audit
|
|
2
2
|
|
|
3
|
-
go 1.
|
|
3
|
+
go 1.27
|
|
4
4
|
|
|
5
|
-
require golang.org/x/tools v0.
|
|
5
|
+
require golang.org/x/tools v0.52.0
|
|
6
6
|
|
|
7
7
|
require (
|
|
8
|
-
golang.org/x/mod v0.
|
|
9
|
-
golang.org/x/sync v0.
|
|
8
|
+
golang.org/x/mod v0.42.0 // indirect
|
|
9
|
+
golang.org/x/sync v0.24.0 // indirect
|
|
10
10
|
)
|
package/tools/shim_audit/go.sum
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
|
2
2
|
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
|
3
|
-
golang.org/x/mod v0.
|
|
4
|
-
golang.org/x/mod v0.
|
|
5
|
-
golang.org/x/sync v0.
|
|
6
|
-
golang.org/x/sync v0.
|
|
7
|
-
golang.org/x/tools v0.
|
|
8
|
-
golang.org/x/tools v0.
|
|
3
|
+
golang.org/x/mod v0.42.0 h1:ICeL3t2L30ljSPHHxDnR4fqVcBt/zR2zJAb9juavmQg=
|
|
4
|
+
golang.org/x/mod v0.42.0/go.mod h1:u5fzIrRInkL8MaO1cbRkUHT64v303YIT5KEqpNr7jRs=
|
|
5
|
+
golang.org/x/sync v0.24.0 h1:iqiDrGoDgyuvAKrhLQthUEzU/R378N78gXbBjxed7oA=
|
|
6
|
+
golang.org/x/sync v0.24.0/go.mod h1:sUUOizhqBxiL6pEWpqNLUiaJn1ShEbZ6BBqskPbjZm0=
|
|
7
|
+
golang.org/x/tools v0.52.0 h1:ryxg4U63oaUYk7uOLTF37n43f4qgtGvqV4Ioit1BaEs=
|
|
8
|
+
golang.org/x/tools v0.52.0/go.mod h1:ItcP5UNaVGG+Yc4eIYmaFLNJ4soEopkx5Y2d4lcEurs=
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
package main
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"errors"
|
|
5
|
+
"fmt"
|
|
6
|
+
"go/ast"
|
|
7
|
+
"go/types"
|
|
8
|
+
"io/fs"
|
|
9
|
+
"path/filepath"
|
|
10
|
+
"sort"
|
|
11
|
+
"strings"
|
|
12
|
+
|
|
13
|
+
"golang.org/x/tools/go/packages"
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
// checkLinknameSignatures fails when a bodyless //go:linkname declaration in a
|
|
17
|
+
// shim disagrees with the signature of the compiler function it names, a
|
|
18
|
+
// method's receiver counting as the first parameter. The Go toolchain links
|
|
19
|
+
// such a pair without complaint and the mismatch surfaces only as corrupted
|
|
20
|
+
// arguments at run time, so a compiler bump that changes a linked signature
|
|
21
|
+
// must fail here instead. Every shim module below shimRoot is loaded with its
|
|
22
|
+
// dependencies, so the target is checked against the pinned compiler's types.
|
|
23
|
+
//
|
|
24
|
+
// Adapted from Danny Wilson's TypeScript 7.1 port (#1727).
|
|
25
|
+
func checkLinknameSignatures(shimRoot string) error {
|
|
26
|
+
var dirs []string
|
|
27
|
+
err := filepath.WalkDir(shimRoot, func(path string, entry fs.DirEntry, err error) error {
|
|
28
|
+
if err != nil {
|
|
29
|
+
return err
|
|
30
|
+
}
|
|
31
|
+
if !entry.IsDir() && entry.Name() == "go.mod" {
|
|
32
|
+
dirs = append(dirs, filepath.Dir(path))
|
|
33
|
+
}
|
|
34
|
+
return nil
|
|
35
|
+
})
|
|
36
|
+
if err != nil {
|
|
37
|
+
return err
|
|
38
|
+
}
|
|
39
|
+
sort.Strings(dirs)
|
|
40
|
+
var problems []string
|
|
41
|
+
for _, dir := range dirs {
|
|
42
|
+
found, err := linknameSignatureProblems(dir)
|
|
43
|
+
if err != nil {
|
|
44
|
+
return err
|
|
45
|
+
}
|
|
46
|
+
problems = append(problems, found...)
|
|
47
|
+
}
|
|
48
|
+
if len(problems) > 0 {
|
|
49
|
+
return fmt.Errorf("go:linkname declarations disagree with their targets:\n %s", strings.Join(problems, "\n "))
|
|
50
|
+
}
|
|
51
|
+
return nil
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// linknameSignatureProblems reports every mismatched bodyless linkname
|
|
55
|
+
// declaration of the package rooted at dir.
|
|
56
|
+
func linknameSignatureProblems(dir string) ([]string, error) {
|
|
57
|
+
loaded, err := packages.Load(&packages.Config{
|
|
58
|
+
Dir: dir,
|
|
59
|
+
Mode: packages.NeedName | packages.NeedSyntax | packages.NeedTypes | packages.NeedTypesInfo | packages.NeedImports | packages.NeedDeps,
|
|
60
|
+
}, ".")
|
|
61
|
+
if err != nil {
|
|
62
|
+
return nil, fmt.Errorf("load %s: %w", dir, err)
|
|
63
|
+
}
|
|
64
|
+
all := map[string]*types.Package{}
|
|
65
|
+
var loadErrors []error
|
|
66
|
+
packages.Visit(loaded, nil, func(pkg *packages.Package) {
|
|
67
|
+
if pkg.Types != nil {
|
|
68
|
+
all[pkg.PkgPath] = pkg.Types
|
|
69
|
+
}
|
|
70
|
+
for _, e := range pkg.Errors {
|
|
71
|
+
loadErrors = append(loadErrors, e)
|
|
72
|
+
}
|
|
73
|
+
})
|
|
74
|
+
if err := errors.Join(loadErrors...); err != nil {
|
|
75
|
+
return nil, fmt.Errorf("load %s: %w", dir, err)
|
|
76
|
+
}
|
|
77
|
+
var problems []string
|
|
78
|
+
for _, pkg := range loaded {
|
|
79
|
+
for _, file := range pkg.Syntax {
|
|
80
|
+
links := map[string]string{}
|
|
81
|
+
for _, group := range file.Comments {
|
|
82
|
+
for _, comment := range group.List {
|
|
83
|
+
if fields := strings.Fields(comment.Text); len(fields) == 3 && fields[0] == "//go:linkname" {
|
|
84
|
+
links[fields[1]] = fields[2]
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
for _, decl := range file.Decls {
|
|
89
|
+
fn, ok := decl.(*ast.FuncDecl)
|
|
90
|
+
if !ok || fn.Body != nil || fn.Recv != nil {
|
|
91
|
+
continue
|
|
92
|
+
}
|
|
93
|
+
target, linked := links[fn.Name.Name]
|
|
94
|
+
if !linked {
|
|
95
|
+
continue
|
|
96
|
+
}
|
|
97
|
+
position := pkg.Fset.Position(fn.Pos())
|
|
98
|
+
local := pkg.TypesInfo.Defs[fn.Name].Type().(*types.Signature)
|
|
99
|
+
want, err := linknameTargetSignature(all, target)
|
|
100
|
+
if err != nil {
|
|
101
|
+
problems = append(problems, fmt.Sprintf("%s: %s -> %s: %v", position, fn.Name.Name, target, err))
|
|
102
|
+
continue
|
|
103
|
+
}
|
|
104
|
+
if mismatch := compareLinkedSignatures(local, want); mismatch != "" {
|
|
105
|
+
problems = append(problems, fmt.Sprintf("%s: %s -> %s: %s", position, fn.Name.Name, target, mismatch))
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return problems, nil
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// linknameTargetSignature resolves "path.name" or "path.(*T).name" against the
|
|
114
|
+
// loaded dependency graph. A method's receiver becomes the first parameter.
|
|
115
|
+
func linknameTargetSignature(all map[string]*types.Package, target string) (*types.Signature, error) {
|
|
116
|
+
slash := strings.LastIndexByte(target, '/')
|
|
117
|
+
dot := strings.IndexByte(target[slash+1:], '.')
|
|
118
|
+
if dot < 0 {
|
|
119
|
+
return nil, errors.New("malformed target")
|
|
120
|
+
}
|
|
121
|
+
path, rest := target[:slash+1+dot], target[slash+1+dot+1:]
|
|
122
|
+
pkg := all[path]
|
|
123
|
+
if pkg == nil {
|
|
124
|
+
return nil, fmt.Errorf("package %s is not compiled into the bridge", path)
|
|
125
|
+
}
|
|
126
|
+
if !strings.HasPrefix(rest, "(") {
|
|
127
|
+
fn, ok := pkg.Scope().Lookup(rest).(*types.Func)
|
|
128
|
+
if !ok {
|
|
129
|
+
return nil, fmt.Errorf("no function %s", rest)
|
|
130
|
+
}
|
|
131
|
+
return fn.Signature(), nil
|
|
132
|
+
}
|
|
133
|
+
closing := strings.IndexByte(rest, ')')
|
|
134
|
+
if closing < 0 || closing+2 > len(rest) {
|
|
135
|
+
return nil, errors.New("malformed method target")
|
|
136
|
+
}
|
|
137
|
+
receiver, name := strings.TrimPrefix(rest[1:closing], "*"), rest[closing+2:]
|
|
138
|
+
typeName, ok := pkg.Scope().Lookup(receiver).(*types.TypeName)
|
|
139
|
+
if !ok {
|
|
140
|
+
return nil, fmt.Errorf("no type %s", receiver)
|
|
141
|
+
}
|
|
142
|
+
object, _, _ := types.LookupFieldOrMethod(types.NewPointer(typeName.Type()), true, pkg, name)
|
|
143
|
+
method, ok := object.(*types.Func)
|
|
144
|
+
if !ok {
|
|
145
|
+
return nil, fmt.Errorf("no method %s", name)
|
|
146
|
+
}
|
|
147
|
+
signature := method.Signature()
|
|
148
|
+
params := []*types.Var{signature.Recv()}
|
|
149
|
+
for i := range signature.Params().Len() {
|
|
150
|
+
params = append(params, signature.Params().At(i))
|
|
151
|
+
}
|
|
152
|
+
return types.NewSignatureType(nil, nil, nil, types.NewTuple(params...), signature.Results(), signature.Variadic()), nil
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// compareLinkedSignatures describes the first difference between the local
|
|
156
|
+
// declaration and its target, or returns "" when they are identical.
|
|
157
|
+
func compareLinkedSignatures(local, want *types.Signature) string {
|
|
158
|
+
if local.Params().Len() != want.Params().Len() {
|
|
159
|
+
return fmt.Sprintf("%d parameters, target has %d (%s)", local.Params().Len(), want.Params().Len(), want)
|
|
160
|
+
}
|
|
161
|
+
if local.Results().Len() != want.Results().Len() {
|
|
162
|
+
return fmt.Sprintf("%d results, target has %d (%s)", local.Results().Len(), want.Results().Len(), want)
|
|
163
|
+
}
|
|
164
|
+
for i := range local.Params().Len() {
|
|
165
|
+
if !types.Identical(local.Params().At(i).Type(), want.Params().At(i).Type()) {
|
|
166
|
+
return fmt.Sprintf("parameter %d is %s, target has %s", i, local.Params().At(i).Type(), want.Params().At(i).Type())
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
for i := range local.Results().Len() {
|
|
170
|
+
if !types.Identical(local.Results().At(i).Type(), want.Results().At(i).Type()) {
|
|
171
|
+
return fmt.Sprintf("result %d is %s, target has %s", i, local.Results().At(i).Type(), want.Results().At(i).Type())
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
if local.Variadic() != want.Variadic() {
|
|
175
|
+
return "variadic parameter differs from the target"
|
|
176
|
+
}
|
|
177
|
+
return ""
|
|
178
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
package main
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"os"
|
|
5
|
+
"path/filepath"
|
|
6
|
+
"strings"
|
|
7
|
+
"testing"
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
// Verifies the linkname gate refuses a bodyless go:linkname declaration whose
|
|
11
|
+
// signature differs from the function it names.
|
|
12
|
+
//
|
|
13
|
+
// The toolchain links such a pair silently and the mismatch corrupts arguments
|
|
14
|
+
// only at run time, which is the failure a compiler bump can introduce.
|
|
15
|
+
//
|
|
16
|
+
// 1. Build a temporary compiler module with an internal package and a bridge
|
|
17
|
+
// module below a shim root linking one function and one method of it.
|
|
18
|
+
// 2. Require the gate to accept matching declarations.
|
|
19
|
+
// 3. Change a parameter type, then drop a parameter, and require the gate to
|
|
20
|
+
// name each mismatched declaration.
|
|
21
|
+
//
|
|
22
|
+
// @evidence contracts/testing.md#behavioral-verification checkLinknameSignatures loads a real temporary module through go/packages and is required to accept matching declarations and reject each drifted one by name.
|
|
23
|
+
// @evidence contracts/testing.md#independent-expectations The target signatures and the drifted declarations are authored literals in the fixture; the expected names come from the fixture, not from the gate's output.
|
|
24
|
+
// @evidence contracts/testing.md#distinguishing-cases A matching function and receiver method pass, a changed parameter type fails, and a missing parameter fails, each with its own expected outcome.
|
|
25
|
+
// @evidence contracts/testing.md#execution-ownership This tools/shim_audit unit writes a temporary module and loads it with the go command in one test process; it reads no repository bridge.
|
|
26
|
+
func TestLinknameSignaturesMatchTheirTargets(t *testing.T) {
|
|
27
|
+
root := t.TempDir()
|
|
28
|
+
write := func(relative, text string) {
|
|
29
|
+
t.Helper()
|
|
30
|
+
filename := filepath.Join(root, filepath.FromSlash(relative))
|
|
31
|
+
if err := os.MkdirAll(filepath.Dir(filename), 0o755); err != nil {
|
|
32
|
+
t.Fatal(err)
|
|
33
|
+
}
|
|
34
|
+
if err := os.WriteFile(filename, []byte(text), 0o644); err != nil {
|
|
35
|
+
t.Fatal(err)
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
write("compiler/go.mod", "module example.com/fixture\n\ngo 1.27\n")
|
|
39
|
+
write("compiler/internal/target/target.go", "package target\n\ntype Box struct{ n int }\n\nfunc join(a string, b int) string { return a }\n\nfunc (b *Box) grow(n int) int { return b.n + n }\n")
|
|
40
|
+
bridge := func(joinParams, growParams string) string {
|
|
41
|
+
return "package bridge\n\nimport (\n _ \"unsafe\"\n\n \"example.com/fixture/internal/target\"\n)\n\n" +
|
|
42
|
+
"//go:linkname Join example.com/fixture/internal/target.join\nfunc Join(" + joinParams + ") string\n\n" +
|
|
43
|
+
"//go:linkname Grow example.com/fixture/internal/target.(*Box).grow\nfunc Grow(" + growParams + ") int\n"
|
|
44
|
+
}
|
|
45
|
+
t.Setenv("GOWORK", "off")
|
|
46
|
+
t.Setenv("GOFLAGS", "-mod=mod")
|
|
47
|
+
|
|
48
|
+
write("shim/bridge/go.mod", "module example.com/fixture/bridge\n\ngo 1.27\n\nrequire example.com/fixture v0.0.0\n\nreplace example.com/fixture => ../../compiler\n")
|
|
49
|
+
write("shim/bridge/bridge.go", bridge("a string, b int", "b *target.Box, n int"))
|
|
50
|
+
if err := checkLinknameSignatures(filepath.Join(root, "shim")); err != nil {
|
|
51
|
+
t.Fatalf("matching declarations rejected: %v", err)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
write("shim/bridge/bridge.go", bridge("a string, b string", "b *target.Box"))
|
|
55
|
+
err := checkLinknameSignatures(filepath.Join(root, "shim"))
|
|
56
|
+
if err == nil {
|
|
57
|
+
t.Fatal("drifted declarations accepted")
|
|
58
|
+
}
|
|
59
|
+
for _, want := range []string{"Join -> example.com/fixture/internal/target.join: parameter 1 is string, target has int", "Grow -> example.com/fixture/internal/target.(*Box).grow: 1 parameters, target has 2"} {
|
|
60
|
+
if !strings.Contains(err.Error(), want) {
|
|
61
|
+
t.Errorf("missing %q in %v", want, err)
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
package main
|
|
2
|
+
|
|
3
|
+
import "testing"
|
|
4
|
+
|
|
5
|
+
// Verifies the reachability scan reads linkname targets of the audited
|
|
6
|
+
// compiler target only.
|
|
7
|
+
//
|
|
8
|
+
// The TypeScript 7.1 bridges link into github.com/microsoft/TypeScript/tsc,
|
|
9
|
+
// while the 7.0 shims link into typescript-go. Recognizing the other target's
|
|
10
|
+
// links would mark symbols reachable that the audited shims cannot name.
|
|
11
|
+
//
|
|
12
|
+
// 1. Build the scanner for the 7.1 internal prefix and match a 7.1 method link
|
|
13
|
+
// and a nested-package function link.
|
|
14
|
+
// 2. Require both scanners to reject a link into the other compiler.
|
|
15
|
+
//
|
|
16
|
+
// @evidence contracts/testing.md#behavioral-verification Calls the production newLinknameRe and asserts the captured package suffix and symbol, or the absence of a match, for each line.
|
|
17
|
+
// @evidence contracts/testing.md#independent-expectations The expected suffixes and names are written beside literal linkname lines taken from the two compilers' module paths.
|
|
18
|
+
// @evidence contracts/testing.md#distinguishing-cases A receiver method and a nested-package function must match under 7.1, and each target's scanner must reject the other compiler's otherwise identical link; TestLinknameRe owns the remaining 7.0 shapes.
|
|
19
|
+
// @evidence contracts/testing.md#execution-ownership This tools/shim_audit unit compiles regular expressions in process; it loads no package and starts no process.
|
|
20
|
+
func TestLinknameTargetsFollowTheAuditedCompiler(t *testing.T) {
|
|
21
|
+
const tsc = "github.com/microsoft/TypeScript/tsc/internal/"
|
|
22
|
+
scanner := newLinknameRe(tsc)
|
|
23
|
+
for _, c := range []struct{ line, pkg, name string }{
|
|
24
|
+
{"//go:linkname checkerGetMinArgumentCount " + tsc + "checker.(*Checker).getMinArgumentCount", "checker", "getMinArgumentCount"},
|
|
25
|
+
{"//go:linkname From " + tsc + "vfs/cachedvfs.From", "vfs/cachedvfs", "From"},
|
|
26
|
+
} {
|
|
27
|
+
m := scanner.FindStringSubmatch(c.line)
|
|
28
|
+
if m == nil || m[1] != c.pkg || m[2] != c.name {
|
|
29
|
+
t.Errorf("%q matched %v, want %s.%s", c.line, m, c.pkg, c.name)
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
if m := scanner.FindStringSubmatch("//go:linkname From " + defaultInternalPrefix + "vfs/cachedvfs.From"); m != nil {
|
|
33
|
+
t.Errorf("7.1 scanner matched a 7.0 link: %v", m)
|
|
34
|
+
}
|
|
35
|
+
if m := newLinknameRe(defaultInternalPrefix).FindStringSubmatch("//go:linkname From " + tsc + "vfs/cachedvfs.From"); m != nil {
|
|
36
|
+
t.Errorf("7.0 scanner matched a 7.1 link: %v", m)
|
|
37
|
+
}
|
|
38
|
+
}
|
package/tools/shim_audit/main.go
CHANGED
|
@@ -67,7 +67,11 @@ import (
|
|
|
67
67
|
"golang.org/x/tools/go/packages"
|
|
68
68
|
)
|
|
69
69
|
|
|
70
|
-
|
|
70
|
+
// defaultInternalPrefix is the TypeScript 7.0 compiler's internal tree.
|
|
71
|
+
const defaultInternalPrefix = "github.com/microsoft/typescript-go/internal/"
|
|
72
|
+
|
|
73
|
+
// internalPrefix is the internal tree of the target being audited (-internal).
|
|
74
|
+
var internalPrefix = defaultInternalPrefix
|
|
71
75
|
|
|
72
76
|
// shimDirs maps each full re-export shim directory to its upstream internal
|
|
73
77
|
// package suffix. Kept explicit (rather than globbed) so a new shim dir is a
|
|
@@ -202,9 +206,14 @@ func opposite(direction flowDirection) flowDirection {
|
|
|
202
206
|
|
|
203
207
|
// linknameRe captures the trailing symbol name of a go:linkname target like
|
|
204
208
|
// `...internal/checker.(*Checker).getMinArgumentCount` or `...checker.foo`.
|
|
205
|
-
var linknameRe =
|
|
206
|
-
|
|
207
|
-
|
|
209
|
+
var linknameRe = newLinknameRe(defaultInternalPrefix)
|
|
210
|
+
|
|
211
|
+
// newLinknameRe matches go:linkname targets below one compiler's internal tree.
|
|
212
|
+
func newLinknameRe(prefix string) *regexp.Regexp {
|
|
213
|
+
return regexp.MustCompile(`(?m)^//go:linkname\s+\S+\s+` +
|
|
214
|
+
regexp.QuoteMeta(prefix) +
|
|
215
|
+
`([A-Za-z0-9_/]+)\.(?:\(\*?[A-Za-z0-9_]+\)\.)?([A-Za-z0-9_]+)`)
|
|
216
|
+
}
|
|
208
217
|
|
|
209
218
|
// scanShimReachable parses every .go file under each shim dir and records the
|
|
210
219
|
// upstream symbols it references.
|
|
@@ -869,7 +878,11 @@ func main() {
|
|
|
869
878
|
baselinePath := flag.String("baseline", "baseline.json", "path to the accepted-gap baseline")
|
|
870
879
|
anchor := flag.String("anchor", "./shim/ast", "module dir anchoring the typescript-go require")
|
|
871
880
|
shimRoot := flag.String("shim", "./shim", "shim root directory")
|
|
881
|
+
internal := flag.String("internal", defaultInternalPrefix, "internal import prefix of the audited compiler target")
|
|
882
|
+
neutralWith := flag.String("neutral-with", "", "shim root of another compiler target whose version-neutral API must match")
|
|
872
883
|
flag.Parse()
|
|
884
|
+
internalPrefix = *internal
|
|
885
|
+
linknameRe = newLinknameRe(internalPrefix)
|
|
873
886
|
|
|
874
887
|
// A shim directory that is not registered for audit coverage would silently
|
|
875
888
|
// escape every check — close that hole before doing anything else.
|
|
@@ -877,6 +890,18 @@ func main() {
|
|
|
877
890
|
fmt.Fprintln(os.Stderr, "shim_audit:", err)
|
|
878
891
|
os.Exit(2)
|
|
879
892
|
}
|
|
893
|
+
// A linked declaration whose signature drifted from its compiler target
|
|
894
|
+
// still links, then corrupts arguments at run time; refuse it outright.
|
|
895
|
+
if err := checkLinknameSignatures(*shimRoot); err != nil {
|
|
896
|
+
fmt.Fprintln(os.Stderr, "shim_audit:", err)
|
|
897
|
+
os.Exit(2)
|
|
898
|
+
}
|
|
899
|
+
if *neutralWith != "" {
|
|
900
|
+
if err := checkNeutralAPI(*shimRoot, *neutralWith); err != nil {
|
|
901
|
+
fmt.Fprintln(os.Stderr, "shim_audit:", err)
|
|
902
|
+
os.Exit(2)
|
|
903
|
+
}
|
|
904
|
+
}
|
|
880
905
|
|
|
881
906
|
r, err := scanShimReachable(*shimRoot)
|
|
882
907
|
if err != nil {
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
package main
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"fmt"
|
|
5
|
+
"go/ast"
|
|
6
|
+
"go/parser"
|
|
7
|
+
"go/token"
|
|
8
|
+
"io/fs"
|
|
9
|
+
"os"
|
|
10
|
+
"path/filepath"
|
|
11
|
+
"sort"
|
|
12
|
+
"strings"
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
// neutralFileName is the file in each shim package that declares the
|
|
16
|
+
// version-neutral API: functions that every compiler target declares with
|
|
17
|
+
// identical signatures, so one plugin source compiles on all of them.
|
|
18
|
+
const neutralFileName = "neutral.go"
|
|
19
|
+
|
|
20
|
+
// neutralFunction is the shape of one exported neutral function that the
|
|
21
|
+
// targets must agree on. Parameter and result types are spelled through each
|
|
22
|
+
// target's own aliases, so the type check belongs to compiling plugin code on
|
|
23
|
+
// every target; this records what the source alone can compare.
|
|
24
|
+
type neutralFunction struct {
|
|
25
|
+
params int
|
|
26
|
+
results int
|
|
27
|
+
variadic bool
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// checkNeutralAPI fails when the shim roots of two compiler targets declare
|
|
31
|
+
// different version-neutral APIs: a package with a neutral.go in one root and
|
|
32
|
+
// not the other, or a function present in one target only or with a
|
|
33
|
+
// different parameter count, result count or variadic final parameter.
|
|
34
|
+
func checkNeutralAPI(firstRoot string, secondRoot string) error {
|
|
35
|
+
first, err := readNeutralAPI(firstRoot)
|
|
36
|
+
if err != nil {
|
|
37
|
+
return err
|
|
38
|
+
}
|
|
39
|
+
second, err := readNeutralAPI(secondRoot)
|
|
40
|
+
if err != nil {
|
|
41
|
+
return err
|
|
42
|
+
}
|
|
43
|
+
var problems []string
|
|
44
|
+
packages := map[string]bool{}
|
|
45
|
+
for pkg := range first {
|
|
46
|
+
packages[pkg] = true
|
|
47
|
+
}
|
|
48
|
+
for pkg := range second {
|
|
49
|
+
packages[pkg] = true
|
|
50
|
+
}
|
|
51
|
+
for _, pkg := range sortedKeys(packages) {
|
|
52
|
+
a, inFirst := first[pkg]
|
|
53
|
+
b, inSecond := second[pkg]
|
|
54
|
+
switch {
|
|
55
|
+
case !inFirst:
|
|
56
|
+
problems = append(problems, fmt.Sprintf("%s: neutral API only in %s", pkg, secondRoot))
|
|
57
|
+
continue
|
|
58
|
+
case !inSecond:
|
|
59
|
+
problems = append(problems, fmt.Sprintf("%s: neutral API only in %s", pkg, firstRoot))
|
|
60
|
+
continue
|
|
61
|
+
}
|
|
62
|
+
names := map[string]bool{}
|
|
63
|
+
for name := range a {
|
|
64
|
+
names[name] = true
|
|
65
|
+
}
|
|
66
|
+
for name := range b {
|
|
67
|
+
names[name] = true
|
|
68
|
+
}
|
|
69
|
+
for _, name := range sortedKeys(names) {
|
|
70
|
+
x, inA := a[name]
|
|
71
|
+
y, inB := b[name]
|
|
72
|
+
switch {
|
|
73
|
+
case !inA:
|
|
74
|
+
problems = append(problems, fmt.Sprintf("%s.%s: declared only in %s", pkg, name, secondRoot))
|
|
75
|
+
case !inB:
|
|
76
|
+
problems = append(problems, fmt.Sprintf("%s.%s: declared only in %s", pkg, name, firstRoot))
|
|
77
|
+
case x != y:
|
|
78
|
+
problems = append(problems, fmt.Sprintf("%s.%s: %d parameters and %d results (variadic %t) in %s, %d and %d (variadic %t) in %s", pkg, name, x.params, x.results, x.variadic, firstRoot, y.params, y.results, y.variadic, secondRoot))
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
if len(problems) > 0 {
|
|
83
|
+
return fmt.Errorf("version-neutral shim APIs differ between targets:\n %s", strings.Join(problems, "\n "))
|
|
84
|
+
}
|
|
85
|
+
return nil
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// readNeutralAPI maps each package below root that has a neutral.go, by its
|
|
89
|
+
// slash-separated directory, to that file's exported functions.
|
|
90
|
+
func readNeutralAPI(root string) (map[string]map[string]neutralFunction, error) {
|
|
91
|
+
api := map[string]map[string]neutralFunction{}
|
|
92
|
+
err := filepath.WalkDir(root, func(path string, entry fs.DirEntry, err error) error {
|
|
93
|
+
if err != nil {
|
|
94
|
+
return err
|
|
95
|
+
}
|
|
96
|
+
if entry.IsDir() || entry.Name() != neutralFileName {
|
|
97
|
+
return nil
|
|
98
|
+
}
|
|
99
|
+
rel, err := filepath.Rel(root, filepath.Dir(path))
|
|
100
|
+
if err != nil {
|
|
101
|
+
return err
|
|
102
|
+
}
|
|
103
|
+
source, err := os.ReadFile(path)
|
|
104
|
+
if err != nil {
|
|
105
|
+
return err
|
|
106
|
+
}
|
|
107
|
+
file, err := parser.ParseFile(token.NewFileSet(), path, source, parser.SkipObjectResolution)
|
|
108
|
+
if err != nil {
|
|
109
|
+
return err
|
|
110
|
+
}
|
|
111
|
+
functions := map[string]neutralFunction{}
|
|
112
|
+
for _, decl := range file.Decls {
|
|
113
|
+
fn, ok := decl.(*ast.FuncDecl)
|
|
114
|
+
if !ok || fn.Recv != nil || !fn.Name.IsExported() {
|
|
115
|
+
continue
|
|
116
|
+
}
|
|
117
|
+
functions[fn.Name.Name] = neutralFunction{
|
|
118
|
+
params: fieldCount(fn.Type.Params),
|
|
119
|
+
results: fieldCount(fn.Type.Results),
|
|
120
|
+
variadic: isVariadic(fn.Type.Params),
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
api[filepath.ToSlash(rel)] = functions
|
|
124
|
+
return nil
|
|
125
|
+
})
|
|
126
|
+
return api, err
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// fieldCount counts the values a field list declares, so `a, b string` is two.
|
|
130
|
+
func fieldCount(list *ast.FieldList) int {
|
|
131
|
+
if list == nil {
|
|
132
|
+
return 0
|
|
133
|
+
}
|
|
134
|
+
count := 0
|
|
135
|
+
for _, field := range list.List {
|
|
136
|
+
if len(field.Names) == 0 {
|
|
137
|
+
count++
|
|
138
|
+
} else {
|
|
139
|
+
count += len(field.Names)
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return count
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
func isVariadic(list *ast.FieldList) bool {
|
|
146
|
+
if list == nil || len(list.List) == 0 {
|
|
147
|
+
return false
|
|
148
|
+
}
|
|
149
|
+
_, ok := list.List[len(list.List)-1].Type.(*ast.Ellipsis)
|
|
150
|
+
return ok
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
func sortedKeys(set map[string]bool) []string {
|
|
154
|
+
keys := make([]string, 0, len(set))
|
|
155
|
+
for key := range set {
|
|
156
|
+
keys = append(keys, key)
|
|
157
|
+
}
|
|
158
|
+
sort.Strings(keys)
|
|
159
|
+
return keys
|
|
160
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
package main
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"os"
|
|
5
|
+
"path/filepath"
|
|
6
|
+
"strings"
|
|
7
|
+
"testing"
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
// Verifies the neutral-API gate accepts matching targets and names every way
|
|
11
|
+
// two targets' version-neutral APIs can drift apart.
|
|
12
|
+
//
|
|
13
|
+
// One plugin source compiles on every compiler target only when each target's
|
|
14
|
+
// neutral.go declares the same functions with the same arity. Types are spelled
|
|
15
|
+
// through each target's own aliases, so arity is what the source can compare.
|
|
16
|
+
//
|
|
17
|
+
// 1. Write two shim roots whose neutral.go files declare the same functions.
|
|
18
|
+
// 2. Require the gate to accept them, including grouped parameters and a
|
|
19
|
+
// variadic tail, and to ignore methods and unexported helpers.
|
|
20
|
+
// 3. Drop a function, change an arity, change variadicity and remove a whole
|
|
21
|
+
// package from one root, and require each drift to be reported by name.
|
|
22
|
+
//
|
|
23
|
+
// @evidence contracts/testing.md#behavioral-verification Calls the production checkNeutralAPI over real temporary files and asserts acceptance or the reported drift lines.
|
|
24
|
+
// @evidence contracts/testing.md#independent-expectations The expected names and counts come from the authored fixture sources, not from the gate's output.
|
|
25
|
+
// @evidence contracts/testing.md#distinguishing-cases A matching pair passes; a missing function, a parameter-count change, a variadic change and a package missing on one side fail; methods and unexported functions must not count.
|
|
26
|
+
// @evidence contracts/testing.md#execution-ownership This tools/shim_audit unit writes temporary files and parses them in process; it loads no module and starts no process.
|
|
27
|
+
func TestNeutralAPIMustMatchAcrossTargets(t *testing.T) {
|
|
28
|
+
write := func(root, rel, text string) {
|
|
29
|
+
t.Helper()
|
|
30
|
+
path := filepath.Join(root, filepath.FromSlash(rel))
|
|
31
|
+
if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil {
|
|
32
|
+
t.Fatal(err)
|
|
33
|
+
}
|
|
34
|
+
if err := os.WriteFile(path, []byte(text), 0o644); err != nil {
|
|
35
|
+
t.Fatal(err)
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
const base = "package tspath\n\nfunc Compare(c bool, a, b string) int { return 0 }\nfunc Join(parts ...string) string { return \"\" }\nfunc helper() {}\ntype T struct{}\nfunc (T) Method(x int) {}\n"
|
|
39
|
+
first, second := t.TempDir(), t.TempDir()
|
|
40
|
+
write(first, "tspath/neutral.go", base)
|
|
41
|
+
write(second, "tspath/neutral.go", strings.ReplaceAll(base, "c bool, a, b string", "c Policy, a Path, b Path")+"type Policy = bool\ntype Path = string\nfunc extra(y string) {}\n")
|
|
42
|
+
write(first, "vfs/shim.go", "package vfs\n\nfunc NotNeutral() {}\n")
|
|
43
|
+
if err := checkNeutralAPI(first, second); err != nil {
|
|
44
|
+
t.Fatalf("matching APIs rejected: %v", err)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
write(second, "tspath/neutral.go", "package tspath\n\nfunc Compare(c bool, a string) int { return 0 }\nfunc Join(parts []string) string { return \"\" }\n")
|
|
48
|
+
write(second, "ast/neutral.go", "package ast\n\nfunc SymbolNameOf(s any) string { return \"\" }\n")
|
|
49
|
+
write(first, "compiler/neutral.go", "package compiler\n\nfunc Only() {}\n")
|
|
50
|
+
err := checkNeutralAPI(first, second)
|
|
51
|
+
if err == nil {
|
|
52
|
+
t.Fatal("drifted APIs accepted")
|
|
53
|
+
}
|
|
54
|
+
for _, want := range []string{
|
|
55
|
+
"tspath.Compare: 3 parameters and 1 results (variadic false)",
|
|
56
|
+
"tspath.Join: 1 parameters and 1 results (variadic true)",
|
|
57
|
+
"ast: neutral API only in " + second,
|
|
58
|
+
"compiler: neutral API only in " + first,
|
|
59
|
+
} {
|
|
60
|
+
if !strings.Contains(err.Error(), want) {
|
|
61
|
+
t.Errorf("missing %q in %v", want, err)
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
write(second, "tspath/neutral.go", base)
|
|
66
|
+
if err := os.Remove(filepath.Join(second, "ast", "neutral.go")); err != nil {
|
|
67
|
+
t.Fatal(err)
|
|
68
|
+
}
|
|
69
|
+
write(first, "compiler/neutral.go", "package compiler\n\nfunc Only() {}\nfunc Gone() {}\n")
|
|
70
|
+
write(second, "compiler/neutral.go", "package compiler\n\nfunc Only() {}\n")
|
|
71
|
+
if err := checkNeutralAPI(first, second); err == nil || !strings.Contains(err.Error(), "compiler.Gone: declared only in "+first) {
|
|
72
|
+
t.Fatalf("dropped function not reported: %v", err)
|
|
73
|
+
}
|
|
74
|
+
}
|