@tsonic/emitter 0.0.74 → 0.0.75
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/dist/.tsbuildinfo +1 -1
- package/dist/array.test.js +277 -6
- package/dist/array.test.js.map +1 -1
- package/dist/core/format/attributes.d.ts +3 -3
- package/dist/core/format/attributes.js +3 -3
- package/dist/core/format/backend-ast/builders.d.ts +1 -0
- package/dist/core/format/backend-ast/builders.d.ts.map +1 -1
- package/dist/core/format/backend-ast/builders.js +44 -22
- package/dist/core/format/backend-ast/builders.js.map +1 -1
- package/dist/core/format/backend-ast/invariants.test.js +15 -8
- package/dist/core/format/backend-ast/invariants.test.js.map +1 -1
- package/dist/core/format/backend-ast/printer-cases/basic-and-declarations.test.d.ts +2 -0
- package/dist/core/format/backend-ast/printer-cases/basic-and-declarations.test.d.ts.map +1 -0
- package/dist/core/format/backend-ast/printer-cases/basic-and-declarations.test.js +226 -0
- package/dist/core/format/backend-ast/printer-cases/basic-and-declarations.test.js.map +1 -0
- package/dist/core/format/backend-ast/printer-cases/control-flow-and-switch.test.d.ts +2 -0
- package/dist/core/format/backend-ast/printer-cases/control-flow-and-switch.test.d.ts.map +1 -0
- package/dist/core/format/backend-ast/printer-cases/control-flow-and-switch.test.js +289 -0
- package/dist/core/format/backend-ast/printer-cases/control-flow-and-switch.test.js.map +1 -0
- package/dist/core/format/backend-ast/printer-cases/helpers.d.ts +6 -0
- package/dist/core/format/backend-ast/printer-cases/helpers.d.ts.map +1 -0
- package/dist/core/format/backend-ast/printer-cases/helpers.js +5 -0
- package/dist/core/format/backend-ast/printer-cases/helpers.js.map +1 -0
- package/dist/core/format/backend-ast/printer-cases/identifiers-and-interpolation.test.d.ts +2 -0
- package/dist/core/format/backend-ast/printer-cases/identifiers-and-interpolation.test.d.ts.map +1 -0
- package/dist/core/format/backend-ast/printer-cases/identifiers-and-interpolation.test.js +211 -0
- package/dist/core/format/backend-ast/printer-cases/identifiers-and-interpolation.test.js.map +1 -0
- package/dist/core/format/backend-ast/printer-cases/remaining-nodes.test.d.ts +2 -0
- package/dist/core/format/backend-ast/printer-cases/remaining-nodes.test.d.ts.map +1 -0
- package/dist/core/format/backend-ast/printer-cases/remaining-nodes.test.js +186 -0
- package/dist/core/format/backend-ast/printer-cases/remaining-nodes.test.js.map +1 -0
- package/dist/core/format/backend-ast/printer-colon-detection.d.ts +14 -0
- package/dist/core/format/backend-ast/printer-colon-detection.d.ts.map +1 -0
- package/dist/core/format/backend-ast/printer-colon-detection.js +141 -0
- package/dist/core/format/backend-ast/printer-colon-detection.js.map +1 -0
- package/dist/core/format/backend-ast/printer-declarations.d.ts +12 -0
- package/dist/core/format/backend-ast/printer-declarations.d.ts.map +1 -0
- package/dist/core/format/backend-ast/printer-declarations.js +212 -0
- package/dist/core/format/backend-ast/printer-declarations.js.map +1 -0
- package/dist/core/format/backend-ast/printer-expressions.d.ts +12 -0
- package/dist/core/format/backend-ast/printer-expressions.d.ts.map +1 -0
- package/dist/core/format/backend-ast/printer-expressions.js +363 -0
- package/dist/core/format/backend-ast/printer-expressions.js.map +1 -0
- package/dist/core/format/backend-ast/printer-identifiers.d.ts +31 -0
- package/dist/core/format/backend-ast/printer-identifiers.d.ts.map +1 -0
- package/dist/core/format/backend-ast/printer-identifiers.js +194 -0
- package/dist/core/format/backend-ast/printer-identifiers.js.map +1 -0
- package/dist/core/format/backend-ast/printer-precedence.d.ts +23 -0
- package/dist/core/format/backend-ast/printer-precedence.d.ts.map +1 -0
- package/dist/core/format/backend-ast/printer-precedence.js +225 -0
- package/dist/core/format/backend-ast/printer-precedence.js.map +1 -0
- package/dist/core/format/backend-ast/printer-shared.d.ts +12 -0
- package/dist/core/format/backend-ast/printer-shared.d.ts.map +1 -0
- package/dist/core/format/backend-ast/printer-shared.js +12 -0
- package/dist/core/format/backend-ast/printer-shared.js.map +1 -0
- package/dist/core/format/backend-ast/printer-statements.d.ts +24 -0
- package/dist/core/format/backend-ast/printer-statements.d.ts.map +1 -0
- package/dist/core/format/backend-ast/printer-statements.js +336 -0
- package/dist/core/format/backend-ast/printer-statements.js.map +1 -0
- package/dist/core/format/backend-ast/printer.d.ts +10 -23
- package/dist/core/format/backend-ast/printer.d.ts.map +1 -1
- package/dist/core/format/backend-ast/printer.js +11 -1389
- package/dist/core/format/backend-ast/printer.js.map +1 -1
- package/dist/core/format/backend-ast/printer.test.d.ts +4 -1
- package/dist/core/format/backend-ast/printer.test.d.ts.map +1 -1
- package/dist/core/format/backend-ast/printer.test.js +4 -795
- package/dist/core/format/backend-ast/printer.test.js.map +1 -1
- package/dist/core/format/backend-ast/types/compilation-unit-ast.d.ts +26 -0
- package/dist/core/format/backend-ast/types/compilation-unit-ast.d.ts.map +1 -0
- package/dist/core/format/backend-ast/types/compilation-unit-ast.js +2 -0
- package/dist/core/format/backend-ast/types/compilation-unit-ast.js.map +1 -0
- package/dist/core/format/backend-ast/types/declaration-ast.d.ts +105 -0
- package/dist/core/format/backend-ast/types/declaration-ast.d.ts.map +1 -0
- package/dist/core/format/backend-ast/types/declaration-ast.js +2 -0
- package/dist/core/format/backend-ast/types/declaration-ast.js.map +1 -0
- package/dist/core/format/backend-ast/types/expression-ast.d.ts +219 -0
- package/dist/core/format/backend-ast/types/expression-ast.d.ts.map +1 -0
- package/dist/core/format/backend-ast/types/expression-ast.js +2 -0
- package/dist/core/format/backend-ast/types/expression-ast.js.map +1 -0
- package/dist/core/format/backend-ast/types/pattern-ast.d.ts +28 -0
- package/dist/core/format/backend-ast/types/pattern-ast.d.ts.map +1 -0
- package/dist/core/format/backend-ast/types/pattern-ast.js +2 -0
- package/dist/core/format/backend-ast/types/pattern-ast.js.map +1 -0
- package/dist/core/format/backend-ast/types/signature-ast.d.ts +34 -0
- package/dist/core/format/backend-ast/types/signature-ast.d.ts.map +1 -0
- package/dist/core/format/backend-ast/types/signature-ast.js +2 -0
- package/dist/core/format/backend-ast/types/signature-ast.js.map +1 -0
- package/dist/core/format/backend-ast/types/statement-ast.d.ts +118 -0
- package/dist/core/format/backend-ast/types/statement-ast.d.ts.map +1 -0
- package/dist/core/format/backend-ast/types/statement-ast.js +2 -0
- package/dist/core/format/backend-ast/types/statement-ast.js.map +1 -0
- package/dist/core/format/backend-ast/types/type-ast.d.ts +50 -0
- package/dist/core/format/backend-ast/types/type-ast.d.ts.map +1 -0
- package/dist/core/format/backend-ast/types/type-ast.js +2 -0
- package/dist/core/format/backend-ast/types/type-ast.js.map +1 -0
- package/dist/core/format/backend-ast/types.d.ts +7 -549
- package/dist/core/format/backend-ast/types.d.ts.map +1 -1
- package/dist/core/format/backend-ast/types.js +7 -1
- package/dist/core/format/backend-ast/types.js.map +1 -1
- package/dist/core/format/backend-ast/utils.d.ts +4 -0
- package/dist/core/format/backend-ast/utils.d.ts.map +1 -1
- package/dist/core/format/backend-ast/utils.js +87 -16
- package/dist/core/format/backend-ast/utils.js.map +1 -1
- package/dist/core/format/backend-ast/utils.test.js +67 -4
- package/dist/core/format/backend-ast/utils.test.js.map +1 -1
- package/dist/core/format/local-names.d.ts +26 -0
- package/dist/core/format/local-names.d.ts.map +1 -1
- package/dist/core/format/local-names.js +59 -0
- package/dist/core/format/local-names.js.map +1 -1
- package/dist/core/format/local-names.test.d.ts +12 -0
- package/dist/core/format/local-names.test.d.ts.map +1 -0
- package/dist/core/format/local-names.test.js +278 -0
- package/dist/core/format/local-names.test.js.map +1 -0
- package/dist/core/format/module-emitter/orchestrator.d.ts.map +1 -1
- package/dist/core/format/module-emitter/orchestrator.js +1 -152
- package/dist/core/format/module-emitter/orchestrator.js.map +1 -1
- package/dist/core/format/module-emitter/static-container.d.ts.map +1 -1
- package/dist/core/format/module-emitter/static-container.js +17 -1
- package/dist/core/format/module-emitter/static-container.js.map +1 -1
- package/dist/core/module-emitter-cases/class-and-recursion.test.d.ts +6 -0
- package/dist/core/module-emitter-cases/class-and-recursion.test.d.ts.map +1 -0
- package/dist/core/module-emitter-cases/class-and-recursion.test.js +263 -0
- package/dist/core/module-emitter-cases/class-and-recursion.test.js.map +1 -0
- package/dist/core/module-emitter-cases/static-containers.test.d.ts +6 -0
- package/dist/core/module-emitter-cases/static-containers.test.d.ts.map +1 -0
- package/dist/core/module-emitter-cases/static-containers.test.js +275 -0
- package/dist/core/module-emitter-cases/static-containers.test.js.map +1 -0
- package/dist/core/module-emitter.test.d.ts +2 -5
- package/dist/core/module-emitter.test.d.ts.map +1 -1
- package/dist/core/module-emitter.test.js +2 -403
- package/dist/core/module-emitter.test.js.map +1 -1
- package/dist/core/semantic/array-expected-types.d.ts +6 -0
- package/dist/core/semantic/array-expected-types.d.ts.map +1 -0
- package/dist/core/semantic/array-expected-types.js +84 -0
- package/dist/core/semantic/array-expected-types.js.map +1 -0
- package/dist/core/semantic/array-expected-types.test.d.ts +2 -0
- package/dist/core/semantic/array-expected-types.test.d.ts.map +1 -0
- package/dist/core/semantic/array-expected-types.test.js +66 -0
- package/dist/core/semantic/array-expected-types.test.js.map +1 -0
- package/dist/core/semantic/assignment-flow.d.ts +9 -0
- package/dist/core/semantic/assignment-flow.d.ts.map +1 -0
- package/dist/core/semantic/assignment-flow.js +161 -0
- package/dist/core/semantic/assignment-flow.js.map +1 -0
- package/dist/core/semantic/async-wrapper-types.d.ts +6 -0
- package/dist/core/semantic/async-wrapper-types.d.ts.map +1 -0
- package/dist/core/semantic/async-wrapper-types.js +65 -0
- package/dist/core/semantic/async-wrapper-types.js.map +1 -0
- package/dist/core/semantic/boolean-condition-emission.d.ts +9 -0
- package/dist/core/semantic/boolean-condition-emission.d.ts.map +1 -0
- package/dist/core/semantic/boolean-condition-emission.js +9 -0
- package/dist/core/semantic/boolean-condition-emission.js.map +1 -0
- package/dist/core/semantic/boolean-condition-main.d.ts +38 -0
- package/dist/core/semantic/boolean-condition-main.d.ts.map +1 -0
- package/dist/core/semantic/boolean-condition-main.js +235 -0
- package/dist/core/semantic/boolean-condition-main.js.map +1 -0
- package/dist/core/semantic/boolean-condition-union.d.ts +20 -0
- package/dist/core/semantic/boolean-condition-union.d.ts.map +1 -0
- package/dist/core/semantic/boolean-condition-union.js +238 -0
- package/dist/core/semantic/boolean-condition-union.js.map +1 -0
- package/dist/core/semantic/boolean-context.d.ts +6 -40
- package/dist/core/semantic/boolean-context.d.ts.map +1 -1
- package/dist/core/semantic/boolean-context.js +6 -709
- package/dist/core/semantic/boolean-context.js.map +1 -1
- package/dist/core/semantic/boolean-context.test.js +22 -2
- package/dist/core/semantic/boolean-context.test.js.map +1 -1
- package/dist/core/semantic/broad-array-storage.d.ts +11 -0
- package/dist/core/semantic/broad-array-storage.d.ts.map +1 -0
- package/dist/core/semantic/broad-array-storage.js +111 -0
- package/dist/core/semantic/broad-array-storage.js.map +1 -0
- package/dist/core/semantic/broad-object-types.d.ts +7 -0
- package/dist/core/semantic/broad-object-types.d.ts.map +1 -0
- package/dist/core/semantic/broad-object-types.js +60 -0
- package/dist/core/semantic/broad-object-types.js.map +1 -0
- package/dist/core/semantic/clr-type-identity.d.ts +21 -0
- package/dist/core/semantic/clr-type-identity.d.ts.map +1 -0
- package/dist/core/semantic/clr-type-identity.js +230 -0
- package/dist/core/semantic/clr-type-identity.js.map +1 -0
- package/dist/core/semantic/comparable-types.d.ts +5 -0
- package/dist/core/semantic/comparable-types.d.ts.map +1 -0
- package/dist/core/semantic/comparable-types.js +108 -0
- package/dist/core/semantic/comparable-types.js.map +1 -0
- package/dist/core/semantic/comparable-types.test.d.ts +2 -0
- package/dist/core/semantic/comparable-types.test.d.ts.map +1 -0
- package/dist/core/semantic/comparable-types.test.js +199 -0
- package/dist/core/semantic/comparable-types.test.js.map +1 -0
- package/dist/core/semantic/condition-branch-narrowing.d.ts +6 -0
- package/dist/core/semantic/condition-branch-narrowing.d.ts.map +1 -0
- package/dist/core/semantic/condition-branch-narrowing.js +50 -0
- package/dist/core/semantic/condition-branch-narrowing.js.map +1 -0
- package/dist/core/semantic/defaults.d.ts +7 -0
- package/dist/core/semantic/defaults.d.ts.map +1 -0
- package/dist/core/semantic/defaults.js +61 -0
- package/dist/core/semantic/defaults.js.map +1 -0
- package/dist/core/semantic/defaults.test.d.ts +2 -0
- package/dist/core/semantic/defaults.test.d.ts.map +1 -0
- package/dist/core/semantic/defaults.test.js +88 -0
- package/dist/core/semantic/defaults.test.js.map +1 -0
- package/dist/core/semantic/deterministic-type-keys.d.ts +8 -0
- package/dist/core/semantic/deterministic-type-keys.d.ts.map +1 -0
- package/dist/core/semantic/deterministic-type-keys.js +277 -0
- package/dist/core/semantic/deterministic-type-keys.js.map +1 -0
- package/dist/core/semantic/direct-storage-ir-types.d.ts +12 -0
- package/dist/core/semantic/direct-storage-ir-types.d.ts.map +1 -0
- package/dist/core/semantic/direct-storage-ir-types.js +189 -0
- package/dist/core/semantic/direct-storage-ir-types.js.map +1 -0
- package/dist/core/semantic/direct-value-surfaces.d.ts +9 -0
- package/dist/core/semantic/direct-value-surfaces.d.ts.map +1 -0
- package/dist/core/semantic/direct-value-surfaces.js +181 -0
- package/dist/core/semantic/direct-value-surfaces.js.map +1 -0
- package/dist/core/semantic/direct-value-surfaces.test.d.ts +2 -0
- package/dist/core/semantic/direct-value-surfaces.test.d.ts.map +1 -0
- package/dist/core/semantic/direct-value-surfaces.test.js +116 -0
- package/dist/core/semantic/direct-value-surfaces.test.js.map +1 -0
- package/dist/core/semantic/expected-type-matching.d.ts +7 -0
- package/dist/core/semantic/expected-type-matching.d.ts.map +1 -0
- package/dist/core/semantic/expected-type-matching.js +101 -0
- package/dist/core/semantic/expected-type-matching.js.map +1 -0
- package/dist/core/semantic/guard-primitives.d.ts +29 -0
- package/dist/core/semantic/guard-primitives.d.ts.map +1 -0
- package/dist/core/semantic/guard-primitives.js +80 -0
- package/dist/core/semantic/guard-primitives.js.map +1 -0
- package/dist/core/semantic/implicit-interfaces.d.ts +34 -0
- package/dist/core/semantic/implicit-interfaces.d.ts.map +1 -0
- package/dist/core/semantic/implicit-interfaces.js +276 -0
- package/dist/core/semantic/implicit-interfaces.js.map +1 -0
- package/dist/core/semantic/implicit-interfaces.test.d.ts +2 -0
- package/dist/core/semantic/implicit-interfaces.test.d.ts.map +1 -0
- package/dist/core/semantic/implicit-interfaces.test.js +280 -0
- package/dist/core/semantic/implicit-interfaces.test.js.map +1 -0
- package/dist/core/semantic/imports-cases/basic-and-local.test.d.ts +6 -0
- package/dist/core/semantic/imports-cases/basic-and-local.test.d.ts.map +1 -0
- package/dist/core/semantic/imports-cases/basic-and-local.test.js +504 -0
- package/dist/core/semantic/imports-cases/basic-and-local.test.js.map +1 -0
- package/dist/core/semantic/imports-cases/bindings-and-namespaces.test.d.ts +6 -0
- package/dist/core/semantic/imports-cases/bindings-and-namespaces.test.d.ts.map +1 -0
- package/dist/core/semantic/imports-cases/bindings-and-namespaces.test.js +932 -0
- package/dist/core/semantic/imports-cases/bindings-and-namespaces.test.js.map +1 -0
- package/dist/core/semantic/imports.d.ts.map +1 -1
- package/dist/core/semantic/imports.js +158 -22
- package/dist/core/semantic/imports.js.map +1 -1
- package/dist/core/semantic/imports.test.d.ts +2 -5
- package/dist/core/semantic/imports.test.d.ts.map +1 -1
- package/dist/core/semantic/imports.test.js +2 -551
- package/dist/core/semantic/imports.test.js.map +1 -1
- package/dist/core/semantic/instanceof-predicate-refinements.d.ts +10 -0
- package/dist/core/semantic/instanceof-predicate-refinements.d.ts.map +1 -0
- package/dist/core/semantic/instanceof-predicate-refinements.js +189 -0
- package/dist/core/semantic/instanceof-predicate-refinements.js.map +1 -0
- package/dist/core/semantic/instanceof-targets.d.ts +10 -0
- package/dist/core/semantic/instanceof-targets.d.ts.map +1 -0
- package/dist/core/semantic/instanceof-targets.js +20 -0
- package/dist/core/semantic/instanceof-targets.js.map +1 -0
- package/dist/core/semantic/iteration-types.d.ts +11 -0
- package/dist/core/semantic/iteration-types.d.ts.map +1 -0
- package/dist/core/semantic/iteration-types.js +116 -0
- package/dist/core/semantic/iteration-types.js.map +1 -0
- package/dist/core/semantic/js-value-types.d.ts +5 -0
- package/dist/core/semantic/js-value-types.d.ts.map +1 -0
- package/dist/core/semantic/js-value-types.js +42 -0
- package/dist/core/semantic/js-value-types.js.map +1 -0
- package/dist/core/semantic/local-type-lookup.d.ts +8 -0
- package/dist/core/semantic/local-type-lookup.d.ts.map +1 -0
- package/dist/core/semantic/local-type-lookup.js +36 -0
- package/dist/core/semantic/local-type-lookup.js.map +1 -0
- package/dist/core/semantic/local-types.d.ts +1 -0
- package/dist/core/semantic/local-types.d.ts.map +1 -1
- package/dist/core/semantic/local-types.js +269 -0
- package/dist/core/semantic/local-types.js.map +1 -1
- package/dist/core/semantic/materialized-narrowing.d.ts +5 -0
- package/dist/core/semantic/materialized-narrowing.d.ts.map +1 -0
- package/dist/core/semantic/materialized-narrowing.js +361 -0
- package/dist/core/semantic/materialized-narrowing.js.map +1 -0
- package/dist/core/semantic/materialized-narrowing.test.d.ts +2 -0
- package/dist/core/semantic/materialized-narrowing.test.d.ts.map +1 -0
- package/dist/core/semantic/materialized-narrowing.test.js +321 -0
- package/dist/core/semantic/materialized-narrowing.test.js.map +1 -0
- package/dist/core/semantic/member-surfaces.d.ts +10 -0
- package/dist/core/semantic/member-surfaces.d.ts.map +1 -0
- package/dist/core/semantic/member-surfaces.js +108 -0
- package/dist/core/semantic/member-surfaces.js.map +1 -0
- package/dist/core/semantic/member-surfaces.test.d.ts +2 -0
- package/dist/core/semantic/member-surfaces.test.d.ts.map +1 -0
- package/dist/core/semantic/member-surfaces.test.js +105 -0
- package/dist/core/semantic/member-surfaces.test.js.map +1 -0
- package/dist/core/semantic/module-map.d.ts.map +1 -1
- package/dist/core/semantic/module-map.js +92 -2
- package/dist/core/semantic/module-map.js.map +1 -1
- package/dist/core/semantic/module-map.test.js +264 -0
- package/dist/core/semantic/module-map.test.js.map +1 -1
- package/dist/core/semantic/mutable-storage-detection.d.ts +10 -0
- package/dist/core/semantic/mutable-storage-detection.d.ts.map +1 -0
- package/dist/core/semantic/mutable-storage-detection.js +10 -0
- package/dist/core/semantic/mutable-storage-detection.js.map +1 -0
- package/dist/core/semantic/mutable-storage-expression-visitor.d.ts +12 -0
- package/dist/core/semantic/mutable-storage-expression-visitor.d.ts.map +1 -0
- package/dist/core/semantic/mutable-storage-expression-visitor.js +126 -0
- package/dist/core/semantic/mutable-storage-expression-visitor.js.map +1 -0
- package/dist/core/semantic/mutable-storage-helpers.d.ts +26 -0
- package/dist/core/semantic/mutable-storage-helpers.d.ts.map +1 -0
- package/dist/core/semantic/mutable-storage-helpers.js +203 -0
- package/dist/core/semantic/mutable-storage-helpers.js.map +1 -0
- package/dist/core/semantic/mutable-storage-statement-visitor.d.ts +5 -0
- package/dist/core/semantic/mutable-storage-statement-visitor.d.ts.map +1 -0
- package/dist/core/semantic/mutable-storage-statement-visitor.js +158 -0
- package/dist/core/semantic/mutable-storage-statement-visitor.js.map +1 -0
- package/dist/core/semantic/mutable-storage-visitors.d.ts +5 -0
- package/dist/core/semantic/mutable-storage-visitors.d.ts.map +1 -0
- package/dist/core/semantic/mutable-storage-visitors.js +17 -0
- package/dist/core/semantic/mutable-storage-visitors.js.map +1 -0
- package/dist/core/semantic/mutable-storage.d.ts +2 -9
- package/dist/core/semantic/mutable-storage.d.ts.map +1 -1
- package/dist/core/semantic/mutable-storage.js +2 -478
- package/dist/core/semantic/mutable-storage.js.map +1 -1
- package/dist/core/semantic/narrowed-expression-types.d.ts +7 -0
- package/dist/core/semantic/narrowed-expression-types.d.ts.map +1 -0
- package/dist/core/semantic/narrowed-expression-types.js +287 -0
- package/dist/core/semantic/narrowed-expression-types.js.map +1 -0
- package/dist/core/semantic/narrowed-expression-types.test.d.ts +2 -0
- package/dist/core/semantic/narrowed-expression-types.test.d.ts.map +1 -0
- package/dist/core/semantic/narrowed-expression-types.test.js +296 -0
- package/dist/core/semantic/narrowed-expression-types.test.js.map +1 -0
- package/dist/core/semantic/narrowed-union-resolution.d.ts +42 -0
- package/dist/core/semantic/narrowed-union-resolution.d.ts.map +1 -0
- package/dist/core/semantic/narrowed-union-resolution.js +162 -0
- package/dist/core/semantic/narrowed-union-resolution.js.map +1 -0
- package/dist/core/semantic/narrowing-builder-core.d.ts +46 -0
- package/dist/core/semantic/narrowing-builder-core.d.ts.map +1 -0
- package/dist/core/semantic/narrowing-builder-core.js +332 -0
- package/dist/core/semantic/narrowing-builder-core.js.map +1 -0
- package/dist/core/semantic/narrowing-builder-core.test.d.ts +2 -0
- package/dist/core/semantic/narrowing-builder-core.test.d.ts.map +1 -0
- package/dist/core/semantic/narrowing-builder-core.test.js +49 -0
- package/dist/core/semantic/narrowing-builder-core.test.js.map +1 -0
- package/dist/core/semantic/narrowing-builder-unions.d.ts +18 -0
- package/dist/core/semantic/narrowing-builder-unions.d.ts.map +1 -0
- package/dist/core/semantic/narrowing-builder-unions.js +336 -0
- package/dist/core/semantic/narrowing-builder-unions.js.map +1 -0
- package/dist/core/semantic/narrowing-builders.d.ts +10 -0
- package/dist/core/semantic/narrowing-builders.d.ts.map +1 -0
- package/dist/core/semantic/narrowing-builders.js +10 -0
- package/dist/core/semantic/narrowing-builders.js.map +1 -0
- package/dist/core/semantic/narrowing-keys.d.ts +6 -0
- package/dist/core/semantic/narrowing-keys.d.ts.map +1 -0
- package/dist/core/semantic/narrowing-keys.js +27 -0
- package/dist/core/semantic/narrowing-keys.js.map +1 -0
- package/dist/core/semantic/narrowing-refinements.d.ts +10 -0
- package/dist/core/semantic/narrowing-refinements.d.ts.map +1 -0
- package/dist/core/semantic/narrowing-refinements.js +10 -0
- package/dist/core/semantic/narrowing-refinements.js.map +1 -0
- package/dist/core/semantic/nullable-typeof-refinements.d.ts +13 -0
- package/dist/core/semantic/nullable-typeof-refinements.d.ts.map +1 -0
- package/dist/core/semantic/nullable-typeof-refinements.js +408 -0
- package/dist/core/semantic/nullable-typeof-refinements.js.map +1 -0
- package/dist/core/semantic/nullish-value-helpers.d.ts +64 -0
- package/dist/core/semantic/nullish-value-helpers.d.ts.map +1 -0
- package/dist/core/semantic/nullish-value-helpers.js +346 -0
- package/dist/core/semantic/nullish-value-helpers.js.map +1 -0
- package/dist/core/semantic/parameter-modifier-types.d.ts +3 -0
- package/dist/core/semantic/parameter-modifier-types.d.ts.map +1 -0
- package/dist/core/semantic/parameter-modifier-types.js +17 -0
- package/dist/core/semantic/parameter-modifier-types.js.map +1 -0
- package/dist/core/semantic/pattern-types.d.ts +59 -0
- package/dist/core/semantic/pattern-types.d.ts.map +1 -0
- package/dist/core/semantic/pattern-types.js +92 -0
- package/dist/core/semantic/pattern-types.js.map +1 -0
- package/dist/core/semantic/property-lookup-membership.d.ts +30 -0
- package/dist/core/semantic/property-lookup-membership.d.ts.map +1 -0
- package/dist/core/semantic/property-lookup-membership.js +176 -0
- package/dist/core/semantic/property-lookup-membership.js.map +1 -0
- package/dist/core/semantic/property-lookup-resolution.d.ts +52 -0
- package/dist/core/semantic/property-lookup-resolution.d.ts.map +1 -0
- package/dist/core/semantic/property-lookup-resolution.js +275 -0
- package/dist/core/semantic/property-lookup-resolution.js.map +1 -0
- package/dist/core/semantic/property-member-lookup.d.ts +10 -0
- package/dist/core/semantic/property-member-lookup.d.ts.map +1 -0
- package/dist/core/semantic/property-member-lookup.js +10 -0
- package/dist/core/semantic/property-member-lookup.js.map +1 -0
- package/dist/core/semantic/reference-type-identity.d.ts +10 -0
- package/dist/core/semantic/reference-type-identity.d.ts.map +1 -0
- package/dist/core/semantic/reference-type-identity.js +28 -0
- package/dist/core/semantic/reference-type-identity.js.map +1 -0
- package/dist/core/semantic/runtime-call-arities.d.ts +4 -0
- package/dist/core/semantic/runtime-call-arities.d.ts.map +1 -0
- package/dist/core/semantic/runtime-call-arities.js +104 -0
- package/dist/core/semantic/runtime-call-arities.js.map +1 -0
- package/dist/core/semantic/runtime-materialization-targets.d.ts +4 -0
- package/dist/core/semantic/runtime-materialization-targets.d.ts.map +1 -0
- package/dist/core/semantic/runtime-materialization-targets.js +69 -0
- package/dist/core/semantic/runtime-materialization-targets.js.map +1 -0
- package/dist/core/semantic/runtime-reification-helpers.d.ts +9 -0
- package/dist/core/semantic/runtime-reification-helpers.d.ts.map +1 -0
- package/dist/core/semantic/runtime-reification-helpers.js +99 -0
- package/dist/core/semantic/runtime-reification-helpers.js.map +1 -0
- package/dist/core/semantic/runtime-reification.d.ts +16 -0
- package/dist/core/semantic/runtime-reification.d.ts.map +1 -0
- package/dist/core/semantic/runtime-reification.js +609 -0
- package/dist/core/semantic/runtime-reification.js.map +1 -0
- package/dist/core/semantic/runtime-union-alias-identity.d.ts +5 -0
- package/dist/core/semantic/runtime-union-alias-identity.d.ts.map +1 -0
- package/dist/core/semantic/runtime-union-alias-identity.js +27 -0
- package/dist/core/semantic/runtime-union-alias-identity.js.map +1 -0
- package/dist/core/semantic/runtime-union-expansion.d.ts +5 -0
- package/dist/core/semantic/runtime-union-expansion.d.ts.map +1 -0
- package/dist/core/semantic/runtime-union-expansion.js +190 -0
- package/dist/core/semantic/runtime-union-expansion.js.map +1 -0
- package/dist/core/semantic/runtime-union-family-preservation.d.ts +5 -0
- package/dist/core/semantic/runtime-union-family-preservation.d.ts.map +1 -0
- package/dist/core/semantic/runtime-union-family-preservation.js +34 -0
- package/dist/core/semantic/runtime-union-family-preservation.js.map +1 -0
- package/dist/core/semantic/runtime-union-matching.d.ts +9 -0
- package/dist/core/semantic/runtime-union-matching.d.ts.map +1 -0
- package/dist/core/semantic/runtime-union-matching.js +121 -0
- package/dist/core/semantic/runtime-union-matching.js.map +1 -0
- package/dist/core/semantic/runtime-union-member-mapping.d.ts +12 -0
- package/dist/core/semantic/runtime-union-member-mapping.d.ts.map +1 -0
- package/dist/core/semantic/runtime-union-member-mapping.js +25 -0
- package/dist/core/semantic/runtime-union-member-mapping.js.map +1 -0
- package/dist/core/semantic/runtime-union-member-mapping.test.d.ts +2 -0
- package/dist/core/semantic/runtime-union-member-mapping.test.d.ts.map +1 -0
- package/dist/core/semantic/runtime-union-member-mapping.test.js +54 -0
- package/dist/core/semantic/runtime-union-member-mapping.test.js.map +1 -0
- package/dist/core/semantic/runtime-union-ordering.d.ts +4 -0
- package/dist/core/semantic/runtime-union-ordering.d.ts.map +1 -0
- package/dist/core/semantic/runtime-union-ordering.js +114 -0
- package/dist/core/semantic/runtime-union-ordering.js.map +1 -0
- package/dist/core/semantic/runtime-union-projection.d.ts +40 -0
- package/dist/core/semantic/runtime-union-projection.d.ts.map +1 -0
- package/dist/core/semantic/runtime-union-projection.js +150 -0
- package/dist/core/semantic/runtime-union-projection.js.map +1 -0
- package/dist/core/semantic/runtime-union-projection.test.d.ts +2 -0
- package/dist/core/semantic/runtime-union-projection.test.d.ts.map +1 -0
- package/dist/core/semantic/runtime-union-projection.test.js +211 -0
- package/dist/core/semantic/runtime-union-projection.test.js.map +1 -0
- package/dist/core/semantic/runtime-union-registry.d.ts +28 -0
- package/dist/core/semantic/runtime-union-registry.d.ts.map +1 -0
- package/dist/core/semantic/runtime-union-registry.js +301 -0
- package/dist/core/semantic/runtime-union-registry.js.map +1 -0
- package/dist/core/semantic/runtime-union-shared.d.ts +23 -0
- package/dist/core/semantic/runtime-union-shared.d.ts.map +1 -0
- package/dist/core/semantic/runtime-union-shared.js +29 -0
- package/dist/core/semantic/runtime-union-shared.js.map +1 -0
- package/dist/core/semantic/runtime-unions.d.ts +14 -0
- package/dist/core/semantic/runtime-unions.d.ts.map +1 -0
- package/dist/core/semantic/runtime-unions.js +330 -0
- package/dist/core/semantic/runtime-unions.js.map +1 -0
- package/dist/core/semantic/runtime-unions.test.d.ts +2 -0
- package/dist/core/semantic/runtime-unions.test.d.ts.map +1 -0
- package/dist/core/semantic/runtime-unions.test.js +922 -0
- package/dist/core/semantic/runtime-unions.test.js.map +1 -0
- package/dist/core/semantic/semantic-union-members.d.ts +46 -0
- package/dist/core/semantic/semantic-union-members.d.ts.map +1 -0
- package/dist/core/semantic/semantic-union-members.js +144 -0
- package/dist/core/semantic/semantic-union-members.js.map +1 -0
- package/dist/core/semantic/storage-erased-adaptation.d.ts +14 -0
- package/dist/core/semantic/storage-erased-adaptation.d.ts.map +1 -0
- package/dist/core/semantic/storage-erased-adaptation.js +191 -0
- package/dist/core/semantic/storage-erased-adaptation.js.map +1 -0
- package/dist/core/semantic/storage-erased-adaptation.test.d.ts +2 -0
- package/dist/core/semantic/storage-erased-adaptation.test.d.ts.map +1 -0
- package/dist/core/semantic/storage-erased-adaptation.test.js +271 -0
- package/dist/core/semantic/storage-erased-adaptation.test.js.map +1 -0
- package/dist/core/semantic/storage-types.d.ts +8 -0
- package/dist/core/semantic/storage-types.d.ts.map +1 -0
- package/dist/core/semantic/storage-types.js +344 -0
- package/dist/core/semantic/storage-types.js.map +1 -0
- package/dist/core/semantic/storage-types.test.d.ts +2 -0
- package/dist/core/semantic/storage-types.test.d.ts.map +1 -0
- package/dist/core/semantic/storage-types.test.js +438 -0
- package/dist/core/semantic/storage-types.test.js.map +1 -0
- package/dist/core/semantic/structural-resolution.d.ts +11 -0
- package/dist/core/semantic/structural-resolution.d.ts.map +1 -0
- package/dist/core/semantic/structural-resolution.js +11 -0
- package/dist/core/semantic/structural-resolution.js.map +1 -0
- package/dist/core/semantic/structural-shape-matching.d.ts +22 -0
- package/dist/core/semantic/structural-shape-matching.d.ts.map +1 -0
- package/dist/core/semantic/structural-shape-matching.js +255 -0
- package/dist/core/semantic/structural-shape-matching.js.map +1 -0
- package/dist/core/semantic/structural-view-types.d.ts +10 -0
- package/dist/core/semantic/structural-view-types.d.ts.map +1 -0
- package/dist/core/semantic/structural-view-types.js +46 -0
- package/dist/core/semantic/structural-view-types.js.map +1 -0
- package/dist/core/semantic/symbol-types.d.ts +80 -0
- package/dist/core/semantic/symbol-types.d.ts.map +1 -0
- package/dist/core/semantic/symbol-types.js +102 -0
- package/dist/core/semantic/symbol-types.js.map +1 -0
- package/dist/core/semantic/ternary-guards.d.ts +43 -0
- package/dist/core/semantic/ternary-guards.d.ts.map +1 -0
- package/dist/core/semantic/ternary-guards.js +232 -0
- package/dist/core/semantic/ternary-guards.js.map +1 -0
- package/dist/core/semantic/transparent-expressions.d.ts +6 -0
- package/dist/core/semantic/transparent-expressions.d.ts.map +1 -0
- package/dist/core/semantic/transparent-expressions.js +18 -0
- package/dist/core/semantic/transparent-expressions.js.map +1 -0
- package/dist/core/semantic/truthiness-evaluation.d.ts +58 -0
- package/dist/core/semantic/truthiness-evaluation.d.ts.map +1 -0
- package/dist/core/semantic/truthiness-evaluation.js +295 -0
- package/dist/core/semantic/truthiness-evaluation.js.map +1 -0
- package/dist/core/semantic/type-alias-index.d.ts.map +1 -1
- package/dist/core/semantic/type-alias-index.js +1 -11
- package/dist/core/semantic/type-alias-index.js.map +1 -1
- package/dist/core/semantic/type-compatibility.d.ts +1 -1
- package/dist/core/semantic/type-compatibility.d.ts.map +1 -1
- package/dist/core/semantic/type-compatibility.js +75 -15
- package/dist/core/semantic/type-compatibility.js.map +1 -1
- package/dist/core/semantic/type-equivalence.d.ts +4 -0
- package/dist/core/semantic/type-equivalence.d.ts.map +1 -0
- package/dist/core/semantic/type-equivalence.js +255 -0
- package/dist/core/semantic/type-equivalence.js.map +1 -0
- package/dist/core/semantic/type-equivalence.test.d.ts +2 -0
- package/dist/core/semantic/type-equivalence.test.d.ts.map +1 -0
- package/dist/core/semantic/type-equivalence.test.js +380 -0
- package/dist/core/semantic/type-equivalence.test.js.map +1 -0
- package/dist/core/semantic/type-param-substitution.d.ts +19 -0
- package/dist/core/semantic/type-param-substitution.d.ts.map +1 -0
- package/dist/core/semantic/type-param-substitution.js +219 -0
- package/dist/core/semantic/type-param-substitution.js.map +1 -0
- package/dist/core/semantic/type-resolution-cases/array-like-element.test.d.ts +2 -0
- package/dist/core/semantic/type-resolution-cases/array-like-element.test.d.ts.map +1 -0
- package/dist/core/semantic/type-resolution-cases/array-like-element.test.js +82 -0
- package/dist/core/semantic/type-resolution-cases/array-like-element.test.js.map +1 -0
- package/dist/core/semantic/type-resolution-cases/contains-type-parameter.test.d.ts +2 -0
- package/dist/core/semantic/type-resolution-cases/contains-type-parameter.test.d.ts.map +1 -0
- package/dist/core/semantic/type-resolution-cases/contains-type-parameter.test.js +101 -0
- package/dist/core/semantic/type-resolution-cases/contains-type-parameter.test.js.map +1 -0
- package/dist/core/semantic/type-resolution-cases/helpers.d.ts +8 -0
- package/dist/core/semantic/type-resolution-cases/helpers.d.ts.map +1 -0
- package/dist/core/semantic/type-resolution-cases/helpers.js +5 -0
- package/dist/core/semantic/type-resolution-cases/helpers.js.map +1 -0
- package/dist/core/semantic/type-resolution-cases/narrow-typeof.test.d.ts +2 -0
- package/dist/core/semantic/type-resolution-cases/narrow-typeof.test.d.ts.map +1 -0
- package/dist/core/semantic/type-resolution-cases/narrow-typeof.test.js +98 -0
- package/dist/core/semantic/type-resolution-cases/narrow-typeof.test.js.map +1 -0
- package/dist/core/semantic/type-resolution-cases/nullish-and-value-type.test.d.ts +2 -0
- package/dist/core/semantic/type-resolution-cases/nullish-and-value-type.test.d.ts.map +1 -0
- package/dist/core/semantic/type-resolution-cases/nullish-and-value-type.test.js +378 -0
- package/dist/core/semantic/type-resolution-cases/nullish-and-value-type.test.js.map +1 -0
- package/dist/core/semantic/type-resolution-cases/object-literal-member-selection.test.d.ts +2 -0
- package/dist/core/semantic/type-resolution-cases/object-literal-member-selection.test.d.ts.map +1 -0
- package/dist/core/semantic/type-resolution-cases/object-literal-member-selection.test.js +137 -0
- package/dist/core/semantic/type-resolution-cases/object-literal-member-selection.test.js.map +1 -0
- package/dist/core/semantic/type-resolution-cases/property-type.test.d.ts +2 -0
- package/dist/core/semantic/type-resolution-cases/property-type.test.d.ts.map +1 -0
- package/dist/core/semantic/type-resolution-cases/property-type.test.js +298 -0
- package/dist/core/semantic/type-resolution-cases/property-type.test.js.map +1 -0
- package/dist/core/semantic/type-resolution-cases/structural-resolution.test.d.ts +2 -0
- package/dist/core/semantic/type-resolution-cases/structural-resolution.test.d.ts.map +1 -0
- package/dist/core/semantic/type-resolution-cases/structural-resolution.test.js +511 -0
- package/dist/core/semantic/type-resolution-cases/structural-resolution.test.js.map +1 -0
- package/dist/core/semantic/type-resolution-cases/structural-target.test.d.ts +2 -0
- package/dist/core/semantic/type-resolution-cases/structural-target.test.d.ts.map +1 -0
- package/dist/core/semantic/type-resolution-cases/structural-target.test.js +80 -0
- package/dist/core/semantic/type-resolution-cases/structural-target.test.js.map +1 -0
- package/dist/core/semantic/type-resolution-cases/substitute-type-args.test.d.ts +2 -0
- package/dist/core/semantic/type-resolution-cases/substitute-type-args.test.d.ts.map +1 -0
- package/dist/core/semantic/type-resolution-cases/substitute-type-args.test.js +80 -0
- package/dist/core/semantic/type-resolution-cases/substitute-type-args.test.js.map +1 -0
- package/dist/core/semantic/type-resolution-cases/union-member-index.test.d.ts +2 -0
- package/dist/core/semantic/type-resolution-cases/union-member-index.test.d.ts.map +1 -0
- package/dist/core/semantic/type-resolution-cases/union-member-index.test.js +142 -0
- package/dist/core/semantic/type-resolution-cases/union-member-index.test.js.map +1 -0
- package/dist/core/semantic/type-resolution.d.ts +19 -132
- package/dist/core/semantic/type-resolution.d.ts.map +1 -1
- package/dist/core/semantic/type-resolution.js +19 -785
- package/dist/core/semantic/type-resolution.js.map +1 -1
- package/dist/core/semantic/type-resolution.test.d.ts +10 -4
- package/dist/core/semantic/type-resolution.test.d.ts.map +1 -1
- package/dist/core/semantic/type-resolution.test.js +10 -552
- package/dist/core/semantic/type-resolution.test.js.map +1 -1
- package/dist/core/semantic/type-substitution.d.ts +10 -0
- package/dist/core/semantic/type-substitution.d.ts.map +1 -0
- package/dist/core/semantic/type-substitution.js +167 -0
- package/dist/core/semantic/type-substitution.js.map +1 -0
- package/dist/core/semantic/union-member-matching.d.ts +10 -0
- package/dist/core/semantic/union-member-matching.d.ts.map +1 -0
- package/dist/core/semantic/union-member-matching.js +10 -0
- package/dist/core/semantic/union-member-matching.js.map +1 -0
- package/dist/core/semantic/union-predicate-matching.d.ts +40 -0
- package/dist/core/semantic/union-predicate-matching.d.ts.map +1 -0
- package/dist/core/semantic/union-predicate-matching.js +313 -0
- package/dist/core/semantic/union-predicate-matching.js.map +1 -0
- package/dist/core/semantic/union-semantics.d.ts +39 -0
- package/dist/core/semantic/union-semantics.d.ts.map +1 -0
- package/dist/core/semantic/union-semantics.js +48 -0
- package/dist/core/semantic/union-semantics.js.map +1 -0
- package/dist/core/semantic/union-semantics.test.d.ts +2 -0
- package/dist/core/semantic/union-semantics.test.d.ts.map +1 -0
- package/dist/core/semantic/union-semantics.test.js +109 -0
- package/dist/core/semantic/union-semantics.test.js.map +1 -0
- package/dist/core/semantic/union-typeof-matching.d.ts +13 -0
- package/dist/core/semantic/union-typeof-matching.d.ts.map +1 -0
- package/dist/core/semantic/union-typeof-matching.js +124 -0
- package/dist/core/semantic/union-typeof-matching.js.map +1 -0
- package/dist/core/semantic/unsafe.d.ts.map +1 -1
- package/dist/core/semantic/unsafe.js +23 -15
- package/dist/core/semantic/unsafe.js.map +1 -1
- package/dist/core/semantic/value-slot-types.d.ts +3 -0
- package/dist/core/semantic/value-slot-types.d.ts.map +1 -0
- package/dist/core/semantic/value-slot-types.js +8 -0
- package/dist/core/semantic/value-slot-types.js.map +1 -0
- package/dist/core/semantic/variable-type-resolution.d.ts +68 -0
- package/dist/core/semantic/variable-type-resolution.d.ts.map +1 -0
- package/dist/core/semantic/variable-type-resolution.js +250 -0
- package/dist/core/semantic/variable-type-resolution.js.map +1 -0
- package/dist/duplicate-type-suppression.d.ts +18 -0
- package/dist/duplicate-type-suppression.d.ts.map +1 -0
- package/dist/duplicate-type-suppression.js +249 -0
- package/dist/duplicate-type-suppression.js.map +1 -0
- package/dist/duplicate-type-suppression.test.d.ts +2 -0
- package/dist/duplicate-type-suppression.test.d.ts.map +1 -0
- package/dist/duplicate-type-suppression.test.js +44 -0
- package/dist/duplicate-type-suppression.test.js.map +1 -0
- package/dist/emitter-types/context.d.ts +3 -2
- package/dist/emitter-types/context.d.ts.map +1 -1
- package/dist/emitter-types/context.js +8 -2
- package/dist/emitter-types/context.js.map +1 -1
- package/dist/emitter-types/core.d.ts +122 -7
- package/dist/emitter-types/core.d.ts.map +1 -1
- package/dist/emitter.d.ts +4 -0
- package/dist/emitter.d.ts.map +1 -1
- package/dist/emitter.js +31 -305
- package/dist/emitter.js.map +1 -1
- package/dist/expression-emitter.d.ts.map +1 -1
- package/dist/expression-emitter.js +55 -1411
- package/dist/expression-emitter.js.map +1 -1
- package/dist/expressions/access-binding.d.ts +19 -0
- package/dist/expressions/access-binding.d.ts.map +1 -0
- package/dist/expressions/access-binding.js +286 -0
- package/dist/expressions/access-binding.js.map +1 -0
- package/dist/expressions/access-computed.d.ts +22 -0
- package/dist/expressions/access-computed.d.ts.map +1 -0
- package/dist/expressions/access-computed.js +339 -0
- package/dist/expressions/access-computed.js.map +1 -0
- package/dist/expressions/access-length.d.ts +20 -0
- package/dist/expressions/access-length.d.ts.map +1 -0
- package/dist/expressions/access-length.js +419 -0
- package/dist/expressions/access-length.js.map +1 -0
- package/dist/expressions/access-length.test.d.ts +2 -0
- package/dist/expressions/access-length.test.d.ts.map +1 -0
- package/dist/expressions/access-length.test.js +39 -0
- package/dist/expressions/access-length.test.js.map +1 -0
- package/dist/expressions/access-property.d.ts +23 -0
- package/dist/expressions/access-property.d.ts.map +1 -0
- package/dist/expressions/access-property.js +267 -0
- package/dist/expressions/access-property.js.map +1 -0
- package/dist/expressions/access-resolution-receivers.d.ts +27 -0
- package/dist/expressions/access-resolution-receivers.d.ts.map +1 -0
- package/dist/expressions/access-resolution-receivers.js +358 -0
- package/dist/expressions/access-resolution-receivers.js.map +1 -0
- package/dist/expressions/access-resolution-types.d.ts +29 -0
- package/dist/expressions/access-resolution-types.d.ts.map +1 -0
- package/dist/expressions/access-resolution-types.js +192 -0
- package/dist/expressions/access-resolution-types.js.map +1 -0
- package/dist/expressions/access-resolution.d.ts +10 -0
- package/dist/expressions/access-resolution.d.ts.map +1 -0
- package/dist/expressions/access-resolution.js +10 -0
- package/dist/expressions/access-resolution.js.map +1 -0
- package/dist/expressions/access.d.ts +8 -3
- package/dist/expressions/access.d.ts.map +1 -1
- package/dist/expressions/access.js +169 -603
- package/dist/expressions/access.js.map +1 -1
- package/dist/expressions/architecture-invariants.test.d.ts +2 -0
- package/dist/expressions/architecture-invariants.test.d.ts.map +1 -0
- package/dist/expressions/architecture-invariants.test.js +73 -0
- package/dist/expressions/architecture-invariants.test.js.map +1 -0
- package/dist/expressions/array-interop.d.ts +3 -0
- package/dist/expressions/array-interop.d.ts.map +1 -0
- package/dist/expressions/array-interop.js +14 -0
- package/dist/expressions/array-interop.js.map +1 -0
- package/dist/expressions/array-literal.d.ts +13 -0
- package/dist/expressions/array-literal.d.ts.map +1 -0
- package/dist/expressions/array-literal.js +373 -0
- package/dist/expressions/array-literal.js.map +1 -0
- package/dist/expressions/await-normalization.d.ts +6 -0
- package/dist/expressions/await-normalization.d.ts.map +1 -0
- package/dist/expressions/await-normalization.js +358 -0
- package/dist/expressions/await-normalization.js.map +1 -0
- package/dist/expressions/calls/call-analysis.d.ts +8 -6
- package/dist/expressions/calls/call-analysis.d.ts.map +1 -1
- package/dist/expressions/calls/call-analysis.js +120 -31
- package/dist/expressions/calls/call-analysis.js.map +1 -1
- package/dist/expressions/calls/call-analysis.test.js +2 -2
- package/dist/expressions/calls/call-analysis.test.js.map +1 -1
- package/dist/expressions/calls/call-arguments-emit.d.ts +16 -0
- package/dist/expressions/calls/call-arguments-emit.d.ts.map +1 -0
- package/dist/expressions/calls/call-arguments-emit.js +1818 -0
- package/dist/expressions/calls/call-arguments-emit.js.map +1 -0
- package/dist/expressions/calls/call-arguments-helpers.d.ts +22 -0
- package/dist/expressions/calls/call-arguments-helpers.d.ts.map +1 -0
- package/dist/expressions/calls/call-arguments-helpers.js +333 -0
- package/dist/expressions/calls/call-arguments-helpers.js.map +1 -0
- package/dist/expressions/calls/call-arguments.d.ts +10 -0
- package/dist/expressions/calls/call-arguments.d.ts.map +1 -0
- package/dist/expressions/calls/call-arguments.js +10 -0
- package/dist/expressions/calls/call-arguments.js.map +1 -0
- package/dist/expressions/calls/call-array-interop.d.ts +10 -0
- package/dist/expressions/calls/call-array-interop.d.ts.map +1 -0
- package/dist/expressions/calls/call-array-interop.js +10 -0
- package/dist/expressions/calls/call-array-interop.js.map +1 -0
- package/dist/expressions/calls/call-array-mutation.d.ts +20 -0
- package/dist/expressions/calls/call-array-mutation.d.ts.map +1 -0
- package/dist/expressions/calls/call-array-mutation.js +260 -0
- package/dist/expressions/calls/call-array-mutation.js.map +1 -0
- package/dist/expressions/calls/call-array-wrapper.d.ts +14 -0
- package/dist/expressions/calls/call-array-wrapper.d.ts.map +1 -0
- package/dist/expressions/calls/call-array-wrapper.js +118 -0
- package/dist/expressions/calls/call-array-wrapper.js.map +1 -0
- package/dist/expressions/calls/call-binding-resolution.d.ts +8 -0
- package/dist/expressions/calls/call-binding-resolution.d.ts.map +1 -0
- package/dist/expressions/calls/call-binding-resolution.js +12 -0
- package/dist/expressions/calls/call-binding-resolution.js.map +1 -0
- package/dist/expressions/calls/call-dynamic-import.d.ts +11 -0
- package/dist/expressions/calls/call-dynamic-import.d.ts.map +1 -0
- package/dist/expressions/calls/call-dynamic-import.js +148 -0
- package/dist/expressions/calls/call-dynamic-import.js.map +1 -0
- package/dist/expressions/calls/call-emitter.d.ts +9 -3
- package/dist/expressions/calls/call-emitter.d.ts.map +1 -1
- package/dist/expressions/calls/call-emitter.js +231 -1918
- package/dist/expressions/calls/call-emitter.js.map +1 -1
- package/dist/expressions/calls/call-emitter.test.d.ts +2 -0
- package/dist/expressions/calls/call-emitter.test.d.ts.map +1 -0
- package/dist/expressions/calls/call-emitter.test.js +407 -0
- package/dist/expressions/calls/call-emitter.test.js.map +1 -0
- package/dist/expressions/calls/call-extension-methods.d.ts +17 -0
- package/dist/expressions/calls/call-extension-methods.d.ts.map +1 -0
- package/dist/expressions/calls/call-extension-methods.js +191 -0
- package/dist/expressions/calls/call-extension-methods.js.map +1 -0
- package/dist/expressions/calls/call-json.d.ts +15 -0
- package/dist/expressions/calls/call-json.d.ts.map +1 -0
- package/dist/expressions/calls/call-json.js +212 -0
- package/dist/expressions/calls/call-json.js.map +1 -0
- package/dist/expressions/calls/call-promise-chains.d.ts +7 -0
- package/dist/expressions/calls/call-promise-chains.d.ts.map +1 -0
- package/dist/expressions/calls/call-promise-chains.js +411 -0
- package/dist/expressions/calls/call-promise-chains.js.map +1 -0
- package/dist/expressions/calls/call-promise-ir-types.d.ts +11 -0
- package/dist/expressions/calls/call-promise-ir-types.d.ts.map +1 -0
- package/dist/expressions/calls/call-promise-ir-types.js +219 -0
- package/dist/expressions/calls/call-promise-ir-types.js.map +1 -0
- package/dist/expressions/calls/call-promise-normalization.d.ts +11 -0
- package/dist/expressions/calls/call-promise-normalization.d.ts.map +1 -0
- package/dist/expressions/calls/call-promise-normalization.js +179 -0
- package/dist/expressions/calls/call-promise-normalization.js.map +1 -0
- package/dist/expressions/calls/call-promise-static.d.ts +7 -0
- package/dist/expressions/calls/call-promise-static.d.ts.map +1 -0
- package/dist/expressions/calls/call-promise-static.js +188 -0
- package/dist/expressions/calls/call-promise-static.js.map +1 -0
- package/dist/expressions/calls/call-promise-task-types.d.ts +9 -0
- package/dist/expressions/calls/call-promise-task-types.d.ts.map +1 -0
- package/dist/expressions/calls/call-promise-task-types.js +88 -0
- package/dist/expressions/calls/call-promise-task-types.js.map +1 -0
- package/dist/expressions/calls/call-promise.d.ts +11 -0
- package/dist/expressions/calls/call-promise.d.ts.map +1 -0
- package/dist/expressions/calls/call-promise.js +11 -0
- package/dist/expressions/calls/call-promise.js.map +1 -0
- package/dist/expressions/calls/call-runtime-union-guards.d.ts +7 -0
- package/dist/expressions/calls/call-runtime-union-guards.d.ts.map +1 -0
- package/dist/expressions/calls/call-runtime-union-guards.js +131 -0
- package/dist/expressions/calls/call-runtime-union-guards.js.map +1 -0
- package/dist/expressions/calls/call-symbol.d.ts +7 -0
- package/dist/expressions/calls/call-symbol.d.ts.map +1 -0
- package/dist/expressions/calls/call-symbol.js +26 -0
- package/dist/expressions/calls/call-symbol.js.map +1 -0
- package/dist/expressions/calls/new-emitter-collections.d.ts +31 -0
- package/dist/expressions/calls/new-emitter-collections.d.ts.map +1 -0
- package/dist/expressions/calls/new-emitter-collections.js +310 -0
- package/dist/expressions/calls/new-emitter-collections.js.map +1 -0
- package/dist/expressions/calls/new-emitter-promise.d.ts +10 -0
- package/dist/expressions/calls/new-emitter-promise.d.ts.map +1 -0
- package/dist/expressions/calls/new-emitter-promise.js +437 -0
- package/dist/expressions/calls/new-emitter-promise.js.map +1 -0
- package/dist/expressions/calls/new-emitter.d.ts.map +1 -1
- package/dist/expressions/calls/new-emitter.js +28 -557
- package/dist/expressions/calls/new-emitter.js.map +1 -1
- package/dist/expressions/calls/runtime-expected-type-preference.d.ts +4 -0
- package/dist/expressions/calls/runtime-expected-type-preference.d.ts.map +1 -0
- package/dist/expressions/calls/runtime-expected-type-preference.js +61 -0
- package/dist/expressions/calls/runtime-expected-type-preference.js.map +1 -0
- package/dist/expressions/collections.d.ts +4 -21
- package/dist/expressions/collections.d.ts.map +1 -1
- package/dist/expressions/collections.js +3 -959
- package/dist/expressions/collections.js.map +1 -1
- package/dist/expressions/dictionary-literal.d.ts +20 -0
- package/dist/expressions/dictionary-literal.d.ts.map +1 -0
- package/dist/expressions/dictionary-literal.js +214 -0
- package/dist/expressions/dictionary-literal.js.map +1 -0
- package/dist/expressions/dictionary-safe-access.d.ts +4 -0
- package/dist/expressions/dictionary-safe-access.d.ts.map +1 -0
- package/dist/expressions/dictionary-safe-access.js +86 -0
- package/dist/expressions/dictionary-safe-access.js.map +1 -0
- package/dist/expressions/direct-storage-types.d.ts +10 -0
- package/dist/expressions/direct-storage-types.d.ts.map +1 -0
- package/dist/expressions/direct-storage-types.js +441 -0
- package/dist/expressions/direct-storage-types.js.map +1 -0
- package/dist/expressions/exact-comparison.d.ts +17 -0
- package/dist/expressions/exact-comparison.d.ts.map +1 -0
- package/dist/expressions/exact-comparison.js +240 -0
- package/dist/expressions/exact-comparison.js.map +1 -0
- package/dist/expressions/exact-global-bindings.d.ts +6 -0
- package/dist/expressions/exact-global-bindings.d.ts.map +1 -0
- package/dist/expressions/exact-global-bindings.js +15 -0
- package/dist/expressions/exact-global-bindings.js.map +1 -0
- package/dist/expressions/expected-type-adaptation.d.ts +55 -0
- package/dist/expressions/expected-type-adaptation.d.ts.map +1 -0
- package/dist/expressions/expected-type-adaptation.js +918 -0
- package/dist/expressions/expected-type-adaptation.js.map +1 -0
- package/dist/expressions/expected-type-adaptation.test.d.ts +2 -0
- package/dist/expressions/expected-type-adaptation.test.d.ts.map +1 -0
- package/dist/expressions/expected-type-adaptation.test.js +1363 -0
- package/dist/expressions/expected-type-adaptation.test.js.map +1 -0
- package/dist/expressions/functions.d.ts +6 -15
- package/dist/expressions/functions.d.ts.map +1 -1
- package/dist/expressions/functions.js +6 -213
- package/dist/expressions/functions.js.map +1 -1
- package/dist/expressions/identifier-storage.d.ts +43 -0
- package/dist/expressions/identifier-storage.d.ts.map +1 -0
- package/dist/expressions/identifier-storage.js +478 -0
- package/dist/expressions/identifier-storage.js.map +1 -0
- package/dist/expressions/identifiers.d.ts.map +1 -1
- package/dist/expressions/identifiers.js +126 -11
- package/dist/expressions/identifiers.js.map +1 -1
- package/dist/expressions/index-cases/alias-carrier-widening.test.d.ts +2 -0
- package/dist/expressions/index-cases/alias-carrier-widening.test.d.ts.map +1 -0
- package/dist/expressions/index-cases/alias-carrier-widening.test.js +347 -0
- package/dist/expressions/index-cases/alias-carrier-widening.test.js.map +1 -0
- package/dist/expressions/index-cases/array-wrapper-recursion-b.test.d.ts +2 -0
- package/dist/expressions/index-cases/array-wrapper-recursion-b.test.d.ts.map +1 -0
- package/dist/expressions/index-cases/array-wrapper-recursion-b.test.js +356 -0
- package/dist/expressions/index-cases/array-wrapper-recursion-b.test.js.map +1 -0
- package/dist/expressions/index-cases/array-wrapper-recursion-c.test.d.ts +2 -0
- package/dist/expressions/index-cases/array-wrapper-recursion-c.test.d.ts.map +1 -0
- package/dist/expressions/index-cases/array-wrapper-recursion-c.test.js +233 -0
- package/dist/expressions/index-cases/array-wrapper-recursion-c.test.js.map +1 -0
- package/dist/expressions/index-cases/basic-literals-and-calls.test.d.ts +2 -0
- package/dist/expressions/index-cases/basic-literals-and-calls.test.d.ts.map +1 -0
- package/dist/expressions/index-cases/basic-literals-and-calls.test.js +550 -0
- package/dist/expressions/index-cases/basic-literals-and-calls.test.js.map +1 -0
- package/dist/expressions/index-cases/defaults-and-char-context.test.d.ts +2 -0
- package/dist/expressions/index-cases/defaults-and-char-context.test.d.ts.map +1 -0
- package/dist/expressions/index-cases/defaults-and-char-context.test.js +951 -0
- package/dist/expressions/index-cases/defaults-and-char-context.test.js.map +1 -0
- package/dist/expressions/index-cases/dictionary-and-object-initializers-a.test.d.ts +2 -0
- package/dist/expressions/index-cases/dictionary-and-object-initializers-a.test.d.ts.map +1 -0
- package/dist/expressions/index-cases/dictionary-and-object-initializers-a.test.js +533 -0
- package/dist/expressions/index-cases/dictionary-and-object-initializers-a.test.js.map +1 -0
- package/dist/expressions/index-cases/dictionary-and-object-initializers-b.test.d.ts +2 -0
- package/dist/expressions/index-cases/dictionary-and-object-initializers-b.test.d.ts.map +1 -0
- package/dist/expressions/index-cases/dictionary-and-object-initializers-b.test.js +336 -0
- package/dist/expressions/index-cases/dictionary-and-object-initializers-b.test.js.map +1 -0
- package/dist/expressions/index-cases/fluent-and-ef-operators.test.d.ts +2 -0
- package/dist/expressions/index-cases/fluent-and-ef-operators.test.d.ts.map +1 -0
- package/dist/expressions/index-cases/fluent-and-ef-operators.test.js +352 -0
- package/dist/expressions/index-cases/fluent-and-ef-operators.test.js.map +1 -0
- package/dist/expressions/index-cases/helpers.d.ts +13 -0
- package/dist/expressions/index-cases/helpers.d.ts.map +1 -0
- package/dist/expressions/index-cases/helpers.js +27 -0
- package/dist/expressions/index-cases/helpers.js.map +1 -0
- package/dist/expressions/index-cases/member-access-and-array-wrappers-a.test.d.ts +2 -0
- package/dist/expressions/index-cases/member-access-and-array-wrappers-a.test.d.ts.map +1 -0
- package/dist/expressions/index-cases/member-access-and-array-wrappers-a.test.js +429 -0
- package/dist/expressions/index-cases/member-access-and-array-wrappers-a.test.js.map +1 -0
- package/dist/expressions/index-cases/nullable-and-comparisons.test.d.ts +2 -0
- package/dist/expressions/index-cases/nullable-and-comparisons.test.d.ts.map +1 -0
- package/dist/expressions/index-cases/nullable-and-comparisons.test.js +423 -0
- package/dist/expressions/index-cases/nullable-and-comparisons.test.js.map +1 -0
- package/dist/expressions/index-cases/runtime-subset-and-assertions.test.d.ts +2 -0
- package/dist/expressions/index-cases/runtime-subset-and-assertions.test.d.ts.map +1 -0
- package/dist/expressions/index-cases/runtime-subset-and-assertions.test.js +482 -0
- package/dist/expressions/index-cases/runtime-subset-and-assertions.test.js.map +1 -0
- package/dist/expressions/index-cases/runtime-union-reification-a.test.d.ts +2 -0
- package/dist/expressions/index-cases/runtime-union-reification-a.test.d.ts.map +1 -0
- package/dist/expressions/index-cases/runtime-union-reification-a.test.js +454 -0
- package/dist/expressions/index-cases/runtime-union-reification-a.test.js.map +1 -0
- package/dist/expressions/index-cases/runtime-union-reification-b.test.d.ts +2 -0
- package/dist/expressions/index-cases/runtime-union-reification-b.test.d.ts.map +1 -0
- package/dist/expressions/index-cases/runtime-union-reification-b.test.js +852 -0
- package/dist/expressions/index-cases/runtime-union-reification-b.test.js.map +1 -0
- package/dist/expressions/index-cases/spreads-and-member-bindings.test.d.ts +2 -0
- package/dist/expressions/index-cases/spreads-and-member-bindings.test.d.ts.map +1 -0
- package/dist/expressions/index-cases/spreads-and-member-bindings.test.js +616 -0
- package/dist/expressions/index-cases/spreads-and-member-bindings.test.js.map +1 -0
- package/dist/expressions/index-cases/string-and-array-fallbacks-a.test.d.ts +2 -0
- package/dist/expressions/index-cases/string-and-array-fallbacks-a.test.d.ts.map +1 -0
- package/dist/expressions/index-cases/string-and-array-fallbacks-a.test.js +304 -0
- package/dist/expressions/index-cases/string-and-array-fallbacks-a.test.js.map +1 -0
- package/dist/expressions/index-cases/string-and-array-fallbacks-b.test.d.ts +2 -0
- package/dist/expressions/index-cases/string-and-array-fallbacks-b.test.d.ts.map +1 -0
- package/dist/expressions/index-cases/string-and-array-fallbacks-b.test.js +369 -0
- package/dist/expressions/index-cases/string-and-array-fallbacks-b.test.js.map +1 -0
- package/dist/expressions/index-cases/tuple-rest-and-unions.test.d.ts +2 -0
- package/dist/expressions/index-cases/tuple-rest-and-unions.test.d.ts.map +1 -0
- package/dist/expressions/index-cases/tuple-rest-and-unions.test.js +392 -0
- package/dist/expressions/index-cases/tuple-rest-and-unions.test.js.map +1 -0
- package/dist/expressions/index.test.d.ts +17 -5
- package/dist/expressions/index.test.d.ts.map +1 -1
- package/dist/expressions/index.test.js +17 -2835
- package/dist/expressions/index.test.js.map +1 -1
- package/dist/expressions/invoked-lambda.d.ts +12 -0
- package/dist/expressions/invoked-lambda.d.ts.map +1 -0
- package/dist/expressions/invoked-lambda.js +69 -0
- package/dist/expressions/invoked-lambda.js.map +1 -0
- package/dist/expressions/lambda-body.d.ts +23 -0
- package/dist/expressions/lambda-body.d.ts.map +1 -0
- package/dist/expressions/lambda-body.js +421 -0
- package/dist/expressions/lambda-body.js.map +1 -0
- package/dist/expressions/lambda-parameters.d.ts +32 -0
- package/dist/expressions/lambda-parameters.d.ts.map +1 -0
- package/dist/expressions/lambda-parameters.js +279 -0
- package/dist/expressions/lambda-parameters.js.map +1 -0
- package/dist/expressions/literals.d.ts.map +1 -1
- package/dist/expressions/literals.js +18 -3
- package/dist/expressions/literals.js.map +1 -1
- package/dist/expressions/literals.test.js +48 -0
- package/dist/expressions/literals.test.js.map +1 -1
- package/dist/expressions/object-helpers.d.ts +22 -0
- package/dist/expressions/object-helpers.d.ts.map +1 -0
- package/dist/expressions/object-helpers.js +98 -0
- package/dist/expressions/object-helpers.js.map +1 -0
- package/dist/expressions/object-literal-spreads.d.ts +20 -0
- package/dist/expressions/object-literal-spreads.d.ts.map +1 -0
- package/dist/expressions/object-literal-spreads.js +188 -0
- package/dist/expressions/object-literal-spreads.js.map +1 -0
- package/dist/expressions/object-literal.d.ts +18 -0
- package/dist/expressions/object-literal.d.ts.map +1 -0
- package/dist/expressions/object-literal.js +178 -0
- package/dist/expressions/object-literal.js.map +1 -0
- package/dist/expressions/operators/assignment-emitter.d.ts.map +1 -1
- package/dist/expressions/operators/assignment-emitter.js +78 -27
- package/dist/expressions/operators/assignment-emitter.js.map +1 -1
- package/dist/expressions/operators/binary-dispatch.d.ts +37 -0
- package/dist/expressions/operators/binary-dispatch.d.ts.map +1 -0
- package/dist/expressions/operators/binary-dispatch.js +449 -0
- package/dist/expressions/operators/binary-dispatch.js.map +1 -0
- package/dist/expressions/operators/binary-emitter.d.ts +6 -29
- package/dist/expressions/operators/binary-emitter.d.ts.map +1 -1
- package/dist/expressions/operators/binary-emitter.js +6 -419
- package/dist/expressions/operators/binary-emitter.js.map +1 -1
- package/dist/expressions/operators/binary-helpers.d.ts +17 -0
- package/dist/expressions/operators/binary-helpers.d.ts.map +1 -0
- package/dist/expressions/operators/binary-helpers.js +119 -0
- package/dist/expressions/operators/binary-helpers.js.map +1 -0
- package/dist/expressions/operators/binary-runtime-union-comparison.d.ts +7 -0
- package/dist/expressions/operators/binary-runtime-union-comparison.d.ts.map +1 -0
- package/dist/expressions/operators/binary-runtime-union-comparison.js +150 -0
- package/dist/expressions/operators/binary-runtime-union-comparison.js.map +1 -0
- package/dist/expressions/operators/binary-special-ops.d.ts +29 -0
- package/dist/expressions/operators/binary-special-ops.d.ts.map +1 -0
- package/dist/expressions/operators/binary-special-ops.js +468 -0
- package/dist/expressions/operators/binary-special-ops.js.map +1 -0
- package/dist/expressions/operators/conditional-emitter.d.ts.map +1 -1
- package/dist/expressions/operators/conditional-emitter.js +221 -216
- package/dist/expressions/operators/conditional-emitter.js.map +1 -1
- package/dist/expressions/operators/helpers.d.ts +10 -0
- package/dist/expressions/operators/helpers.d.ts.map +1 -1
- package/dist/expressions/operators/helpers.js +30 -0
- package/dist/expressions/operators/helpers.js.map +1 -1
- package/dist/expressions/operators/logical-emitter.d.ts +2 -2
- package/dist/expressions/operators/logical-emitter.d.ts.map +1 -1
- package/dist/expressions/operators/logical-emitter.js +293 -10
- package/dist/expressions/operators/logical-emitter.js.map +1 -1
- package/dist/expressions/operators/unary-emitter.d.ts.map +1 -1
- package/dist/expressions/operators/unary-emitter.js +6 -21
- package/dist/expressions/operators/unary-emitter.js.map +1 -1
- package/dist/expressions/operators/write-targets.d.ts +5 -0
- package/dist/expressions/operators/write-targets.d.ts.map +1 -0
- package/dist/expressions/operators/write-targets.js +65 -0
- package/dist/expressions/operators/write-targets.js.map +1 -0
- package/dist/expressions/other.d.ts.map +1 -1
- package/dist/expressions/other.js +17 -50
- package/dist/expressions/other.js.map +1 -1
- package/dist/expressions/post-emission-adaptation.d.ts +19 -0
- package/dist/expressions/post-emission-adaptation.d.ts.map +1 -0
- package/dist/expressions/post-emission-adaptation.js +939 -0
- package/dist/expressions/post-emission-adaptation.js.map +1 -0
- package/dist/expressions/runtime-union-adaptation-projection.d.ts +12 -0
- package/dist/expressions/runtime-union-adaptation-projection.d.ts.map +1 -0
- package/dist/expressions/runtime-union-adaptation-projection.js +182 -0
- package/dist/expressions/runtime-union-adaptation-projection.js.map +1 -0
- package/dist/expressions/runtime-union-adaptation-upcast.d.ts +11 -0
- package/dist/expressions/runtime-union-adaptation-upcast.d.ts.map +1 -0
- package/dist/expressions/runtime-union-adaptation-upcast.js +722 -0
- package/dist/expressions/runtime-union-adaptation-upcast.js.map +1 -0
- package/dist/expressions/runtime-union-adaptation.d.ts +10 -0
- package/dist/expressions/runtime-union-adaptation.d.ts.map +1 -0
- package/dist/expressions/runtime-union-adaptation.js +10 -0
- package/dist/expressions/runtime-union-adaptation.js.map +1 -0
- package/dist/expressions/structural-adaptation-types.d.ts +12 -0
- package/dist/expressions/structural-adaptation-types.d.ts.map +1 -0
- package/dist/expressions/structural-adaptation-types.js +3 -0
- package/dist/expressions/structural-adaptation-types.js.map +1 -0
- package/dist/expressions/structural-adaptation.d.ts +16 -0
- package/dist/expressions/structural-adaptation.d.ts.map +1 -0
- package/dist/expressions/structural-adaptation.js +14 -0
- package/dist/expressions/structural-adaptation.js.map +1 -0
- package/dist/expressions/structural-anonymous-targets.d.ts +4 -0
- package/dist/expressions/structural-anonymous-targets.d.ts.map +1 -0
- package/dist/expressions/structural-anonymous-targets.js +156 -0
- package/dist/expressions/structural-anonymous-targets.js.map +1 -0
- package/dist/expressions/structural-collection-adaptation.d.ts +7 -0
- package/dist/expressions/structural-collection-adaptation.d.ts.map +1 -0
- package/dist/expressions/structural-collection-adaptation.js +682 -0
- package/dist/expressions/structural-collection-adaptation.js.map +1 -0
- package/dist/expressions/structural-object-adaptation.d.ts +6 -0
- package/dist/expressions/structural-object-adaptation.d.ts.map +1 -0
- package/dist/expressions/structural-object-adaptation.js +213 -0
- package/dist/expressions/structural-object-adaptation.js.map +1 -0
- package/dist/expressions/structural-property-model.d.ts +6 -0
- package/dist/expressions/structural-property-model.d.ts.map +1 -0
- package/dist/expressions/structural-property-model.js +304 -0
- package/dist/expressions/structural-property-model.js.map +1 -0
- package/dist/expressions/structural-type-shapes.d.ts +19 -0
- package/dist/expressions/structural-type-shapes.d.ts.map +1 -0
- package/dist/expressions/structural-type-shapes.js +318 -0
- package/dist/expressions/structural-type-shapes.js.map +1 -0
- package/dist/expressions/structural-type-shapes.test.d.ts +2 -0
- package/dist/expressions/structural-type-shapes.test.d.ts.map +1 -0
- package/dist/expressions/structural-type-shapes.test.js +60 -0
- package/dist/expressions/structural-type-shapes.test.js.map +1 -0
- package/dist/expressions/type-assertion-emitters.d.ts +50 -0
- package/dist/expressions/type-assertion-emitters.d.ts.map +1 -0
- package/dist/expressions/type-assertion-emitters.js +675 -0
- package/dist/expressions/type-assertion-emitters.js.map +1 -0
- package/dist/fixture-regression-mirrors.test.d.ts +2 -0
- package/dist/fixture-regression-mirrors.test.d.ts.map +1 -0
- package/dist/fixture-regression-mirrors.test.js +580 -0
- package/dist/fixture-regression-mirrors.test.js.map +1 -0
- package/dist/generated-files.d.ts +19 -0
- package/dist/generated-files.d.ts.map +1 -0
- package/dist/generated-files.js +519 -0
- package/dist/generated-files.js.map +1 -0
- package/dist/generated-files.test.d.ts +2 -0
- package/dist/generated-files.test.d.ts.map +1 -0
- package/dist/generated-files.test.js +103 -0
- package/dist/generated-files.test.js.map +1 -0
- package/dist/generator-cases/bidirectional-core.test.d.ts +6 -0
- package/dist/generator-cases/bidirectional-core.test.d.ts.map +1 -0
- package/dist/generator-cases/bidirectional-core.test.js +272 -0
- package/dist/generator-cases/bidirectional-core.test.js.map +1 -0
- package/dist/generator-cases/bidirectional-features.test.d.ts +6 -0
- package/dist/generator-cases/bidirectional-features.test.d.ts.map +1 -0
- package/dist/generator-cases/bidirectional-features.test.js +360 -0
- package/dist/generator-cases/bidirectional-features.test.js.map +1 -0
- package/dist/generator-cases/simple-generators.test.d.ts +6 -0
- package/dist/generator-cases/simple-generators.test.d.ts.map +1 -0
- package/dist/generator-cases/simple-generators.test.js +227 -0
- package/dist/generator-cases/simple-generators.test.js.map +1 -0
- package/dist/generator-exchange.d.ts +3 -2
- package/dist/generator-exchange.d.ts.map +1 -1
- package/dist/generator-exchange.js +46 -15
- package/dist/generator-exchange.js.map +1 -1
- package/dist/generator-wrapper-builders.d.ts +10 -0
- package/dist/generator-wrapper-builders.d.ts.map +1 -0
- package/dist/generator-wrapper-builders.js +288 -0
- package/dist/generator-wrapper-builders.js.map +1 -0
- package/dist/generator-wrapper.d.ts +16 -5
- package/dist/generator-wrapper.d.ts.map +1 -1
- package/dist/generator-wrapper.js +47 -288
- package/dist/generator-wrapper.js.map +1 -1
- package/dist/generator.test.d.ts +3 -5
- package/dist/generator.test.d.ts.map +1 -1
- package/dist/generator.test.js +3 -766
- package/dist/generator.test.js.map +1 -1
- package/dist/golden-tests/config-parser.d.ts.map +1 -1
- package/dist/golden-tests/config-parser.js +7 -0
- package/dist/golden-tests/config-parser.js.map +1 -1
- package/dist/golden-tests/discovery.js +1 -0
- package/dist/golden-tests/discovery.js.map +1 -1
- package/dist/golden-tests/runner.d.ts.map +1 -1
- package/dist/golden-tests/runner.js +12 -40
- package/dist/golden-tests/runner.js.map +1 -1
- package/dist/golden-tests/types.d.ts +2 -0
- package/dist/golden-tests/types.d.ts.map +1 -1
- package/dist/hierarchical-bindings.test.js +6 -9
- package/dist/hierarchical-bindings.test.js.map +1 -1
- package/dist/integration-cases/arrow-and-generics-a.test.d.ts +2 -0
- package/dist/integration-cases/arrow-and-generics-a.test.d.ts.map +1 -0
- package/dist/integration-cases/arrow-and-generics-a.test.js +695 -0
- package/dist/integration-cases/arrow-and-generics-a.test.js.map +1 -0
- package/dist/integration-cases/arrow-and-generics-b.test.d.ts +2 -0
- package/dist/integration-cases/arrow-and-generics-b.test.d.ts.map +1 -0
- package/dist/integration-cases/arrow-and-generics-b.test.js +218 -0
- package/dist/integration-cases/arrow-and-generics-b.test.js.map +1 -0
- package/dist/integration-cases/await-and-intrinsics.test.d.ts +2 -0
- package/dist/integration-cases/await-and-intrinsics.test.d.ts.map +1 -0
- package/dist/integration-cases/await-and-intrinsics.test.js +237 -0
- package/dist/integration-cases/await-and-intrinsics.test.js.map +1 -0
- package/dist/integration-cases/clr-iterable-overloads.test.d.ts +2 -0
- package/dist/integration-cases/clr-iterable-overloads.test.d.ts.map +1 -0
- package/dist/integration-cases/clr-iterable-overloads.test.js +446 -0
- package/dist/integration-cases/clr-iterable-overloads.test.js.map +1 -0
- package/dist/integration-cases/full-module-and-promises.test.d.ts +2 -0
- package/dist/integration-cases/full-module-and-promises.test.d.ts.map +1 -0
- package/dist/integration-cases/full-module-and-promises.test.js +472 -0
- package/dist/integration-cases/full-module-and-promises.test.js.map +1 -0
- package/dist/integration-cases/helpers.d.ts +7 -0
- package/dist/integration-cases/helpers.d.ts.map +1 -0
- package/dist/integration-cases/helpers.js +348 -0
- package/dist/integration-cases/helpers.js.map +1 -0
- package/dist/integration-cases/object-literals-and-channels.test.d.ts +2 -0
- package/dist/integration-cases/object-literals-and-channels.test.d.ts.map +1 -0
- package/dist/integration-cases/object-literals-and-channels.test.js +72 -0
- package/dist/integration-cases/object-literals-and-channels.test.js.map +1 -0
- package/dist/integration-cases/regression-coverage-a.test.d.ts +2 -0
- package/dist/integration-cases/regression-coverage-a.test.d.ts.map +1 -0
- package/dist/integration-cases/regression-coverage-a.test.js +533 -0
- package/dist/integration-cases/regression-coverage-a.test.js.map +1 -0
- package/dist/integration-cases/regression-coverage-b.test.d.ts +2 -0
- package/dist/integration-cases/regression-coverage-b.test.d.ts.map +1 -0
- package/dist/integration-cases/regression-coverage-b.test.js +806 -0
- package/dist/integration-cases/regression-coverage-b.test.js.map +1 -0
- package/dist/integration-cases/regression-coverage-c.test.d.ts +2 -0
- package/dist/integration-cases/regression-coverage-c.test.d.ts.map +1 -0
- package/dist/integration-cases/regression-coverage-c.test.js +4139 -0
- package/dist/integration-cases/regression-coverage-c.test.js.map +1 -0
- package/dist/integration.test.d.ts +9 -5
- package/dist/integration.test.d.ts.map +1 -1
- package/dist/integration.test.js +9 -1223
- package/dist/integration.test.js.map +1 -1
- package/dist/invariants/numeric-proof-contract-cases/emitter-and-annotations.test.d.ts +5 -0
- package/dist/invariants/numeric-proof-contract-cases/emitter-and-annotations.test.d.ts.map +1 -0
- package/dist/invariants/numeric-proof-contract-cases/emitter-and-annotations.test.js +93 -0
- package/dist/invariants/numeric-proof-contract-cases/emitter-and-annotations.test.js.map +1 -0
- package/dist/invariants/numeric-proof-contract-cases/helpers.d.ts +14 -0
- package/dist/invariants/numeric-proof-contract-cases/helpers.d.ts.map +1 -0
- package/dist/invariants/numeric-proof-contract-cases/helpers.js +158 -0
- package/dist/invariants/numeric-proof-contract-cases/helpers.js.map +1 -0
- package/dist/invariants/numeric-proof-contract-cases/proof-and-diagnostics.test.d.ts +5 -0
- package/dist/invariants/numeric-proof-contract-cases/proof-and-diagnostics.test.d.ts.map +1 -0
- package/dist/invariants/numeric-proof-contract-cases/proof-and-diagnostics.test.js +242 -0
- package/dist/invariants/numeric-proof-contract-cases/proof-and-diagnostics.test.js.map +1 -0
- package/dist/invariants/numeric-proof-contract.test.d.ts +2 -18
- package/dist/invariants/numeric-proof-contract.test.d.ts.map +1 -1
- package/dist/invariants/numeric-proof-contract.test.js +2 -510
- package/dist/invariants/numeric-proof-contract.test.js.map +1 -1
- package/dist/json-aot-generic.test.js +320 -5
- package/dist/json-aot-generic.test.js.map +1 -1
- package/dist/naming-policy.d.ts.map +1 -1
- package/dist/naming-policy.js +19 -0
- package/dist/naming-policy.js.map +1 -1
- package/dist/patterns/local-lowering.d.ts +27 -0
- package/dist/patterns/local-lowering.d.ts.map +1 -0
- package/dist/patterns/local-lowering.js +296 -0
- package/dist/patterns/local-lowering.js.map +1 -0
- package/dist/patterns/static-assignment-lowering.d.ts +11 -0
- package/dist/patterns/static-assignment-lowering.d.ts.map +1 -0
- package/dist/patterns/static-assignment-lowering.js +11 -0
- package/dist/patterns/static-assignment-lowering.js.map +1 -0
- package/dist/patterns/static-lowering-assignments.d.ts +16 -0
- package/dist/patterns/static-lowering-assignments.d.ts.map +1 -0
- package/dist/patterns/static-lowering-assignments.js +269 -0
- package/dist/patterns/static-lowering-assignments.js.map +1 -0
- package/dist/patterns/static-lowering-members.d.ts +15 -0
- package/dist/patterns/static-lowering-members.d.ts.map +1 -0
- package/dist/patterns/static-lowering-members.js +231 -0
- package/dist/patterns/static-lowering-members.js.map +1 -0
- package/dist/patterns-cases/array-and-object.test.d.ts +2 -0
- package/dist/patterns-cases/array-and-object.test.d.ts.map +1 -0
- package/dist/patterns-cases/array-and-object.test.js +370 -0
- package/dist/patterns-cases/array-and-object.test.js.map +1 -0
- package/dist/patterns-cases/assignments-and-complex.test.d.ts +2 -0
- package/dist/patterns-cases/assignments-and-complex.test.d.ts.map +1 -0
- package/dist/patterns-cases/assignments-and-complex.test.js +361 -0
- package/dist/patterns-cases/assignments-and-complex.test.js.map +1 -0
- package/dist/patterns-cases/edge-cases.test.d.ts +2 -0
- package/dist/patterns-cases/edge-cases.test.d.ts.map +1 -0
- package/dist/patterns-cases/edge-cases.test.js +133 -0
- package/dist/patterns-cases/edge-cases.test.js.map +1 -0
- package/dist/patterns-cases/helpers.d.ts +6 -0
- package/dist/patterns-cases/helpers.d.ts.map +1 -0
- package/dist/patterns-cases/helpers.js +33 -0
- package/dist/patterns-cases/helpers.js.map +1 -0
- package/dist/patterns-cases/loops-and-parameters.test.d.ts +2 -0
- package/dist/patterns-cases/loops-and-parameters.test.d.ts.map +1 -0
- package/dist/patterns-cases/loops-and-parameters.test.js +275 -0
- package/dist/patterns-cases/loops-and-parameters.test.js.map +1 -0
- package/dist/patterns-cases/methods-and-semantic-infra.test.d.ts +2 -0
- package/dist/patterns-cases/methods-and-semantic-infra.test.d.ts.map +1 -0
- package/dist/patterns-cases/methods-and-semantic-infra.test.js +438 -0
- package/dist/patterns-cases/methods-and-semantic-infra.test.js.map +1 -0
- package/dist/patterns.d.ts +5 -20
- package/dist/patterns.d.ts.map +1 -1
- package/dist/patterns.js +3 -809
- package/dist/patterns.js.map +1 -1
- package/dist/patterns.test.d.ts +5 -14
- package/dist/patterns.test.d.ts.map +1 -1
- package/dist/patterns.test.js +5 -1341
- package/dist/patterns.test.js.map +1 -1
- package/dist/runtime-union-cases/helpers.d.ts +7 -0
- package/dist/runtime-union-cases/helpers.d.ts.map +1 -0
- package/dist/runtime-union-cases/helpers.js +17 -0
- package/dist/runtime-union-cases/helpers.js.map +1 -0
- package/dist/specialization/generic-functions-cases/basics-and-structural.test.d.ts +6 -0
- package/dist/specialization/generic-functions-cases/basics-and-structural.test.d.ts.map +1 -0
- package/dist/specialization/generic-functions-cases/basics-and-structural.test.js +357 -0
- package/dist/specialization/generic-functions-cases/basics-and-structural.test.js.map +1 -0
- package/dist/specialization/generic-functions-cases/class-and-interface-constraints.test.d.ts +6 -0
- package/dist/specialization/generic-functions-cases/class-and-interface-constraints.test.d.ts.map +1 -0
- package/dist/specialization/generic-functions-cases/class-and-interface-constraints.test.js +304 -0
- package/dist/specialization/generic-functions-cases/class-and-interface-constraints.test.js.map +1 -0
- package/dist/specialization/generic-functions.test.d.ts +2 -5
- package/dist/specialization/generic-functions.test.d.ts.map +1 -1
- package/dist/specialization/generic-functions.test.js +2 -650
- package/dist/specialization/generic-functions.test.js.map +1 -1
- package/dist/specialization/helpers.d.ts.map +1 -1
- package/dist/specialization/helpers.js +2 -16
- package/dist/specialization/helpers.js.map +1 -1
- package/dist/specialization/interfaces.test.js +58 -0
- package/dist/specialization/interfaces.test.js.map +1 -1
- package/dist/specialization/naming.d.ts.map +1 -1
- package/dist/specialization/naming.js +9 -2
- package/dist/specialization/naming.js.map +1 -1
- package/dist/statements/block-emitters/block-and-return.d.ts +10 -0
- package/dist/statements/block-emitters/block-and-return.d.ts.map +1 -0
- package/dist/statements/block-emitters/block-and-return.js +132 -0
- package/dist/statements/block-emitters/block-and-return.js.map +1 -0
- package/dist/statements/block-emitters/expression-statements.d.ts +7 -0
- package/dist/statements/block-emitters/expression-statements.d.ts.map +1 -0
- package/dist/statements/block-emitters/expression-statements.js +72 -0
- package/dist/statements/block-emitters/expression-statements.js.map +1 -0
- package/dist/statements/block-emitters/yield-statements.d.ts +13 -0
- package/dist/statements/block-emitters/yield-statements.d.ts.map +1 -0
- package/dist/statements/block-emitters/yield-statements.js +217 -0
- package/dist/statements/block-emitters/yield-statements.js.map +1 -0
- package/dist/statements/blocks.d.ts +3 -86
- package/dist/statements/blocks.d.ts.map +1 -1
- package/dist/statements/blocks.js +3 -443
- package/dist/statements/blocks.js.map +1 -1
- package/dist/statements/classes/members/constructors.d.ts.map +1 -1
- package/dist/statements/classes/members/constructors.js +105 -13
- package/dist/statements/classes/members/constructors.js.map +1 -1
- package/dist/statements/classes/members/methods.d.ts +1 -1
- package/dist/statements/classes/members/methods.d.ts.map +1 -1
- package/dist/statements/classes/members/methods.js +329 -76
- package/dist/statements/classes/members/methods.js.map +1 -1
- package/dist/statements/classes/members/orchestrator.d.ts +3 -3
- package/dist/statements/classes/members/orchestrator.d.ts.map +1 -1
- package/dist/statements/classes/members/orchestrator.js +10 -4
- package/dist/statements/classes/members/orchestrator.js.map +1 -1
- package/dist/statements/classes/members/properties.d.ts.map +1 -1
- package/dist/statements/classes/members/properties.js +29 -5
- package/dist/statements/classes/members/properties.js.map +1 -1
- package/dist/statements/classes/members/shadowing.test.js +3 -2
- package/dist/statements/classes/members/shadowing.test.js.map +1 -1
- package/dist/statements/classes/parameters.d.ts +9 -1
- package/dist/statements/classes/parameters.d.ts.map +1 -1
- package/dist/statements/classes/parameters.js +86 -6
- package/dist/statements/classes/parameters.js.map +1 -1
- package/dist/statements/classes/properties.d.ts.map +1 -1
- package/dist/statements/classes/properties.js +2 -1
- package/dist/statements/classes/properties.js.map +1 -1
- package/dist/statements/control/conditionals/branch-context.d.ts +58 -0
- package/dist/statements/control/conditionals/branch-context.d.ts.map +1 -0
- package/dist/statements/control/conditionals/branch-context.js +530 -0
- package/dist/statements/control/conditionals/branch-context.js.map +1 -0
- package/dist/statements/control/conditionals/branch-context.test.d.ts +2 -0
- package/dist/statements/control/conditionals/branch-context.test.d.ts.map +1 -0
- package/dist/statements/control/conditionals/branch-context.test.js +34 -0
- package/dist/statements/control/conditionals/branch-context.test.js.map +1 -0
- package/dist/statements/control/conditionals/guard-analysis.d.ts +8 -208
- package/dist/statements/control/conditionals/guard-analysis.d.ts.map +1 -1
- package/dist/statements/control/conditionals/guard-analysis.js +8 -763
- package/dist/statements/control/conditionals/guard-analysis.js.map +1 -1
- package/dist/statements/control/conditionals/guard-detectors-discriminant.d.ts +20 -0
- package/dist/statements/control/conditionals/guard-detectors-discriminant.d.ts.map +1 -0
- package/dist/statements/control/conditionals/guard-detectors-discriminant.js +214 -0
- package/dist/statements/control/conditionals/guard-detectors-discriminant.js.map +1 -0
- package/dist/statements/control/conditionals/guard-detectors-structural.d.ts +32 -0
- package/dist/statements/control/conditionals/guard-detectors-structural.d.ts.map +1 -0
- package/dist/statements/control/conditionals/guard-detectors-structural.js +302 -0
- package/dist/statements/control/conditionals/guard-detectors-structural.js.map +1 -0
- package/dist/statements/control/conditionals/guard-detectors.d.ts +11 -0
- package/dist/statements/control/conditionals/guard-detectors.d.ts.map +1 -0
- package/dist/statements/control/conditionals/guard-detectors.js +11 -0
- package/dist/statements/control/conditionals/guard-detectors.js.map +1 -0
- package/dist/statements/control/conditionals/guard-extraction.d.ts +30 -0
- package/dist/statements/control/conditionals/guard-extraction.d.ts.map +1 -0
- package/dist/statements/control/conditionals/guard-extraction.js +304 -0
- package/dist/statements/control/conditionals/guard-extraction.js.map +1 -0
- package/dist/statements/control/conditionals/guard-types.d.ts +214 -0
- package/dist/statements/control/conditionals/guard-types.d.ts.map +1 -0
- package/dist/statements/control/conditionals/guard-types.js +242 -0
- package/dist/statements/control/conditionals/guard-types.js.map +1 -0
- package/dist/statements/control/conditionals/if-emit-instanceof-guards.d.ts +28 -0
- package/dist/statements/control/conditionals/if-emit-instanceof-guards.d.ts.map +1 -0
- package/dist/statements/control/conditionals/if-emit-instanceof-guards.js +261 -0
- package/dist/statements/control/conditionals/if-emit-instanceof-guards.js.map +1 -0
- package/dist/statements/control/conditionals/if-emit-predicate-guards.d.ts +24 -0
- package/dist/statements/control/conditionals/if-emit-predicate-guards.d.ts.map +1 -0
- package/dist/statements/control/conditionals/if-emit-predicate-guards.js +165 -0
- package/dist/statements/control/conditionals/if-emit-predicate-guards.js.map +1 -0
- package/dist/statements/control/conditionals/if-emit-property-discriminant-guards.d.ts +24 -0
- package/dist/statements/control/conditionals/if-emit-property-discriminant-guards.d.ts.map +1 -0
- package/dist/statements/control/conditionals/if-emit-property-discriminant-guards.js +391 -0
- package/dist/statements/control/conditionals/if-emit-property-discriminant-guards.js.map +1 -0
- package/dist/statements/control/conditionals/if-emit-type-guards.d.ts +10 -0
- package/dist/statements/control/conditionals/if-emit-type-guards.d.ts.map +1 -0
- package/dist/statements/control/conditionals/if-emit-type-guards.js +10 -0
- package/dist/statements/control/conditionals/if-emit-type-guards.js.map +1 -0
- package/dist/statements/control/conditionals/if-emit-typeof-array-guards.d.ts +23 -0
- package/dist/statements/control/conditionals/if-emit-typeof-array-guards.d.ts.map +1 -0
- package/dist/statements/control/conditionals/if-emit-typeof-array-guards.js +264 -0
- package/dist/statements/control/conditionals/if-emit-typeof-array-guards.js.map +1 -0
- package/dist/statements/control/conditionals/if-emit-union-guards.d.ts +10 -0
- package/dist/statements/control/conditionals/if-emit-union-guards.d.ts.map +1 -0
- package/dist/statements/control/conditionals/if-emit-union-guards.js +10 -0
- package/dist/statements/control/conditionals/if-emit-union-guards.js.map +1 -0
- package/dist/statements/control/conditionals/if-emitter.d.ts +6 -3
- package/dist/statements/control/conditionals/if-emitter.d.ts.map +1 -1
- package/dist/statements/control/conditionals/if-emitter.js +99 -916
- package/dist/statements/control/conditionals/if-emitter.js.map +1 -1
- package/dist/statements/control/exceptions.d.ts.map +1 -1
- package/dist/statements/control/exceptions.js +19 -2
- package/dist/statements/control/exceptions.js.map +1 -1
- package/dist/statements/control/loop-helpers.d.ts +13 -0
- package/dist/statements/control/loop-helpers.d.ts.map +1 -0
- package/dist/statements/control/loop-helpers.js +75 -0
- package/dist/statements/control/loop-helpers.js.map +1 -0
- package/dist/statements/control/loops.d.ts.map +1 -1
- package/dist/statements/control/loops.js +85 -169
- package/dist/statements/control/loops.js.map +1 -1
- package/dist/statements/declarations/class-emitter-helpers.d.ts +17 -0
- package/dist/statements/declarations/class-emitter-helpers.d.ts.map +1 -0
- package/dist/statements/declarations/class-emitter-helpers.js +126 -0
- package/dist/statements/declarations/class-emitter-helpers.js.map +1 -0
- package/dist/statements/declarations/classes.d.ts.map +1 -1
- package/dist/statements/declarations/classes.js +102 -27
- package/dist/statements/declarations/classes.js.map +1 -1
- package/dist/statements/declarations/function-local-emitter.d.ts +7 -0
- package/dist/statements/declarations/function-local-emitter.d.ts.map +1 -0
- package/dist/statements/declarations/function-local-emitter.js +363 -0
- package/dist/statements/declarations/function-local-emitter.js.map +1 -0
- package/dist/statements/declarations/function-module-emitter.d.ts +7 -0
- package/dist/statements/declarations/function-module-emitter.d.ts.map +1 -0
- package/dist/statements/declarations/function-module-emitter.js +372 -0
- package/dist/statements/declarations/function-module-emitter.js.map +1 -0
- package/dist/statements/declarations/function-shared.d.ts +43 -0
- package/dist/statements/declarations/function-shared.d.ts.map +1 -0
- package/dist/statements/declarations/function-shared.js +246 -0
- package/dist/statements/declarations/function-shared.js.map +1 -0
- package/dist/statements/declarations/functions.d.ts +2 -27
- package/dist/statements/declarations/functions.d.ts.map +1 -1
- package/dist/statements/declarations/functions.js +2 -709
- package/dist/statements/declarations/functions.js.map +1 -1
- package/dist/statements/declarations/interfaces.d.ts.map +1 -1
- package/dist/statements/declarations/interfaces.js +25 -9
- package/dist/statements/declarations/interfaces.js.map +1 -1
- package/dist/statements/declarations/type-aliases.d.ts.map +1 -1
- package/dist/statements/declarations/type-aliases.js +3 -4
- package/dist/statements/declarations/type-aliases.js.map +1 -1
- package/dist/statements/declarations/variable-local-type.d.ts +36 -0
- package/dist/statements/declarations/variable-local-type.d.ts.map +1 -0
- package/dist/statements/declarations/variable-local-type.js +122 -0
- package/dist/statements/declarations/variable-local-type.js.map +1 -0
- package/dist/statements/declarations/variable-static-arrow.d.ts +47 -0
- package/dist/statements/declarations/variable-static-arrow.d.ts.map +1 -0
- package/dist/statements/declarations/variable-static-arrow.js +363 -0
- package/dist/statements/declarations/variable-static-arrow.js.map +1 -0
- package/dist/statements/declarations/variable-type-helpers.d.ts +86 -0
- package/dist/statements/declarations/variable-type-helpers.d.ts.map +1 -0
- package/dist/statements/declarations/variable-type-helpers.js +242 -0
- package/dist/statements/declarations/variable-type-helpers.js.map +1 -0
- package/dist/statements/declarations/variable-type-resolution.d.ts +11 -0
- package/dist/statements/declarations/variable-type-resolution.d.ts.map +1 -0
- package/dist/statements/declarations/variable-type-resolution.js +11 -0
- package/dist/statements/declarations/variable-type-resolution.js.map +1 -0
- package/dist/statements/declarations/variables.d.ts +5 -1
- package/dist/statements/declarations/variables.d.ts.map +1 -1
- package/dist/statements/declarations/variables.js +116 -596
- package/dist/statements/declarations/variables.js.map +1 -1
- package/dist/statements/index.test.d.ts +10 -5
- package/dist/statements/index.test.d.ts.map +1 -1
- package/dist/statements/index.test.js +10 -1969
- package/dist/statements/index.test.js.map +1 -1
- package/dist/statements/parameter-defaults.d.ts +17 -0
- package/dist/statements/parameter-defaults.d.ts.map +1 -0
- package/dist/statements/parameter-defaults.js +122 -0
- package/dist/statements/parameter-defaults.js.map +1 -0
- package/dist/statements/statement-cases/async-returns.test.d.ts +2 -0
- package/dist/statements/statement-cases/async-returns.test.d.ts.map +1 -0
- package/dist/statements/statement-cases/async-returns.test.js +311 -0
- package/dist/statements/statement-cases/async-returns.test.js.map +1 -0
- package/dist/statements/statement-cases/flow-and-void.test.d.ts +2 -0
- package/dist/statements/statement-cases/flow-and-void.test.d.ts.map +1 -0
- package/dist/statements/statement-cases/flow-and-void.test.js +405 -0
- package/dist/statements/statement-cases/flow-and-void.test.js.map +1 -0
- package/dist/statements/statement-cases/helpers.d.ts +6 -0
- package/dist/statements/statement-cases/helpers.d.ts.map +1 -0
- package/dist/statements/statement-cases/helpers.js +4 -0
- package/dist/statements/statement-cases/helpers.js.map +1 -0
- package/dist/statements/statement-cases/if-and-instanceof-guards.test.d.ts +2 -0
- package/dist/statements/statement-cases/if-and-instanceof-guards.test.d.ts.map +1 -0
- package/dist/statements/statement-cases/if-and-instanceof-guards.test.js +826 -0
- package/dist/statements/statement-cases/if-and-instanceof-guards.test.js.map +1 -0
- package/dist/statements/statement-cases/loops.test.d.ts +2 -0
- package/dist/statements/statement-cases/loops.test.d.ts.map +1 -0
- package/dist/statements/statement-cases/loops.test.js +433 -0
- package/dist/statements/statement-cases/loops.test.js.map +1 -0
- package/dist/statements/statement-cases/scopes-and-storage.test.d.ts +2 -0
- package/dist/statements/statement-cases/scopes-and-storage.test.d.ts.map +1 -0
- package/dist/statements/statement-cases/scopes-and-storage.test.js +216 -0
- package/dist/statements/statement-cases/scopes-and-storage.test.js.map +1 -0
- package/dist/statements/statement-cases/union-guards-basic.test.d.ts +2 -0
- package/dist/statements/statement-cases/union-guards-basic.test.d.ts.map +1 -0
- package/dist/statements/statement-cases/union-guards-basic.test.js +235 -0
- package/dist/statements/statement-cases/union-guards-basic.test.js.map +1 -0
- package/dist/statements/statement-cases/union-guards-nullish-and-object.test.d.ts +2 -0
- package/dist/statements/statement-cases/union-guards-nullish-and-object.test.d.ts.map +1 -0
- package/dist/statements/statement-cases/union-guards-nullish-and-object.test.js +265 -0
- package/dist/statements/statement-cases/union-guards-nullish-and-object.test.js.map +1 -0
- package/dist/statements/statement-cases/union-guards-predicate-and-truthy.test.d.ts +2 -0
- package/dist/statements/statement-cases/union-guards-predicate-and-truthy.test.d.ts.map +1 -0
- package/dist/statements/statement-cases/union-guards-predicate-and-truthy.test.js +630 -0
- package/dist/statements/statement-cases/union-guards-predicate-and-truthy.test.js.map +1 -0
- package/dist/statements/statement-cases/union-guards-remapped-a.test.d.ts +2 -0
- package/dist/statements/statement-cases/union-guards-remapped-a.test.d.ts.map +1 -0
- package/dist/statements/statement-cases/union-guards-remapped-a.test.js +382 -0
- package/dist/statements/statement-cases/union-guards-remapped-a.test.js.map +1 -0
- package/dist/statements/statement-cases/union-guards-remapped-b.test.d.ts +2 -0
- package/dist/statements/statement-cases/union-guards-remapped-b.test.d.ts.map +1 -0
- package/dist/statements/statement-cases/union-guards-remapped-b.test.js +397 -0
- package/dist/statements/statement-cases/union-guards-remapped-b.test.js.map +1 -0
- package/dist/type-assertion.test.js +258 -10
- package/dist/type-assertion.test.js.map +1 -1
- package/dist/types/arrays.d.ts.map +1 -1
- package/dist/types/arrays.js +10 -1
- package/dist/types/arrays.js.map +1 -1
- package/dist/types/emitter.d.ts.map +1 -1
- package/dist/types/emitter.js +129 -24
- package/dist/types/emitter.js.map +1 -1
- package/dist/types/index.test.js +205 -1
- package/dist/types/index.test.js.map +1 -1
- package/dist/types/objects.d.ts +2 -2
- package/dist/types/objects.d.ts.map +1 -1
- package/dist/types/objects.js +2 -2
- package/dist/types/objects.js.map +1 -1
- package/dist/types/parameters.d.ts.map +1 -1
- package/dist/types/parameters.js +88 -18
- package/dist/types/parameters.js.map +1 -1
- package/dist/types/reference-lookup.d.ts +16 -0
- package/dist/types/reference-lookup.d.ts.map +1 -0
- package/dist/types/reference-lookup.js +133 -0
- package/dist/types/reference-lookup.js.map +1 -0
- package/dist/types/reference-structural-signatures.d.ts +10 -0
- package/dist/types/reference-structural-signatures.d.ts.map +1 -0
- package/dist/types/reference-structural-signatures.js +310 -0
- package/dist/types/reference-structural-signatures.js.map +1 -0
- package/dist/types/references-cases/array-and-cross-module.test.d.ts +2 -0
- package/dist/types/references-cases/array-and-cross-module.test.d.ts.map +1 -0
- package/dist/types/references-cases/array-and-cross-module.test.js +150 -0
- package/dist/types/references-cases/array-and-cross-module.test.js.map +1 -0
- package/dist/types/references-cases/bindings-and-local.test.d.ts +2 -0
- package/dist/types/references-cases/bindings-and-local.test.d.ts.map +1 -0
- package/dist/types/references-cases/bindings-and-local.test.js +368 -0
- package/dist/types/references-cases/bindings-and-local.test.js.map +1 -0
- package/dist/types/references-cases/helpers.d.ts +14 -0
- package/dist/types/references-cases/helpers.d.ts.map +1 -0
- package/dist/types/references-cases/helpers.js +39 -0
- package/dist/types/references-cases/helpers.js.map +1 -0
- package/dist/types/references-cases/polymorphic-and-recursive.test.d.ts +2 -0
- package/dist/types/references-cases/polymorphic-and-recursive.test.d.ts.map +1 -0
- package/dist/types/references-cases/polymorphic-and-recursive.test.js +387 -0
- package/dist/types/references-cases/polymorphic-and-recursive.test.js.map +1 -0
- package/dist/types/references-cases/primitive-and-builtins.test.d.ts +2 -0
- package/dist/types/references-cases/primitive-and-builtins.test.d.ts.map +1 -0
- package/dist/types/references-cases/primitive-and-builtins.test.js +116 -0
- package/dist/types/references-cases/primitive-and-builtins.test.js.map +1 -0
- package/dist/types/references-cases/resolved-and-imported.test.d.ts +2 -0
- package/dist/types/references-cases/resolved-and-imported.test.d.ts.map +1 -0
- package/dist/types/references-cases/resolved-and-imported.test.js +669 -0
- package/dist/types/references-cases/resolved-and-imported.test.js.map +1 -0
- package/dist/types/references.d.ts.map +1 -1
- package/dist/types/references.js +250 -154
- package/dist/types/references.js.map +1 -1
- package/dist/types/references.test.d.ts +5 -10
- package/dist/types/references.test.d.ts.map +1 -1
- package/dist/types/references.test.js +5 -730
- package/dist/types/references.test.js.map +1 -1
- package/dist/types/unions-cases/basic-and-ordering.test.d.ts +6 -0
- package/dist/types/unions-cases/basic-and-ordering.test.d.ts.map +1 -0
- package/dist/types/unions-cases/basic-and-ordering.test.js +322 -0
- package/dist/types/unions-cases/basic-and-ordering.test.js.map +1 -0
- package/dist/types/unions-cases/large-and-fallback.test.d.ts +6 -0
- package/dist/types/unions-cases/large-and-fallback.test.d.ts.map +1 -0
- package/dist/types/unions-cases/large-and-fallback.test.js +246 -0
- package/dist/types/unions-cases/large-and-fallback.test.js.map +1 -0
- package/dist/types/unions-cases/multi-surface.test.d.ts +6 -0
- package/dist/types/unions-cases/multi-surface.test.d.ts.map +1 -0
- package/dist/types/unions-cases/multi-surface.test.js +268 -0
- package/dist/types/unions-cases/multi-surface.test.js.map +1 -0
- package/dist/types/unions.d.ts +1 -1
- package/dist/types/unions.d.ts.map +1 -1
- package/dist/types/unions.js +60 -65
- package/dist/types/unions.js.map +1 -1
- package/dist/types/unions.test.d.ts +3 -5
- package/dist/types/unions.test.d.ts.map +1 -1
- package/dist/types/unions.test.js +3 -413
- package/dist/types/unions.test.js.map +1 -1
- package/package.json +4 -4
|
@@ -0,0 +1,4139 @@
|
|
|
1
|
+
import { describe, it } from "mocha";
|
|
2
|
+
import { expect } from "chai";
|
|
3
|
+
import { compileProjectToCSharp, compileToCSharp } from "./helpers.js";
|
|
4
|
+
import { normalizeRuntimeUnionCarrierNames } from "../runtime-union-cases/helpers.js";
|
|
5
|
+
describe("End-to-End Integration", () => {
|
|
6
|
+
describe("Regression Coverage", () => {
|
|
7
|
+
it("adapts inline structural object arguments to the callee interface type", () => {
|
|
8
|
+
const source = `
|
|
9
|
+
import type { int } from "@tsonic/core/types.js";
|
|
10
|
+
|
|
11
|
+
interface CreateParams {
|
|
12
|
+
isPrivate?: int;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
declare function subscribe(params?: CreateParams): void;
|
|
16
|
+
|
|
17
|
+
export function run(inviteOnly: int | undefined): void {
|
|
18
|
+
const createParams: { isPrivate?: int } = { isPrivate: inviteOnly };
|
|
19
|
+
subscribe(createParams);
|
|
20
|
+
}
|
|
21
|
+
`;
|
|
22
|
+
const csharp = compileToCSharp(source);
|
|
23
|
+
expect(csharp).to.match(/global::Test\.__Anon_[A-Za-z0-9_]+\s+createParams\s*=\s*new global::Test\.__Anon_[A-Za-z0-9_]+\s*\{\s*isPrivate = inviteOnly\s*\};/);
|
|
24
|
+
expect(csharp).to.include("subscribe(new CreateParams { isPrivate = createParams.isPrivate });");
|
|
25
|
+
expect(csharp).not.to.include("CreateParams createParams =");
|
|
26
|
+
expect(csharp).not.to.include("subscribe(createParams);");
|
|
27
|
+
expect(csharp).not.to.include("subscribe(((global::System.Func<CreateParams>)(() =>");
|
|
28
|
+
});
|
|
29
|
+
it("materializes source-package structural local arguments to callee parameter types", () => {
|
|
30
|
+
const packageExports = {
|
|
31
|
+
".": "./src/index.ts",
|
|
32
|
+
"./index.js": "./src/index.ts",
|
|
33
|
+
"./Jotster.Presence.js": "./src/index.ts",
|
|
34
|
+
};
|
|
35
|
+
const csharp = compileProjectToCSharp({
|
|
36
|
+
"src/handler.ts": `
|
|
37
|
+
import { updatePresenceDomain } from "@fixture/presence/Jotster.Presence.js";
|
|
38
|
+
|
|
39
|
+
export function run(status: string, client?: string): string {
|
|
40
|
+
const input = {
|
|
41
|
+
status,
|
|
42
|
+
client,
|
|
43
|
+
pingOnly: false,
|
|
44
|
+
slimPresence: undefined,
|
|
45
|
+
historyLimitDays: undefined,
|
|
46
|
+
lastUpdateId: undefined,
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
return updatePresenceDomain(input);
|
|
50
|
+
}
|
|
51
|
+
`,
|
|
52
|
+
"node_modules/@fixture/presence/package.json": JSON.stringify({
|
|
53
|
+
name: "@fixture/presence",
|
|
54
|
+
version: "1.0.0",
|
|
55
|
+
type: "module",
|
|
56
|
+
exports: packageExports,
|
|
57
|
+
}, null, 2),
|
|
58
|
+
"node_modules/@fixture/presence/tsonic.package.json": JSON.stringify({
|
|
59
|
+
schemaVersion: 1,
|
|
60
|
+
kind: "tsonic-source-package",
|
|
61
|
+
surfaces: ["@tsonic/js"],
|
|
62
|
+
source: {
|
|
63
|
+
namespace: "Fixture.Presence",
|
|
64
|
+
exports: packageExports,
|
|
65
|
+
},
|
|
66
|
+
}, null, 2),
|
|
67
|
+
"node_modules/@fixture/presence/src/index.ts": `
|
|
68
|
+
export { updatePresenceDomain } from "./domain/update-presence-domain.ts";
|
|
69
|
+
`,
|
|
70
|
+
"node_modules/@fixture/presence/src/domain/update-presence-domain.ts": `
|
|
71
|
+
interface UpdatePresenceParams {
|
|
72
|
+
status: string;
|
|
73
|
+
client?: string;
|
|
74
|
+
pingOnly?: boolean;
|
|
75
|
+
slimPresence?: boolean;
|
|
76
|
+
historyLimitDays?: number;
|
|
77
|
+
lastUpdateId?: number;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export function updatePresenceDomain(params: UpdatePresenceParams): string {
|
|
81
|
+
return params.client ?? params.status;
|
|
82
|
+
}
|
|
83
|
+
`,
|
|
84
|
+
}, "src/handler.ts", { surface: "@tsonic/js" });
|
|
85
|
+
expect(csharp).to.match(/updatePresenceDomain\(new global::Fixture\.Presence\.domain\.UpdatePresenceParams\s*\{\s*status = input\.status,\s*client = input\.client,\s*pingOnly = input\.pingOnly,\s*slimPresence = input\.slimPresence,\s*historyLimitDays = input\.historyLimitDays,\s*lastUpdateId = input\.lastUpdateId\s*\}\)/);
|
|
86
|
+
expect(csharp).not.to.include("(global::Fixture.Presence.domain.UpdatePresenceParams)(object)input");
|
|
87
|
+
});
|
|
88
|
+
it("uses runtime equality for JsValue-vs-boolean strict comparisons", () => {
|
|
89
|
+
const source = `
|
|
90
|
+
export function hasSubdomain(body: Record<string, JsValue>): boolean {
|
|
91
|
+
return body.allow_subdomains === true;
|
|
92
|
+
}
|
|
93
|
+
`;
|
|
94
|
+
const csharp = compileToCSharp(source);
|
|
95
|
+
expect(csharp).to.include('global::System.Object.Equals(body["allow_subdomains"], true)');
|
|
96
|
+
expect(csharp).not.to.include('body["allow_subdomains"] == true');
|
|
97
|
+
});
|
|
98
|
+
it("casts JsValue record member reads after typeof guards when assigning to nullable concrete slots", () => {
|
|
99
|
+
const source = `
|
|
100
|
+
import type { JsValue } from "@tsonic/core/types.js";
|
|
101
|
+
|
|
102
|
+
type JwtPayload = {
|
|
103
|
+
email?: string;
|
|
104
|
+
exp?: number;
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
export function read(payloadObject: Record<string, JsValue>): JwtPayload {
|
|
108
|
+
let exp: number | undefined = undefined;
|
|
109
|
+
if (typeof payloadObject.exp === "number") {
|
|
110
|
+
exp = payloadObject.exp as number;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const payload: JwtPayload = {};
|
|
114
|
+
if (typeof payloadObject.email === "string") {
|
|
115
|
+
payload.email = payloadObject.email as string;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
if (exp !== undefined) {
|
|
119
|
+
payload.exp = exp as number;
|
|
120
|
+
}
|
|
121
|
+
return payload;
|
|
122
|
+
}
|
|
123
|
+
`;
|
|
124
|
+
const csharp = compileToCSharp(source, "/test/test.ts", {
|
|
125
|
+
surface: "@tsonic/js",
|
|
126
|
+
});
|
|
127
|
+
expect(csharp).to.match(/exp\s*=\s*\(double\??\)/);
|
|
128
|
+
expect(csharp).to.match(/payload\.email\s*=\s*\(string\??\)/);
|
|
129
|
+
expect(csharp).not.to.include('exp = payloadObject["exp"];');
|
|
130
|
+
expect(csharp).not.to.include('payload.email = payloadObject["email"];');
|
|
131
|
+
});
|
|
132
|
+
it("materializes broad JsValue Array.isArray narrows for length and index reads", () => {
|
|
133
|
+
const source = `
|
|
134
|
+
import type { JsValue } from "@tsonic/core/types.js";
|
|
135
|
+
|
|
136
|
+
declare function parseJsonValueText(value: string): JsValue;
|
|
137
|
+
|
|
138
|
+
export function countObjects(value: string): number {
|
|
139
|
+
const parsed = parseJsonValueText(value);
|
|
140
|
+
if (!Array.isArray(parsed)) {
|
|
141
|
+
return -1;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
let count = 0;
|
|
145
|
+
for (let i = 0; i < parsed.length; i++) {
|
|
146
|
+
const item = parsed[i];
|
|
147
|
+
if (item !== null && typeof item === "object" && !Array.isArray(item)) {
|
|
148
|
+
count += 1;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
return count;
|
|
152
|
+
}
|
|
153
|
+
`;
|
|
154
|
+
const csharp = compileToCSharp(source, "/test/test.ts", {
|
|
155
|
+
surface: "@tsonic/js",
|
|
156
|
+
});
|
|
157
|
+
expect(csharp).to.include("((global::System.Array)parsed).Length");
|
|
158
|
+
expect(csharp).to.include("((global::System.Array)parsed).GetValue(i)");
|
|
159
|
+
expect(csharp).not.to.include("((object)parsed).Length");
|
|
160
|
+
expect(csharp).not.to.include("((object)parsed)[i]");
|
|
161
|
+
});
|
|
162
|
+
it("compares optional runtime-union member reads to literals without Match projections", () => {
|
|
163
|
+
const source = `
|
|
164
|
+
interface CookieOptions {
|
|
165
|
+
sameSite?: string | boolean;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
export function resolveSameSite(options?: CookieOptions): string {
|
|
169
|
+
if (typeof options?.sameSite === "string" && options.sameSite.length > 0) {
|
|
170
|
+
return options.sameSite;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
if (options?.sameSite === true) {
|
|
174
|
+
return "Strict";
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
return "None";
|
|
178
|
+
}
|
|
179
|
+
`;
|
|
180
|
+
const csharp = compileToCSharp(source);
|
|
181
|
+
expect(csharp).to.include("options?.sameSite is global::Tsonic.Internal.Union<bool, string> __tsonic_union_compare_1");
|
|
182
|
+
expect(csharp).to.include("__tsonic_union_compare_1.Is1()");
|
|
183
|
+
expect(csharp).to.include("__tsonic_union_compare_1.As1() == true");
|
|
184
|
+
expect(csharp).not.to.include("options?.sameSite.Match");
|
|
185
|
+
});
|
|
186
|
+
it("allocates distinct runtime-union comparison temps for sibling literal checks", () => {
|
|
187
|
+
const csharp = compileToCSharp(`
|
|
188
|
+
interface CookieOptions {
|
|
189
|
+
sameSite?: string | boolean;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
export function classifySameSite(options?: CookieOptions): string {
|
|
193
|
+
if (options?.sameSite === true) {
|
|
194
|
+
return "strict";
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
if (options?.sameSite === false) {
|
|
198
|
+
return "lax";
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
return "other";
|
|
202
|
+
}
|
|
203
|
+
`);
|
|
204
|
+
expect(csharp).to.include("__tsonic_union_compare_1");
|
|
205
|
+
expect(csharp).to.include("__tsonic_union_compare_2");
|
|
206
|
+
});
|
|
207
|
+
it("preserves final fallback runtime-union slots after chained typeof guards", () => {
|
|
208
|
+
const csharp = compileToCSharp(`
|
|
209
|
+
type TcpSocketConnectOpts = {
|
|
210
|
+
readonly port: number;
|
|
211
|
+
readonly host?: string;
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
declare function connectPath(path: string): string;
|
|
215
|
+
declare function connectPort(port: number, host?: string): string;
|
|
216
|
+
|
|
217
|
+
export function connect(
|
|
218
|
+
portOrOptionsOrPath: number | TcpSocketConnectOpts | string
|
|
219
|
+
): string {
|
|
220
|
+
if (typeof portOrOptionsOrPath === "string") {
|
|
221
|
+
return connectPath(portOrOptionsOrPath);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
if (typeof portOrOptionsOrPath === "number") {
|
|
225
|
+
return connectPort(portOrOptionsOrPath);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
return connectPort(
|
|
229
|
+
portOrOptionsOrPath.port,
|
|
230
|
+
portOrOptionsOrPath.host
|
|
231
|
+
);
|
|
232
|
+
}
|
|
233
|
+
`);
|
|
234
|
+
expect(csharp).to.include("portOrOptionsOrPath.Is2()");
|
|
235
|
+
expect(csharp).to.include("portOrOptionsOrPath.Is1()");
|
|
236
|
+
expect(csharp).to.include("return connectPort((portOrOptionsOrPath.As3()).port, (portOrOptionsOrPath.As3()).host);");
|
|
237
|
+
expect(csharp).not.to.include("portOrOptionsOrPath.As2()).port");
|
|
238
|
+
expect(csharp).not.to.include("portOrOptionsOrPath.As2()).host");
|
|
239
|
+
});
|
|
240
|
+
it("reuses the original carrier when chained typeof guards narrow an optional union twice", () => {
|
|
241
|
+
const csharp = compileToCSharp(`
|
|
242
|
+
declare function decodeInputBytes(
|
|
243
|
+
data: string | number,
|
|
244
|
+
encoding?: string
|
|
245
|
+
): void;
|
|
246
|
+
|
|
247
|
+
export function create(
|
|
248
|
+
generatorOrEncodingStr?: number | string,
|
|
249
|
+
generatorEncoding?: string
|
|
250
|
+
): void {
|
|
251
|
+
let generatorBytes = 0;
|
|
252
|
+
|
|
253
|
+
if (typeof generatorOrEncodingStr === "number") {
|
|
254
|
+
generatorBytes = generatorOrEncodingStr;
|
|
255
|
+
} else if (typeof generatorOrEncodingStr === "string") {
|
|
256
|
+
decodeInputBytes(
|
|
257
|
+
generatorOrEncodingStr,
|
|
258
|
+
generatorEncoding ?? "base64"
|
|
259
|
+
);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
`);
|
|
263
|
+
expect(csharp).to.include("else if (((global::System.Object)(generatorOrEncodingStr)) != null && generatorOrEncodingStr.Is2())");
|
|
264
|
+
expect(csharp).to.include('decodeInputBytes(generatorOrEncodingStr, generatorEncoding ?? "base64");');
|
|
265
|
+
expect(csharp).not.to.include("default(string) : (generatorOrEncodingStr.As2())).As2()");
|
|
266
|
+
});
|
|
267
|
+
it("keeps sibling typeof fallback checks on the original nullable union carrier", () => {
|
|
268
|
+
const csharp = compileToCSharp(`
|
|
269
|
+
export class LookupOptions {
|
|
270
|
+
family: number | string | null = null;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
export function run(options: LookupOptions | null): number | null {
|
|
274
|
+
if (options === null) {
|
|
275
|
+
return null;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
const family = options.family;
|
|
279
|
+
if (typeof family === "string") {
|
|
280
|
+
if (family === "IPv4") {
|
|
281
|
+
return 4;
|
|
282
|
+
}
|
|
283
|
+
if (family === "IPv6") {
|
|
284
|
+
return 6;
|
|
285
|
+
}
|
|
286
|
+
return null;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
if (typeof family === "number") {
|
|
290
|
+
if (family === 0) {
|
|
291
|
+
return 0;
|
|
292
|
+
}
|
|
293
|
+
if (family === 4) {
|
|
294
|
+
return 4;
|
|
295
|
+
}
|
|
296
|
+
if (family === 6) {
|
|
297
|
+
return 6;
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
return null;
|
|
302
|
+
}
|
|
303
|
+
`);
|
|
304
|
+
expect(csharp).to.include("if (((global::System.Object)(family)) != null && family.Is1())");
|
|
305
|
+
expect(csharp).not.to.include('if (global::Tsonic.Runtime.Operators.@typeof((object)family == null ? default(double) : (family.As1())) == "number")');
|
|
306
|
+
});
|
|
307
|
+
it("materializes local structural alias arguments through generic result helpers", () => {
|
|
308
|
+
const csharp = compileToCSharp(`
|
|
309
|
+
type Ok<T> = { success: true; data: T };
|
|
310
|
+
type Err<E> = { success: false; error: E };
|
|
311
|
+
type Result<T, E> = Ok<T> | Err<E>;
|
|
312
|
+
|
|
313
|
+
declare function ok<T>(data: T): Ok<T>;
|
|
314
|
+
|
|
315
|
+
type Payload = {
|
|
316
|
+
foundAnchor: boolean;
|
|
317
|
+
foundNewest: boolean;
|
|
318
|
+
foundOldest: boolean;
|
|
319
|
+
};
|
|
320
|
+
|
|
321
|
+
export function run(anchor: string): Result<Payload, string> {
|
|
322
|
+
const foundAnchor = anchor !== "newest" && anchor !== "oldest";
|
|
323
|
+
const foundNewest = anchor === "newest";
|
|
324
|
+
const foundOldest = anchor === "oldest";
|
|
325
|
+
return ok({ foundAnchor, foundNewest, foundOldest });
|
|
326
|
+
}
|
|
327
|
+
`);
|
|
328
|
+
expect(csharp).to.include("Result<Payload__Alias, string>.From2(ok(new Payload__Alias");
|
|
329
|
+
expect(csharp).not.to.include("From2(ok(new global::Test.__Anon_");
|
|
330
|
+
});
|
|
331
|
+
it("preserves instanceof catch narrowing across conditional fallbacks", () => {
|
|
332
|
+
const csharp = compileToCSharp(`
|
|
333
|
+
type SendFileCallback = (error: Error | null) => void;
|
|
334
|
+
|
|
335
|
+
export function run(callback?: SendFileCallback): string {
|
|
336
|
+
try {
|
|
337
|
+
throw new Error("boom");
|
|
338
|
+
} catch (error) {
|
|
339
|
+
const resolved =
|
|
340
|
+
error instanceof Error ? error : new Error("sendFile failed");
|
|
341
|
+
if (callback) {
|
|
342
|
+
callback(resolved);
|
|
343
|
+
return "callback";
|
|
344
|
+
}
|
|
345
|
+
return resolved.message;
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
`, "/test/test.ts", {
|
|
349
|
+
surface: "@tsonic/js",
|
|
350
|
+
});
|
|
351
|
+
expect(csharp).to.include('error is global::js.Error ? (global::js.Error)error : new global::js.Error("sendFile failed")');
|
|
352
|
+
expect(csharp).not.to.include('error is global::js.Error ? error : new global::js.Error("sendFile failed")');
|
|
353
|
+
expect(csharp).not.to.include('error is global::js.Error ? (object?)(global::js.Error)error : new global::js.Error("sendFile failed")');
|
|
354
|
+
expect(csharp).to.include("return resolved.message;");
|
|
355
|
+
expect(csharp).not.to.include("((object?)resolved).message");
|
|
356
|
+
});
|
|
357
|
+
it("materializes proof-narrowed conditional identifiers before nullable object slots", () => {
|
|
358
|
+
const csharp = compileToCSharp(`
|
|
359
|
+
type Result = { error: Error | undefined };
|
|
360
|
+
|
|
361
|
+
export function run(error: object): Result {
|
|
362
|
+
const result: Result = { error: undefined };
|
|
363
|
+
result.error =
|
|
364
|
+
error instanceof Error ? error : new Error("sendFile failed");
|
|
365
|
+
return result;
|
|
366
|
+
}
|
|
367
|
+
`, "/test/test.ts", {
|
|
368
|
+
surface: "@tsonic/js",
|
|
369
|
+
});
|
|
370
|
+
expect(csharp).to.include('result.error = error is global::js.Error ? (global::js.Error)error : new global::js.Error("sendFile failed");');
|
|
371
|
+
expect(csharp).not.to.include('result.error = error is global::js.Error ? error : new global::js.Error("sendFile failed");');
|
|
372
|
+
expect(csharp).not.to.include('result.error = error is global::js.Error ? (object?)(global::js.Error)error : new global::js.Error("sendFile failed");');
|
|
373
|
+
});
|
|
374
|
+
it("collapses literal-plus-string optional callback aliases before default emission", () => {
|
|
375
|
+
const csharp = compileToCSharp(`
|
|
376
|
+
type NextControl = "route" | "router" | string | null | undefined;
|
|
377
|
+
type NextFunction = (value?: NextControl) => void | Promise<void>;
|
|
378
|
+
|
|
379
|
+
export async function run(next: NextFunction): Promise<void> {
|
|
380
|
+
await next(undefined);
|
|
381
|
+
}
|
|
382
|
+
`);
|
|
383
|
+
expect(csharp).to.include("next(default(string?))");
|
|
384
|
+
expect(csharp).not.to.include("next(default(object))");
|
|
385
|
+
});
|
|
386
|
+
it("uses source-backed call surfaces through asinterface structural views", () => {
|
|
387
|
+
const csharp = normalizeRuntimeUnionCarrierNames(compileToCSharp(`
|
|
388
|
+
import { asinterface } from "@tsonic/core/lang.js";
|
|
389
|
+
import type { ServerResponse } from "@tsonic/nodejs/http.js";
|
|
390
|
+
|
|
391
|
+
interface TextEndableResponse {
|
|
392
|
+
end(chunk: string): void;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
interface ResponseHeaderLookup {
|
|
396
|
+
getHeader(name: string): string | readonly string[] | undefined;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
declare function normalizeHeaderValue(
|
|
400
|
+
value: string | readonly string[] | undefined
|
|
401
|
+
): string | undefined;
|
|
402
|
+
|
|
403
|
+
export function run(resp: ServerResponse, text: string): string | undefined {
|
|
404
|
+
asinterface<TextEndableResponse>(resp).end(text);
|
|
405
|
+
return normalizeHeaderValue(
|
|
406
|
+
asinterface<ResponseHeaderLookup>(resp).getHeader("x-test")
|
|
407
|
+
);
|
|
408
|
+
}
|
|
409
|
+
`, "/test/test.ts", { surface: "@tsonic/nodejs" }));
|
|
410
|
+
expect(csharp).to.match(/resp\.end\(global::Tsonic\.Internal\.Union<[^>]+>\.From4\(text\)\);/);
|
|
411
|
+
expect(csharp).to.include('normalizeHeaderValue(resp.getHeader("x-test") == null ? default(global::Tsonic.Internal.Union<string[], string>?) : global::Tsonic.Internal.Union<string[], string>.From2(resp.getHeader("x-test")));');
|
|
412
|
+
expect(csharp).not.to.include("resp.end(text);");
|
|
413
|
+
expect(csharp).not.to.include('normalizeHeaderValue(resp.getHeader("x-test"));');
|
|
414
|
+
});
|
|
415
|
+
it("preserves method-wide local-name reservations across terminating typeof branches", () => {
|
|
416
|
+
const csharp = compileToCSharp(`
|
|
417
|
+
declare function connectPath(path: string, listener?: () => void): string;
|
|
418
|
+
declare function connectPort(
|
|
419
|
+
port: number,
|
|
420
|
+
host?: string,
|
|
421
|
+
listener?: () => void
|
|
422
|
+
): string;
|
|
423
|
+
|
|
424
|
+
export function connect(
|
|
425
|
+
portOrOptionsOrPath: number | string,
|
|
426
|
+
hostOrListener?: string | (() => void),
|
|
427
|
+
connectionListener?: () => void
|
|
428
|
+
): string {
|
|
429
|
+
if (typeof portOrOptionsOrPath === "string") {
|
|
430
|
+
const listener =
|
|
431
|
+
typeof hostOrListener === "function" ? hostOrListener : undefined;
|
|
432
|
+
return connectPath(portOrOptionsOrPath, listener);
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
if (typeof portOrOptionsOrPath === "number") {
|
|
436
|
+
const host =
|
|
437
|
+
typeof hostOrListener === "string" ? hostOrListener : undefined;
|
|
438
|
+
const listener =
|
|
439
|
+
typeof hostOrListener === "function"
|
|
440
|
+
? hostOrListener
|
|
441
|
+
: connectionListener;
|
|
442
|
+
return connectPort(portOrOptionsOrPath, host, listener);
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
const listener =
|
|
446
|
+
typeof hostOrListener === "function" ? hostOrListener : undefined;
|
|
447
|
+
return connectPath("fallback", listener);
|
|
448
|
+
}
|
|
449
|
+
`);
|
|
450
|
+
expect(csharp).to.include("var listener =");
|
|
451
|
+
expect(csharp).to.include("var listener__1 =");
|
|
452
|
+
expect(csharp).to.include("var listener__2 =");
|
|
453
|
+
});
|
|
454
|
+
it("passes boxed storage values through broad calls after typeof-number narrowing", () => {
|
|
455
|
+
const csharp = compileToCSharp(`
|
|
456
|
+
import type { JsValue } from "@tsonic/core/types.js";
|
|
457
|
+
|
|
458
|
+
const toNumberArg = (value: JsValue): number => {
|
|
459
|
+
return Number(value);
|
|
460
|
+
};
|
|
461
|
+
|
|
462
|
+
export function run(args: readonly JsValue[]): number {
|
|
463
|
+
const arg0 = args.length > 0 ? args[0] : undefined;
|
|
464
|
+
if (typeof arg0 === "number") {
|
|
465
|
+
return toNumberArg(arg0);
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
return 0;
|
|
469
|
+
}
|
|
470
|
+
`, "/test/test.ts", { surface: "@tsonic/js" });
|
|
471
|
+
expect(csharp).to.include('if (global::Tsonic.Runtime.Operators.@typeof(arg0) == "number")');
|
|
472
|
+
expect(csharp).to.include("return toNumberArg(arg0);");
|
|
473
|
+
expect(csharp).not.to.include("toNumberArg((object?)(double)arg0)");
|
|
474
|
+
});
|
|
475
|
+
it("keeps broad JsValue typeof-object guards on the runtime typeof helper instead of union member checks", () => {
|
|
476
|
+
const csharp = compileToCSharp(`
|
|
477
|
+
import type { JsValue } from "@tsonic/core/types.js";
|
|
478
|
+
|
|
479
|
+
export class Checker {
|
|
480
|
+
static isObject(value: JsValue | undefined): boolean {
|
|
481
|
+
if (value === undefined || value === null) {
|
|
482
|
+
return false;
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
if (typeof value !== "object") {
|
|
486
|
+
return false;
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
return true;
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
`, "/test/test.ts", { surface: "@tsonic/js" });
|
|
493
|
+
expect(csharp).to.include('if (global::Tsonic.Runtime.Operators.@typeof(value) != "object")');
|
|
494
|
+
expect(csharp).not.to.include("if (!(((global::System.Object)(value)) != null && (value.Is1() || value.Is2())))");
|
|
495
|
+
});
|
|
496
|
+
it("calls exact external member overloads instead of wrapping object arguments into implementation unions", () => {
|
|
497
|
+
const csharp = compileProjectToCSharp({
|
|
498
|
+
"package.json": JSON.stringify({ name: "emitter-test-project", version: "1.0.0", type: "module" }, null, 2),
|
|
499
|
+
"src/index.ts": [
|
|
500
|
+
'import { BindOptions, Socket } from "@fixture/net/index.js";',
|
|
501
|
+
"",
|
|
502
|
+
"export function run(socket: Socket): void {",
|
|
503
|
+
" const options = new BindOptions();",
|
|
504
|
+
" options.port = 0;",
|
|
505
|
+
' options.address = "127.0.0.1";',
|
|
506
|
+
" socket.bind(options);",
|
|
507
|
+
"}",
|
|
508
|
+
].join("\n"),
|
|
509
|
+
"node_modules/@fixture/net/package.json": JSON.stringify({ name: "@fixture/net", version: "1.0.0", type: "module" }, null, 2),
|
|
510
|
+
"node_modules/@fixture/net/index.js": [
|
|
511
|
+
"export class BindOptions {}",
|
|
512
|
+
"export class Socket {}",
|
|
513
|
+
].join("\n"),
|
|
514
|
+
"node_modules/@fixture/net/index.d.ts": [
|
|
515
|
+
"export class BindOptions {",
|
|
516
|
+
" port?: number;",
|
|
517
|
+
" fd?: number;",
|
|
518
|
+
" address?: string;",
|
|
519
|
+
"}",
|
|
520
|
+
"",
|
|
521
|
+
"export class Socket {",
|
|
522
|
+
" bind(): void;",
|
|
523
|
+
" bind(port: number, address?: string, callback?: () => void): void;",
|
|
524
|
+
" bind(port: number, callback: () => void): void;",
|
|
525
|
+
" bind(callback: () => void): void;",
|
|
526
|
+
" bind(options: BindOptions, callback?: () => void): void;",
|
|
527
|
+
"}",
|
|
528
|
+
].join("\n"),
|
|
529
|
+
}, "src/index.ts");
|
|
530
|
+
expect(csharp).to.include("socket.bind(options);");
|
|
531
|
+
expect(csharp).not.to.include("global::Tsonic.Internal.Union<global::System.Action, double, BindOptions>.From3(options)");
|
|
532
|
+
});
|
|
533
|
+
it("calls exact external delegate overloads instead of the implementation union surface", () => {
|
|
534
|
+
const csharp = compileProjectToCSharp({
|
|
535
|
+
"package.json": JSON.stringify({ name: "emitter-test-project", version: "1.0.0", type: "module" }, null, 2),
|
|
536
|
+
"src/index.ts": [
|
|
537
|
+
'import { createServer } from "@fixture/tls/index.js";',
|
|
538
|
+
"",
|
|
539
|
+
"export function run(): void {",
|
|
540
|
+
" createServer((_socket) => {});",
|
|
541
|
+
"}",
|
|
542
|
+
].join("\n"),
|
|
543
|
+
"node_modules/@fixture/tls/package.json": JSON.stringify({ name: "@fixture/tls", version: "1.0.0", type: "module" }, null, 2),
|
|
544
|
+
"node_modules/@fixture/tls/index.js": [
|
|
545
|
+
"export function createServer(..._args) {",
|
|
546
|
+
" return undefined;",
|
|
547
|
+
"}",
|
|
548
|
+
].join("\n"),
|
|
549
|
+
"node_modules/@fixture/tls/index.d.ts": [
|
|
550
|
+
"export class TLSSocket {}",
|
|
551
|
+
"export class TlsOptions {",
|
|
552
|
+
" requestCert?: boolean;",
|
|
553
|
+
"}",
|
|
554
|
+
"export function createServer(",
|
|
555
|
+
" options: TlsOptions,",
|
|
556
|
+
" secureConnectionListener?: (socket: TLSSocket) => void",
|
|
557
|
+
"): void;",
|
|
558
|
+
"export function createServer(",
|
|
559
|
+
" secureConnectionListener?: (socket: TLSSocket) => void",
|
|
560
|
+
"): void;",
|
|
561
|
+
].join("\n"),
|
|
562
|
+
}, "src/index.ts");
|
|
563
|
+
expect(csharp).to.include("createServer((global::TLSSocket _socket) =>");
|
|
564
|
+
expect(csharp).not.to.include("global::Tsonic.Internal.Union<global::System.Action<TLSSocket>, TlsOptions>.From1");
|
|
565
|
+
});
|
|
566
|
+
it("materializes source-package function listeners through the runtime union carrier", () => {
|
|
567
|
+
const csharp = compileProjectToCSharp({
|
|
568
|
+
"package.json": JSON.stringify({ name: "emitter-test-project", version: "1.0.0", type: "module" }, null, 2),
|
|
569
|
+
"src/index.ts": [
|
|
570
|
+
'import { createServer } from "@fixture/tls/index.js";',
|
|
571
|
+
"",
|
|
572
|
+
"export function run(): void {",
|
|
573
|
+
" createServer((_socket) => {});",
|
|
574
|
+
"}",
|
|
575
|
+
].join("\n"),
|
|
576
|
+
"node_modules/@fixture/tls/package.json": JSON.stringify({
|
|
577
|
+
name: "@fixture/tls",
|
|
578
|
+
version: "1.0.0",
|
|
579
|
+
type: "module",
|
|
580
|
+
exports: {
|
|
581
|
+
"./index.js": "./src/index.ts",
|
|
582
|
+
},
|
|
583
|
+
}, null, 2),
|
|
584
|
+
"node_modules/@fixture/tls/tsonic.package.json": JSON.stringify({
|
|
585
|
+
schemaVersion: 1,
|
|
586
|
+
kind: "tsonic-source-package",
|
|
587
|
+
surfaces: ["clr"],
|
|
588
|
+
source: {
|
|
589
|
+
namespace: "fixture.tls",
|
|
590
|
+
exports: {
|
|
591
|
+
"./index.js": "./src/index.ts",
|
|
592
|
+
},
|
|
593
|
+
},
|
|
594
|
+
}, null, 2),
|
|
595
|
+
"node_modules/@fixture/tls/src/index.ts": [
|
|
596
|
+
"export class TLSSocket {}",
|
|
597
|
+
"export class TlsOptions {",
|
|
598
|
+
" requestCert?: boolean;",
|
|
599
|
+
"}",
|
|
600
|
+
"export class TLSServer {}",
|
|
601
|
+
"export const createServer = (",
|
|
602
|
+
" optionsOrListener?: TlsOptions | ((socket: TLSSocket) => void),",
|
|
603
|
+
" secureConnectionListener?: (socket: TLSSocket) => void,",
|
|
604
|
+
"): TLSServer => {",
|
|
605
|
+
" void optionsOrListener;",
|
|
606
|
+
" void secureConnectionListener;",
|
|
607
|
+
" return new TLSServer();",
|
|
608
|
+
"};",
|
|
609
|
+
].join("\n"),
|
|
610
|
+
}, "src/index.ts");
|
|
611
|
+
expect(csharp).to.include("global::fixture.tls.index.createServer(global::Tsonic.Internal.Union<global::System.Action<global::fixture.tls.TLSSocket>, global::fixture.tls.TlsOptions>.From1((global::fixture.tls.TLSSocket _socket) =>");
|
|
612
|
+
expect(csharp).not.to.include("global::fixture.tls.index.createServer((global::fixture.tls.TLSSocket _socket) =>");
|
|
613
|
+
});
|
|
614
|
+
it("materializes direct constructor lambda arguments through runtime union carriers", () => {
|
|
615
|
+
const csharp = compileToCSharp(`
|
|
616
|
+
class TLSSocket {}
|
|
617
|
+
class TlsOptions {}
|
|
618
|
+
class TLSServer {
|
|
619
|
+
constructor(
|
|
620
|
+
options?: TlsOptions | ((socket: TLSSocket) => void),
|
|
621
|
+
listener?: ((socket: TLSSocket) => void) | null
|
|
622
|
+
) {}
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
export function run(): void {
|
|
626
|
+
void new TLSServer((_socket) => {});
|
|
627
|
+
}
|
|
628
|
+
`);
|
|
629
|
+
expect(csharp).to.match(/new TLSServer\(global::Tsonic\.Internal\.Union<global::System\.Action<(?:global::Test\.)?TLSSocket>, (?:global::Test\.)?TlsOptions>\.From1\(\(TLSSocket _socket\) =>/);
|
|
630
|
+
expect(csharp).not.to.include("new TLSServer((TLSSocket _socket) =>");
|
|
631
|
+
});
|
|
632
|
+
it("adapts named constructor arguments to inline structural constructor parameter types", () => {
|
|
633
|
+
const csharp = compileToCSharp(`
|
|
634
|
+
class SocketAddressInitOptions {
|
|
635
|
+
address?: string;
|
|
636
|
+
family?: string;
|
|
637
|
+
flowlabel?: number;
|
|
638
|
+
port?: number;
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
class SocketAddress {
|
|
642
|
+
constructor(options: {
|
|
643
|
+
address?: string;
|
|
644
|
+
family?: string;
|
|
645
|
+
flowlabel?: number;
|
|
646
|
+
port?: number;
|
|
647
|
+
}) {}
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
export function run(): void {
|
|
651
|
+
const options = new SocketAddressInitOptions();
|
|
652
|
+
options.address = "127.0.0.1";
|
|
653
|
+
options.port = 8080;
|
|
654
|
+
void new SocketAddress(options);
|
|
655
|
+
}
|
|
656
|
+
`);
|
|
657
|
+
expect(csharp).to.include("new SocketAddress(new global::Test.__Anon_");
|
|
658
|
+
expect(csharp).to.include("address = options.address");
|
|
659
|
+
expect(csharp).to.include("family = options.family");
|
|
660
|
+
expect(csharp).to.include("flowlabel = options.flowlabel");
|
|
661
|
+
expect(csharp).to.include("port = options.port");
|
|
662
|
+
expect(csharp).to.include('address = "127.0.0.1"');
|
|
663
|
+
expect(csharp).to.include("port = 8080");
|
|
664
|
+
expect(csharp).not.to.include("new SocketAddress(options);");
|
|
665
|
+
});
|
|
666
|
+
it("casts preserved runtime-union carriers for nullish checks after callable branch elimination", () => {
|
|
667
|
+
const csharp = compileToCSharp(`
|
|
668
|
+
class TLSSocket {}
|
|
669
|
+
class TlsOptions {}
|
|
670
|
+
class TLSServer {
|
|
671
|
+
constructor(
|
|
672
|
+
options?: TlsOptions | ((socket: TLSSocket) => void),
|
|
673
|
+
listener?: ((socket: TLSSocket) => void) | null
|
|
674
|
+
) {}
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
export const createServer = (
|
|
678
|
+
optionsOrListener?: TlsOptions | ((socket: TLSSocket) => void),
|
|
679
|
+
secureConnectionListener?: (socket: TLSSocket) => void,
|
|
680
|
+
): TLSServer => {
|
|
681
|
+
if (typeof optionsOrListener === "function") {
|
|
682
|
+
return new TLSServer(optionsOrListener);
|
|
683
|
+
}
|
|
684
|
+
if (optionsOrListener !== undefined) {
|
|
685
|
+
return new TLSServer(optionsOrListener, secureConnectionListener ?? null);
|
|
686
|
+
}
|
|
687
|
+
return new TLSServer();
|
|
688
|
+
};
|
|
689
|
+
`);
|
|
690
|
+
expect(csharp).to.include("if (((global::System.Object)(optionsOrListener)) != null)");
|
|
691
|
+
expect(csharp).not.to.include("if (optionsOrListener != null)");
|
|
692
|
+
});
|
|
693
|
+
it("uses declared out locals instead of bare discards for non-lvalue out arguments", () => {
|
|
694
|
+
const csharp = compileToCSharp(`
|
|
695
|
+
import type { int, out } from "@tsonic/core/types.js";
|
|
696
|
+
|
|
697
|
+
declare class Bytes {}
|
|
698
|
+
declare class Reader {
|
|
699
|
+
consume(bytes: Bytes, read: out<int>): void;
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
export function run(reader: Reader, bytes: Bytes): void {
|
|
703
|
+
reader.consume(bytes, 0 as out<int>);
|
|
704
|
+
}
|
|
705
|
+
`);
|
|
706
|
+
expect(csharp).to.match(/reader\.consume\(bytes,\s*out var __tsonic_out_discard_\d+\);/);
|
|
707
|
+
expect(csharp).not.to.include("reader.consume(bytes, out _);");
|
|
708
|
+
expect(csharp).not.to.include("reader.consume(bytes, (int)0);");
|
|
709
|
+
});
|
|
710
|
+
it("reuses inferred structural locals for inline object-type parameters when CLR surfaces already align", () => {
|
|
711
|
+
const source = `
|
|
712
|
+
import type { int } from "@tsonic/core/types.js";
|
|
713
|
+
|
|
714
|
+
declare function createBotDomain(input: { fullName: string; shortName: string; botType?: int }): void;
|
|
715
|
+
|
|
716
|
+
export function run(botType: int | undefined): void {
|
|
717
|
+
const input = { fullName: "Bot", shortName: "bot", botType };
|
|
718
|
+
createBotDomain(input);
|
|
719
|
+
}
|
|
720
|
+
`;
|
|
721
|
+
const csharp = compileToCSharp(source);
|
|
722
|
+
expect(csharp).to.include("new global::Test.__Anon_");
|
|
723
|
+
expect(csharp).to.include("var input = new global::Test.__Anon_");
|
|
724
|
+
expect(csharp).to.include('fullName = "Bot"');
|
|
725
|
+
expect(csharp).to.include('shortName = "bot"');
|
|
726
|
+
expect(csharp).to.include("botType = botType");
|
|
727
|
+
expect(csharp).not.to.include("createBotDomain(((global::System.Func<global::Test.__Anon_");
|
|
728
|
+
expect(csharp).to.include("createBotDomain(input);");
|
|
729
|
+
expect(csharp).not.to.include("createBotDomain(new global::Test.__Anon_");
|
|
730
|
+
});
|
|
731
|
+
it("adapts named structural aliases into compiler-owned carriers for inline object-type parameters", () => {
|
|
732
|
+
const source = `
|
|
733
|
+
import type { int } from "@tsonic/core/types.js";
|
|
734
|
+
|
|
735
|
+
type CreateInput = { fullName: string; shortName: string; botType?: int };
|
|
736
|
+
|
|
737
|
+
declare function createBotDomain(input: { fullName: string; shortName: string; botType?: int }): void;
|
|
738
|
+
|
|
739
|
+
export function run(botType: int | undefined): void {
|
|
740
|
+
const input: CreateInput = { fullName: "Bot", shortName: "bot", botType };
|
|
741
|
+
createBotDomain(input);
|
|
742
|
+
}
|
|
743
|
+
`;
|
|
744
|
+
const csharp = compileToCSharp(source);
|
|
745
|
+
expect(csharp).to.include('CreateInput__Alias input = new CreateInput__Alias { fullName = "Bot", shortName = "bot", botType = botType };');
|
|
746
|
+
expect(csharp).to.include("createBotDomain(new global::Test.__Anon_");
|
|
747
|
+
expect(csharp).to.include("fullName = input.fullName");
|
|
748
|
+
expect(csharp).to.include("shortName = input.shortName");
|
|
749
|
+
expect(csharp).to.include("botType = input.botType");
|
|
750
|
+
});
|
|
751
|
+
it("reuses named structural array aliases for inline object-type element parameters when CLR surfaces align", () => {
|
|
752
|
+
const source = `
|
|
753
|
+
type AddItem = { name: string; description?: string };
|
|
754
|
+
|
|
755
|
+
declare function bulkUpdate(add?: { name: string; description?: string }[]): void;
|
|
756
|
+
|
|
757
|
+
export function run(addRaw: string | undefined): void {
|
|
758
|
+
const addList = addRaw ? JSON.parse(addRaw) as AddItem[] : undefined;
|
|
759
|
+
bulkUpdate(addList);
|
|
760
|
+
}
|
|
761
|
+
`;
|
|
762
|
+
const csharp = compileToCSharp(source, "/test/test.ts", {
|
|
763
|
+
surface: "@tsonic/js",
|
|
764
|
+
});
|
|
765
|
+
expect(csharp).to.include("global::System.Text.Json.JsonSerializer.Deserialize<AddItem__Alias[]>(addRaw)");
|
|
766
|
+
expect(csharp).to.include("bulkUpdate(addList);");
|
|
767
|
+
expect(csharp).not.to.include("bulkUpdate((global::Test.__Anon_");
|
|
768
|
+
});
|
|
769
|
+
it("reuses named structural dictionary value aliases for inline object-type parameters when CLR surfaces align", () => {
|
|
770
|
+
const source = `
|
|
771
|
+
type ProfileEntry = { value: string };
|
|
772
|
+
|
|
773
|
+
declare function updateProfileData(profileData: Record<string, { value: string }>): void;
|
|
774
|
+
|
|
775
|
+
export function run(profileData: Record<string, ProfileEntry>): void {
|
|
776
|
+
updateProfileData(profileData);
|
|
777
|
+
}
|
|
778
|
+
`;
|
|
779
|
+
const csharp = compileToCSharp(source);
|
|
780
|
+
expect(csharp).to.include("global::System.Collections.Generic.Dictionary<string, ProfileEntry__Alias> profileData");
|
|
781
|
+
expect(csharp).to.include("updateProfileData(profileData);");
|
|
782
|
+
expect(csharp).not.to.include("new global::System.Collections.Generic.Dictionary");
|
|
783
|
+
});
|
|
784
|
+
it("preserves imported named dictionary value types on indexed object-literal writes", () => {
|
|
785
|
+
const csharp = compileProjectToCSharp({
|
|
786
|
+
"src/profile-types.ts": `
|
|
787
|
+
export interface ProfileDataValueInput {
|
|
788
|
+
value: string;
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
export type ProfileDataUpdate = Record<string, ProfileDataValueInput>;
|
|
792
|
+
`,
|
|
793
|
+
"src/index.ts": `
|
|
794
|
+
import type { ProfileDataUpdate } from "./profile-types.js";
|
|
795
|
+
|
|
796
|
+
export function run(key: string, rawValue: string): ProfileDataUpdate {
|
|
797
|
+
const result: ProfileDataUpdate = {};
|
|
798
|
+
result[key] = { value: rawValue };
|
|
799
|
+
return result;
|
|
800
|
+
}
|
|
801
|
+
`,
|
|
802
|
+
}, "src/index.ts");
|
|
803
|
+
expect(csharp).not.to.include("ICE: Anonymous object type reached emitter");
|
|
804
|
+
expect(csharp).to.match(/result\[key\]\s*=\s*new\s+ProfileDataValueInput\s*\{\s*value\s*=\s*rawValue\s*\}/);
|
|
805
|
+
});
|
|
806
|
+
it("materializes imported structural alias locals without re-emitting anonymous object types", () => {
|
|
807
|
+
const csharp = compileToCSharp(`
|
|
808
|
+
type AppContext = {
|
|
809
|
+
readonly options: string;
|
|
810
|
+
readonly config: string;
|
|
811
|
+
};
|
|
812
|
+
|
|
813
|
+
export function run(): void {
|
|
814
|
+
const options = "cs";
|
|
815
|
+
const config = "http://localhost:3000";
|
|
816
|
+
const ctx: AppContext = { options, config };
|
|
817
|
+
void ctx;
|
|
818
|
+
}
|
|
819
|
+
`);
|
|
820
|
+
expect(csharp).to.include("class AppContext__Alias");
|
|
821
|
+
expect(csharp).to.match(/AppContext__Alias\s+ctx\s*=\s*new\s+AppContext__Alias\s*\{\s*options\s*=\s*options,\s*config\s*=\s*config\s*\}/);
|
|
822
|
+
expect(csharp).not.to.match(/AppContext__Alias\s+ctx\s*=\s*\(\(global::System\.Func<AppContext__Alias>\)/);
|
|
823
|
+
expect(csharp).not.to.include("ICE: Anonymous object type reached emitter");
|
|
824
|
+
});
|
|
825
|
+
it("preserves compiler-generated anonymous carriers over unrelated structural globals", () => {
|
|
826
|
+
const csharp = compileToCSharp(`
|
|
827
|
+
declare function deepEqual(left: JsValue, right: JsValue): void;
|
|
828
|
+
|
|
829
|
+
export function run(): void {
|
|
830
|
+
const first = { user: { name: "Alice" } };
|
|
831
|
+
const second = { user: { name: "Alice" } };
|
|
832
|
+
deepEqual(first, second);
|
|
833
|
+
}
|
|
834
|
+
`);
|
|
835
|
+
expect(csharp).to.match(/new global::Test\.__Anon_[A-Za-z0-9_]+ \{ user = new global::Test\.__Anon_[A-Za-z0-9_]+ \{ name = "Alice" \} \}/);
|
|
836
|
+
expect(csharp).not.to.include('new global::js.RangeError { name = "Alice" }');
|
|
837
|
+
});
|
|
838
|
+
it("lowers anonymous object type arguments retained in constructor source metadata", () => {
|
|
839
|
+
const csharp = compileToCSharp(`
|
|
840
|
+
import type { long } from "@tsonic/core/types.js";
|
|
841
|
+
import { List } from "@tsonic/dotnet/System.Collections.Generic.js";
|
|
842
|
+
|
|
843
|
+
export function run(userId: long, email: string): long {
|
|
844
|
+
const targetUsers = new List<{ id: long; email: string }>();
|
|
845
|
+
targetUsers.Add({ id: userId, email });
|
|
846
|
+
const target = targetUsers[0];
|
|
847
|
+
return target.id;
|
|
848
|
+
}
|
|
849
|
+
`);
|
|
850
|
+
expect(csharp).to.match(/new global::System\.Collections\.Generic\.List<global::Test\.__Anon_[A-Za-z0-9_]+>\(\)/);
|
|
851
|
+
expect(csharp).to.match(/targetUsers\.Add\(new global::Test\.__Anon_[A-Za-z0-9_]+ \{ id = userId, email = email \}\);/);
|
|
852
|
+
expect(csharp).not.to.include("ICE: Anonymous object type reached emitter");
|
|
853
|
+
});
|
|
854
|
+
it("resolves emitted structural alias storage names during CLR member materialization", () => {
|
|
855
|
+
const csharp = compileToCSharp(`
|
|
856
|
+
import type { JsValue } from "@tsonic/core/types.js";
|
|
857
|
+
import { List } from "@tsonic/dotnet/System.Collections.Generic.js";
|
|
858
|
+
|
|
859
|
+
type NarrowFilter = {
|
|
860
|
+
op: string;
|
|
861
|
+
value: JsValue | undefined;
|
|
862
|
+
negated?: boolean;
|
|
863
|
+
};
|
|
864
|
+
|
|
865
|
+
declare function getObjectField(value: JsValue, key: string): JsValue | undefined;
|
|
866
|
+
|
|
867
|
+
export function parse(entries: JsValue[]): NarrowFilter[] | undefined {
|
|
868
|
+
const filters = new List<NarrowFilter>();
|
|
869
|
+
for (let i = 0; i < entries.length; i++) {
|
|
870
|
+
const entry = entries[i]!;
|
|
871
|
+
if (Array.isArray(entry)) {
|
|
872
|
+
const tuple = entry as JsValue[];
|
|
873
|
+
const filter: NarrowFilter = {
|
|
874
|
+
op: tuple[0] as string,
|
|
875
|
+
value: tuple[1],
|
|
876
|
+
};
|
|
877
|
+
filters.Add(filter);
|
|
878
|
+
continue;
|
|
879
|
+
}
|
|
880
|
+
|
|
881
|
+
const filter: NarrowFilter = {
|
|
882
|
+
op: "operator",
|
|
883
|
+
value: getObjectField(entry, "operand"),
|
|
884
|
+
negated: getObjectField(entry, "negated") === true,
|
|
885
|
+
};
|
|
886
|
+
filters.Add(filter);
|
|
887
|
+
}
|
|
888
|
+
return filters.ToArray();
|
|
889
|
+
}
|
|
890
|
+
`);
|
|
891
|
+
expect(csharp).to.include("class NarrowFilter__Alias");
|
|
892
|
+
expect(csharp).to.include("new global::System.Collections.Generic.List<NarrowFilter__Alias>()");
|
|
893
|
+
expect(csharp).to.include("filters.Add(filter);");
|
|
894
|
+
expect(csharp).to.include("return filters.ToArray();");
|
|
895
|
+
expect(csharp).not.to.include("ICE: Unresolved reference type");
|
|
896
|
+
});
|
|
897
|
+
it("reuses structural alias carrier members in typeof checks over boolean unions", () => {
|
|
898
|
+
const csharp = compileToCSharp(`
|
|
899
|
+
import type { int } from "@tsonic/core/types.js";
|
|
900
|
+
|
|
901
|
+
type MkdirOptions = {
|
|
902
|
+
readonly recursive?: boolean;
|
|
903
|
+
readonly mode?: int;
|
|
904
|
+
};
|
|
905
|
+
|
|
906
|
+
export function isRecursive(options?: boolean | MkdirOptions): boolean {
|
|
907
|
+
if (options === undefined) {
|
|
908
|
+
return false;
|
|
909
|
+
}
|
|
910
|
+
|
|
911
|
+
if (typeof options === "boolean") {
|
|
912
|
+
return options;
|
|
913
|
+
}
|
|
914
|
+
|
|
915
|
+
return options.recursive === true;
|
|
916
|
+
}
|
|
917
|
+
`);
|
|
918
|
+
expect(csharp).to.include("class MkdirOptions__Alias");
|
|
919
|
+
expect(csharp).to.include("((global::System.Object)(options)) != null");
|
|
920
|
+
expect(csharp).to.include("options.Is1()");
|
|
921
|
+
expect(csharp).not.to.include("ICE: Anonymous object type reached emitter");
|
|
922
|
+
});
|
|
923
|
+
it("normalizes imported clr constructor values in instanceof checks", () => {
|
|
924
|
+
const csharp = compileToCSharp(`
|
|
925
|
+
import { FileNotFoundException } from "@tsonic/dotnet/System.IO.js";
|
|
926
|
+
|
|
927
|
+
export function isMissing(error: JsValue): boolean {
|
|
928
|
+
return error instanceof FileNotFoundException;
|
|
929
|
+
}
|
|
930
|
+
`);
|
|
931
|
+
expect(csharp).to.include("is global::System.IO.FileNotFoundException");
|
|
932
|
+
expect(csharp).not.to.include("ICE: Anonymous object type reached emitter");
|
|
933
|
+
});
|
|
934
|
+
it("directly specializes async promise-return overloads when omitted parameters fold away", () => {
|
|
935
|
+
const csharp = compileToCSharp(`
|
|
936
|
+
import { overloads as O } from "@tsonic/core/lang.js";
|
|
937
|
+
|
|
938
|
+
export function readValue(flag: boolean): Promise<boolean>;
|
|
939
|
+
export function readValue(flag: boolean, encoding: string): Promise<string>;
|
|
940
|
+
export async function readValue(_flag: any, _encoding?: any): Promise<any> {
|
|
941
|
+
throw new Error("stub");
|
|
942
|
+
}
|
|
943
|
+
|
|
944
|
+
export async function readValue_flag(flag: boolean): Promise<boolean> {
|
|
945
|
+
return flag;
|
|
946
|
+
}
|
|
947
|
+
|
|
948
|
+
export async function readValue_encoding(
|
|
949
|
+
flag: boolean,
|
|
950
|
+
encoding: string
|
|
951
|
+
): Promise<string> {
|
|
952
|
+
void flag;
|
|
953
|
+
return encoding;
|
|
954
|
+
}
|
|
955
|
+
|
|
956
|
+
O(readValue_flag).family(readValue);
|
|
957
|
+
O(readValue_encoding).family(readValue);
|
|
958
|
+
`);
|
|
959
|
+
expect(csharp).to.include("public static async global::System.Threading.Tasks.Task<bool> readValue(bool flag)");
|
|
960
|
+
expect(csharp).to.include("public static async global::System.Threading.Tasks.Task<string> readValue(bool flag, string encoding)");
|
|
961
|
+
expect(csharp).to.include("return flag;");
|
|
962
|
+
expect(csharp).to.include("return encoding;");
|
|
963
|
+
expect(csharp).not.to.include("readValue_flag");
|
|
964
|
+
expect(csharp).not.to.include("readValue_encoding");
|
|
965
|
+
});
|
|
966
|
+
it("directly specializes awaited array-or-string overloads when omitted parameters fold away", () => {
|
|
967
|
+
const csharp = compileToCSharp(`
|
|
968
|
+
import { overloads as O } from "@tsonic/core/lang.js";
|
|
969
|
+
import type { byte } from "@tsonic/core/types.js";
|
|
970
|
+
|
|
971
|
+
declare function implBytes(path: string): Promise<byte[]>;
|
|
972
|
+
declare function implText(path: string, encoding: string): Promise<string>;
|
|
973
|
+
|
|
974
|
+
export function readFile(path: string): Promise<byte[]>;
|
|
975
|
+
export function readFile(path: string, encoding: string): Promise<string>;
|
|
976
|
+
export async function readFile(_path: any, _encoding?: any): Promise<any> {
|
|
977
|
+
throw new Error("stub");
|
|
978
|
+
}
|
|
979
|
+
|
|
980
|
+
export async function readFile_bytes(path: string): Promise<byte[]> {
|
|
981
|
+
return await implBytes(path);
|
|
982
|
+
}
|
|
983
|
+
|
|
984
|
+
export async function readFile_text(
|
|
985
|
+
path: string,
|
|
986
|
+
encoding: string
|
|
987
|
+
): Promise<string> {
|
|
988
|
+
return await implText(path, encoding);
|
|
989
|
+
}
|
|
990
|
+
|
|
991
|
+
O(readFile_bytes).family(readFile);
|
|
992
|
+
O(readFile_text).family(readFile);
|
|
993
|
+
`);
|
|
994
|
+
expect(csharp).to.include("public static async global::System.Threading.Tasks.Task<byte[]> readFile(string path)");
|
|
995
|
+
expect(csharp).to.include("public static async global::System.Threading.Tasks.Task<string> readFile(string path, string encoding)");
|
|
996
|
+
expect(csharp).to.include("return await implBytes(path);");
|
|
997
|
+
expect(csharp).to.include("return await implText(path, encoding);");
|
|
998
|
+
expect(csharp).not.to.include("readFile_bytes");
|
|
999
|
+
expect(csharp).not.to.include("readFile_text");
|
|
1000
|
+
});
|
|
1001
|
+
it("re-lowers refreshed anonymous array element carriers before emission", () => {
|
|
1002
|
+
const csharp = compileToCSharp(`
|
|
1003
|
+
const buildListenerAttempts = (): { prefixes: string[]; address: string; family: string }[] => {
|
|
1004
|
+
return [
|
|
1005
|
+
{
|
|
1006
|
+
prefixes: ["http://127.0.0.1:8080/"],
|
|
1007
|
+
address: "127.0.0.1",
|
|
1008
|
+
family: "IPv4",
|
|
1009
|
+
},
|
|
1010
|
+
];
|
|
1011
|
+
};
|
|
1012
|
+
|
|
1013
|
+
export function readAddress(): string {
|
|
1014
|
+
const attempts = buildListenerAttempts();
|
|
1015
|
+
|
|
1016
|
+
for (const attempt of attempts) {
|
|
1017
|
+
return attempt.address;
|
|
1018
|
+
}
|
|
1019
|
+
|
|
1020
|
+
return "";
|
|
1021
|
+
}
|
|
1022
|
+
`);
|
|
1023
|
+
expect(csharp).to.include("class __Anon_");
|
|
1024
|
+
expect(csharp).to.include("foreach");
|
|
1025
|
+
expect(csharp).not.to.include("ICE: Anonymous object type reached emitter");
|
|
1026
|
+
});
|
|
1027
|
+
it("null-checks optional typeof runtime-union guards before member tests", () => {
|
|
1028
|
+
const csharp = compileToCSharp(`
|
|
1029
|
+
import type { int } from "@tsonic/core/types.js";
|
|
1030
|
+
|
|
1031
|
+
type MkdirOptions = {
|
|
1032
|
+
readonly recursive?: boolean;
|
|
1033
|
+
readonly mode?: int;
|
|
1034
|
+
};
|
|
1035
|
+
|
|
1036
|
+
export function pickRecursive(options?: boolean | MkdirOptions): boolean {
|
|
1037
|
+
const recursive =
|
|
1038
|
+
typeof options === "boolean" ? options : options?.recursive ?? false;
|
|
1039
|
+
return recursive;
|
|
1040
|
+
}
|
|
1041
|
+
`);
|
|
1042
|
+
expect(csharp).to.include("((global::System.Object)(options)) != null");
|
|
1043
|
+
expect(csharp).to.include("options.Is1()");
|
|
1044
|
+
});
|
|
1045
|
+
it("preserves undefined in typeof complement branches for optional union receivers", () => {
|
|
1046
|
+
const csharp = compileToCSharp(`
|
|
1047
|
+
type ServerOpts = {
|
|
1048
|
+
readonly allowHalfOpen?: boolean;
|
|
1049
|
+
readonly pauseOnConnect?: boolean;
|
|
1050
|
+
};
|
|
1051
|
+
|
|
1052
|
+
export class ServerLike {
|
|
1053
|
+
private readonly _allowHalfOpen: boolean;
|
|
1054
|
+
|
|
1055
|
+
constructor(
|
|
1056
|
+
optionsOrListener?: ServerOpts | (() => void)
|
|
1057
|
+
) {
|
|
1058
|
+
if (typeof optionsOrListener === "function") {
|
|
1059
|
+
this._allowHalfOpen = false;
|
|
1060
|
+
} else {
|
|
1061
|
+
this._allowHalfOpen = optionsOrListener?.allowHalfOpen ?? false;
|
|
1062
|
+
}
|
|
1063
|
+
}
|
|
1064
|
+
}
|
|
1065
|
+
`);
|
|
1066
|
+
expect(csharp).to.include("((object)optionsOrListener == null ? default(ServerOpts__Alias) : (optionsOrListener.As2()))?.allowHalfOpen");
|
|
1067
|
+
expect(csharp).to.not.include("(optionsOrListener.As2())?.allowHalfOpen");
|
|
1068
|
+
});
|
|
1069
|
+
it("preserves original runtime union slots across chained typeof object branches", () => {
|
|
1070
|
+
const csharp = compileToCSharp(`
|
|
1071
|
+
import type { int } from "@tsonic/core/types.js";
|
|
1072
|
+
|
|
1073
|
+
type BindOptions = {
|
|
1074
|
+
readonly fd?: int;
|
|
1075
|
+
readonly port?: int;
|
|
1076
|
+
readonly address?: string;
|
|
1077
|
+
};
|
|
1078
|
+
|
|
1079
|
+
export function bindLike(
|
|
1080
|
+
portOrCallbackOrOptions?: int | (() => void) | BindOptions
|
|
1081
|
+
): int {
|
|
1082
|
+
if (typeof portOrCallbackOrOptions === "function") {
|
|
1083
|
+
return 0;
|
|
1084
|
+
} else if (
|
|
1085
|
+
typeof portOrCallbackOrOptions === "object" &&
|
|
1086
|
+
portOrCallbackOrOptions !== null &&
|
|
1087
|
+
portOrCallbackOrOptions !== undefined
|
|
1088
|
+
) {
|
|
1089
|
+
return portOrCallbackOrOptions.port ?? 0;
|
|
1090
|
+
}
|
|
1091
|
+
|
|
1092
|
+
return portOrCallbackOrOptions ?? 0;
|
|
1093
|
+
}
|
|
1094
|
+
`);
|
|
1095
|
+
expect(csharp).to.include("portOrCallbackOrOptions.Is3()");
|
|
1096
|
+
expect(csharp).to.not.include("portOrCallbackOrOptions.Is2()");
|
|
1097
|
+
expect(csharp).to.not.include("(portOrCallbackOrOptions.As2())");
|
|
1098
|
+
expect(csharp).to.not.include("((global::Tsonic.Internal.Union<int, BindOptions>?)portOrCallbackOrOptions)");
|
|
1099
|
+
});
|
|
1100
|
+
it("emits source-owned union aliases with source alias carrier names", () => {
|
|
1101
|
+
const csharp = compileToCSharp(`
|
|
1102
|
+
class Ok<T> {
|
|
1103
|
+
constructor(public value: T) {}
|
|
1104
|
+
}
|
|
1105
|
+
|
|
1106
|
+
class Err<E> {
|
|
1107
|
+
constructor(public error: E) {}
|
|
1108
|
+
}
|
|
1109
|
+
|
|
1110
|
+
type Result<T, E> = Ok<T> | Err<E>;
|
|
1111
|
+
|
|
1112
|
+
export function ok(value: string): Result<string, string> {
|
|
1113
|
+
return new Ok(value);
|
|
1114
|
+
}
|
|
1115
|
+
`);
|
|
1116
|
+
expect(csharp).to.include("public sealed class Result<T, E>");
|
|
1117
|
+
expect(csharp).to.include("global::Test.Result<");
|
|
1118
|
+
expect(csharp).to.include(".From");
|
|
1119
|
+
expect(csharp).to.not.include("Tsonic.Internal.Union");
|
|
1120
|
+
});
|
|
1121
|
+
it("directly specializes async void overloads when omitted parameters fold away", () => {
|
|
1122
|
+
const csharp = compileToCSharp(`
|
|
1123
|
+
import { overloads as O } from "@tsonic/core/lang.js";
|
|
1124
|
+
|
|
1125
|
+
declare function implDefault(path: string): Promise<void>;
|
|
1126
|
+
declare function implRecursive(path: string, recursive: boolean): Promise<void>;
|
|
1127
|
+
|
|
1128
|
+
export function mkdir(path: string): Promise<void>;
|
|
1129
|
+
export function mkdir(path: string, recursive: boolean): Promise<void>;
|
|
1130
|
+
export async function mkdir(_path: any, _recursive?: any): Promise<any> {
|
|
1131
|
+
throw new Error("stub");
|
|
1132
|
+
}
|
|
1133
|
+
|
|
1134
|
+
export async function mkdir_default(path: string): Promise<void> {
|
|
1135
|
+
return await implDefault(path);
|
|
1136
|
+
}
|
|
1137
|
+
|
|
1138
|
+
export async function mkdir_recursive(
|
|
1139
|
+
path: string,
|
|
1140
|
+
recursive: boolean
|
|
1141
|
+
): Promise<void> {
|
|
1142
|
+
return await implRecursive(path, recursive);
|
|
1143
|
+
}
|
|
1144
|
+
|
|
1145
|
+
O(mkdir_default).family(mkdir);
|
|
1146
|
+
O(mkdir_recursive).family(mkdir);
|
|
1147
|
+
`);
|
|
1148
|
+
expect(csharp).to.include("public static async global::System.Threading.Tasks.Task mkdir(string path)");
|
|
1149
|
+
expect(csharp).to.include("public static async global::System.Threading.Tasks.Task mkdir(string path, bool recursive)");
|
|
1150
|
+
expect(csharp).to.include("await implDefault(path);");
|
|
1151
|
+
expect(csharp).to.include("await implRecursive(path, recursive);");
|
|
1152
|
+
expect(csharp).to.not.include("__tsonic_discard");
|
|
1153
|
+
expect(csharp).to.not.include("mkdir_default");
|
|
1154
|
+
expect(csharp).to.not.include("mkdir_recursive");
|
|
1155
|
+
});
|
|
1156
|
+
it("reuses named structural option types in directly specialized overloads", () => {
|
|
1157
|
+
const csharp = compileToCSharp(`
|
|
1158
|
+
import { overloads as O } from "@tsonic/core/lang.js";
|
|
1159
|
+
import type { int } from "@tsonic/core/types.js";
|
|
1160
|
+
|
|
1161
|
+
export class MkdirOptions {
|
|
1162
|
+
public recursive?: boolean;
|
|
1163
|
+
public mode?: int;
|
|
1164
|
+
}
|
|
1165
|
+
|
|
1166
|
+
declare function implDefault(path: string): Promise<void>;
|
|
1167
|
+
declare function implRecursive(path: string, recursive: boolean): Promise<void>;
|
|
1168
|
+
declare function implOptions(path: string, options: MkdirOptions): Promise<void>;
|
|
1169
|
+
|
|
1170
|
+
export function mkdir(path: string): Promise<void>;
|
|
1171
|
+
export function mkdir(path: string, recursive: boolean): Promise<void>;
|
|
1172
|
+
export function mkdir(path: string, options: { recursive?: boolean; mode?: int }): Promise<void>;
|
|
1173
|
+
export async function mkdir(_path: any, _options?: any): Promise<any> {
|
|
1174
|
+
throw new Error("stub");
|
|
1175
|
+
}
|
|
1176
|
+
export async function mkdir_default(path: string): Promise<void> {
|
|
1177
|
+
return await implDefault(path);
|
|
1178
|
+
}
|
|
1179
|
+
export async function mkdir_recursive(
|
|
1180
|
+
path: string,
|
|
1181
|
+
recursive: boolean
|
|
1182
|
+
): Promise<void> {
|
|
1183
|
+
return await implRecursive(path, recursive);
|
|
1184
|
+
}
|
|
1185
|
+
export async function mkdir_options(
|
|
1186
|
+
path: string,
|
|
1187
|
+
options: MkdirOptions
|
|
1188
|
+
): Promise<void> {
|
|
1189
|
+
return await implOptions(path, options);
|
|
1190
|
+
}
|
|
1191
|
+
|
|
1192
|
+
O(mkdir_default).family(mkdir);
|
|
1193
|
+
O(mkdir_recursive).family(mkdir);
|
|
1194
|
+
O(mkdir_options).family(mkdir);
|
|
1195
|
+
`);
|
|
1196
|
+
expect(csharp).to.include("public static async global::System.Threading.Tasks.Task mkdir(string path, MkdirOptions options)");
|
|
1197
|
+
expect(csharp).to.include("await implOptions(path, options);");
|
|
1198
|
+
expect(csharp).to.not.include("public static global::System.Threading.Tasks.Task mkdir(string path, global::Test.__Anon_");
|
|
1199
|
+
expect(csharp).to.not.include("global::Tsonic.Internal.Union<bool, __Anon_");
|
|
1200
|
+
});
|
|
1201
|
+
it("adapts named structural instances at structural overload call sites", () => {
|
|
1202
|
+
const csharp = compileToCSharp(`
|
|
1203
|
+
import type { int } from "@tsonic/core/types.js";
|
|
1204
|
+
|
|
1205
|
+
export class MkdirOptions {
|
|
1206
|
+
public recursive?: boolean;
|
|
1207
|
+
public mode?: int;
|
|
1208
|
+
}
|
|
1209
|
+
|
|
1210
|
+
declare const fs: {
|
|
1211
|
+
mkdirSync(path: string): void;
|
|
1212
|
+
mkdirSync(path: string, recursive: boolean): void;
|
|
1213
|
+
mkdirSync(path: string, options: { recursive?: boolean; mode?: int }): void;
|
|
1214
|
+
};
|
|
1215
|
+
|
|
1216
|
+
export function ensure(dir: string): void {
|
|
1217
|
+
const options = new MkdirOptions();
|
|
1218
|
+
options.recursive = true;
|
|
1219
|
+
fs.mkdirSync(dir, options);
|
|
1220
|
+
}
|
|
1221
|
+
`);
|
|
1222
|
+
expect(csharp).to.include("fs.mkdirSync(dir, new global::Test.__Anon_");
|
|
1223
|
+
expect(csharp).to.include("recursive = options.recursive");
|
|
1224
|
+
expect(csharp).to.include("mode = options.mode");
|
|
1225
|
+
expect(csharp).to.not.include("fs.mkdirSync(dir, options);");
|
|
1226
|
+
});
|
|
1227
|
+
it("preserves imported named structural instances at structural overload call sites", () => {
|
|
1228
|
+
const csharp = compileToCSharp(`
|
|
1229
|
+
import { fs, MkdirOptions } from "@tsonic/nodejs/fs.js";
|
|
1230
|
+
|
|
1231
|
+
export function ensure(dir: string): void {
|
|
1232
|
+
const options = new MkdirOptions();
|
|
1233
|
+
options.recursive = true;
|
|
1234
|
+
fs.mkdirSync(dir, options);
|
|
1235
|
+
}
|
|
1236
|
+
`, "/test/test.ts", { surface: "@tsonic/js" });
|
|
1237
|
+
expect(csharp).to.include("fs.mkdirSync(dir, options);");
|
|
1238
|
+
expect(csharp).to.not.include("fs.mkdirSync(dir, new global::js.__Anon_");
|
|
1239
|
+
});
|
|
1240
|
+
it("preserves imported named structural instances at async structural overload call sites", () => {
|
|
1241
|
+
const csharp = compileToCSharp(`
|
|
1242
|
+
import { fs, MkdirOptions } from "@tsonic/nodejs/fs.js";
|
|
1243
|
+
|
|
1244
|
+
export async function ensure(dir: string): Promise<void> {
|
|
1245
|
+
const options = new MkdirOptions();
|
|
1246
|
+
options.recursive = true;
|
|
1247
|
+
await fs.mkdir(dir, options);
|
|
1248
|
+
}
|
|
1249
|
+
`, "/test/test.ts", { surface: "@tsonic/js" });
|
|
1250
|
+
expect(csharp).to.include("fs.mkdir(dir, options)");
|
|
1251
|
+
expect(csharp).to.not.include("fs.mkdir(dir, new global::js.__Anon_");
|
|
1252
|
+
});
|
|
1253
|
+
it("materializes imported structural object literals at structural overload call sites", () => {
|
|
1254
|
+
const csharp = compileProjectToCSharp({
|
|
1255
|
+
"package.json": JSON.stringify({ name: "emitter-test-project", version: "1.0.0", type: "module" }, null, 2),
|
|
1256
|
+
"src/index.ts": [
|
|
1257
|
+
'import { fs, MkdirOptions } from "@tsonic/nodejs/fs.js";',
|
|
1258
|
+
"",
|
|
1259
|
+
"export function ensure(dir: string): void {",
|
|
1260
|
+
" const options = new MkdirOptions();",
|
|
1261
|
+
" options.recursive = true;",
|
|
1262
|
+
" fs.mkdirSync(dir, { recursive: options.recursive, mode: options.mode });",
|
|
1263
|
+
"}",
|
|
1264
|
+
].join("\n"),
|
|
1265
|
+
}, "src/index.ts", { surface: "@tsonic/js" });
|
|
1266
|
+
expect(csharp).to.include("fs.mkdirSync(dir, new global::nodejs.MkdirOptions { recursive = options.recursive, mode = options.mode });");
|
|
1267
|
+
expect(csharp).to.not.include("fs.mkdirSync(dir, new global::js.__Anon_");
|
|
1268
|
+
});
|
|
1269
|
+
it("materializes imported structural object literals at async structural overload call sites", () => {
|
|
1270
|
+
const csharp = compileProjectToCSharp({
|
|
1271
|
+
"package.json": JSON.stringify({ name: "emitter-test-project", version: "1.0.0", type: "module" }, null, 2),
|
|
1272
|
+
"src/index.ts": [
|
|
1273
|
+
'import { fs, MkdirOptions } from "@tsonic/nodejs/fs.js";',
|
|
1274
|
+
"",
|
|
1275
|
+
"export async function ensure(dir: string): Promise<void> {",
|
|
1276
|
+
" const options = new MkdirOptions();",
|
|
1277
|
+
" options.recursive = true;",
|
|
1278
|
+
" await fs.mkdir(dir, { recursive: options.recursive, mode: options.mode });",
|
|
1279
|
+
"}",
|
|
1280
|
+
].join("\n"),
|
|
1281
|
+
}, "src/index.ts", { surface: "@tsonic/js" });
|
|
1282
|
+
expect(csharp).to.include("new global::nodejs.MkdirOptions");
|
|
1283
|
+
expect(csharp).to.not.include("new global::js.__Anon_");
|
|
1284
|
+
});
|
|
1285
|
+
it("emits generic property empty-array initializers using the declared element type", () => {
|
|
1286
|
+
const csharp = compileToCSharp(`
|
|
1287
|
+
export class Box<T> {
|
|
1288
|
+
public items: Array<T | null> = [] as Array<T | null>;
|
|
1289
|
+
}
|
|
1290
|
+
`);
|
|
1291
|
+
expect(csharp).to.include("public T?[] items { get; set; } = global::System.Array.Empty<T?>();");
|
|
1292
|
+
expect(csharp).not.to.include("Select<double, T?>");
|
|
1293
|
+
});
|
|
1294
|
+
it("emits generic undefined constructor arguments using the generic default type", () => {
|
|
1295
|
+
const csharp = compileToCSharp(`
|
|
1296
|
+
export class IntervalIterationResult<T> {
|
|
1297
|
+
public constructor(
|
|
1298
|
+
public readonly done: boolean,
|
|
1299
|
+
public readonly value: T | undefined
|
|
1300
|
+
) {}
|
|
1301
|
+
}
|
|
1302
|
+
|
|
1303
|
+
export class IntervalAsyncIterator<T> {
|
|
1304
|
+
public close(): IntervalIterationResult<T> {
|
|
1305
|
+
return new IntervalIterationResult(true, undefined);
|
|
1306
|
+
}
|
|
1307
|
+
}
|
|
1308
|
+
`);
|
|
1309
|
+
expect(csharp).to.include("new IntervalIterationResult<T>(true, default(T))");
|
|
1310
|
+
expect(csharp).not.to.include("default(object)");
|
|
1311
|
+
});
|
|
1312
|
+
it("directly specializes promise-union overload families across module and class methods", () => {
|
|
1313
|
+
const csharp = compileToCSharp(`
|
|
1314
|
+
import { overloads as O } from "@tsonic/core/lang.js";
|
|
1315
|
+
import type { byte } from "@tsonic/core/types.js";
|
|
1316
|
+
|
|
1317
|
+
declare function implBytes(path: string): Promise<byte[]>;
|
|
1318
|
+
declare function implText(path: string, encoding: string): Promise<string>;
|
|
1319
|
+
|
|
1320
|
+
export function readFile(path: string): Promise<byte[]>;
|
|
1321
|
+
export function readFile(path: string, encoding: string): Promise<string>;
|
|
1322
|
+
export async function readFile(_path: any, _encoding?: any): Promise<any> {
|
|
1323
|
+
throw new Error("stub");
|
|
1324
|
+
}
|
|
1325
|
+
export async function readFile_bytes(path: string): Promise<byte[]> {
|
|
1326
|
+
return await implBytes(path);
|
|
1327
|
+
}
|
|
1328
|
+
export async function readFile_text(
|
|
1329
|
+
path: string,
|
|
1330
|
+
encoding: string
|
|
1331
|
+
): Promise<string> {
|
|
1332
|
+
return await implText(path, encoding);
|
|
1333
|
+
}
|
|
1334
|
+
|
|
1335
|
+
O(readFile_bytes).family(readFile);
|
|
1336
|
+
O(readFile_text).family(readFile);
|
|
1337
|
+
|
|
1338
|
+
export class FsPromises {
|
|
1339
|
+
public readFile(path: string): Promise<byte[]>;
|
|
1340
|
+
public readFile(path: string, encoding: string): Promise<string>;
|
|
1341
|
+
public readFile(_path: any, _encoding?: any): any {
|
|
1342
|
+
throw new Error("stub");
|
|
1343
|
+
}
|
|
1344
|
+
public readFile_bytes(path: string): Promise<byte[]> {
|
|
1345
|
+
return readFile(path);
|
|
1346
|
+
}
|
|
1347
|
+
public readFile_text(path: string, encoding: string): Promise<string> {
|
|
1348
|
+
return readFile(path, encoding);
|
|
1349
|
+
}
|
|
1350
|
+
}
|
|
1351
|
+
|
|
1352
|
+
O<FsPromises>().method(x => x.readFile_bytes).family(x => x.readFile);
|
|
1353
|
+
O<FsPromises>().method(x => x.readFile_text).family(x => x.readFile);
|
|
1354
|
+
`);
|
|
1355
|
+
expect(csharp).to.include("public global::System.Threading.Tasks.Task<byte[]> readFile(string path)");
|
|
1356
|
+
expect(csharp).to.include("public global::System.Threading.Tasks.Task<string> readFile(string path, string encoding)");
|
|
1357
|
+
expect(csharp).to.include("return readFile(path);");
|
|
1358
|
+
expect(csharp).to.include("return readFile(path, encoding);");
|
|
1359
|
+
expect(csharp).not.to.include("__tsonic_overload_impl_readFile");
|
|
1360
|
+
expect(csharp).to.not.include("(global::System.Threading.Tasks.Task<global::Tsonic.Internal.Union<byte[], string>>)test.readFile(path)");
|
|
1361
|
+
});
|
|
1362
|
+
it("directly specializes sync array-or-string overloads when omitted parameters fold away", () => {
|
|
1363
|
+
const csharp = compileToCSharp(`
|
|
1364
|
+
import { overloads as O } from "@tsonic/core/lang.js";
|
|
1365
|
+
import type { byte } from "@tsonic/core/types.js";
|
|
1366
|
+
|
|
1367
|
+
declare function implBytes(path: string): byte[];
|
|
1368
|
+
declare function implText(path: string, encoding: string): string;
|
|
1369
|
+
|
|
1370
|
+
export function readFileSync(path: string): byte[];
|
|
1371
|
+
export function readFileSync(path: string, encoding: string): string;
|
|
1372
|
+
export function readFileSync(_path: any, _encoding?: any): any {
|
|
1373
|
+
throw new Error("stub");
|
|
1374
|
+
}
|
|
1375
|
+
|
|
1376
|
+
export function readFileSync_bytes(path: string): byte[] {
|
|
1377
|
+
return implBytes(path);
|
|
1378
|
+
}
|
|
1379
|
+
|
|
1380
|
+
export function readFileSync_text(
|
|
1381
|
+
path: string,
|
|
1382
|
+
encoding: string
|
|
1383
|
+
): string {
|
|
1384
|
+
return implText(path, encoding);
|
|
1385
|
+
}
|
|
1386
|
+
|
|
1387
|
+
O(readFileSync_bytes).family(readFileSync);
|
|
1388
|
+
O(readFileSync_text).family(readFileSync);
|
|
1389
|
+
|
|
1390
|
+
export class FsModuleNamespace {
|
|
1391
|
+
public readFileSync(path: string): byte[];
|
|
1392
|
+
public readFileSync(path: string, encoding: string): string;
|
|
1393
|
+
public readFileSync(_path: any, _encoding?: any): any {
|
|
1394
|
+
throw new Error("stub");
|
|
1395
|
+
}
|
|
1396
|
+
|
|
1397
|
+
public readFileSync_bytes(path: string): byte[] {
|
|
1398
|
+
return readFileSync(path);
|
|
1399
|
+
}
|
|
1400
|
+
|
|
1401
|
+
public readFileSync_text(path: string, encoding: string): string {
|
|
1402
|
+
return readFileSync(path, encoding);
|
|
1403
|
+
}
|
|
1404
|
+
}
|
|
1405
|
+
|
|
1406
|
+
O<FsModuleNamespace>().method(x => x.readFileSync_bytes).family(
|
|
1407
|
+
x => x.readFileSync
|
|
1408
|
+
);
|
|
1409
|
+
O<FsModuleNamespace>().method(x => x.readFileSync_text).family(
|
|
1410
|
+
x => x.readFileSync
|
|
1411
|
+
);
|
|
1412
|
+
`);
|
|
1413
|
+
expect(csharp).to.include("public static byte[] readFileSync(string path)");
|
|
1414
|
+
expect(csharp).to.include("public static string readFileSync(string path, string encoding)");
|
|
1415
|
+
expect(csharp).to.include("public byte[] readFileSync(string path)");
|
|
1416
|
+
expect(csharp).to.include("public string readFileSync(string path, string encoding)");
|
|
1417
|
+
expect(csharp).to.include("return implBytes(path);");
|
|
1418
|
+
expect(csharp).to.include("return implText(path, encoding);");
|
|
1419
|
+
expect(csharp).to.include("return readFileSync(path);");
|
|
1420
|
+
expect(csharp).to.include("return readFileSync(path, encoding);");
|
|
1421
|
+
expect(csharp).not.to.include("readFileSync_bytes");
|
|
1422
|
+
expect(csharp).not.to.include("readFileSync_text");
|
|
1423
|
+
});
|
|
1424
|
+
it("directly specializes sync structural nominal unions when omitted parameters fold away", () => {
|
|
1425
|
+
const csharp = compileToCSharp(`
|
|
1426
|
+
import { overloads as O } from "@tsonic/core/lang.js";
|
|
1427
|
+
|
|
1428
|
+
declare class Buffer {
|
|
1429
|
+
readonly length: number;
|
|
1430
|
+
}
|
|
1431
|
+
|
|
1432
|
+
declare function implBytes(path: string): Buffer;
|
|
1433
|
+
declare function implText(path: string, encoding: string): string;
|
|
1434
|
+
|
|
1435
|
+
export function readFileSync(path: string): Buffer;
|
|
1436
|
+
export function readFileSync(path: string, encoding: string): string;
|
|
1437
|
+
export function readFileSync(_path: any, _encoding?: any): any {
|
|
1438
|
+
throw new Error("stub");
|
|
1439
|
+
}
|
|
1440
|
+
|
|
1441
|
+
export function readFileSync_buffer(path: string): Buffer {
|
|
1442
|
+
return implBytes(path);
|
|
1443
|
+
}
|
|
1444
|
+
|
|
1445
|
+
export function readFileSync_text(
|
|
1446
|
+
path: string,
|
|
1447
|
+
encoding: string
|
|
1448
|
+
): string {
|
|
1449
|
+
return implText(path, encoding);
|
|
1450
|
+
}
|
|
1451
|
+
|
|
1452
|
+
O(readFileSync_buffer).family(readFileSync);
|
|
1453
|
+
O(readFileSync_text).family(readFileSync);
|
|
1454
|
+
`);
|
|
1455
|
+
expect(csharp).to.include("public static global::Test.Buffer readFileSync(string path)");
|
|
1456
|
+
expect(csharp).to.include("public static string readFileSync(string path, string encoding)");
|
|
1457
|
+
expect(csharp).to.include("return implBytes(path);");
|
|
1458
|
+
expect(csharp).to.include("return implText(path, encoding);");
|
|
1459
|
+
expect(csharp).not.to.include("readFileSync_buffer");
|
|
1460
|
+
expect(csharp).not.to.include("readFileSync_text");
|
|
1461
|
+
expect(csharp).not.to.include("global::Tsonic.Internal.Union<string, global::Test.Buffer>");
|
|
1462
|
+
});
|
|
1463
|
+
it("prefers deterministic numeric overloads for erased number arguments", () => {
|
|
1464
|
+
const csharp = compileToCSharp(`
|
|
1465
|
+
import type { byte, double, int, long } from "@tsonic/core/types.js";
|
|
1466
|
+
|
|
1467
|
+
declare class Convert {
|
|
1468
|
+
static ToInt32(value: byte): int;
|
|
1469
|
+
static ToInt32(value: double): int;
|
|
1470
|
+
static ToInt64(value: byte): long;
|
|
1471
|
+
static ToInt64(value: double): long;
|
|
1472
|
+
}
|
|
1473
|
+
|
|
1474
|
+
declare const holder: { readonly TotalMilliseconds: double };
|
|
1475
|
+
|
|
1476
|
+
export function fromMember(): long {
|
|
1477
|
+
return Convert.ToInt64(holder.TotalMilliseconds);
|
|
1478
|
+
}
|
|
1479
|
+
|
|
1480
|
+
export function fromBinary(month: number): int {
|
|
1481
|
+
return Convert.ToInt32(month + 1);
|
|
1482
|
+
}
|
|
1483
|
+
|
|
1484
|
+
export function fromExplicit(value: byte): int {
|
|
1485
|
+
return Convert.ToInt32(value);
|
|
1486
|
+
}
|
|
1487
|
+
`);
|
|
1488
|
+
expect(csharp).to.include("return global::System.Convert.ToInt64(holder.TotalMilliseconds);");
|
|
1489
|
+
expect(csharp).to.include("return global::System.Convert.ToInt32(month + 1);");
|
|
1490
|
+
expect(csharp).to.include("return global::System.Convert.ToInt32(value);");
|
|
1491
|
+
expect(csharp).not.to.include("return global::System.Convert.ToInt64((byte)holder.TotalMilliseconds);");
|
|
1492
|
+
expect(csharp).not.to.include("return global::System.Convert.ToInt32((byte)(month + 1));");
|
|
1493
|
+
});
|
|
1494
|
+
it("casts broad JS numbers to imported CLR integral overload parameters", () => {
|
|
1495
|
+
const csharp = compileToCSharp(`
|
|
1496
|
+
import type { int } from "@tsonic/core/types.js";
|
|
1497
|
+
import { Process } from "@tsonic/dotnet/System.Diagnostics.js";
|
|
1498
|
+
|
|
1499
|
+
declare const process: Process;
|
|
1500
|
+
|
|
1501
|
+
class ExecOptions {
|
|
1502
|
+
public timeout: number = 0;
|
|
1503
|
+
}
|
|
1504
|
+
|
|
1505
|
+
export function run(options?: ExecOptions | null): boolean {
|
|
1506
|
+
const timeout = options?.timeout ?? 0;
|
|
1507
|
+
return process.WaitForExit(timeout);
|
|
1508
|
+
}
|
|
1509
|
+
`);
|
|
1510
|
+
expect(csharp).to.include("return process.WaitForExit((int)timeout);");
|
|
1511
|
+
expect(csharp).not.to.include("return process.WaitForExit(timeout);");
|
|
1512
|
+
});
|
|
1513
|
+
it("null-checks optional Array.isArray runtime-union guards before member tests", () => {
|
|
1514
|
+
const csharp = compileToCSharp(`
|
|
1515
|
+
export function hasArray(values?: string[] | number): boolean {
|
|
1516
|
+
return Array.isArray(values);
|
|
1517
|
+
}
|
|
1518
|
+
`);
|
|
1519
|
+
expect(csharp).to.include("((global::System.Object)(values)) != null");
|
|
1520
|
+
expect(csharp).to.include("values.Is1()");
|
|
1521
|
+
});
|
|
1522
|
+
it("preserves ?? fallbacks after JS-surface optional array-wrapper length lowering", () => {
|
|
1523
|
+
const source = `
|
|
1524
|
+
export function run(values?: string[]): number {
|
|
1525
|
+
return values?.length ?? 0;
|
|
1526
|
+
}
|
|
1527
|
+
`;
|
|
1528
|
+
const csharp = compileToCSharp(source, "/test/test.ts", {
|
|
1529
|
+
rootNamespace: "Test",
|
|
1530
|
+
surface: "@tsonic/js",
|
|
1531
|
+
});
|
|
1532
|
+
expect(csharp).to.include("(values == null ? default(int?) : values.Length)");
|
|
1533
|
+
expect(csharp).to.include("?? 0");
|
|
1534
|
+
});
|
|
1535
|
+
it("collapses imported nullish date fallbacks to the concrete receiver type", () => {
|
|
1536
|
+
const csharp = compileToCSharp(`
|
|
1537
|
+
import { statSync } from "@tsonic/nodejs/fs.js";
|
|
1538
|
+
|
|
1539
|
+
class FrontMatter {
|
|
1540
|
+
date: Date | undefined = undefined;
|
|
1541
|
+
}
|
|
1542
|
+
|
|
1543
|
+
export function render(fm: FrontMatter): string {
|
|
1544
|
+
const lastModifiedAt = new Date(statSync("tsonic.workspace.json").mtimeMs);
|
|
1545
|
+
const dateUtc = fm.date ?? lastModifiedAt;
|
|
1546
|
+
return dateUtc.toISOString();
|
|
1547
|
+
}
|
|
1548
|
+
`, "/test/test.ts", {
|
|
1549
|
+
surface: "@tsonic/js",
|
|
1550
|
+
});
|
|
1551
|
+
expect(csharp).to.include("var dateUtc = fm.date ?? lastModifiedAt;");
|
|
1552
|
+
expect(csharp).to.include("return dateUtc.toISOString();");
|
|
1553
|
+
expect(csharp).to.not.include("dateUtc.As");
|
|
1554
|
+
});
|
|
1555
|
+
it("keeps constructor-backed nullish fallbacks direct in constructor arguments", () => {
|
|
1556
|
+
const csharp = compileToCSharp(`
|
|
1557
|
+
class Page {}
|
|
1558
|
+
|
|
1559
|
+
class Box {
|
|
1560
|
+
constructor(page: Page) {}
|
|
1561
|
+
}
|
|
1562
|
+
|
|
1563
|
+
class Holder {
|
|
1564
|
+
page: Page | undefined = undefined;
|
|
1565
|
+
}
|
|
1566
|
+
|
|
1567
|
+
export function run(holder: Holder): Box {
|
|
1568
|
+
const fallback = new Page();
|
|
1569
|
+
const selected = holder.page ?? fallback;
|
|
1570
|
+
return new Box(selected);
|
|
1571
|
+
}
|
|
1572
|
+
`);
|
|
1573
|
+
expect(csharp).to.include("var selected = holder.page ?? fallback;");
|
|
1574
|
+
expect(csharp).to.include("return new Box(selected);");
|
|
1575
|
+
expect(csharp).not.to.include("return new Box(global::Tsonic.Internal.Union<global::Test.Page, global::Test.Page>.From1(selected));");
|
|
1576
|
+
});
|
|
1577
|
+
it("preserves ?? fallbacks after dictionary safe-access lowering for value types", () => {
|
|
1578
|
+
const csharp = compileToCSharp(`
|
|
1579
|
+
export function run(
|
|
1580
|
+
allowedCounts: Record<string, number>,
|
|
1581
|
+
name: string,
|
|
1582
|
+
): number {
|
|
1583
|
+
const current = allowedCounts[name] ?? 0;
|
|
1584
|
+
const nextCount = current + 1;
|
|
1585
|
+
allowedCounts[name] = nextCount;
|
|
1586
|
+
return nextCount;
|
|
1587
|
+
}
|
|
1588
|
+
`, "/test/test.ts", {
|
|
1589
|
+
surface: "@tsonic/js",
|
|
1590
|
+
});
|
|
1591
|
+
expect(csharp).to.include("ContainsKey(__tsonic_key) ? __tsonic_dict[__tsonic_key] : default");
|
|
1592
|
+
expect(csharp).to.include("?? 0");
|
|
1593
|
+
});
|
|
1594
|
+
it("keeps local safe-read numerics aligned with their emitted storage", () => {
|
|
1595
|
+
const csharp = compileToCSharp(`
|
|
1596
|
+
import type { int } from "@tsonic/core/types.js";
|
|
1597
|
+
|
|
1598
|
+
class Settings {
|
|
1599
|
+
Count: int = 0;
|
|
1600
|
+
}
|
|
1601
|
+
|
|
1602
|
+
export function run(
|
|
1603
|
+
updates: Record<string, int>,
|
|
1604
|
+
keys: string[],
|
|
1605
|
+
): Settings {
|
|
1606
|
+
const settings = new Settings();
|
|
1607
|
+
for (let i = 0; i < keys.length; i++) {
|
|
1608
|
+
const value = updates[keys[i]];
|
|
1609
|
+
settings.Count = value;
|
|
1610
|
+
}
|
|
1611
|
+
return settings;
|
|
1612
|
+
}
|
|
1613
|
+
`, "/test/test.ts", {
|
|
1614
|
+
surface: "@tsonic/js",
|
|
1615
|
+
});
|
|
1616
|
+
expect(csharp).to.include("ContainsKey(__tsonic_key) ? __tsonic_dict[__tsonic_key] : default");
|
|
1617
|
+
expect(csharp).to.include("var value = ((global::System.Func<int>)(() =>");
|
|
1618
|
+
expect(csharp).not.to.include("settings.Count = value.Value;");
|
|
1619
|
+
});
|
|
1620
|
+
it("reuses exact union-returning safe dictionary reads without rematerializing them", () => {
|
|
1621
|
+
const csharp = compileToCSharp(`
|
|
1622
|
+
function normalizeHeaderValue(
|
|
1623
|
+
value: string | readonly string[] | undefined,
|
|
1624
|
+
): string | undefined {
|
|
1625
|
+
if (value === undefined) {
|
|
1626
|
+
return undefined;
|
|
1627
|
+
}
|
|
1628
|
+
if (typeof value === "string") {
|
|
1629
|
+
return value;
|
|
1630
|
+
}
|
|
1631
|
+
return value.join(", ");
|
|
1632
|
+
}
|
|
1633
|
+
|
|
1634
|
+
export function run(
|
|
1635
|
+
requestHeaders: Record<string, string | readonly string[] | undefined>,
|
|
1636
|
+
): Record<string, string> {
|
|
1637
|
+
const headers: Record<string, string> = {};
|
|
1638
|
+
for (const key in requestHeaders) {
|
|
1639
|
+
const headerValue = normalizeHeaderValue(requestHeaders[key]);
|
|
1640
|
+
if (headerValue !== undefined) {
|
|
1641
|
+
headers[key] = headerValue;
|
|
1642
|
+
}
|
|
1643
|
+
}
|
|
1644
|
+
return headers;
|
|
1645
|
+
}
|
|
1646
|
+
`, "/test/test.ts", {
|
|
1647
|
+
surface: "@tsonic/js",
|
|
1648
|
+
});
|
|
1649
|
+
expect(csharp).to.include("var headerValue = normalizeHeaderValue(((global::System.Func<global::Tsonic.Internal.Union<string[], string>?>)(() =>");
|
|
1650
|
+
expect(csharp).not.to.include("var headerValue = normalizeHeaderValue(((global::System.Object)(((global::System.Object)");
|
|
1651
|
+
});
|
|
1652
|
+
it("prefers contextual union surfaces for local safe dictionary reads", () => {
|
|
1653
|
+
const csharp = compileToCSharp(`
|
|
1654
|
+
import { asinterface } from "@tsonic/core/lang.js";
|
|
1655
|
+
import type { JsValue } from "@tsonic/core/types.js";
|
|
1656
|
+
|
|
1657
|
+
interface RequestWithHeadersLookup {
|
|
1658
|
+
headers: Record<string, string | readonly string[] | undefined>;
|
|
1659
|
+
}
|
|
1660
|
+
|
|
1661
|
+
function normalizeHeaderValue(
|
|
1662
|
+
value: string | readonly string[] | undefined,
|
|
1663
|
+
): string | undefined {
|
|
1664
|
+
if (value === undefined) {
|
|
1665
|
+
return undefined;
|
|
1666
|
+
}
|
|
1667
|
+
if (typeof value === "string") {
|
|
1668
|
+
return value;
|
|
1669
|
+
}
|
|
1670
|
+
return value.join(", ");
|
|
1671
|
+
}
|
|
1672
|
+
|
|
1673
|
+
export function run(request: JsValue): Record<string, string> {
|
|
1674
|
+
const headers: Record<string, string> = {};
|
|
1675
|
+
const requestHeaders = asinterface<RequestWithHeadersLookup>(request).headers;
|
|
1676
|
+
for (const key in requestHeaders) {
|
|
1677
|
+
const headerValue = normalizeHeaderValue(requestHeaders[key]);
|
|
1678
|
+
if (headerValue !== undefined) {
|
|
1679
|
+
headers[key] = headerValue;
|
|
1680
|
+
}
|
|
1681
|
+
}
|
|
1682
|
+
return headers;
|
|
1683
|
+
}
|
|
1684
|
+
`, "/test/test.ts", {
|
|
1685
|
+
surface: "@tsonic/js",
|
|
1686
|
+
});
|
|
1687
|
+
expect(csharp).to.include("var headerValue = normalizeHeaderValue(((global::System.Func<global::Tsonic.Internal.Union<string[], string>?>)(() =>");
|
|
1688
|
+
expect(csharp).not.to.include("((global::System.Func<string?>)(() =>");
|
|
1689
|
+
expect(csharp).not.to.include("var headerValue = normalizeHeaderValue(((global::System.Object)(((global::System.Object)");
|
|
1690
|
+
});
|
|
1691
|
+
it("keeps source-package adapted dictionary locals on union safe-read surfaces", () => {
|
|
1692
|
+
const csharp = compileProjectToCSharp({
|
|
1693
|
+
"package.json": JSON.stringify({ name: "emitter-test-project", version: "1.0.0", type: "module" }, null, 2),
|
|
1694
|
+
"src/index.ts": [
|
|
1695
|
+
'import { asinterface } from "@tsonic/core/lang.js";',
|
|
1696
|
+
'import type { IncomingMessage } from "@fixture/http/index.js";',
|
|
1697
|
+
"",
|
|
1698
|
+
"interface RequestWithHeadersLookup {",
|
|
1699
|
+
" headers: Record<string, string | readonly string[] | undefined>;",
|
|
1700
|
+
"}",
|
|
1701
|
+
"",
|
|
1702
|
+
"function normalizeHeaderValue(",
|
|
1703
|
+
" value: string | readonly string[] | undefined,",
|
|
1704
|
+
"): string | undefined {",
|
|
1705
|
+
" if (value === undefined) {",
|
|
1706
|
+
" return undefined;",
|
|
1707
|
+
" }",
|
|
1708
|
+
' if (typeof value === "string") {',
|
|
1709
|
+
" return value;",
|
|
1710
|
+
" }",
|
|
1711
|
+
' return value.join(", ");',
|
|
1712
|
+
"}",
|
|
1713
|
+
"",
|
|
1714
|
+
"export function run(request: IncomingMessage): Record<string, string> {",
|
|
1715
|
+
" const headers: Record<string, string> = {};",
|
|
1716
|
+
" const requestHeaders = asinterface<RequestWithHeadersLookup>(request).headers;",
|
|
1717
|
+
" for (const key in requestHeaders) {",
|
|
1718
|
+
" const headerValue = normalizeHeaderValue(requestHeaders[key]);",
|
|
1719
|
+
" if (headerValue !== undefined) {",
|
|
1720
|
+
" headers[key] = headerValue;",
|
|
1721
|
+
" }",
|
|
1722
|
+
" }",
|
|
1723
|
+
" return headers;",
|
|
1724
|
+
"}",
|
|
1725
|
+
].join("\n"),
|
|
1726
|
+
"node_modules/@fixture/http/package.json": JSON.stringify({
|
|
1727
|
+
name: "@fixture/http",
|
|
1728
|
+
version: "1.0.0",
|
|
1729
|
+
type: "module",
|
|
1730
|
+
exports: {
|
|
1731
|
+
".": "./src/index.ts",
|
|
1732
|
+
"./index.js": "./src/index.ts",
|
|
1733
|
+
},
|
|
1734
|
+
}, null, 2),
|
|
1735
|
+
"node_modules/@fixture/http/tsonic.package.json": JSON.stringify({
|
|
1736
|
+
schemaVersion: 1,
|
|
1737
|
+
kind: "tsonic-source-package",
|
|
1738
|
+
surfaces: ["@tsonic/js"],
|
|
1739
|
+
source: {
|
|
1740
|
+
namespace: "Fixture.Http",
|
|
1741
|
+
exports: {
|
|
1742
|
+
".": "./src/index.ts",
|
|
1743
|
+
"./index.js": "./src/index.ts",
|
|
1744
|
+
},
|
|
1745
|
+
},
|
|
1746
|
+
}, null, 2),
|
|
1747
|
+
"node_modules/@fixture/http/src/index.ts": [
|
|
1748
|
+
"export class IncomingMessage {",
|
|
1749
|
+
" headers: Record<string, string> = {};",
|
|
1750
|
+
"}",
|
|
1751
|
+
].join("\n"),
|
|
1752
|
+
}, "src/index.ts", { surface: "@tsonic/js" });
|
|
1753
|
+
expect(csharp).to.include("var requestHeaders = global::System.Linq.Enumerable.ToDictionary(request.headers, kvp => kvp.Key, kvp => global::Tsonic.Internal.Union");
|
|
1754
|
+
expect(csharp).to.include("var headerValue = normalizeHeaderValue(((global::System.Func<global::Tsonic.Internal.Union");
|
|
1755
|
+
expect(csharp).not.to.include("((global::System.Func<string?>)(() =>");
|
|
1756
|
+
});
|
|
1757
|
+
it("wraps int-valued returns into JS-number union members", () => {
|
|
1758
|
+
const csharp = compileToCSharp([
|
|
1759
|
+
'import type { int } from "@tsonic/core/types.js";',
|
|
1760
|
+
"",
|
|
1761
|
+
"class ParsedRangeResult {}",
|
|
1762
|
+
"",
|
|
1763
|
+
"export function run(",
|
|
1764
|
+
" shouldReturnCode: boolean,",
|
|
1765
|
+
" code: int,",
|
|
1766
|
+
"): ParsedRangeResult | number {",
|
|
1767
|
+
" if (shouldReturnCode) {",
|
|
1768
|
+
" return code;",
|
|
1769
|
+
" }",
|
|
1770
|
+
"",
|
|
1771
|
+
" return new ParsedRangeResult();",
|
|
1772
|
+
"}",
|
|
1773
|
+
].join("\n"), "/test/test.ts", { surface: "@tsonic/js" });
|
|
1774
|
+
expect(csharp).to.include("public static global::Tsonic.Internal.Union<double, global::Test.ParsedRangeResult> run");
|
|
1775
|
+
expect(csharp).to.include("return global::Tsonic.Internal.Union<double, global::Test.ParsedRangeResult>.From1((double)code);");
|
|
1776
|
+
expect(csharp).not.to.include("return code;");
|
|
1777
|
+
});
|
|
1778
|
+
it("wraps int literals into JS-number union members", () => {
|
|
1779
|
+
const csharp = compileToCSharp([
|
|
1780
|
+
"class ParsedRangeResult {}",
|
|
1781
|
+
"",
|
|
1782
|
+
"export function run(",
|
|
1783
|
+
" shouldReturnCode: boolean,",
|
|
1784
|
+
"): ParsedRangeResult | number {",
|
|
1785
|
+
" if (shouldReturnCode) {",
|
|
1786
|
+
" return -2;",
|
|
1787
|
+
" }",
|
|
1788
|
+
"",
|
|
1789
|
+
" return new ParsedRangeResult();",
|
|
1790
|
+
"}",
|
|
1791
|
+
].join("\n"), "/test/test.ts", { surface: "@tsonic/js" });
|
|
1792
|
+
expect(csharp).to.include("public static global::Tsonic.Internal.Union<double, global::Test.ParsedRangeResult> run");
|
|
1793
|
+
expect(csharp).to.include("return global::Tsonic.Internal.Union<double, global::Test.ParsedRangeResult>.From1(-2);");
|
|
1794
|
+
expect(csharp).not.to.include("return -2;");
|
|
1795
|
+
});
|
|
1796
|
+
it("keeps value-type union arms from matching structural object arms", () => {
|
|
1797
|
+
const csharp = compileToCSharp([
|
|
1798
|
+
"class ParsedByteRange {",
|
|
1799
|
+
" start: number;",
|
|
1800
|
+
" end: number;",
|
|
1801
|
+
"",
|
|
1802
|
+
" constructor(start: number, end: number) {",
|
|
1803
|
+
" this.start = start;",
|
|
1804
|
+
" this.end = end;",
|
|
1805
|
+
" }",
|
|
1806
|
+
"}",
|
|
1807
|
+
"",
|
|
1808
|
+
"class ParsedRangeResult {",
|
|
1809
|
+
" type: string;",
|
|
1810
|
+
" ranges: ParsedByteRange[];",
|
|
1811
|
+
"",
|
|
1812
|
+
" constructor(type: string, ranges: ParsedByteRange[]) {",
|
|
1813
|
+
" this.type = type;",
|
|
1814
|
+
" this.ranges = ranges;",
|
|
1815
|
+
" }",
|
|
1816
|
+
"}",
|
|
1817
|
+
"",
|
|
1818
|
+
"export function range(",
|
|
1819
|
+
" header: string | undefined,",
|
|
1820
|
+
" size: number,",
|
|
1821
|
+
"): ParsedRangeResult | number {",
|
|
1822
|
+
" if (!header) {",
|
|
1823
|
+
" return -2;",
|
|
1824
|
+
" }",
|
|
1825
|
+
"",
|
|
1826
|
+
" if (size <= 0) {",
|
|
1827
|
+
" return -1;",
|
|
1828
|
+
" }",
|
|
1829
|
+
"",
|
|
1830
|
+
' return new ParsedRangeResult("bytes", []);',
|
|
1831
|
+
"}",
|
|
1832
|
+
].join("\n"), "/test/test.ts", { surface: "@tsonic/js" });
|
|
1833
|
+
expect(csharp).to.include("public static global::Tsonic.Internal.Union<double, global::Test.ParsedRangeResult> range");
|
|
1834
|
+
expect(csharp).to.include("return global::Tsonic.Internal.Union<double, global::Test.ParsedRangeResult>.From1(-2);");
|
|
1835
|
+
expect(csharp).to.include("return global::Tsonic.Internal.Union<double, global::Test.ParsedRangeResult>.From1(-1);");
|
|
1836
|
+
const rangeMethodStart = csharp.indexOf("public static global::Tsonic.Internal.Union<double, global::Test.ParsedRangeResult> range");
|
|
1837
|
+
const rangeMethodEnd = csharp.indexOf("\n }\n", rangeMethodStart);
|
|
1838
|
+
const rangeMethod = csharp.slice(rangeMethodStart, rangeMethodEnd);
|
|
1839
|
+
expect(rangeMethod).not.to.include("return -2;");
|
|
1840
|
+
expect(rangeMethod).not.to.include("return -1;");
|
|
1841
|
+
});
|
|
1842
|
+
it("passes CLR ref-like generic locals without object bridge casts", () => {
|
|
1843
|
+
const csharp = compileToCSharp([
|
|
1844
|
+
'import type { int } from "@tsonic/core/types.js";',
|
|
1845
|
+
'import { Span } from "@tsonic/dotnet/System.js";',
|
|
1846
|
+
"",
|
|
1847
|
+
"function processInChunks(span: Span<int>, chunkSize: int): void {",
|
|
1848
|
+
" const chunk = span.Slice(0, chunkSize);",
|
|
1849
|
+
"}",
|
|
1850
|
+
"",
|
|
1851
|
+
"export function run(numbers: int[], dest: int[]): void {",
|
|
1852
|
+
" const span = new Span<int>(numbers);",
|
|
1853
|
+
" processInChunks(span, 3);",
|
|
1854
|
+
" const destSpan = new Span<int>(dest);",
|
|
1855
|
+
" span.CopyTo(destSpan);",
|
|
1856
|
+
"}",
|
|
1857
|
+
].join("\n"), "/test/App.ts", { surface: "@tsonic/js" });
|
|
1858
|
+
expect(csharp).to.include("processInChunks(span, 3);");
|
|
1859
|
+
expect(csharp).to.include("span.CopyTo(destSpan);");
|
|
1860
|
+
expect(csharp).not.to.include("(object)span");
|
|
1861
|
+
expect(csharp).not.to.include("(object)destSpan");
|
|
1862
|
+
});
|
|
1863
|
+
it("keeps JsValue spread-array conditionals on object arrays instead of numeric unions", () => {
|
|
1864
|
+
const csharp = compileToCSharp(`
|
|
1865
|
+
declare function inspect(value: JsValue): string;
|
|
1866
|
+
|
|
1867
|
+
export function format(
|
|
1868
|
+
message?: JsValue,
|
|
1869
|
+
optionalParams: readonly JsValue[] = []
|
|
1870
|
+
): string {
|
|
1871
|
+
const values =
|
|
1872
|
+
message === undefined ? [...optionalParams] : [message, ...optionalParams];
|
|
1873
|
+
return values.map((value) => inspect(value)).join(" ");
|
|
1874
|
+
}
|
|
1875
|
+
`);
|
|
1876
|
+
expect(csharp).not.to.include("Union<double[], object?[]>");
|
|
1877
|
+
expect(csharp).not.to.include("(double)message");
|
|
1878
|
+
expect(csharp).not.to.include('.toArray().join(" ")');
|
|
1879
|
+
});
|
|
1880
|
+
it("avoids identity Match projections for identical optional union passthrough calls", () => {
|
|
1881
|
+
const source = `
|
|
1882
|
+
import type { int } from "@tsonic/core/types.js";
|
|
1883
|
+
|
|
1884
|
+
function normalizeSignal(signal?: int | string): string {
|
|
1885
|
+
return signal === undefined ? "SIGTERM" : typeof signal === "string" ? signal : "n";
|
|
1886
|
+
}
|
|
1887
|
+
|
|
1888
|
+
export function run(signal?: int | string): string {
|
|
1889
|
+
return normalizeSignal(signal);
|
|
1890
|
+
}
|
|
1891
|
+
`;
|
|
1892
|
+
const csharp = compileToCSharp(source);
|
|
1893
|
+
expect(csharp).to.include("return normalizeSignal(signal);");
|
|
1894
|
+
expect(csharp).not.to.include("signal.Match");
|
|
1895
|
+
});
|
|
1896
|
+
it("widens narrowed runtime-subset handlers without re-matching extracted members", () => {
|
|
1897
|
+
const csharp = compileToCSharp(`
|
|
1898
|
+
type RequestHandler = (request: string) => void;
|
|
1899
|
+
type ErrorRequestHandler = (error: JsValue, request: string) => void;
|
|
1900
|
+
|
|
1901
|
+
class Router {}
|
|
1902
|
+
|
|
1903
|
+
type MiddlewareLike = RequestHandler | Router;
|
|
1904
|
+
type LayerHandler = RequestHandler | ErrorRequestHandler;
|
|
1905
|
+
|
|
1906
|
+
declare function accept(handlers: LayerHandler[]): void;
|
|
1907
|
+
|
|
1908
|
+
export function run(handlers: MiddlewareLike[]): void {
|
|
1909
|
+
for (const handler of handlers) {
|
|
1910
|
+
if (handler instanceof Router) {
|
|
1911
|
+
continue;
|
|
1912
|
+
}
|
|
1913
|
+
|
|
1914
|
+
accept([handler]);
|
|
1915
|
+
}
|
|
1916
|
+
}
|
|
1917
|
+
`);
|
|
1918
|
+
expect(csharp).to.include("From1((handler.As1()))");
|
|
1919
|
+
expect(csharp).not.to.include("(handler.As1()).Match");
|
|
1920
|
+
});
|
|
1921
|
+
it("preserves original carrier slot numbering across chained guard refinements", () => {
|
|
1922
|
+
const csharp = compileToCSharp(`
|
|
1923
|
+
type RequestHandler = (value: string) => void;
|
|
1924
|
+
type MiddlewareLike = RequestHandler | Router | readonly MiddlewareLike[];
|
|
1925
|
+
|
|
1926
|
+
class Router {}
|
|
1927
|
+
|
|
1928
|
+
declare function accept(value: RequestHandler | Router): void;
|
|
1929
|
+
|
|
1930
|
+
function isMiddlewareHandler(value: MiddlewareLike): value is RequestHandler {
|
|
1931
|
+
return typeof value === "function";
|
|
1932
|
+
}
|
|
1933
|
+
|
|
1934
|
+
export function run(handler: MiddlewareLike): void {
|
|
1935
|
+
if (Array.isArray(handler)) {
|
|
1936
|
+
return;
|
|
1937
|
+
}
|
|
1938
|
+
|
|
1939
|
+
if (handler instanceof Router) {
|
|
1940
|
+
return;
|
|
1941
|
+
}
|
|
1942
|
+
|
|
1943
|
+
if (!isMiddlewareHandler(handler)) {
|
|
1944
|
+
throw new Error("bad");
|
|
1945
|
+
}
|
|
1946
|
+
|
|
1947
|
+
accept(handler);
|
|
1948
|
+
}
|
|
1949
|
+
`, "/test/test.ts", { surface: "@tsonic/js" });
|
|
1950
|
+
expect(csharp).to.include("accept(global::Tsonic.Internal.Union<global::System.Action<string>, global::Test.Router>.From1((handler.As2())));");
|
|
1951
|
+
expect(csharp).not.to.include("accept(global::Tsonic.Internal.Union<global::System.Action<string>, global::Test.Router>.From2((handler.As2())))");
|
|
1952
|
+
});
|
|
1953
|
+
it("reuses narrowed recursive array carriers for explicit assertions inside Array.isArray branches", () => {
|
|
1954
|
+
const csharp = compileToCSharp(`
|
|
1955
|
+
type RequestHandler = (value: string) => void;
|
|
1956
|
+
type MiddlewareParam = RequestHandler | readonly MiddlewareParam[];
|
|
1957
|
+
type MiddlewareLike = MiddlewareParam | Router | readonly MiddlewareLike[];
|
|
1958
|
+
|
|
1959
|
+
class Router {}
|
|
1960
|
+
|
|
1961
|
+
export function flatten(entries: readonly MiddlewareLike[]): readonly (RequestHandler | Router)[] {
|
|
1962
|
+
const result: (RequestHandler | Router)[] = [];
|
|
1963
|
+
|
|
1964
|
+
const append = (handler: MiddlewareLike): void => {
|
|
1965
|
+
if (Array.isArray(handler)) {
|
|
1966
|
+
const items = handler as readonly MiddlewareLike[];
|
|
1967
|
+
for (let index = 0; index < items.length; index += 1) {
|
|
1968
|
+
append(items[index]!);
|
|
1969
|
+
}
|
|
1970
|
+
return;
|
|
1971
|
+
}
|
|
1972
|
+
|
|
1973
|
+
result.push(handler);
|
|
1974
|
+
};
|
|
1975
|
+
|
|
1976
|
+
for (const entry of entries) {
|
|
1977
|
+
append(entry);
|
|
1978
|
+
}
|
|
1979
|
+
|
|
1980
|
+
return result;
|
|
1981
|
+
}
|
|
1982
|
+
`, "/test/test.ts", { surface: "@tsonic/js" });
|
|
1983
|
+
expect(csharp).to.include("global::Test.MiddlewareLike[] items = (handler.As1());");
|
|
1984
|
+
expect(csharp).not.to.include("handler.Match<object?[]>");
|
|
1985
|
+
expect(csharp).not.to.include(".Match<object[]>(");
|
|
1986
|
+
});
|
|
1987
|
+
it("wraps recursive middleware rest arrays through nested alias-owned union arms", () => {
|
|
1988
|
+
const csharp = compileToCSharp(`
|
|
1989
|
+
type NextControl = "route" | "router" | string | null | undefined;
|
|
1990
|
+
type NextFunction = (value?: NextControl) => void | Promise<void>;
|
|
1991
|
+
interface Request { path: string; }
|
|
1992
|
+
interface Response { send(text: string): void; }
|
|
1993
|
+
interface RequestHandler {
|
|
1994
|
+
(req: Request, res: Response, next: NextFunction): void | Promise<void>;
|
|
1995
|
+
}
|
|
1996
|
+
type MiddlewareParam = RequestHandler | readonly MiddlewareParam[];
|
|
1997
|
+
type MiddlewareLike = MiddlewareParam | Router | readonly MiddlewareLike[];
|
|
1998
|
+
|
|
1999
|
+
class Router {
|
|
2000
|
+
use(...handlers: readonly MiddlewareLike[]): this {
|
|
2001
|
+
return this;
|
|
2002
|
+
}
|
|
2003
|
+
}
|
|
2004
|
+
|
|
2005
|
+
class Application extends Router {
|
|
2006
|
+
mount(path: string, ...handlers: readonly MiddlewareLike[]): this {
|
|
2007
|
+
const state = { path, handlers, owner: this };
|
|
2008
|
+
this.use(handlers);
|
|
2009
|
+
return state.owner;
|
|
2010
|
+
}
|
|
2011
|
+
}
|
|
2012
|
+
|
|
2013
|
+
export function main(): Application {
|
|
2014
|
+
const app = new Application();
|
|
2015
|
+
const handler: RequestHandler = async (_req, _res, next) => {
|
|
2016
|
+
await next("route");
|
|
2017
|
+
};
|
|
2018
|
+
return app.mount("/", [handler]);
|
|
2019
|
+
}
|
|
2020
|
+
`, "/test/test.ts", { surface: "@tsonic/js" });
|
|
2021
|
+
expect(csharp).to.include('return app.mount("/", global::Test.MiddlewareLike.From1(new global::Test.MiddlewareLike[] { global::Test.MiddlewareLike.From2(global::Test.MiddlewareParam.From2(handler)) }));');
|
|
2022
|
+
expect(csharp).not.to.include("global::Test.MiddlewareLike.From3(handler)");
|
|
2023
|
+
});
|
|
2024
|
+
it("packs rest arrays for local function values inferred from call results", () => {
|
|
2025
|
+
const csharp = compileToCSharp(`
|
|
2026
|
+
type DebugLogFunction = (message: string, ...args: JsValue[]) => void;
|
|
2027
|
+
|
|
2028
|
+
declare function debuglog(section: string): DebugLogFunction;
|
|
2029
|
+
declare function deprecate(
|
|
2030
|
+
fn: (...args: JsValue[]) => JsValue,
|
|
2031
|
+
message: string
|
|
2032
|
+
): (...args: JsValue[]) => JsValue;
|
|
2033
|
+
|
|
2034
|
+
export function run(): void {
|
|
2035
|
+
const debug = debuglog("test");
|
|
2036
|
+
debug("test message");
|
|
2037
|
+
debug("test message with args: {0}", 42);
|
|
2038
|
+
|
|
2039
|
+
const wrapped = deprecate(() => 42, "deprecated");
|
|
2040
|
+
wrapped();
|
|
2041
|
+
}
|
|
2042
|
+
`);
|
|
2043
|
+
expect(csharp).to.match(/debug\("test message", (?:new object\?\[0\]|new object\?\[] \{\s*\})\);/);
|
|
2044
|
+
expect(csharp).to.match(/debug\("test message with args: \{0\}", new object\?\[] \{[\s\S]*42[\s\S]*\}\);/);
|
|
2045
|
+
expect(csharp).to.match(/wrapped\((?:new object\?\[0\]|new object\?\[] \{\s*\})\);/);
|
|
2046
|
+
});
|
|
2047
|
+
it("invokes narrowed handler assertions without matching extracted delegate members", () => {
|
|
2048
|
+
const csharp = compileToCSharp(`
|
|
2049
|
+
type RequestHandler = (request: string) => void;
|
|
2050
|
+
type ErrorRequestHandler = (error: JsValue, request: string) => void;
|
|
2051
|
+
type MiddlewareHandler = RequestHandler | ErrorRequestHandler;
|
|
2052
|
+
|
|
2053
|
+
export function run(
|
|
2054
|
+
handlers: MiddlewareHandler[],
|
|
2055
|
+
currentError?: JsValue
|
|
2056
|
+
): void {
|
|
2057
|
+
const entry = handlers[0]!;
|
|
2058
|
+
if (currentError === undefined) {
|
|
2059
|
+
(entry as RequestHandler)("ok");
|
|
2060
|
+
return;
|
|
2061
|
+
}
|
|
2062
|
+
|
|
2063
|
+
(entry as ErrorRequestHandler)(currentError, "ok");
|
|
2064
|
+
}
|
|
2065
|
+
`);
|
|
2066
|
+
expect(csharp).to.include("entry.Match");
|
|
2067
|
+
expect(csharp).not.to.include("(entry.As1()).Match");
|
|
2068
|
+
expect(csharp).not.to.include("(entry.As2()).Match");
|
|
2069
|
+
expect(csharp).not.to.include("((global::System.Func<string, object?>)entry)");
|
|
2070
|
+
expect(csharp).not.to.include("((global::System.Func<object?, string, object?>)entry)");
|
|
2071
|
+
});
|
|
2072
|
+
it("invokes predicate-fallthrough callable subsets through their projected member slot", () => {
|
|
2073
|
+
const csharp = compileToCSharp(`
|
|
2074
|
+
type Request = { readonly path: string };
|
|
2075
|
+
type Response = { send(text: string): void };
|
|
2076
|
+
type NextControl = "route" | "router" | string | null | undefined;
|
|
2077
|
+
type NextFunction = (value?: NextControl) => void | Promise<void>;
|
|
2078
|
+
type RequestHandler = (
|
|
2079
|
+
request: Request,
|
|
2080
|
+
response: Response,
|
|
2081
|
+
next: NextFunction
|
|
2082
|
+
) => JsValue | Promise<JsValue>;
|
|
2083
|
+
type ErrorRequestHandler = (
|
|
2084
|
+
error: JsValue,
|
|
2085
|
+
request: Request,
|
|
2086
|
+
response: Response,
|
|
2087
|
+
next: NextFunction
|
|
2088
|
+
) => JsValue | Promise<JsValue>;
|
|
2089
|
+
type MiddlewareHandler = RequestHandler | ErrorRequestHandler;
|
|
2090
|
+
|
|
2091
|
+
declare function isMiddlewareHandler(value: JsValue): value is MiddlewareHandler;
|
|
2092
|
+
declare function isErrorHandler(
|
|
2093
|
+
value: MiddlewareHandler,
|
|
2094
|
+
treatAsError: boolean
|
|
2095
|
+
): value is ErrorRequestHandler;
|
|
2096
|
+
|
|
2097
|
+
export async function run(
|
|
2098
|
+
handlers: JsValue[],
|
|
2099
|
+
request: Request,
|
|
2100
|
+
response: Response,
|
|
2101
|
+
currentError: JsValue
|
|
2102
|
+
): Promise<void> {
|
|
2103
|
+
let error = currentError;
|
|
2104
|
+
const next = async (_value?: NextControl): Promise<void> => {};
|
|
2105
|
+
|
|
2106
|
+
for (const handler of handlers) {
|
|
2107
|
+
if (!isMiddlewareHandler(handler)) {
|
|
2108
|
+
continue;
|
|
2109
|
+
}
|
|
2110
|
+
|
|
2111
|
+
if (error === undefined) {
|
|
2112
|
+
if (isErrorHandler(handler, false)) {
|
|
2113
|
+
continue;
|
|
2114
|
+
}
|
|
2115
|
+
await handler(request, response, next);
|
|
2116
|
+
} else {
|
|
2117
|
+
if (!isErrorHandler(handler, true)) {
|
|
2118
|
+
continue;
|
|
2119
|
+
}
|
|
2120
|
+
await handler(error, request, response, next);
|
|
2121
|
+
}
|
|
2122
|
+
}
|
|
2123
|
+
}
|
|
2124
|
+
`);
|
|
2125
|
+
expect(csharp).to.include("isErrorHandler(");
|
|
2126
|
+
expect(csharp).to.include("MiddlewareHandler From1(global::System.Func<object?, Request__Alias, Response__Alias");
|
|
2127
|
+
expect(csharp).to.include("MiddlewareHandler From2(global::System.Func<Request__Alias, Response__Alias");
|
|
2128
|
+
expect(csharp).to.match(/\.As2\(\)\)\(request, response, next\)\.Match(?:<[^\n]+>)?\(/);
|
|
2129
|
+
expect(csharp).to.match(/\.As1\(\)\)\(error, request, response, next\)\.Match(?:<[^\n]+>)?\(/);
|
|
2130
|
+
expect(csharp).not.to.include("handler.Is2()");
|
|
2131
|
+
});
|
|
2132
|
+
it("passes callable and nominal source-union members directly into broad JsValue guard predicates", () => {
|
|
2133
|
+
const csharp = compileToCSharp(`
|
|
2134
|
+
class Router {}
|
|
2135
|
+
|
|
2136
|
+
type PathSpec = string | RegExp | readonly PathSpec[];
|
|
2137
|
+
type RequestHandler = (request: string) => void;
|
|
2138
|
+
|
|
2139
|
+
declare function isPathSpec(value: JsValue): value is PathSpec;
|
|
2140
|
+
|
|
2141
|
+
export function run(first: PathSpec | RequestHandler | Router): boolean {
|
|
2142
|
+
return isPathSpec(first);
|
|
2143
|
+
}
|
|
2144
|
+
`);
|
|
2145
|
+
expect(csharp).to.include("first.Match<object?>(");
|
|
2146
|
+
expect(csharp.split(".Match<object?>(").length - 1).to.equal(2);
|
|
2147
|
+
expect(csharp).not.to.include("new global::System.InvalidCastException");
|
|
2148
|
+
});
|
|
2149
|
+
it("narrows predicate-guarded source unions before exact branch-local call arguments", () => {
|
|
2150
|
+
const csharp = compileToCSharp(`
|
|
2151
|
+
class Router {}
|
|
2152
|
+
|
|
2153
|
+
type PathSpec = string | RegExp | readonly PathSpec[];
|
|
2154
|
+
type RequestHandler = (request: string) => void;
|
|
2155
|
+
type MiddlewareLike = RequestHandler | Router;
|
|
2156
|
+
|
|
2157
|
+
declare function isPathSpec(value: JsValue): value is PathSpec;
|
|
2158
|
+
declare function addMiddlewareLayer(path: PathSpec, handlers: readonly MiddlewareLike[]): void;
|
|
2159
|
+
declare function useRootMiddleware(first: MiddlewareLike, rest: readonly MiddlewareLike[]): void;
|
|
2160
|
+
|
|
2161
|
+
export function run(first: PathSpec | MiddlewareLike, rest: readonly MiddlewareLike[]): void {
|
|
2162
|
+
if (isPathSpec(first)) {
|
|
2163
|
+
addMiddlewareLayer(first, rest);
|
|
2164
|
+
return;
|
|
2165
|
+
}
|
|
2166
|
+
|
|
2167
|
+
useRootMiddleware(first, rest);
|
|
2168
|
+
}
|
|
2169
|
+
`);
|
|
2170
|
+
expect(csharp).to.include("if (isPathSpec(first.Match<object?>(");
|
|
2171
|
+
expect(csharp).to.include("addMiddlewareLayer((first.As1()), rest);");
|
|
2172
|
+
expect(csharp).to.include("useRootMiddleware((first.As2()), rest);");
|
|
2173
|
+
expect(csharp).not.to.include("addMiddlewareLayer(first, rest);");
|
|
2174
|
+
expect(csharp).not.to.include("useRootMiddleware(first, rest);");
|
|
2175
|
+
});
|
|
2176
|
+
it("keeps broad JsValue call arguments on their storage carrier after typeof narrowing", () => {
|
|
2177
|
+
const csharp = compileToCSharp(`
|
|
2178
|
+
declare function toNumericValue(value: JsValue): number;
|
|
2179
|
+
|
|
2180
|
+
export function run(value?: JsValue): number {
|
|
2181
|
+
if (value === undefined || value === null) {
|
|
2182
|
+
return 0;
|
|
2183
|
+
}
|
|
2184
|
+
|
|
2185
|
+
if (typeof value === "boolean") {
|
|
2186
|
+
return value ? 1 : 0;
|
|
2187
|
+
}
|
|
2188
|
+
|
|
2189
|
+
if (typeof value === "string") {
|
|
2190
|
+
return value.length;
|
|
2191
|
+
}
|
|
2192
|
+
|
|
2193
|
+
return toNumericValue(value);
|
|
2194
|
+
}
|
|
2195
|
+
`);
|
|
2196
|
+
expect(csharp).to.include("return toNumericValue(value);");
|
|
2197
|
+
expect(csharp).not.to.include("toNumericValue(value.Match<object?>");
|
|
2198
|
+
});
|
|
2199
|
+
it("uses runtime equality for unannotated broad assertion locals", () => {
|
|
2200
|
+
const csharp = compileToCSharp(`
|
|
2201
|
+
import type { JsValue } from "@tsonic/core/types.js";
|
|
2202
|
+
|
|
2203
|
+
export function run<T>(left: T, right: T): boolean {
|
|
2204
|
+
const leftValue = left as JsValue | undefined;
|
|
2205
|
+
const rightValue = right as JsValue | undefined;
|
|
2206
|
+
return leftValue === rightValue;
|
|
2207
|
+
}
|
|
2208
|
+
`, "/test/test.ts", { surface: "@tsonic/js" });
|
|
2209
|
+
expect(csharp).to.include("return global::System.Object.Equals(leftValue, rightValue);");
|
|
2210
|
+
expect(csharp).not.to.include("return leftValue == rightValue;");
|
|
2211
|
+
});
|
|
2212
|
+
it("casts Array.isArray-narrowed broad storage directly for concrete array assertions", () => {
|
|
2213
|
+
const csharp = compileToCSharp(`
|
|
2214
|
+
import type { JsValue } from "@tsonic/core/types.js";
|
|
2215
|
+
|
|
2216
|
+
export function run(value: JsValue): string[] | undefined {
|
|
2217
|
+
if (Array.isArray(value)) {
|
|
2218
|
+
const list = value as string[];
|
|
2219
|
+
list.push("x");
|
|
2220
|
+
return list;
|
|
2221
|
+
}
|
|
2222
|
+
|
|
2223
|
+
return undefined;
|
|
2224
|
+
}
|
|
2225
|
+
`, "/test/test.ts", { surface: "@tsonic/js" });
|
|
2226
|
+
expect(csharp).to.include("string[] list = (string[])value;");
|
|
2227
|
+
expect(csharp).not.to.include("(global::js.Array)value");
|
|
2228
|
+
expect(csharp).not.to.match(/global::System\.Linq\.Enumerable\.Select<object\?, string>\(\(global::js\.Array\)value/);
|
|
2229
|
+
});
|
|
2230
|
+
it("keeps recursive Array.isArray fallthrough guards on the original runtime carrier", () => {
|
|
2231
|
+
const csharp = compileToCSharp(`
|
|
2232
|
+
import { FileInfo } from "@tsonic/dotnet/System.IO.js";
|
|
2233
|
+
|
|
2234
|
+
type PathSpec = string | FileInfo | readonly PathSpec[] | null | undefined;
|
|
2235
|
+
|
|
2236
|
+
export function matchesPathSpec(
|
|
2237
|
+
pathSpec: PathSpec,
|
|
2238
|
+
requestPath: string
|
|
2239
|
+
): boolean {
|
|
2240
|
+
if (pathSpec == null) {
|
|
2241
|
+
return true;
|
|
2242
|
+
}
|
|
2243
|
+
|
|
2244
|
+
if (typeof pathSpec === "string") {
|
|
2245
|
+
return pathSpec.length >= 0 && requestPath.length >= 0;
|
|
2246
|
+
}
|
|
2247
|
+
|
|
2248
|
+
if (pathSpec instanceof FileInfo) {
|
|
2249
|
+
return requestPath.length >= 0;
|
|
2250
|
+
}
|
|
2251
|
+
|
|
2252
|
+
if (Array.isArray(pathSpec)) {
|
|
2253
|
+
for (let index = 0; index < pathSpec.length; index += 1) {
|
|
2254
|
+
if (matchesPathSpec(pathSpec[index]!, requestPath)) {
|
|
2255
|
+
return true;
|
|
2256
|
+
}
|
|
2257
|
+
}
|
|
2258
|
+
|
|
2259
|
+
return false;
|
|
2260
|
+
}
|
|
2261
|
+
|
|
2262
|
+
return false;
|
|
2263
|
+
}
|
|
2264
|
+
`);
|
|
2265
|
+
expect(csharp).to.include("pathSpec.Is1()");
|
|
2266
|
+
expect(csharp).not.to.include("(pathSpec.As1()).Is1()");
|
|
2267
|
+
expect(csharp).not.to.include("((pathSpec.As1()).As1())[index]");
|
|
2268
|
+
expect(csharp).to.include("for (int index = 0; index < (pathSpec.As1()).Length; index += 1)");
|
|
2269
|
+
expect(csharp).to.include("if (matchesPathSpec((pathSpec.As1())[index], requestPath))");
|
|
2270
|
+
});
|
|
2271
|
+
it("preserves runtime carrier slot numbers in typeof string guards over aliased unions", () => {
|
|
2272
|
+
const csharp = compileToCSharp(`
|
|
2273
|
+
import { FileInfo } from "@tsonic/dotnet/System.IO.js";
|
|
2274
|
+
|
|
2275
|
+
type PathSpec = string | FileInfo | readonly PathSpec[];
|
|
2276
|
+
|
|
2277
|
+
export function read(pathOrName: string | PathSpec): string | undefined {
|
|
2278
|
+
if (typeof pathOrName === "string") {
|
|
2279
|
+
return pathOrName;
|
|
2280
|
+
}
|
|
2281
|
+
|
|
2282
|
+
return undefined;
|
|
2283
|
+
}
|
|
2284
|
+
`);
|
|
2285
|
+
expect(csharp).to.include("pathOrName.Is1()");
|
|
2286
|
+
expect(csharp).not.to.include("pathOrName.Is3()");
|
|
2287
|
+
expect(csharp).to.include("pathOrName.As1()");
|
|
2288
|
+
});
|
|
2289
|
+
it("keeps js Date nullish constructor fallbacks direct in constructor arguments", () => {
|
|
2290
|
+
const csharp = compileToCSharp(`
|
|
2291
|
+
class Holder {
|
|
2292
|
+
public date: Date | undefined;
|
|
2293
|
+
|
|
2294
|
+
public constructor(date?: Date) {
|
|
2295
|
+
this.date = date;
|
|
2296
|
+
}
|
|
2297
|
+
}
|
|
2298
|
+
|
|
2299
|
+
class Box {
|
|
2300
|
+
public readonly value: Date;
|
|
2301
|
+
|
|
2302
|
+
public constructor(value: Date) {
|
|
2303
|
+
this.value = value;
|
|
2304
|
+
}
|
|
2305
|
+
}
|
|
2306
|
+
|
|
2307
|
+
export function wrap(holder: Holder): Box {
|
|
2308
|
+
const fallback = new Date(0);
|
|
2309
|
+
const selected = holder.date ?? fallback;
|
|
2310
|
+
return new Box(selected);
|
|
2311
|
+
}
|
|
2312
|
+
`, "/test/src/index.ts", { surface: "@tsonic/js" });
|
|
2313
|
+
expect(csharp).to.include("var fallback = new global::js.Date((object)(double)0);");
|
|
2314
|
+
expect(csharp).to.include("var selected = holder.date ?? fallback;");
|
|
2315
|
+
expect(csharp).to.include("return new Box(selected);");
|
|
2316
|
+
expect(csharp).not.to.include("Union2_");
|
|
2317
|
+
expect(csharp).not.to.include(".From1(selected)");
|
|
2318
|
+
});
|
|
2319
|
+
it("returns narrowed string members from overload implementations with broad return types", () => {
|
|
2320
|
+
const csharp = compileToCSharp(`
|
|
2321
|
+
import { overloads as O } from "@tsonic/core/lang.js";
|
|
2322
|
+
import { FileInfo } from "@tsonic/dotnet/System.IO.js";
|
|
2323
|
+
|
|
2324
|
+
type RouteHandler = () => void;
|
|
2325
|
+
|
|
2326
|
+
class Router {
|
|
2327
|
+
get(path: PathSpec, ...handlers: RouteHandler[]): this {
|
|
2328
|
+
return this;
|
|
2329
|
+
}
|
|
2330
|
+
}
|
|
2331
|
+
|
|
2332
|
+
type PathSpec = string | FileInfo | readonly PathSpec[];
|
|
2333
|
+
|
|
2334
|
+
class Application extends Router {
|
|
2335
|
+
get(name: string): JsValue;
|
|
2336
|
+
override get(path: PathSpec, ...handlers: RouteHandler[]): this;
|
|
2337
|
+
override get(_nameOrPath: any, ..._handlers: any[]): any {
|
|
2338
|
+
throw new Error("stub");
|
|
2339
|
+
}
|
|
2340
|
+
|
|
2341
|
+
get_name(name: string): JsValue {
|
|
2342
|
+
return name;
|
|
2343
|
+
}
|
|
2344
|
+
|
|
2345
|
+
get_path(path: PathSpec, ...handlers: RouteHandler[]): this {
|
|
2346
|
+
return super.get(path, ...handlers);
|
|
2347
|
+
}
|
|
2348
|
+
}
|
|
2349
|
+
|
|
2350
|
+
O<Application>().method(x => x.get_name).family(x => x.get);
|
|
2351
|
+
O<Application>().method(x => x.get_path).family(x => x.get);
|
|
2352
|
+
`);
|
|
2353
|
+
expect(csharp).to.include("public object? get(string name)");
|
|
2354
|
+
expect(csharp).to.include("return name;");
|
|
2355
|
+
expect(csharp).to.not.include("name.Is");
|
|
2356
|
+
expect(csharp).not.to.include("get_name");
|
|
2357
|
+
expect(csharp).not.to.include("get_path");
|
|
2358
|
+
});
|
|
2359
|
+
it("erases runtime-union member probes from specialized void overload bodies", () => {
|
|
2360
|
+
const csharp = compileToCSharp(`
|
|
2361
|
+
import { overloads as O } from "@tsonic/core/lang.js";
|
|
2362
|
+
|
|
2363
|
+
export class KeyStore {
|
|
2364
|
+
setValue(value: string): void;
|
|
2365
|
+
setValue(value: number): void;
|
|
2366
|
+
setValue(_value: any): any {
|
|
2367
|
+
throw new Error("stub");
|
|
2368
|
+
}
|
|
2369
|
+
|
|
2370
|
+
setValue_string(value: string): void {
|
|
2371
|
+
void value;
|
|
2372
|
+
}
|
|
2373
|
+
|
|
2374
|
+
setValue_number(value: number): void {
|
|
2375
|
+
const stable = value;
|
|
2376
|
+
void stable;
|
|
2377
|
+
}
|
|
2378
|
+
}
|
|
2379
|
+
|
|
2380
|
+
O<KeyStore>().method(x => x.setValue_string).family(x => x.setValue);
|
|
2381
|
+
O<KeyStore>().method(x => x.setValue_number).family(x => x.setValue);
|
|
2382
|
+
`);
|
|
2383
|
+
expect(csharp).to.not.include("publicKey.Is1()");
|
|
2384
|
+
expect(csharp).to.not.include("value.Is1()");
|
|
2385
|
+
expect(csharp).to.not.include("value.As2()");
|
|
2386
|
+
expect(csharp).to.not.include("setValue_string");
|
|
2387
|
+
expect(csharp).to.not.include("setValue_number");
|
|
2388
|
+
});
|
|
2389
|
+
it("lowers Uint8Array array-literal constructors through byte arrays", () => {
|
|
2390
|
+
const csharp = compileToCSharp(`
|
|
2391
|
+
export function run(): void {
|
|
2392
|
+
const bytes = new Uint8Array([1, 2, 3]);
|
|
2393
|
+
void bytes;
|
|
2394
|
+
}
|
|
2395
|
+
`, "/test/test.ts", {
|
|
2396
|
+
surface: "@tsonic/js",
|
|
2397
|
+
});
|
|
2398
|
+
expect(csharp).to.include("new global::js.Uint8Array(global::js.TypedArrayConstructorInput<byte>.From2(global::js.TypedArrayInput<byte>.From1(new byte[] { 1, 2, 3 })))");
|
|
2399
|
+
expect(csharp).not.to.include("new global::js.Uint8Array(new int[] { 1, 2, 3 })");
|
|
2400
|
+
});
|
|
2401
|
+
it("rewraps identifier typed-array constructor arguments through the selected source-backed surface arm", () => {
|
|
2402
|
+
const csharp = compileProjectToCSharp({
|
|
2403
|
+
"src/typed-array-core.ts": `
|
|
2404
|
+
export type TypedArrayInput<TElement extends number> =
|
|
2405
|
+
| readonly TElement[]
|
|
2406
|
+
| Iterable<number>;
|
|
2407
|
+
|
|
2408
|
+
export type TypedArrayConstructorInput<TElement extends number> =
|
|
2409
|
+
| number
|
|
2410
|
+
| TypedArrayInput<TElement>;
|
|
2411
|
+
|
|
2412
|
+
export class Uint16Array {
|
|
2413
|
+
public constructor(lengthOrValues: TypedArrayConstructorInput<number>) {
|
|
2414
|
+
void lengthOrValues;
|
|
2415
|
+
}
|
|
2416
|
+
}
|
|
2417
|
+
`,
|
|
2418
|
+
"src/index.ts": `
|
|
2419
|
+
import { Uint16Array } from "./typed-array-core.js";
|
|
2420
|
+
|
|
2421
|
+
export function run(values: number[]): Uint16Array {
|
|
2422
|
+
return new Uint16Array(values);
|
|
2423
|
+
}
|
|
2424
|
+
`,
|
|
2425
|
+
}, "src/index.ts", {
|
|
2426
|
+
surface: "@tsonic/js",
|
|
2427
|
+
}, {
|
|
2428
|
+
sourceRootRelativePath: "src",
|
|
2429
|
+
rootNamespace: "Test",
|
|
2430
|
+
});
|
|
2431
|
+
expect(csharp).to.include("new global::Test.Uint16Array(");
|
|
2432
|
+
expect(csharp).to.include("global::js.TypedArrayConstructorInput");
|
|
2433
|
+
expect(csharp).to.include(".From2(global::js.TypedArrayInput");
|
|
2434
|
+
expect(csharp).to.include(".From1(");
|
|
2435
|
+
expect(csharp).not.to.include("new global::Test.Uint16Array((global::js.TypedArrayConstructorInput");
|
|
2436
|
+
});
|
|
2437
|
+
it("rewraps null-guarded member-access typed-array constructor arguments through the selected source-backed surface arm", () => {
|
|
2438
|
+
const csharp = compileProjectToCSharp({
|
|
2439
|
+
"src/typed-array-core.ts": `
|
|
2440
|
+
export type TypedArrayInput<TElement extends number> =
|
|
2441
|
+
| readonly TElement[]
|
|
2442
|
+
| Iterable<number>;
|
|
2443
|
+
|
|
2444
|
+
export type TypedArrayConstructorInput<TElement extends number> =
|
|
2445
|
+
| number
|
|
2446
|
+
| TypedArrayInput<TElement>;
|
|
2447
|
+
|
|
2448
|
+
export class Uint8Array {
|
|
2449
|
+
public constructor(lengthOrValues: TypedArrayConstructorInput<number>) {
|
|
2450
|
+
void lengthOrValues;
|
|
2451
|
+
}
|
|
2452
|
+
}
|
|
2453
|
+
`,
|
|
2454
|
+
"src/index.ts": `
|
|
2455
|
+
import type { byte } from "@tsonic/core/types.js";
|
|
2456
|
+
import { Uint8Array } from "./typed-array-core.js";
|
|
2457
|
+
|
|
2458
|
+
class Parameters {
|
|
2459
|
+
public Modulus: byte[] | null = null;
|
|
2460
|
+
}
|
|
2461
|
+
|
|
2462
|
+
export function run(parameters: Parameters): Uint8Array {
|
|
2463
|
+
if (parameters.Modulus === null || parameters.Modulus === undefined) {
|
|
2464
|
+
throw new Error("missing");
|
|
2465
|
+
}
|
|
2466
|
+
|
|
2467
|
+
return new Uint8Array(parameters.Modulus);
|
|
2468
|
+
}
|
|
2469
|
+
`,
|
|
2470
|
+
}, "src/index.ts", {
|
|
2471
|
+
surface: "@tsonic/js",
|
|
2472
|
+
}, {
|
|
2473
|
+
sourceRootRelativePath: "src",
|
|
2474
|
+
rootNamespace: "Test",
|
|
2475
|
+
});
|
|
2476
|
+
expect(csharp).to.include("new global::Test.Uint8Array(");
|
|
2477
|
+
expect(csharp).to.include(".From2(global::js.TypedArrayInput<byte>.From1(parameters.Modulus))");
|
|
2478
|
+
expect(csharp).not.to.include("new global::Test.Uint8Array((global::js.TypedArrayConstructorInput");
|
|
2479
|
+
});
|
|
2480
|
+
it("rewraps imported source-package typed-array constructor arguments through nested alias arms", () => {
|
|
2481
|
+
const csharp = compileProjectToCSharp({
|
|
2482
|
+
"src/index.ts": `
|
|
2483
|
+
import type { byte } from "@tsonic/core/types.js";
|
|
2484
|
+
import { Uint8Array } from "@tsonic/js/index.js";
|
|
2485
|
+
|
|
2486
|
+
class Parameters {
|
|
2487
|
+
public Modulus: byte[] | null = null;
|
|
2488
|
+
}
|
|
2489
|
+
|
|
2490
|
+
export function run(parameters: Parameters): Uint8Array {
|
|
2491
|
+
if (parameters.Modulus === null || parameters.Modulus === undefined) {
|
|
2492
|
+
throw new Error("missing");
|
|
2493
|
+
}
|
|
2494
|
+
|
|
2495
|
+
return new Uint8Array(parameters.Modulus);
|
|
2496
|
+
}
|
|
2497
|
+
`,
|
|
2498
|
+
}, "src/index.ts", {
|
|
2499
|
+
surface: "@tsonic/js",
|
|
2500
|
+
});
|
|
2501
|
+
expect(csharp).to.include("new global::js.Uint8Array(");
|
|
2502
|
+
expect(csharp).to.include(".From2(global::js.TypedArrayInput<byte>.From1(parameters.Modulus))");
|
|
2503
|
+
expect(csharp).not.to.include("new global::js.Uint8Array((global::js.TypedArrayConstructorInput");
|
|
2504
|
+
});
|
|
2505
|
+
it("materializes source-owned alias carriers before passing them to inline union base constructors", () => {
|
|
2506
|
+
const csharp = compileProjectToCSharp({
|
|
2507
|
+
"src/typed-array-core.ts": `
|
|
2508
|
+
import type { int } from "@tsonic/core/types.js";
|
|
2509
|
+
|
|
2510
|
+
export type TypedArrayInput<TElement extends number> =
|
|
2511
|
+
| readonly TElement[]
|
|
2512
|
+
| Iterable<number>;
|
|
2513
|
+
|
|
2514
|
+
export type TypedArrayConstructorInput<TElement extends number> =
|
|
2515
|
+
| int
|
|
2516
|
+
| TypedArrayInput<TElement>;
|
|
2517
|
+
|
|
2518
|
+
export class TypedArrayBase<TElement extends number> {
|
|
2519
|
+
protected constructor(lengthOrValues: int | TypedArrayInput<TElement>) {
|
|
2520
|
+
void lengthOrValues;
|
|
2521
|
+
}
|
|
2522
|
+
}
|
|
2523
|
+
|
|
2524
|
+
export class Uint8Array extends TypedArrayBase<number> {
|
|
2525
|
+
public constructor(lengthOrValues: TypedArrayConstructorInput<number>) {
|
|
2526
|
+
super(lengthOrValues);
|
|
2527
|
+
}
|
|
2528
|
+
}
|
|
2529
|
+
`,
|
|
2530
|
+
"src/index.ts": `
|
|
2531
|
+
import { Uint8Array } from "./typed-array-core.js";
|
|
2532
|
+
|
|
2533
|
+
export function run(length: number): Uint8Array {
|
|
2534
|
+
return new Uint8Array(length);
|
|
2535
|
+
}
|
|
2536
|
+
`,
|
|
2537
|
+
}, "src/index.ts", {
|
|
2538
|
+
surface: "@tsonic/js",
|
|
2539
|
+
}, {
|
|
2540
|
+
sourceRootRelativePath: "src",
|
|
2541
|
+
rootNamespace: "Test",
|
|
2542
|
+
});
|
|
2543
|
+
expect(csharp).to.include(": base(lengthOrValues.Match<global::Tsonic.Internal.Union");
|
|
2544
|
+
expect(csharp).to.include(".From1(__tsonic_union_member_1)");
|
|
2545
|
+
expect(csharp).to.include(".From2(__tsonic_union_member_2)");
|
|
2546
|
+
expect(csharp).not.to.include("lengthOrValues.Match<object>");
|
|
2547
|
+
expect(csharp).not.to.include("Unreachable runtime union reification path");
|
|
2548
|
+
});
|
|
2549
|
+
it("lowers Uint8Array.set array literals through byte arrays", () => {
|
|
2550
|
+
const csharp = compileToCSharp(`
|
|
2551
|
+
export function run(): void {
|
|
2552
|
+
const copied = new Uint8Array(4);
|
|
2553
|
+
copied.set([4, 5], 1);
|
|
2554
|
+
}
|
|
2555
|
+
`, "/test/test.ts", {
|
|
2556
|
+
surface: "@tsonic/js",
|
|
2557
|
+
});
|
|
2558
|
+
expect(csharp).to.include("copied.set(new byte[] { 4, 5 }, 1);");
|
|
2559
|
+
expect(csharp).not.to.include("copied.set(new int[] { 4, 5 }, 1);");
|
|
2560
|
+
});
|
|
2561
|
+
it("preserves narrowed runtime-union members when coercing Uint8Array byte elements", () => {
|
|
2562
|
+
const csharp = compileToCSharp(`
|
|
2563
|
+
export function create(
|
|
2564
|
+
generatorOrEncoding: number | Uint8Array | string
|
|
2565
|
+
): Uint8Array {
|
|
2566
|
+
if (typeof generatorOrEncoding === "number") {
|
|
2567
|
+
return new Uint8Array([generatorOrEncoding]);
|
|
2568
|
+
}
|
|
2569
|
+
|
|
2570
|
+
return new Uint8Array([2]);
|
|
2571
|
+
}
|
|
2572
|
+
`, "/test/test.ts", {
|
|
2573
|
+
surface: "@tsonic/js",
|
|
2574
|
+
});
|
|
2575
|
+
expect(csharp).to.include("new global::js.Uint8Array(global::js.TypedArrayConstructorInput<byte>.From2(global::js.TypedArrayInput<byte>.From1(new byte[] { (byte)(generatorOrEncoding.As2()) })))");
|
|
2576
|
+
expect(csharp).not.to.include("new global::js.Uint8Array(new byte[] { (byte)generatorOrEncoding })");
|
|
2577
|
+
});
|
|
2578
|
+
it("rewraps plain string call arguments through runtime-union surfaces", () => {
|
|
2579
|
+
const csharp = normalizeRuntimeUnionCarrierNames(compileToCSharp(`
|
|
2580
|
+
declare class Buffer {
|
|
2581
|
+
public static from(
|
|
2582
|
+
value: number[] | Uint8Array | string,
|
|
2583
|
+
encodingOrOffset?: number | string,
|
|
2584
|
+
): Buffer;
|
|
2585
|
+
}
|
|
2586
|
+
|
|
2587
|
+
declare function toUint8Array(value: Buffer): Uint8Array;
|
|
2588
|
+
|
|
2589
|
+
export function run(rawText: string): Uint8Array {
|
|
2590
|
+
return toUint8Array(Buffer.from(rawText, "utf-8"));
|
|
2591
|
+
}
|
|
2592
|
+
`, "/test/test.ts", {
|
|
2593
|
+
surface: "@tsonic/js",
|
|
2594
|
+
}));
|
|
2595
|
+
expect(csharp).to.include('Buffer.from(global::Tsonic.Internal.Union<double[], global::js.Uint8Array, string>.From3(rawText), global::Tsonic.Internal.Union<double, string>.From2("utf-8"))');
|
|
2596
|
+
expect(csharp).not.to.include('Buffer.from(rawText, global::Tsonic.Internal.Union<double, string>.From2("utf-8"))');
|
|
2597
|
+
});
|
|
2598
|
+
it("projects typeof-excluded call arguments onto the surviving runtime-union subset", () => {
|
|
2599
|
+
const csharp = normalizeRuntimeUnionCarrierNames(compileProjectToCSharp({
|
|
2600
|
+
"src/index.ts": `
|
|
2601
|
+
import { Uint8Array } from "@fixture/js/index.js";
|
|
2602
|
+
|
|
2603
|
+
export class Buffer {
|
|
2604
|
+
static fromString(_value: string, _encoding?: string): Buffer {
|
|
2605
|
+
return new Buffer();
|
|
2606
|
+
}
|
|
2607
|
+
|
|
2608
|
+
static fromNonString(_value: number[] | Buffer | Uint8Array): Buffer {
|
|
2609
|
+
return new Buffer();
|
|
2610
|
+
}
|
|
2611
|
+
|
|
2612
|
+
static from(
|
|
2613
|
+
value: string | number[] | Buffer | Uint8Array,
|
|
2614
|
+
encodingOrOffset?: string | number,
|
|
2615
|
+
): Buffer {
|
|
2616
|
+
if (typeof value === "string") {
|
|
2617
|
+
return Buffer.fromString(
|
|
2618
|
+
value,
|
|
2619
|
+
typeof encodingOrOffset === "string" ? encodingOrOffset : "utf8",
|
|
2620
|
+
);
|
|
2621
|
+
}
|
|
2622
|
+
|
|
2623
|
+
return Buffer.fromNonString(value);
|
|
2624
|
+
}
|
|
2625
|
+
}
|
|
2626
|
+
`,
|
|
2627
|
+
"node_modules/@fixture/js/package.json": JSON.stringify({ name: "@fixture/js", version: "1.0.0", type: "module" }, null, 2),
|
|
2628
|
+
"node_modules/@fixture/js/tsonic.package.json": JSON.stringify({
|
|
2629
|
+
schemaVersion: 1,
|
|
2630
|
+
kind: "tsonic-source-package",
|
|
2631
|
+
surfaces: ["@tsonic/js"],
|
|
2632
|
+
source: {
|
|
2633
|
+
namespace: "fixturejs",
|
|
2634
|
+
exports: {
|
|
2635
|
+
"./index.js": "./src/index.ts",
|
|
2636
|
+
},
|
|
2637
|
+
},
|
|
2638
|
+
}, null, 2),
|
|
2639
|
+
"node_modules/@fixture/js/src/index.ts": `
|
|
2640
|
+
export class Uint8Array {}
|
|
2641
|
+
`,
|
|
2642
|
+
}, "src/index.ts", { surface: "@tsonic/js" }));
|
|
2643
|
+
expect(csharp).to.include("return Buffer.fromNonString((global::Tsonic.Internal.Union<double[], global::Test.Buffer, global::fixturejs.Uint8Array>)value.Match<global::Tsonic.Internal.Union<double[], global::Test.Buffer, global::fixturejs.Uint8Array>>(");
|
|
2644
|
+
expect(csharp).not.to.include("return Buffer.fromNonString(value);");
|
|
2645
|
+
expect(csharp).not.to.include("return Buffer.fromNonString(global::Tsonic.Internal.Union<double[], global::Test.Buffer, global::fixturejs.Uint8Array, string>");
|
|
2646
|
+
});
|
|
2647
|
+
it("preserves narrowed runtime-union members in typed byte array literals", () => {
|
|
2648
|
+
const csharp = compileToCSharp(`
|
|
2649
|
+
import type { byte } from "@tsonic/core/types.js";
|
|
2650
|
+
|
|
2651
|
+
declare function takesBytes(values: byte[]): void;
|
|
2652
|
+
|
|
2653
|
+
export function create(
|
|
2654
|
+
generatorOrEncoding: number | Uint8Array | string
|
|
2655
|
+
): void {
|
|
2656
|
+
if (typeof generatorOrEncoding === "number") {
|
|
2657
|
+
takesBytes([generatorOrEncoding]);
|
|
2658
|
+
}
|
|
2659
|
+
}
|
|
2660
|
+
`, "/test/test.ts", {
|
|
2661
|
+
surface: "@tsonic/js",
|
|
2662
|
+
});
|
|
2663
|
+
expect(csharp).to.include("takesBytes(new byte[] { (byte)(generatorOrEncoding.As2()) })");
|
|
2664
|
+
expect(csharp).not.to.include("takesBytes(new byte[] { (byte)generatorOrEncoding })");
|
|
2665
|
+
});
|
|
2666
|
+
it("preserves explicit numeric assertion targets in arithmetic operands", () => {
|
|
2667
|
+
const csharp = compileToCSharp(`
|
|
2668
|
+
import type { int, long } from "@tsonic/core/types.js";
|
|
2669
|
+
|
|
2670
|
+
export function run(x: int): long {
|
|
2671
|
+
return (x as long) * 2000000000;
|
|
2672
|
+
}
|
|
2673
|
+
`);
|
|
2674
|
+
expect(csharp).to.include("(long)x * 2000000000");
|
|
2675
|
+
expect(csharp).not.to.include("(int)(long)x");
|
|
2676
|
+
});
|
|
2677
|
+
it("does not unbox nullable numeric arguments with the same CLR carrier", () => {
|
|
2678
|
+
const csharp = compileToCSharp(`
|
|
2679
|
+
import type { long } from "@tsonic/core/types.js";
|
|
2680
|
+
|
|
2681
|
+
interface Box {
|
|
2682
|
+
value?: long;
|
|
2683
|
+
}
|
|
2684
|
+
|
|
2685
|
+
export function take(value: long | undefined | null): long {
|
|
2686
|
+
return value ?? (0 as long);
|
|
2687
|
+
}
|
|
2688
|
+
|
|
2689
|
+
export function run(box: Box): long {
|
|
2690
|
+
return take(box.value);
|
|
2691
|
+
}
|
|
2692
|
+
`);
|
|
2693
|
+
expect(csharp).to.include("take(box.value)");
|
|
2694
|
+
expect(csharp).not.to.include("take((long)box.value)");
|
|
2695
|
+
});
|
|
2696
|
+
it("converts concrete integral storage to JS number without object boxing", () => {
|
|
2697
|
+
const csharp = compileToCSharp(`
|
|
2698
|
+
import type { long } from "@tsonic/core/types.js";
|
|
2699
|
+
|
|
2700
|
+
export function take(value: number): number {
|
|
2701
|
+
return value;
|
|
2702
|
+
}
|
|
2703
|
+
|
|
2704
|
+
export function run(userId: long): number {
|
|
2705
|
+
return take(userId);
|
|
2706
|
+
}
|
|
2707
|
+
`);
|
|
2708
|
+
expect(csharp).to.include("return take((double)userId);");
|
|
2709
|
+
expect(csharp).not.to.include("(double)(object)userId");
|
|
2710
|
+
});
|
|
2711
|
+
it("emits shadowed instanceof receivers from actual local storage", () => {
|
|
2712
|
+
const csharp = compileToCSharp(`
|
|
2713
|
+
class BoolValue {
|
|
2714
|
+
public value: boolean;
|
|
2715
|
+
|
|
2716
|
+
constructor(value: boolean) {
|
|
2717
|
+
this.value = value;
|
|
2718
|
+
}
|
|
2719
|
+
}
|
|
2720
|
+
|
|
2721
|
+
export function run(): void {
|
|
2722
|
+
const shadow = 42;
|
|
2723
|
+
{
|
|
2724
|
+
const shadow = new BoolValue(false);
|
|
2725
|
+
if (shadow instanceof BoolValue) {
|
|
2726
|
+
void shadow.value;
|
|
2727
|
+
}
|
|
2728
|
+
}
|
|
2729
|
+
void shadow;
|
|
2730
|
+
}
|
|
2731
|
+
`);
|
|
2732
|
+
expect(csharp).to.match(/if \(shadow__1 is BoolValue shadow__is_\d+\)/);
|
|
2733
|
+
expect(csharp).not.to.include("(int)(object)shadow__1 is BoolValue");
|
|
2734
|
+
});
|
|
2735
|
+
it("casts numeric Uint8Array length constructors to int", () => {
|
|
2736
|
+
const csharp = compileToCSharp(`
|
|
2737
|
+
export function run(start: number, end: number): Uint8Array {
|
|
2738
|
+
return new Uint8Array(end - start);
|
|
2739
|
+
}
|
|
2740
|
+
`, "/test/test.ts", {
|
|
2741
|
+
surface: "@tsonic/js",
|
|
2742
|
+
});
|
|
2743
|
+
expect(csharp).to.include("new global::js.Uint8Array(global::js.TypedArrayConstructorInput<byte>.From1((int)(end - start)))");
|
|
2744
|
+
expect(csharp).not.to.include("new global::js.Uint8Array((int)global::js.TypedArrayConstructorInput");
|
|
2745
|
+
});
|
|
2746
|
+
it("does not recast materialized typed-array constructor length unions", () => {
|
|
2747
|
+
const csharp = compileToCSharp(`
|
|
2748
|
+
export function run(): Uint8Array {
|
|
2749
|
+
return new Uint8Array(8);
|
|
2750
|
+
}
|
|
2751
|
+
`, "/test/test.ts", {
|
|
2752
|
+
surface: "@tsonic/js",
|
|
2753
|
+
});
|
|
2754
|
+
expect(csharp).to.include("return new global::js.Uint8Array(global::js.TypedArrayConstructorInput<byte>.From1(8));");
|
|
2755
|
+
expect(csharp).not.to.include("new global::js.Uint8Array((int)global::js.TypedArrayConstructorInput");
|
|
2756
|
+
});
|
|
2757
|
+
it("keeps asserted int Uint8Array length constructors on the numeric arm", () => {
|
|
2758
|
+
const csharp = compileToCSharp(`
|
|
2759
|
+
import type { int } from "@tsonic/core/types.js";
|
|
2760
|
+
|
|
2761
|
+
export function run(): Uint8Array {
|
|
2762
|
+
return new Uint8Array(0 as int);
|
|
2763
|
+
}
|
|
2764
|
+
`, "/test/test.ts", {
|
|
2765
|
+
surface: "@tsonic/js",
|
|
2766
|
+
});
|
|
2767
|
+
expect(csharp).to.include("return new global::js.Uint8Array(global::js.TypedArrayConstructorInput<byte>.From1(0));");
|
|
2768
|
+
expect(csharp).not.to.include("From2((global::js.TypedArrayInput<TElement>)");
|
|
2769
|
+
expect(csharp).not.to.include("TypedArrayInput<byte>)0");
|
|
2770
|
+
});
|
|
2771
|
+
it("keeps conditional Uint8Array length constructors on the numeric arm", () => {
|
|
2772
|
+
const csharp = compileToCSharp(`
|
|
2773
|
+
export function run(totalLength: number): Uint8Array {
|
|
2774
|
+
return new Uint8Array(totalLength === 0 ? 1 : totalLength);
|
|
2775
|
+
}
|
|
2776
|
+
`, "/test/test.ts", {
|
|
2777
|
+
surface: "@tsonic/js",
|
|
2778
|
+
});
|
|
2779
|
+
expect(csharp).to.include("return new global::js.Uint8Array(global::js.TypedArrayConstructorInput<byte>.From1((int)(");
|
|
2780
|
+
expect(csharp).to.include("totalLength == 0 ? 1 :");
|
|
2781
|
+
expect(csharp).not.to.include("return new global::js.Uint8Array(totalLength == 0 ? global::js.TypedArrayConstructorInput<byte>.From2(");
|
|
2782
|
+
});
|
|
2783
|
+
it("keeps narrowed Uint8Array length access as a direct member read", () => {
|
|
2784
|
+
const csharp = compileToCSharp(`
|
|
2785
|
+
export function run(chunk: string | Uint8Array): number {
|
|
2786
|
+
if (chunk instanceof Uint8Array) {
|
|
2787
|
+
return chunk.length;
|
|
2788
|
+
}
|
|
2789
|
+
|
|
2790
|
+
return 0;
|
|
2791
|
+
}
|
|
2792
|
+
`, "/test/test.ts", {
|
|
2793
|
+
surface: "@tsonic/js",
|
|
2794
|
+
});
|
|
2795
|
+
expect(csharp).to.include("chunk__is_1.length");
|
|
2796
|
+
expect(csharp).not.to.include("new global::js.Array<object>(chunk__is_1).length");
|
|
2797
|
+
});
|
|
2798
|
+
it("materializes imported nullable value-type member reads exactly once after null guards", () => {
|
|
2799
|
+
const csharp = compileProjectToCSharp({
|
|
2800
|
+
"src/options.ts": `
|
|
2801
|
+
export interface MultipartField {
|
|
2802
|
+
name: string;
|
|
2803
|
+
maxCount?: number;
|
|
2804
|
+
}
|
|
2805
|
+
`,
|
|
2806
|
+
"src/index.ts": `
|
|
2807
|
+
import type { MultipartField } from "./options.js";
|
|
2808
|
+
|
|
2809
|
+
function findAllowRule(
|
|
2810
|
+
allowList: readonly MultipartField[],
|
|
2811
|
+
fieldname: string
|
|
2812
|
+
): MultipartField | undefined {
|
|
2813
|
+
for (let index = 0; index < allowList.length; index += 1) {
|
|
2814
|
+
const candidate = allowList[index]!;
|
|
2815
|
+
if (candidate.name.toLowerCase() === fieldname.toLowerCase()) {
|
|
2816
|
+
return candidate;
|
|
2817
|
+
}
|
|
2818
|
+
}
|
|
2819
|
+
|
|
2820
|
+
return undefined;
|
|
2821
|
+
}
|
|
2822
|
+
|
|
2823
|
+
export function run(
|
|
2824
|
+
allowList: readonly MultipartField[],
|
|
2825
|
+
fieldname: string
|
|
2826
|
+
): void {
|
|
2827
|
+
const rule = findAllowRule(allowList, fieldname);
|
|
2828
|
+
if (!rule) {
|
|
2829
|
+
return;
|
|
2830
|
+
}
|
|
2831
|
+
|
|
2832
|
+
if (rule.maxCount !== undefined) {
|
|
2833
|
+
const current = 0;
|
|
2834
|
+
const nextCount = current + 1;
|
|
2835
|
+
if (nextCount > rule.maxCount) {
|
|
2836
|
+
throw new Error(String(rule.maxCount));
|
|
2837
|
+
}
|
|
2838
|
+
}
|
|
2839
|
+
}
|
|
2840
|
+
`,
|
|
2841
|
+
}, "src/index.ts");
|
|
2842
|
+
expect(csharp).to.include("if (nextCount > rule.maxCount.Value)");
|
|
2843
|
+
expect(csharp).to.include("String(rule.maxCount.Value)");
|
|
2844
|
+
expect(csharp).not.to.include("rule.maxCount.Value.Value");
|
|
2845
|
+
});
|
|
2846
|
+
it("keeps source-package Uint8Array length reads direct inside array-like wrappers", () => {
|
|
2847
|
+
const csharp = compileProjectToCSharp({
|
|
2848
|
+
"src/index.ts": `
|
|
2849
|
+
import { ServerResponse } from "@tsonic/nodejs/http.js";
|
|
2850
|
+
|
|
2851
|
+
export function run(chunk: Uint8Array): boolean {
|
|
2852
|
+
const response = new ServerResponse();
|
|
2853
|
+
return response.write(chunk);
|
|
2854
|
+
}
|
|
2855
|
+
`,
|
|
2856
|
+
}, "src/index.ts", {
|
|
2857
|
+
surface: "@tsonic/js",
|
|
2858
|
+
});
|
|
2859
|
+
expect(csharp).to.include("if (chunk.Is3())");
|
|
2860
|
+
expect(csharp).to.include("chunk__is_1.length");
|
|
2861
|
+
expect(csharp).to.include("chunk__is_1.at(index)");
|
|
2862
|
+
expect(csharp).not.to.include("new global::js.Array<object>(chunk__is_1).length");
|
|
2863
|
+
});
|
|
2864
|
+
it("lowers non-byte typed-array array-literal constructors through concrete CLR arrays", () => {
|
|
2865
|
+
const csharp = compileToCSharp(`
|
|
2866
|
+
export function run(): void {
|
|
2867
|
+
const ints = new Int16Array([1, 2, 3]);
|
|
2868
|
+
const floats = new Float32Array([1.25, 2.5]);
|
|
2869
|
+
void ints;
|
|
2870
|
+
void floats;
|
|
2871
|
+
}
|
|
2872
|
+
`, "/test/test.ts", {
|
|
2873
|
+
surface: "@tsonic/js",
|
|
2874
|
+
});
|
|
2875
|
+
expect(csharp).to.include("new global::js.Int16Array(global::js.TypedArrayConstructorInput<short>.From2(global::js.TypedArrayInput<short>.From1(new short[] { 1, 2, 3 })))");
|
|
2876
|
+
expect(csharp).to.include("new global::js.Float32Array(global::js.TypedArrayConstructorInput<float>.From2(global::js.TypedArrayInput<float>.From1(new float[] { 1.25f, 2.5f })))");
|
|
2877
|
+
expect(csharp).not.to.include("new Int16Array(global::Tsonic.Internal.Union<double[], global::System.Collections.Generic.IEnumerable<double>>");
|
|
2878
|
+
expect(csharp).not.to.include("new Float32Array(global::Tsonic.Internal.Union<double[], global::System.Collections.Generic.IEnumerable<double>>");
|
|
2879
|
+
});
|
|
2880
|
+
it("casts non-byte typed-array numeric length constructors to int", () => {
|
|
2881
|
+
const csharp = compileToCSharp(`
|
|
2882
|
+
export function run(start: number, end: number): void {
|
|
2883
|
+
const view = new Int16Array(end - start);
|
|
2884
|
+
void view;
|
|
2885
|
+
}
|
|
2886
|
+
`, "/test/test.ts", {
|
|
2887
|
+
surface: "@tsonic/js",
|
|
2888
|
+
});
|
|
2889
|
+
expect(csharp).to.include("new global::js.Int16Array(global::js.TypedArrayConstructorInput<short>.From1((int)(end - start)))");
|
|
2890
|
+
});
|
|
2891
|
+
it("casts Uint8Array element assignments to byte", () => {
|
|
2892
|
+
const csharp = compileToCSharp(`
|
|
2893
|
+
import type { int } from "@tsonic/core/types.js";
|
|
2894
|
+
|
|
2895
|
+
export function run(i: int): void {
|
|
2896
|
+
const data = new Uint8Array(16);
|
|
2897
|
+
data[i] = 255;
|
|
2898
|
+
}
|
|
2899
|
+
`, "/test/test.ts", {
|
|
2900
|
+
surface: "@tsonic/js",
|
|
2901
|
+
});
|
|
2902
|
+
expect(csharp).to.include("data.set(i, 255);");
|
|
2903
|
+
expect(csharp).not.to.include("data[i] = 255;");
|
|
2904
|
+
});
|
|
2905
|
+
it("casts JS numeric expressions when assigning into int slots", () => {
|
|
2906
|
+
const csharp = compileToCSharp(`
|
|
2907
|
+
import type { int } from "@tsonic/core/types.js";
|
|
2908
|
+
|
|
2909
|
+
class CursorPosition {
|
|
2910
|
+
public rows: int = 0;
|
|
2911
|
+
}
|
|
2912
|
+
|
|
2913
|
+
export function run(totalLength: number): CursorPosition {
|
|
2914
|
+
const pos = new CursorPosition();
|
|
2915
|
+
pos.rows = Math.floor(totalLength / 80);
|
|
2916
|
+
return pos;
|
|
2917
|
+
}
|
|
2918
|
+
`, "/test/test.ts", {
|
|
2919
|
+
surface: "@tsonic/js",
|
|
2920
|
+
});
|
|
2921
|
+
expect(csharp).to.include("pos.rows = (int)global::js.Math.floor(totalLength / 80);");
|
|
2922
|
+
});
|
|
2923
|
+
it("casts JS numeric expressions when assigning through exact int property slots", () => {
|
|
2924
|
+
const csharp = compileToCSharp(`
|
|
2925
|
+
import type { int } from "@tsonic/core/types.js";
|
|
2926
|
+
|
|
2927
|
+
class Counter {
|
|
2928
|
+
private _value: int = 0;
|
|
2929
|
+
|
|
2930
|
+
public set value(v: number) {
|
|
2931
|
+
const offset = 123;
|
|
2932
|
+
this._value = v + offset;
|
|
2933
|
+
}
|
|
2934
|
+
}
|
|
2935
|
+
|
|
2936
|
+
export function run(value: number): void {
|
|
2937
|
+
const counter = new Counter();
|
|
2938
|
+
counter.value = value;
|
|
2939
|
+
}
|
|
2940
|
+
`, "/test/test.ts", {
|
|
2941
|
+
surface: "@tsonic/js",
|
|
2942
|
+
});
|
|
2943
|
+
expect(csharp).to.include("this._value = (int)(v + offset);");
|
|
2944
|
+
});
|
|
2945
|
+
it("keeps context-narrowed numeric conditionals on the contextual branch type", () => {
|
|
2946
|
+
const csharp = compileToCSharp(`
|
|
2947
|
+
export function build(): number[] {
|
|
2948
|
+
const table: number[] = new Array<number>(1);
|
|
2949
|
+
const polynomial = 0xedb88320;
|
|
2950
|
+
let crc = 0;
|
|
2951
|
+
crc = (crc & 1) === 1 ? (crc >>> 1) ^ polynomial : crc >>> 1;
|
|
2952
|
+
table[0] = crc;
|
|
2953
|
+
return table;
|
|
2954
|
+
}
|
|
2955
|
+
`);
|
|
2956
|
+
expect(csharp).to.include("crc = ((int)crc & (int)1) == 1");
|
|
2957
|
+
expect(csharp).not.to.include(": (global::System.Double)((int)crc >>> (int)1)");
|
|
2958
|
+
});
|
|
2959
|
+
it("materializes inline object-type elements through generic List<T>.Add", () => {
|
|
2960
|
+
const source = `
|
|
2961
|
+
declare class List<T> {
|
|
2962
|
+
Add(item: T): void;
|
|
2963
|
+
ToArray(): T[];
|
|
2964
|
+
}
|
|
2965
|
+
|
|
2966
|
+
declare function createDraftsDomain(inputs: { type: string; to: string; topic?: string; content: string }[]): void;
|
|
2967
|
+
|
|
2968
|
+
export function run(): void {
|
|
2969
|
+
const inputs = new List<{ type: string; to: string; topic?: string; content: string }>();
|
|
2970
|
+
inputs.Add({ type: "stream", to: "general", topic: "t", content: "hi" });
|
|
2971
|
+
createDraftsDomain(inputs.ToArray());
|
|
2972
|
+
}
|
|
2973
|
+
`;
|
|
2974
|
+
const csharp = compileToCSharp(source);
|
|
2975
|
+
expect(csharp).to.match(/inputs\.Add\(new .* \{ type = "stream", to = "general", topic = "t", content = "hi" \}\);/);
|
|
2976
|
+
expect(csharp).not.to.include("inputs.Add(new global::System.Collections.Generic.Dictionary");
|
|
2977
|
+
});
|
|
2978
|
+
it("materializes inline object-type arrays through generic List<T>.ToArray()", () => {
|
|
2979
|
+
const source = `
|
|
2980
|
+
declare class List<T> {
|
|
2981
|
+
Add(item: T): void;
|
|
2982
|
+
ToArray(): T[];
|
|
2983
|
+
}
|
|
2984
|
+
|
|
2985
|
+
declare function createDraftsDomain(inputs: { type: string; to: string; topic?: string; content: string }[]): void;
|
|
2986
|
+
|
|
2987
|
+
export function run(drafts: { type: string; to: string; topic?: string; content: string }[]): void {
|
|
2988
|
+
const inputs = new List<{ type: string; to: string; topic?: string; content: string }>();
|
|
2989
|
+
for (let i = 0; i < drafts.length; i++) {
|
|
2990
|
+
const d = drafts[i];
|
|
2991
|
+
inputs.Add({ type: d.type, to: d.to, topic: d.topic, content: d.content });
|
|
2992
|
+
}
|
|
2993
|
+
createDraftsDomain(inputs.ToArray());
|
|
2994
|
+
}
|
|
2995
|
+
`;
|
|
2996
|
+
const csharp = compileToCSharp(source);
|
|
2997
|
+
expect(csharp).to.match(/inputs\.Add\(new .* \{ type = d\.type, to = d\.to, topic = d\.topic, content = d\.content \}\);/);
|
|
2998
|
+
expect(csharp).to.include("createDraftsDomain(inputs.ToArray());");
|
|
2999
|
+
});
|
|
3000
|
+
it("materializes source-owned anonymous List<T>.ToArray() arrays to named structural array parameters", () => {
|
|
3001
|
+
const source = `
|
|
3002
|
+
import type { long } from "@tsonic/core/types.js";
|
|
3003
|
+
|
|
3004
|
+
declare class List<T> {
|
|
3005
|
+
Add(item: T): void;
|
|
3006
|
+
ToArray(): T[];
|
|
3007
|
+
}
|
|
3008
|
+
|
|
3009
|
+
type SubscriptionPropertyUpdate = {
|
|
3010
|
+
streamId: long;
|
|
3011
|
+
property: string;
|
|
3012
|
+
propValue: string;
|
|
3013
|
+
};
|
|
3014
|
+
|
|
3015
|
+
declare function update(inputs: SubscriptionPropertyUpdate[]): void;
|
|
3016
|
+
|
|
3017
|
+
export function run(id: long, property: string, propValue: string): void {
|
|
3018
|
+
const updates = new List<{ streamId: long; property: string; propValue: string }>();
|
|
3019
|
+
updates.Add({ streamId: id, property, propValue });
|
|
3020
|
+
update(updates.ToArray());
|
|
3021
|
+
}
|
|
3022
|
+
`;
|
|
3023
|
+
const csharp = compileToCSharp(source);
|
|
3024
|
+
expect(csharp).to.include("global::System.Linq.Enumerable.Select");
|
|
3025
|
+
expect(csharp).to.include("new SubscriptionPropertyUpdate__Alias");
|
|
3026
|
+
expect(csharp).not.to.include("update(updates.ToArray());");
|
|
3027
|
+
});
|
|
3028
|
+
it("reifies structural alias array elements after generic List<T>.ToArray()", () => {
|
|
3029
|
+
const source = `
|
|
3030
|
+
declare class List<T> {
|
|
3031
|
+
Add(item: T): void;
|
|
3032
|
+
ToArray(): T[];
|
|
3033
|
+
}
|
|
3034
|
+
|
|
3035
|
+
type TopRow = {
|
|
3036
|
+
key: string;
|
|
3037
|
+
pageviews: number;
|
|
3038
|
+
};
|
|
3039
|
+
|
|
3040
|
+
export function run(): number {
|
|
3041
|
+
const rows = new List<TopRow>();
|
|
3042
|
+
rows.Add({ key: "home", pageviews: 1 });
|
|
3043
|
+
const arr = rows.ToArray();
|
|
3044
|
+
return arr[0]!.pageviews;
|
|
3045
|
+
}
|
|
3046
|
+
`;
|
|
3047
|
+
const csharp = compileToCSharp(source);
|
|
3048
|
+
expect(csharp).to.not.include("ICE: Anonymous object type reached emitter");
|
|
3049
|
+
expect(csharp).to.include("rows.ToArray()");
|
|
3050
|
+
expect(csharp).to.match(/return .*pageviews;/);
|
|
3051
|
+
});
|
|
3052
|
+
it("emits empty inline object-type locals with optional properties", () => {
|
|
3053
|
+
const source = `
|
|
3054
|
+
import type { int } from "@tsonic/core/types.js";
|
|
3055
|
+
|
|
3056
|
+
export function run(name: string | undefined, active: int | undefined): void {
|
|
3057
|
+
const updates: { name?: string; active?: int } = {};
|
|
3058
|
+
if (name) updates.name = name;
|
|
3059
|
+
if (active !== undefined) updates.active = active;
|
|
3060
|
+
void updates;
|
|
3061
|
+
}
|
|
3062
|
+
`;
|
|
3063
|
+
const csharp = compileToCSharp(source);
|
|
3064
|
+
expect(csharp).to.match(/__Anon_[A-Za-z0-9_]+\s+updates\s*=\s*new\s+global::Test\.__Anon_[A-Za-z0-9_]+\(\);/);
|
|
3065
|
+
expect(csharp).not.to.include("new global::System.Collections.Generic.Dictionary");
|
|
3066
|
+
});
|
|
3067
|
+
it("preserves original runtime-union slots across chained typeof complements with nullish wrappers", () => {
|
|
3068
|
+
const csharp = compileToCSharp(`
|
|
3069
|
+
declare function a(n: number): string;
|
|
3070
|
+
declare function b(s: string): string;
|
|
3071
|
+
|
|
3072
|
+
export function run(x?: number | string): string {
|
|
3073
|
+
let y = a(2);
|
|
3074
|
+
if (typeof x === "number") {
|
|
3075
|
+
y = a(x);
|
|
3076
|
+
} else if (typeof x === "string") {
|
|
3077
|
+
y = b(x);
|
|
3078
|
+
}
|
|
3079
|
+
return y;
|
|
3080
|
+
}
|
|
3081
|
+
`);
|
|
3082
|
+
expect(csharp).to.include("x.Is1()");
|
|
3083
|
+
expect(csharp).to.include("x.Is2()");
|
|
3084
|
+
expect(csharp).to.include("y = b((x.As2()));");
|
|
3085
|
+
expect(csharp).not.to.include("y = b((string)x);");
|
|
3086
|
+
});
|
|
3087
|
+
it("preserves original carrier slot numbering across nested typeof fallthrough guards", () => {
|
|
3088
|
+
const csharp = compileToCSharp(`
|
|
3089
|
+
type Hostname = string;
|
|
3090
|
+
type ListenCb = () => void;
|
|
3091
|
+
|
|
3092
|
+
declare function acceptBacklog(backlog: number): void;
|
|
3093
|
+
|
|
3094
|
+
export function run(hostname?: number | Hostname | ListenCb | null): void {
|
|
3095
|
+
if (typeof hostname === "function") {
|
|
3096
|
+
return;
|
|
3097
|
+
}
|
|
3098
|
+
|
|
3099
|
+
if (typeof hostname === "number") {
|
|
3100
|
+
acceptBacklog(hostname);
|
|
3101
|
+
}
|
|
3102
|
+
}
|
|
3103
|
+
`, "/test/test.ts", { surface: "@tsonic/js" });
|
|
3104
|
+
expect(csharp).to.include("acceptBacklog((hostname.As2()));");
|
|
3105
|
+
expect(csharp).not.to.include("global::Tsonic.Internal.Union<global::System.Action, double>.From2((hostname.As2()))");
|
|
3106
|
+
expect(csharp).not.to.include("(global::Tsonic.Internal.Union<global::System.Action, double>?)(hostname.As2())");
|
|
3107
|
+
});
|
|
3108
|
+
it("keeps prior typeof complements alive across later undefined guards", () => {
|
|
3109
|
+
const csharp = compileToCSharp(`
|
|
3110
|
+
type TlsOptions = {
|
|
3111
|
+
readonly allowHalfOpen?: boolean;
|
|
3112
|
+
};
|
|
3113
|
+
|
|
3114
|
+
export function run(
|
|
3115
|
+
optionsOrListener?: TlsOptions | (() => void),
|
|
3116
|
+
): boolean {
|
|
3117
|
+
if (typeof optionsOrListener === "function") {
|
|
3118
|
+
return false;
|
|
3119
|
+
}
|
|
3120
|
+
|
|
3121
|
+
if (optionsOrListener !== undefined) {
|
|
3122
|
+
return optionsOrListener.allowHalfOpen ?? false;
|
|
3123
|
+
}
|
|
3124
|
+
|
|
3125
|
+
return false;
|
|
3126
|
+
}
|
|
3127
|
+
`, "/test/test.ts", { surface: "@tsonic/js" });
|
|
3128
|
+
expect(csharp).to.include("if (((global::System.Object)(optionsOrListener)) != null)");
|
|
3129
|
+
expect(csharp).to.include("return (optionsOrListener.As2()).allowHalfOpen ?? false;");
|
|
3130
|
+
expect(csharp).not.to.include("return optionsOrListener.allowHalfOpen ?? false;");
|
|
3131
|
+
expect(csharp).not.to.include("return ((TlsOptions__Alias)optionsOrListener).allowHalfOpen ?? false;");
|
|
3132
|
+
});
|
|
3133
|
+
it("materializes typeof complements before later constructor arguments", () => {
|
|
3134
|
+
const csharp = compileToCSharp(`
|
|
3135
|
+
type TlsOptions = {
|
|
3136
|
+
readonly allowHalfOpen?: boolean;
|
|
3137
|
+
};
|
|
3138
|
+
|
|
3139
|
+
class TLSSocket {}
|
|
3140
|
+
|
|
3141
|
+
class TLSServer {
|
|
3142
|
+
constructor(
|
|
3143
|
+
options?: TlsOptions | ((socket: TLSSocket) => void) | null,
|
|
3144
|
+
listener?: ((socket: TLSSocket) => void) | null,
|
|
3145
|
+
) {}
|
|
3146
|
+
}
|
|
3147
|
+
|
|
3148
|
+
export const createServer = (
|
|
3149
|
+
optionsOrListener?: TlsOptions | ((socket: TLSSocket) => void),
|
|
3150
|
+
secureConnectionListener?: (socket: TLSSocket) => void,
|
|
3151
|
+
): TLSServer => {
|
|
3152
|
+
if (typeof optionsOrListener === "function") {
|
|
3153
|
+
return new TLSServer(optionsOrListener);
|
|
3154
|
+
}
|
|
3155
|
+
|
|
3156
|
+
if (optionsOrListener !== undefined) {
|
|
3157
|
+
return new TLSServer(
|
|
3158
|
+
optionsOrListener,
|
|
3159
|
+
secureConnectionListener ?? null,
|
|
3160
|
+
);
|
|
3161
|
+
}
|
|
3162
|
+
|
|
3163
|
+
return new TLSServer();
|
|
3164
|
+
};
|
|
3165
|
+
`, "/test/test.ts", { surface: "@tsonic/js" });
|
|
3166
|
+
expect(csharp).to.include("if (((global::System.Object)(optionsOrListener)) != null)");
|
|
3167
|
+
expect(csharp).to.include("return new TLSServer(optionsOrListener, secureConnectionListener ?? null);");
|
|
3168
|
+
expect(csharp).not.to.include("return new TLSServer((TlsOptions__Alias)(optionsOrListener.As2()), secureConnectionListener ?? null);");
|
|
3169
|
+
expect(csharp).not.to.include("global::Tsonic.Internal.Union<global::System.Action<TLSSocket>, TlsOptions__Alias>.From2");
|
|
3170
|
+
});
|
|
3171
|
+
it("materializes typeof complements before later local initializers in nested nullish guards", () => {
|
|
3172
|
+
const csharp = compileToCSharp(`
|
|
3173
|
+
import type { byte } from "@tsonic/core/types.js";
|
|
3174
|
+
|
|
3175
|
+
declare class Buffer {}
|
|
3176
|
+
declare class Uint8Array {}
|
|
3177
|
+
|
|
3178
|
+
export function probe(
|
|
3179
|
+
chunkOrCallback?:
|
|
3180
|
+
| string
|
|
3181
|
+
| Buffer
|
|
3182
|
+
| byte[]
|
|
3183
|
+
| Uint8Array
|
|
3184
|
+
| (() => void)
|
|
3185
|
+
| null,
|
|
3186
|
+
): void {
|
|
3187
|
+
if (typeof chunkOrCallback === "function") {
|
|
3188
|
+
return;
|
|
3189
|
+
}
|
|
3190
|
+
|
|
3191
|
+
if (
|
|
3192
|
+
chunkOrCallback !== undefined &&
|
|
3193
|
+
chunkOrCallback !== null &&
|
|
3194
|
+
typeof chunkOrCallback !== "function"
|
|
3195
|
+
) {
|
|
3196
|
+
const value = chunkOrCallback;
|
|
3197
|
+
void value;
|
|
3198
|
+
}
|
|
3199
|
+
}
|
|
3200
|
+
`, "/test/test.ts", { surface: "@tsonic/js" });
|
|
3201
|
+
expect(csharp).to.include("var value = chunkOrCallback.Match");
|
|
3202
|
+
expect(csharp).to.include("global::Tsonic.Internal.Union<byte[], global::js.Uint8Array, string, global::Test.Buffer>");
|
|
3203
|
+
expect(csharp).to.include('__tsonic_union_member_2 => throw new global::System.InvalidCastException("Cannot materialize runtime union functionType to unionType")');
|
|
3204
|
+
expect(csharp).not.to.include("var value = (global::Tsonic.Internal.Union<byte[], global::js.Uint8Array, string, global::Test.Buffer>)chunkOrCallback;");
|
|
3205
|
+
});
|
|
3206
|
+
it("tightens sequential typeof-plus-undefined ternary locals before storage reuse", () => {
|
|
3207
|
+
const csharp = compileToCSharp(`
|
|
3208
|
+
type Locals = {
|
|
3209
|
+
readonly name: string;
|
|
3210
|
+
};
|
|
3211
|
+
|
|
3212
|
+
type RenderCallback = (error: object | undefined, html: string) => void;
|
|
3213
|
+
|
|
3214
|
+
export function render(
|
|
3215
|
+
localsOrCallback?: Locals | RenderCallback,
|
|
3216
|
+
maybeCallback?: RenderCallback,
|
|
3217
|
+
): void {
|
|
3218
|
+
const locals =
|
|
3219
|
+
typeof localsOrCallback === "function" ||
|
|
3220
|
+
localsOrCallback === undefined
|
|
3221
|
+
? { name: "fallback" }
|
|
3222
|
+
: localsOrCallback;
|
|
3223
|
+
const callback =
|
|
3224
|
+
typeof localsOrCallback === "function"
|
|
3225
|
+
? localsOrCallback
|
|
3226
|
+
: maybeCallback;
|
|
3227
|
+
callback?.(undefined, locals.name);
|
|
3228
|
+
}
|
|
3229
|
+
`, "/test/test.ts", { surface: "@tsonic/js" });
|
|
3230
|
+
expect(csharp).to.include("var locals =");
|
|
3231
|
+
expect(csharp).to.match(/var __struct = \(localsOrCallback\.As2\(\)\);/);
|
|
3232
|
+
expect(csharp).to.match(/return new global::Test\.__Anon_[A-Za-z0-9_]+ \{ name = __struct\.name \};/);
|
|
3233
|
+
expect(csharp).not.to.include("localsOrCallback == null ? default");
|
|
3234
|
+
expect(csharp).not.to.match(/\(\(global::System\.Object\)\(localsOrCallback\)\) == null \? default\(global::Test\.__Anon_[A-Za-z0-9_]+\)/);
|
|
3235
|
+
});
|
|
3236
|
+
it("reuses ternary discriminant narrowings without rematerializing matched members", () => {
|
|
3237
|
+
const csharp = compileToCSharp(`
|
|
3238
|
+
type Shape =
|
|
3239
|
+
| { kind: "square"; side: number }
|
|
3240
|
+
| { kind: "circle"; radius: number };
|
|
3241
|
+
|
|
3242
|
+
export function tern(s: Shape): number {
|
|
3243
|
+
return s.kind === "circle" ? s.radius : 0;
|
|
3244
|
+
}
|
|
3245
|
+
|
|
3246
|
+
export function tern2(s: Shape): number {
|
|
3247
|
+
return s.kind !== "circle" ? 0 : s.radius;
|
|
3248
|
+
}
|
|
3249
|
+
`, "/test/test.ts", { surface: "@tsonic/js" });
|
|
3250
|
+
expect(csharp).to.include("return s.Is1() ? (s.As1()).radius : 0;");
|
|
3251
|
+
expect(csharp).to.include("return !s.Is1() ? 0 : (s.As1()).radius;");
|
|
3252
|
+
expect(csharp).not.to.include("(s.As1()).Match<");
|
|
3253
|
+
});
|
|
3254
|
+
it("wraps narrowed typeof members before union-typed call arguments", () => {
|
|
3255
|
+
const csharp = compileToCSharp(`
|
|
3256
|
+
declare function decodeInputBytes(
|
|
3257
|
+
data: string | Uint8Array,
|
|
3258
|
+
encoding?: string,
|
|
3259
|
+
): Uint8Array;
|
|
3260
|
+
|
|
3261
|
+
class Hmac {
|
|
3262
|
+
constructor(algorithm: string, key: Uint8Array) {}
|
|
3263
|
+
}
|
|
3264
|
+
|
|
3265
|
+
export const createHmac = (
|
|
3266
|
+
algorithm: string,
|
|
3267
|
+
key: string | Uint8Array,
|
|
3268
|
+
): Hmac => {
|
|
3269
|
+
if (typeof key === "string") {
|
|
3270
|
+
return new Hmac(algorithm, decodeInputBytes(key, "utf8"));
|
|
3271
|
+
}
|
|
3272
|
+
|
|
3273
|
+
return new Hmac(algorithm, key);
|
|
3274
|
+
};
|
|
3275
|
+
`, "/test/test.ts", { surface: "@tsonic/js" });
|
|
3276
|
+
expect(csharp).to.include('return new Hmac(algorithm, decodeInputBytes(key, "utf8"));');
|
|
3277
|
+
expect(csharp).not.to.include('decodeInputBytes(global::Tsonic.Internal.Union<string, global::js.Uint8Array>.From1(key), "utf8")');
|
|
3278
|
+
});
|
|
3279
|
+
it("materializes explicit string assertions before wrapping union return arms", () => {
|
|
3280
|
+
const csharp = compileToCSharp(`
|
|
3281
|
+
declare function encodeOutputBytes(
|
|
3282
|
+
bytes: Uint8Array,
|
|
3283
|
+
encoding?: string,
|
|
3284
|
+
): string | Uint8Array;
|
|
3285
|
+
|
|
3286
|
+
export function run(
|
|
3287
|
+
publicKey: Uint8Array,
|
|
3288
|
+
encoding?: string,
|
|
3289
|
+
): string | Uint8Array {
|
|
3290
|
+
if (typeof encoding === "string") {
|
|
3291
|
+
return encodeOutputBytes(publicKey, encoding) as string;
|
|
3292
|
+
}
|
|
3293
|
+
|
|
3294
|
+
return publicKey;
|
|
3295
|
+
}
|
|
3296
|
+
`, "/test/test.ts", { surface: "@tsonic/js" });
|
|
3297
|
+
expect(csharp).to.include("encodeOutputBytes(publicKey, encoding).Match<string>");
|
|
3298
|
+
expect(csharp).to.include("throw new global::System.InvalidCastException(");
|
|
3299
|
+
expect(csharp).not.to.include("encodeOutputBytes(publicKey, encoding).Match<string>(__tsonic_union_member_1 => __tsonic_union_member_1, __tsonic_union_member_2 => __tsonic_union_member_2)");
|
|
3300
|
+
expect(csharp).not.to.include("global::Tsonic.Internal.Union<string, global::Uint8Array>.From1(encodeOutputBytes(publicKey, encoding))");
|
|
3301
|
+
});
|
|
3302
|
+
it("preserves generic iterable assertion surfaces after predicate narrowing", () => {
|
|
3303
|
+
const csharp = compileToCSharp(`
|
|
3304
|
+
declare function isIterableObject(
|
|
3305
|
+
value: JsValue,
|
|
3306
|
+
): value is Iterable<JsValue>;
|
|
3307
|
+
declare function consume<T>(value: T): void;
|
|
3308
|
+
|
|
3309
|
+
export function run<T>(item: JsValue): void {
|
|
3310
|
+
if (isIterableObject(item)) {
|
|
3311
|
+
for (const value of item as Iterable<T>) {
|
|
3312
|
+
consume(value);
|
|
3313
|
+
}
|
|
3314
|
+
}
|
|
3315
|
+
}
|
|
3316
|
+
`, "/test/test.ts", { surface: "@tsonic/js" });
|
|
3317
|
+
expect(csharp).to.include("foreach (var value in (global::System.Collections.Generic.IEnumerable<T>)item)");
|
|
3318
|
+
expect(csharp).not.to.include("foreach (var value in (global::System.Collections.Generic.IEnumerable<object?>)item)");
|
|
3319
|
+
});
|
|
3320
|
+
it("uses instanceof-specific runtime-union probes after primitive fallthrough branches", () => {
|
|
3321
|
+
const csharp = compileToCSharp(`
|
|
3322
|
+
class Bytes {}
|
|
3323
|
+
class KeyObject {}
|
|
3324
|
+
class PublicKeyObject extends KeyObject {}
|
|
3325
|
+
class PrivateKeyObject extends KeyObject {}
|
|
3326
|
+
|
|
3327
|
+
declare function importPublicKey(key: string | Bytes): KeyObject;
|
|
3328
|
+
declare function extractPublicKey(key: PrivateKeyObject): KeyObject;
|
|
3329
|
+
|
|
3330
|
+
export function createPublicKey(
|
|
3331
|
+
key: string | Bytes | KeyObject
|
|
3332
|
+
): KeyObject {
|
|
3333
|
+
if (typeof key === "string" || key instanceof Bytes) {
|
|
3334
|
+
return importPublicKey(key);
|
|
3335
|
+
}
|
|
3336
|
+
if (key instanceof PublicKeyObject) {
|
|
3337
|
+
return key;
|
|
3338
|
+
}
|
|
3339
|
+
if (key instanceof PrivateKeyObject) {
|
|
3340
|
+
return extractPublicKey(key);
|
|
3341
|
+
}
|
|
3342
|
+
if (key instanceof KeyObject) {
|
|
3343
|
+
return key;
|
|
3344
|
+
}
|
|
3345
|
+
return importPublicKey(key);
|
|
3346
|
+
}
|
|
3347
|
+
`);
|
|
3348
|
+
expect(csharp).to.include("if ((key.As3()) is PublicKeyObject key__is_1)");
|
|
3349
|
+
expect(csharp).to.include("if ((key.As3()) is PrivateKeyObject key__is_2)");
|
|
3350
|
+
expect(csharp).to.include("if (key.Is3())");
|
|
3351
|
+
expect(csharp).not.to.include("if (key is KeyObject");
|
|
3352
|
+
expect(csharp).not.to.include("(key.As2()) is PrivateKeyObject");
|
|
3353
|
+
expect(csharp).not.to.include("importPublicKey(global::Tsonic.Internal.Union<string, Bytes>.From2((key.As2())))");
|
|
3354
|
+
});
|
|
3355
|
+
it("preserves runtime carrier probes after predicate fallthrough to a base class member", () => {
|
|
3356
|
+
const csharp = compileToCSharp(`
|
|
3357
|
+
class Uint8Array {}
|
|
3358
|
+
class KeyObject { get type(): string { return "key"; } }
|
|
3359
|
+
class PublicKeyObject extends KeyObject {}
|
|
3360
|
+
class PrivateKeyObject extends KeyObject {}
|
|
3361
|
+
|
|
3362
|
+
declare function isStringOrBytesKey(
|
|
3363
|
+
key: KeyObject | string | Uint8Array
|
|
3364
|
+
): key is string | Uint8Array;
|
|
3365
|
+
declare function importPublicKey(
|
|
3366
|
+
key: string | Uint8Array
|
|
3367
|
+
): PublicKeyObject;
|
|
3368
|
+
declare function extractPublicKey(
|
|
3369
|
+
key: PrivateKeyObject
|
|
3370
|
+
): PublicKeyObject;
|
|
3371
|
+
|
|
3372
|
+
export function coercePublicKeyObject(
|
|
3373
|
+
key: KeyObject | string | Uint8Array
|
|
3374
|
+
): PublicKeyObject {
|
|
3375
|
+
if (isStringOrBytesKey(key)) {
|
|
3376
|
+
return importPublicKey(key);
|
|
3377
|
+
}
|
|
3378
|
+
if (key instanceof PublicKeyObject) {
|
|
3379
|
+
return key;
|
|
3380
|
+
}
|
|
3381
|
+
if (key instanceof PrivateKeyObject) {
|
|
3382
|
+
return extractPublicKey(key);
|
|
3383
|
+
}
|
|
3384
|
+
if (key instanceof KeyObject) {
|
|
3385
|
+
return new PublicKeyObject();
|
|
3386
|
+
}
|
|
3387
|
+
throw new Error("Unexpected key shape");
|
|
3388
|
+
}
|
|
3389
|
+
`);
|
|
3390
|
+
expect(csharp).to.include("if ((key.As2()) is PublicKeyObject key__is_1)");
|
|
3391
|
+
expect(csharp).to.include("if ((key.As2()) is PrivateKeyObject key__is_2)");
|
|
3392
|
+
expect(csharp).to.include("if (key.Is2())");
|
|
3393
|
+
expect(csharp).not.to.include("if (key is KeyObject");
|
|
3394
|
+
});
|
|
3395
|
+
it("fully qualifies module static helpers when class methods shadow the module container name", () => {
|
|
3396
|
+
const csharp = compileToCSharp(`
|
|
3397
|
+
export function signBytes(): string {
|
|
3398
|
+
return "ok";
|
|
3399
|
+
}
|
|
3400
|
+
|
|
3401
|
+
export class Sign {
|
|
3402
|
+
sign(): string {
|
|
3403
|
+
return signBytes();
|
|
3404
|
+
}
|
|
3405
|
+
}
|
|
3406
|
+
`, "/test/sign.ts");
|
|
3407
|
+
expect(csharp).to.include("return global::Test.sign.signBytes();");
|
|
3408
|
+
expect(csharp).not.to.include("return sign.signBytes();");
|
|
3409
|
+
});
|
|
3410
|
+
it("materializes narrower function arrays into union-element arrays at call sites", () => {
|
|
3411
|
+
const csharp = compileToCSharp(`
|
|
3412
|
+
type RouteHandler = (req: string) => JsValue;
|
|
3413
|
+
type ErrorHandler = (error: JsValue, req: string) => JsValue;
|
|
3414
|
+
type Handler = RouteHandler | ErrorHandler;
|
|
3415
|
+
|
|
3416
|
+
class RouteBox {
|
|
3417
|
+
constructor(readonly handlers: Handler[]) {}
|
|
3418
|
+
}
|
|
3419
|
+
|
|
3420
|
+
function flatten(handlers: RouteHandler[]): RouteHandler[] {
|
|
3421
|
+
return handlers;
|
|
3422
|
+
}
|
|
3423
|
+
|
|
3424
|
+
export function main(handler: RouteHandler): RouteBox {
|
|
3425
|
+
return new RouteBox(flatten([handler]));
|
|
3426
|
+
}
|
|
3427
|
+
`);
|
|
3428
|
+
expect(csharp).to.include("global::System.Linq.Enumerable.Select");
|
|
3429
|
+
expect(csharp).to.match(/\.From1\(__item\)/);
|
|
3430
|
+
});
|
|
3431
|
+
it("erases imported alias chains that end in callable interface aliases", () => {
|
|
3432
|
+
const csharp = compileProjectToCSharp({
|
|
3433
|
+
"src/types.ts": `
|
|
3434
|
+
export type NextFunction = () => void;
|
|
3435
|
+
export interface RequestHandler {
|
|
3436
|
+
(req: string, next: NextFunction): string;
|
|
3437
|
+
}
|
|
3438
|
+
export type RouteHandler = RequestHandler;
|
|
3439
|
+
`,
|
|
3440
|
+
"src/route.ts": `
|
|
3441
|
+
import type { RouteHandler } from "./types.js";
|
|
3442
|
+
|
|
3443
|
+
export class Route {
|
|
3444
|
+
get(...handlers: RouteHandler[]): this {
|
|
3445
|
+
return this;
|
|
3446
|
+
}
|
|
3447
|
+
}
|
|
3448
|
+
`,
|
|
3449
|
+
}, "src/route.ts", {}, { sourceRootRelativePath: "src", rootNamespace: "Test" });
|
|
3450
|
+
expect(csharp).to.include("params global::System.Func<string, global::System.Action, string>[] handlers");
|
|
3451
|
+
expect(csharp).not.to.include("RequestHandler[]");
|
|
3452
|
+
expect(csharp).not.to.include("RouteHandler[]");
|
|
3453
|
+
});
|
|
3454
|
+
it("treats fixed lambda parameters against rest callbacks as positional values", () => {
|
|
3455
|
+
const csharp = compileToCSharp(`
|
|
3456
|
+
type EventListener = (...args: JsValue[]) => void;
|
|
3457
|
+
|
|
3458
|
+
declare function consume(listener: EventListener): void;
|
|
3459
|
+
|
|
3460
|
+
export function main(): void {
|
|
3461
|
+
let first: JsValue = undefined;
|
|
3462
|
+
let second: JsValue = undefined;
|
|
3463
|
+
let third: JsValue = undefined;
|
|
3464
|
+
|
|
3465
|
+
consume((arg1, arg2, arg3) => {
|
|
3466
|
+
first = arg1;
|
|
3467
|
+
second = arg2;
|
|
3468
|
+
third = arg3;
|
|
3469
|
+
});
|
|
3470
|
+
}
|
|
3471
|
+
`);
|
|
3472
|
+
expect(csharp).to.include("object? arg1 = __unused_args[0];");
|
|
3473
|
+
expect(csharp).to.include("first = arg1;");
|
|
3474
|
+
expect(csharp).to.not.include("first = (object?[])arg1;");
|
|
3475
|
+
});
|
|
3476
|
+
it("preserves nullable array arguments when forwarding identical signatures", () => {
|
|
3477
|
+
const csharp = compileToCSharp(`
|
|
3478
|
+
class Child {}
|
|
3479
|
+
|
|
3480
|
+
function spawn(command: string, args?: string[] | null): Child {
|
|
3481
|
+
return new Child();
|
|
3482
|
+
}
|
|
3483
|
+
|
|
3484
|
+
export function fork(
|
|
3485
|
+
modulePath: string,
|
|
3486
|
+
args?: string[] | null
|
|
3487
|
+
): Child {
|
|
3488
|
+
return spawn(modulePath, args);
|
|
3489
|
+
}
|
|
3490
|
+
`);
|
|
3491
|
+
expect(csharp).to.include("return spawn(modulePath, args);");
|
|
3492
|
+
expect(csharp).to.not.include("(string[])(object)args");
|
|
3493
|
+
expect(csharp).to.not.include("Enumerable.Select<string, string>(args");
|
|
3494
|
+
});
|
|
3495
|
+
it("preserves readable array surfaces after setter writes before length reads", () => {
|
|
3496
|
+
const csharp = compileToCSharp(`
|
|
3497
|
+
declare class Assert {
|
|
3498
|
+
static Equal(expected: JsValue, actual: JsValue): void;
|
|
3499
|
+
}
|
|
3500
|
+
|
|
3501
|
+
class Proc {
|
|
3502
|
+
private _argv: string[] = [];
|
|
3503
|
+
|
|
3504
|
+
get argv(): string[] {
|
|
3505
|
+
return this._argv;
|
|
3506
|
+
}
|
|
3507
|
+
|
|
3508
|
+
set argv(value: string[] | undefined) {
|
|
3509
|
+
this._argv = value ?? [];
|
|
3510
|
+
}
|
|
3511
|
+
}
|
|
3512
|
+
|
|
3513
|
+
export function main(p: Proc): void {
|
|
3514
|
+
p.argv = undefined;
|
|
3515
|
+
Assert.Equal(0, p.argv.length);
|
|
3516
|
+
}
|
|
3517
|
+
`, "/test/test.ts", { surface: "@tsonic/js" });
|
|
3518
|
+
expect(csharp).to.include("p.argv = default(string[]);");
|
|
3519
|
+
expect(csharp).to.include("Assert.Equal((object)(double)0, (object)(double)p.argv.Length);");
|
|
3520
|
+
expect(csharp).to.not.include("new global::js.Array<object>((object)p.argv).length");
|
|
3521
|
+
});
|
|
3522
|
+
it("erases compiler-generated structural assertion casts for nominal receivers", () => {
|
|
3523
|
+
const csharp = compileToCSharp(`
|
|
3524
|
+
class Server {
|
|
3525
|
+
listen(path: string, callback: () => void): void {
|
|
3526
|
+
callback();
|
|
3527
|
+
}
|
|
3528
|
+
}
|
|
3529
|
+
|
|
3530
|
+
class Request {
|
|
3531
|
+
on(name: string, listener: (chunk?: string) => void): void {
|
|
3532
|
+
listener(name);
|
|
3533
|
+
}
|
|
3534
|
+
}
|
|
3535
|
+
|
|
3536
|
+
export function main(server: Server, request: Request): void {
|
|
3537
|
+
(
|
|
3538
|
+
server as object as {
|
|
3539
|
+
listen(path: string, callback: () => void): void;
|
|
3540
|
+
}
|
|
3541
|
+
).listen("/tmp/socket", () => undefined);
|
|
3542
|
+
|
|
3543
|
+
(
|
|
3544
|
+
request as object as {
|
|
3545
|
+
on(name: string, listener: (chunk?: string) => void): void;
|
|
3546
|
+
}
|
|
3547
|
+
).on("data", (_chunk) => undefined);
|
|
3548
|
+
}
|
|
3549
|
+
`);
|
|
3550
|
+
expect(csharp).to.not.match(/\(\(global::js\.__Anon_/);
|
|
3551
|
+
expect(csharp).to.include('server.listen("/tmp/socket"');
|
|
3552
|
+
expect(csharp).to.include('request.on("data"');
|
|
3553
|
+
});
|
|
3554
|
+
it("prefers inferred conditional array surfaces over broad JsValue sinks", () => {
|
|
3555
|
+
const csharp = compileToCSharp(`
|
|
3556
|
+
import type { JsValue } from "@tsonic/core/types.js";
|
|
3557
|
+
|
|
3558
|
+
declare function readIds(json: string): string[];
|
|
3559
|
+
|
|
3560
|
+
export function run(json: string, useJson: boolean): Record<string, JsValue> {
|
|
3561
|
+
const obj: Record<string, JsValue> = {};
|
|
3562
|
+
obj["channel_ids"] = useJson ? readIds(json) : [];
|
|
3563
|
+
return obj;
|
|
3564
|
+
}
|
|
3565
|
+
`, "/test/test.ts", { surface: "@tsonic/js" });
|
|
3566
|
+
expect(csharp).to.include('obj["channel_ids"] = useJson ? readIds(json) : global::System.Array.Empty<string>();');
|
|
3567
|
+
});
|
|
3568
|
+
it("keeps nullable conditional array call surfaces direct over broad JsValue sinks", () => {
|
|
3569
|
+
const csharp = compileToCSharp(`
|
|
3570
|
+
import type { JsValue } from "@tsonic/core/types.js";
|
|
3571
|
+
|
|
3572
|
+
declare function maybeIds(json: string): string[] | undefined;
|
|
3573
|
+
|
|
3574
|
+
export function run(json: string, useJson: boolean): Record<string, JsValue> {
|
|
3575
|
+
const obj: Record<string, JsValue> = {};
|
|
3576
|
+
obj["channel_ids"] = useJson ? maybeIds(json) : [];
|
|
3577
|
+
return obj;
|
|
3578
|
+
}
|
|
3579
|
+
`, "/test/test.ts", { surface: "@tsonic/js" });
|
|
3580
|
+
expect(csharp).to.include('obj["channel_ids"] = useJson ? maybeIds(json) : global::System.Array.Empty<string>();');
|
|
3581
|
+
expect(csharp).to.not.include(".Match<object?");
|
|
3582
|
+
});
|
|
3583
|
+
it("keeps conditional reference-array surfaces direct when one branch is nullish", () => {
|
|
3584
|
+
const csharp = compileToCSharp(`
|
|
3585
|
+
import type { JsValue } from "@tsonic/core/types.js";
|
|
3586
|
+
import { JsonSerializer } from "@tsonic/dotnet/System.Text.Json.js";
|
|
3587
|
+
|
|
3588
|
+
export function run(json: string, useJson: boolean): Record<string, JsValue> {
|
|
3589
|
+
const obj: Record<string, JsValue> = {};
|
|
3590
|
+
obj["channel_ids"] =
|
|
3591
|
+
useJson ? JsonSerializer.Deserialize<string[]>(json) : [];
|
|
3592
|
+
return obj;
|
|
3593
|
+
}
|
|
3594
|
+
`, "/test/test.ts", { surface: "@tsonic/js" });
|
|
3595
|
+
expect(csharp).to.include('obj["channel_ids"] = useJson ? global::System.Text.Json.JsonSerializer.Deserialize<string[]>(json) : global::System.Array.Empty<string>();');
|
|
3596
|
+
expect(csharp).not.to.include(".Match<object?>(__tsonic_union_member_1 => __tsonic_union_member_1, __tsonic_union_member_2 => __tsonic_union_member_2)");
|
|
3597
|
+
});
|
|
3598
|
+
it("preserves source-backed awaited result aliases for inferred locals", () => {
|
|
3599
|
+
const csharp = compileToCSharp(`
|
|
3600
|
+
type Result<T, E> =
|
|
3601
|
+
| { success: true; payload: T }
|
|
3602
|
+
| { success: false; error: E };
|
|
3603
|
+
|
|
3604
|
+
declare function ok<T, E>(value: T): Result<T, E>;
|
|
3605
|
+
declare function err<T, E>(error: E): Result<T, E>;
|
|
3606
|
+
declare function deleteExport(): Promise<Result<boolean, string>>;
|
|
3607
|
+
|
|
3608
|
+
export async function run(): Promise<Result<boolean, string>> {
|
|
3609
|
+
const result = await deleteExport();
|
|
3610
|
+
if (!result.success) {
|
|
3611
|
+
return err<boolean, string>(result.error);
|
|
3612
|
+
}
|
|
3613
|
+
return ok<boolean, string>(true);
|
|
3614
|
+
}
|
|
3615
|
+
`);
|
|
3616
|
+
expect(csharp).to.include("var result = await deleteExport();");
|
|
3617
|
+
expect(csharp).to.include("if (!result.Match<bool>(__tsonic_union_member_1 => __tsonic_union_member_1.success, __tsonic_union_member_2 => __tsonic_union_member_2.success))");
|
|
3618
|
+
expect(csharp).to.not.include("(await deleteExport()).Match<global::Test.Result<bool, string>>");
|
|
3619
|
+
expect(csharp).to.not.include("(global::Test.Ok__Alias<bool>)");
|
|
3620
|
+
expect(csharp).to.not.include("(global::Test.Err__Alias<string>)");
|
|
3621
|
+
expect(csharp).to.not.include("__Anon_");
|
|
3622
|
+
});
|
|
3623
|
+
it("returns awaited result aliases directly from inferred locals", () => {
|
|
3624
|
+
const csharp = compileToCSharp(`
|
|
3625
|
+
type Result<T, E> =
|
|
3626
|
+
| { success: true; payload: T }
|
|
3627
|
+
| { success: false; error: E };
|
|
3628
|
+
|
|
3629
|
+
declare function isUserInGroup(): Promise<Result<boolean, string>>;
|
|
3630
|
+
|
|
3631
|
+
export async function run(): Promise<Result<boolean, string>> {
|
|
3632
|
+
const membershipResult = await isUserInGroup();
|
|
3633
|
+
return membershipResult;
|
|
3634
|
+
}
|
|
3635
|
+
`);
|
|
3636
|
+
expect(csharp).to.include("return membershipResult;");
|
|
3637
|
+
expect(csharp).to.not.include("return membershipResult.Match<global::Tsonic.Internal.");
|
|
3638
|
+
expect(csharp).to.not.include("Cannot materialize runtime union referenceType to unionType");
|
|
3639
|
+
});
|
|
3640
|
+
it("returns awaited imported result aliases directly from inferred locals", () => {
|
|
3641
|
+
const csharp = compileProjectToCSharp({
|
|
3642
|
+
"src/result.ts": `
|
|
3643
|
+
export type Result<T, E> =
|
|
3644
|
+
| { success: true; payload: T }
|
|
3645
|
+
| { success: false; error: E };
|
|
3646
|
+
|
|
3647
|
+
export async function isUserInGroup(): Promise<Result<boolean, string>> {
|
|
3648
|
+
return { success: true, payload: true };
|
|
3649
|
+
}
|
|
3650
|
+
`,
|
|
3651
|
+
"src/test.ts": `
|
|
3652
|
+
import type { Result } from "./result.ts";
|
|
3653
|
+
import { isUserInGroup } from "./result.ts";
|
|
3654
|
+
|
|
3655
|
+
export async function run(): Promise<Result<boolean, string>> {
|
|
3656
|
+
const membershipResult = await isUserInGroup();
|
|
3657
|
+
return membershipResult;
|
|
3658
|
+
}
|
|
3659
|
+
`,
|
|
3660
|
+
}, "src/test.ts");
|
|
3661
|
+
expect(csharp).to.include("return membershipResult;");
|
|
3662
|
+
expect(csharp).to.not.include("return membershipResult.Match<global::Tsonic.Internal.");
|
|
3663
|
+
expect(csharp).to.not.include("Cannot materialize runtime union referenceType to unionType");
|
|
3664
|
+
});
|
|
3665
|
+
it("wraps narrowed source-owned union members when returning to the carrier alias", () => {
|
|
3666
|
+
const csharp = compileToCSharp(`
|
|
3667
|
+
type Ok<T> = { success: true; data: T };
|
|
3668
|
+
type Err<E> = { success: false; error: E };
|
|
3669
|
+
type Result<T, E> = Err<E> | Ok<T>;
|
|
3670
|
+
|
|
3671
|
+
declare function checkPermission(): Promise<Result<boolean, string>>;
|
|
3672
|
+
|
|
3673
|
+
export async function run(): Promise<Result<boolean, string>> {
|
|
3674
|
+
const result = await checkPermission();
|
|
3675
|
+
|
|
3676
|
+
if (!result.success) {
|
|
3677
|
+
return result;
|
|
3678
|
+
}
|
|
3679
|
+
|
|
3680
|
+
return { success: true, data: true };
|
|
3681
|
+
}
|
|
3682
|
+
`);
|
|
3683
|
+
expect(csharp).to.match(/return global::Test\.Result<bool, string>\.From1\(result__1_\d+\);/);
|
|
3684
|
+
expect(csharp).to.not.match(/return result__1_\d+;/);
|
|
3685
|
+
});
|
|
3686
|
+
it("does not lower truthiness property guards to union tags without literal proof", () => {
|
|
3687
|
+
const csharp = compileToCSharp(`
|
|
3688
|
+
type Ok = {
|
|
3689
|
+
success: boolean;
|
|
3690
|
+
value: string;
|
|
3691
|
+
};
|
|
3692
|
+
type Err = {
|
|
3693
|
+
success: false;
|
|
3694
|
+
error: string;
|
|
3695
|
+
};
|
|
3696
|
+
|
|
3697
|
+
export function run(result: Ok | Err): string {
|
|
3698
|
+
if (!result.success) {
|
|
3699
|
+
return "not-success";
|
|
3700
|
+
}
|
|
3701
|
+
return "success";
|
|
3702
|
+
}
|
|
3703
|
+
`);
|
|
3704
|
+
expect(csharp).not.to.include("if (!result.Is1())");
|
|
3705
|
+
expect(csharp).not.to.include("if (result.Is2())");
|
|
3706
|
+
expect(csharp).to.include("result.Match");
|
|
3707
|
+
});
|
|
3708
|
+
it("returns awaited imported source-package result aliases directly from inferred locals", () => {
|
|
3709
|
+
const csharp = compileProjectToCSharp({
|
|
3710
|
+
"src/repo.ts": `
|
|
3711
|
+
import type { Result } from "@fixture/core/Jotster.Core.js";
|
|
3712
|
+
import { ok } from "@fixture/core/Jotster.Core.js";
|
|
3713
|
+
|
|
3714
|
+
export async function isUserInGroup(): Promise<Result<boolean, string>> {
|
|
3715
|
+
return ok(true);
|
|
3716
|
+
}
|
|
3717
|
+
`,
|
|
3718
|
+
"src/test.ts": `
|
|
3719
|
+
import type { Result } from "@fixture/core/Jotster.Core.js";
|
|
3720
|
+
import { isUserInGroup } from "./repo.ts";
|
|
3721
|
+
|
|
3722
|
+
export async function run(): Promise<Result<boolean, string>> {
|
|
3723
|
+
const membershipResult = await isUserInGroup();
|
|
3724
|
+
return membershipResult;
|
|
3725
|
+
}
|
|
3726
|
+
`,
|
|
3727
|
+
"node_modules/@fixture/core/package.json": JSON.stringify({
|
|
3728
|
+
name: "@fixture/core",
|
|
3729
|
+
version: "1.0.0",
|
|
3730
|
+
type: "module",
|
|
3731
|
+
exports: {
|
|
3732
|
+
".": "./src/index.ts",
|
|
3733
|
+
"./index.js": "./src/index.ts",
|
|
3734
|
+
"./Jotster.Core.js": "./src/index.ts",
|
|
3735
|
+
},
|
|
3736
|
+
}, null, 2),
|
|
3737
|
+
"node_modules/@fixture/core/tsonic.package.json": JSON.stringify({
|
|
3738
|
+
schemaVersion: 1,
|
|
3739
|
+
kind: "tsonic-source-package",
|
|
3740
|
+
surfaces: ["@tsonic/js"],
|
|
3741
|
+
source: {
|
|
3742
|
+
namespace: "Fixture.Core",
|
|
3743
|
+
exports: {
|
|
3744
|
+
".": "./src/index.ts",
|
|
3745
|
+
"./index.js": "./src/index.ts",
|
|
3746
|
+
"./Jotster.Core.js": "./src/index.ts",
|
|
3747
|
+
},
|
|
3748
|
+
},
|
|
3749
|
+
}, null, 2),
|
|
3750
|
+
"node_modules/@fixture/core/src/index.ts": `
|
|
3751
|
+
export { ok, err } from "./types/result.ts";
|
|
3752
|
+
export type { Result, Ok, Err } from "./types/result.ts";
|
|
3753
|
+
`,
|
|
3754
|
+
"node_modules/@fixture/core/src/types/result.ts": `
|
|
3755
|
+
export type Ok<T> = { success: true; payload: T };
|
|
3756
|
+
export type Err<E> = { success: false; error: E };
|
|
3757
|
+
export type Result<T, E> = Err<E> | Ok<T>;
|
|
3758
|
+
export const ok = <T>(value: T): Ok<T> => ({ success: true, payload: value });
|
|
3759
|
+
export const err = <E>(error: E): Err<E> => ({ success: false, error });
|
|
3760
|
+
`,
|
|
3761
|
+
}, "src/test.ts", { surface: "@tsonic/js" });
|
|
3762
|
+
expect(csharp).to.include("return membershipResult;");
|
|
3763
|
+
expect(csharp).to.not.include("return membershipResult.Match<global::Tsonic.Internal.");
|
|
3764
|
+
expect(csharp).to.not.include("Cannot materialize runtime union referenceType to unionType");
|
|
3765
|
+
});
|
|
3766
|
+
it("auto-awaits async source-package result returns before union adaptation", () => {
|
|
3767
|
+
const packageExports = {
|
|
3768
|
+
".": "./src/index.ts",
|
|
3769
|
+
"./index.js": "./src/index.ts",
|
|
3770
|
+
"./Jotster.Core.js": "./src/index.ts",
|
|
3771
|
+
};
|
|
3772
|
+
const csharp = compileProjectToCSharp({
|
|
3773
|
+
"src/domain.ts": `
|
|
3774
|
+
import type { Result } from "@fixture/core/Jotster.Core.js";
|
|
3775
|
+
import { ok } from "@fixture/core/Jotster.Core.js";
|
|
3776
|
+
|
|
3777
|
+
export async function setVisibility(): Promise<Result<void, string>> {
|
|
3778
|
+
return ok(undefined);
|
|
3779
|
+
}
|
|
3780
|
+
`,
|
|
3781
|
+
"src/test.ts": `
|
|
3782
|
+
import type { Result } from "@fixture/core/Jotster.Core.js";
|
|
3783
|
+
import { setVisibility } from "./domain.ts";
|
|
3784
|
+
|
|
3785
|
+
export async function run(): Promise<Result<void, string>> {
|
|
3786
|
+
return setVisibility();
|
|
3787
|
+
}
|
|
3788
|
+
`,
|
|
3789
|
+
"node_modules/@fixture/core/package.json": JSON.stringify({
|
|
3790
|
+
name: "@fixture/core",
|
|
3791
|
+
version: "1.0.0",
|
|
3792
|
+
type: "module",
|
|
3793
|
+
exports: packageExports,
|
|
3794
|
+
}, null, 2),
|
|
3795
|
+
"node_modules/@fixture/core/tsonic.package.json": JSON.stringify({
|
|
3796
|
+
schemaVersion: 1,
|
|
3797
|
+
kind: "tsonic-source-package",
|
|
3798
|
+
surfaces: ["@tsonic/js"],
|
|
3799
|
+
source: {
|
|
3800
|
+
namespace: "Fixture.Core",
|
|
3801
|
+
exports: packageExports,
|
|
3802
|
+
},
|
|
3803
|
+
}, null, 2),
|
|
3804
|
+
"node_modules/@fixture/core/src/index.ts": `
|
|
3805
|
+
export { ok, err } from "./types/result.ts";
|
|
3806
|
+
export type { Result, Ok, Err } from "./types/result.ts";
|
|
3807
|
+
`,
|
|
3808
|
+
"node_modules/@fixture/core/src/types/result.ts": `
|
|
3809
|
+
export type Ok<T> = { success: true; payload: T };
|
|
3810
|
+
export type Err<E> = { success: false; error: E };
|
|
3811
|
+
export type Result<T, E> = Err<E> | Ok<T>;
|
|
3812
|
+
export const ok = <T>(value: T): Ok<T> => ({ success: true, payload: value });
|
|
3813
|
+
export const err = <E>(error: E): Err<E> => ({ success: false, error });
|
|
3814
|
+
`,
|
|
3815
|
+
}, "src/test.ts", { surface: "@tsonic/js" });
|
|
3816
|
+
expect(csharp).to.match(/return await .*setVisibility\(\);/);
|
|
3817
|
+
expect(csharp).not.to.match(/From[12]\([^;]*setVisibility\(\)/);
|
|
3818
|
+
});
|
|
3819
|
+
it("wraps source-package generic result helpers through the matching nominal arm", () => {
|
|
3820
|
+
const packageExports = {
|
|
3821
|
+
".": "./src/index.ts",
|
|
3822
|
+
"./index.js": "./src/index.ts",
|
|
3823
|
+
"./Jotster.Core.js": "./src/index.ts",
|
|
3824
|
+
};
|
|
3825
|
+
const csharp = compileProjectToCSharp({
|
|
3826
|
+
"src/test.ts": `
|
|
3827
|
+
import type { Result } from "@fixture/core/Jotster.Core.js";
|
|
3828
|
+
import { err, ok } from "@fixture/core/Jotster.Core.js";
|
|
3829
|
+
|
|
3830
|
+
type Payload = { email?: string };
|
|
3831
|
+
type VerificationError = "segments" | "header";
|
|
3832
|
+
|
|
3833
|
+
export const verify = (token: string): Result<Payload, VerificationError> => {
|
|
3834
|
+
if (token.length === 0) {
|
|
3835
|
+
return err("segments");
|
|
3836
|
+
}
|
|
3837
|
+
return ok({ email: token });
|
|
3838
|
+
};
|
|
3839
|
+
`,
|
|
3840
|
+
"node_modules/@fixture/core/package.json": JSON.stringify({
|
|
3841
|
+
name: "@fixture/core",
|
|
3842
|
+
version: "1.0.0",
|
|
3843
|
+
type: "module",
|
|
3844
|
+
exports: packageExports,
|
|
3845
|
+
}, null, 2),
|
|
3846
|
+
"node_modules/@fixture/core/tsonic.package.json": JSON.stringify({
|
|
3847
|
+
schemaVersion: 1,
|
|
3848
|
+
kind: "tsonic-source-package",
|
|
3849
|
+
surfaces: ["@tsonic/js"],
|
|
3850
|
+
source: {
|
|
3851
|
+
namespace: "Fixture.Core",
|
|
3852
|
+
exports: packageExports,
|
|
3853
|
+
},
|
|
3854
|
+
}, null, 2),
|
|
3855
|
+
"node_modules/@fixture/core/src/index.ts": `
|
|
3856
|
+
export { ok, err } from "./types/result.ts";
|
|
3857
|
+
export type { Result, Ok, Err } from "./types/result.ts";
|
|
3858
|
+
`,
|
|
3859
|
+
"node_modules/@fixture/core/src/types/result.ts": `
|
|
3860
|
+
export type Ok<T> = { success: true; data: T };
|
|
3861
|
+
export type Err<E> = { success: false; error: E };
|
|
3862
|
+
export type Result<T, E> = Err<E> | Ok<T>;
|
|
3863
|
+
export const ok = <T>(data: T): Ok<T> => ({ success: true, data });
|
|
3864
|
+
export const err = <E>(error: E): Err<E> => ({ success: false, error });
|
|
3865
|
+
`,
|
|
3866
|
+
}, "src/test.ts", { surface: "@tsonic/js" });
|
|
3867
|
+
expect(csharp).to.include('return global::Fixture.Core.types.Result<global::Test.Payload__Alias, string>.From1(global::Fixture.Core.types.result.err("segments"));');
|
|
3868
|
+
expect(csharp).to.include("return global::Fixture.Core.types.Result<global::Test.Payload__Alias, string>.From2(global::Fixture.Core.types.result.ok(new Payload__Alias { email = token }));");
|
|
3869
|
+
expect(csharp).not.to.include("From2((global::Fixture.Core.types.Ok__Alias<Payload__Alias>)global::Fixture.Core.types.result.err");
|
|
3870
|
+
});
|
|
3871
|
+
it("keeps awaited source-backed non-Promise result aliases aligned with runtime slots", () => {
|
|
3872
|
+
const packageExports = {
|
|
3873
|
+
".": "./src/index.ts",
|
|
3874
|
+
"./index.js": "./src/index.ts",
|
|
3875
|
+
"./Jotster.Core.js": "./src/index.ts",
|
|
3876
|
+
};
|
|
3877
|
+
const csharp = compileProjectToCSharp({
|
|
3878
|
+
"src/render.ts": `
|
|
3879
|
+
import type { Result } from "@fixture/core/Jotster.Core.js";
|
|
3880
|
+
import { ok } from "@fixture/core/Jotster.Core.js";
|
|
3881
|
+
|
|
3882
|
+
export function render(): Result<{ rendered: string }, string> {
|
|
3883
|
+
return ok({ rendered: "ok" });
|
|
3884
|
+
}
|
|
3885
|
+
`,
|
|
3886
|
+
"src/test.ts": `
|
|
3887
|
+
import { render } from "./render.ts";
|
|
3888
|
+
|
|
3889
|
+
export async function run(): Promise<string> {
|
|
3890
|
+
const result = await render();
|
|
3891
|
+
if (!result.success) {
|
|
3892
|
+
return result.error;
|
|
3893
|
+
}
|
|
3894
|
+
return result.data.rendered;
|
|
3895
|
+
}
|
|
3896
|
+
`,
|
|
3897
|
+
"node_modules/@fixture/core/package.json": JSON.stringify({
|
|
3898
|
+
name: "@fixture/core",
|
|
3899
|
+
version: "1.0.0",
|
|
3900
|
+
type: "module",
|
|
3901
|
+
exports: packageExports,
|
|
3902
|
+
}, null, 2),
|
|
3903
|
+
"node_modules/@fixture/core/tsonic.package.json": JSON.stringify({
|
|
3904
|
+
schemaVersion: 1,
|
|
3905
|
+
kind: "tsonic-source-package",
|
|
3906
|
+
surfaces: ["@tsonic/js"],
|
|
3907
|
+
source: {
|
|
3908
|
+
namespace: "Fixture.Core",
|
|
3909
|
+
exports: packageExports,
|
|
3910
|
+
},
|
|
3911
|
+
}, null, 2),
|
|
3912
|
+
"node_modules/@fixture/core/src/index.ts": `
|
|
3913
|
+
export { ok, err } from "./types/result.ts";
|
|
3914
|
+
export type { Result, Ok, Err } from "./types/result.ts";
|
|
3915
|
+
`,
|
|
3916
|
+
"node_modules/@fixture/core/src/types/result.ts": `
|
|
3917
|
+
export type Ok<T> = { success: true; data: T };
|
|
3918
|
+
export type Err<E> = { success: false; error: E };
|
|
3919
|
+
export type Result<T, E> = Ok<T> | Err<E>;
|
|
3920
|
+
export const ok = <T>(data: T): Ok<T> => ({ success: true, data });
|
|
3921
|
+
export const err = <E>(error: E): Err<E> => ({ success: false, error });
|
|
3922
|
+
`,
|
|
3923
|
+
}, "src/test.ts", { surface: "@tsonic/js" });
|
|
3924
|
+
expect(csharp).to.include("public static Result<T, E> From1(Err__Alias<E> value)");
|
|
3925
|
+
expect(csharp).to.include("var result = await global::System.Threading.Tasks.Task.FromResult(render());");
|
|
3926
|
+
expect(csharp).to.include("if (!result.Match<bool>(__tsonic_union_member_1 => __tsonic_union_member_1.success, __tsonic_union_member_2 => __tsonic_union_member_2.success))");
|
|
3927
|
+
expect(csharp).to.match(/return result__1_\d+\.error;/);
|
|
3928
|
+
expect(csharp).not.to.include("if (result.Is2())");
|
|
3929
|
+
expect(csharp).not.to.include("return (result.As1()).data.rendered;");
|
|
3930
|
+
});
|
|
3931
|
+
it("keeps source-package same-name structural return types in their inferred namespace", () => {
|
|
3932
|
+
const packageExports = {
|
|
3933
|
+
".": "./src/index.ts",
|
|
3934
|
+
"./Jotster.Channels.js": "./src/index.ts",
|
|
3935
|
+
};
|
|
3936
|
+
const csharp = compileProjectToCSharp({
|
|
3937
|
+
"src/handler.ts": `
|
|
3938
|
+
import { getDomainItems } from "@fixture/channels/Jotster.Channels.js";
|
|
3939
|
+
|
|
3940
|
+
export async function run(): Promise<number> {
|
|
3941
|
+
const items = await getDomainItems();
|
|
3942
|
+
return items.length;
|
|
3943
|
+
}
|
|
3944
|
+
`,
|
|
3945
|
+
"node_modules/@fixture/channels/package.json": JSON.stringify({
|
|
3946
|
+
name: "@fixture/channels",
|
|
3947
|
+
version: "1.0.0",
|
|
3948
|
+
type: "module",
|
|
3949
|
+
exports: packageExports,
|
|
3950
|
+
}, null, 2),
|
|
3951
|
+
"node_modules/@fixture/channels/tsonic.package.json": JSON.stringify({
|
|
3952
|
+
schemaVersion: 1,
|
|
3953
|
+
kind: "tsonic-source-package",
|
|
3954
|
+
surfaces: ["@tsonic/js"],
|
|
3955
|
+
source: {
|
|
3956
|
+
namespace: "Fixture.Channels",
|
|
3957
|
+
exports: packageExports,
|
|
3958
|
+
},
|
|
3959
|
+
}, null, 2),
|
|
3960
|
+
"node_modules/@fixture/channels/src/index.ts": `
|
|
3961
|
+
export { getDomainItems } from "./domain/get.ts";
|
|
3962
|
+
`,
|
|
3963
|
+
"node_modules/@fixture/channels/src/repo/get.ts": `
|
|
3964
|
+
import { List } from "@tsonic/dotnet/System.Collections.Generic.js";
|
|
3965
|
+
|
|
3966
|
+
interface Item {
|
|
3967
|
+
id: number;
|
|
3968
|
+
}
|
|
3969
|
+
|
|
3970
|
+
export async function getItems(): Promise<Item[]> {
|
|
3971
|
+
const result = new List<Item>();
|
|
3972
|
+
result.Add({ id: 1 });
|
|
3973
|
+
return result.ToArray();
|
|
3974
|
+
}
|
|
3975
|
+
`,
|
|
3976
|
+
"node_modules/@fixture/channels/src/domain/get.ts": `
|
|
3977
|
+
import { getItems } from "../repo/get.ts";
|
|
3978
|
+
|
|
3979
|
+
interface Item {
|
|
3980
|
+
id: number;
|
|
3981
|
+
}
|
|
3982
|
+
|
|
3983
|
+
export async function getDomainItems(): Promise<Item[]> {
|
|
3984
|
+
const items = await getItems();
|
|
3985
|
+
return items;
|
|
3986
|
+
}
|
|
3987
|
+
`,
|
|
3988
|
+
}, "src/handler.ts", { surface: "@tsonic/js" });
|
|
3989
|
+
expect(csharp).to.include("var items = await global::Fixture.Channels.domain.get.getDomainItems();");
|
|
3990
|
+
expect(csharp).to.include("global::System.Threading.Tasks.Task<global::Fixture.Channels.domain.Item[]>");
|
|
3991
|
+
expect(csharp).not.to.include("Fixture.Channels.repo.Item");
|
|
3992
|
+
expect(csharp).not.to.include("Select<global::Fixture.Channels.domain.Item, global::Fixture.Channels.repo.Item>");
|
|
3993
|
+
});
|
|
3994
|
+
it("materializes optional numeric operands before arithmetic calls", () => {
|
|
3995
|
+
const csharp = compileToCSharp(`
|
|
3996
|
+
import type { int } from "@tsonic/core/types.js";
|
|
3997
|
+
|
|
3998
|
+
declare function getLength(value: string): int;
|
|
3999
|
+
declare function clamp(value: int, min: int, max: int): int;
|
|
4000
|
+
|
|
4001
|
+
export function sliceLike(
|
|
4002
|
+
value: string,
|
|
4003
|
+
start: int = 0 as int,
|
|
4004
|
+
end?: int
|
|
4005
|
+
): string {
|
|
4006
|
+
const lengthValue = getLength(value);
|
|
4007
|
+
const actualEnd: int =
|
|
4008
|
+
end === undefined
|
|
4009
|
+
? lengthValue
|
|
4010
|
+
: end < 0
|
|
4011
|
+
? clamp(lengthValue + end, 0 as int, lengthValue)
|
|
4012
|
+
: clamp(end, 0 as int, lengthValue);
|
|
4013
|
+
return String(actualEnd + start);
|
|
4014
|
+
}
|
|
4015
|
+
`, "/test/test.ts", { surface: "@tsonic/js" });
|
|
4016
|
+
expect(csharp).to.include("clamp(lengthValue + (int)end.Value, 0, lengthValue)");
|
|
4017
|
+
expect(csharp).to.include("clamp((int)end.Value, 0, lengthValue)");
|
|
4018
|
+
expect(csharp).not.to.include("clamp(lengthValue + end, 0, lengthValue)");
|
|
4019
|
+
});
|
|
4020
|
+
it("wraps nested runtime-union carriers without projecting members", () => {
|
|
4021
|
+
const csharp = compileToCSharp(`
|
|
4022
|
+
import { Uint8Array } from "@tsonic/js/Uint8Array.js";
|
|
4023
|
+
import { readFileSync } from "@tsonic/nodejs/fs.js";
|
|
4024
|
+
|
|
4025
|
+
export function run(filePath: string): Uint8Array {
|
|
4026
|
+
return new Uint8Array(readFileSync(filePath));
|
|
4027
|
+
}
|
|
4028
|
+
`, "/test/test.ts", { surface: "@tsonic/js" });
|
|
4029
|
+
expect(csharp).to.include("return new global::js.Uint8Array(global::js.TypedArrayConstructorInput<byte>.From2(global::js.TypedArrayInput<byte>.From2(");
|
|
4030
|
+
expect(csharp).to.include("global::System.Linq.Enumerable.Select<byte, double>(global::nodejs.FsModule.readFileSync(filePath).__tsonic_symbol_iterator(), __item => (double)__item)");
|
|
4031
|
+
expect(csharp).not.to.include(".Match<global::js.TypedArrayConstructorInput<byte>>");
|
|
4032
|
+
expect(csharp).not.to.include("(global::js.TypedArrayInput<byte>)__tsonic_union_member_2");
|
|
4033
|
+
});
|
|
4034
|
+
it("does not nullable-unwrap already projected optional runtime-union members", () => {
|
|
4035
|
+
const csharp = compileToCSharp(`
|
|
4036
|
+
import type { int } from "@tsonic/core/types.js";
|
|
4037
|
+
|
|
4038
|
+
declare function getBufferLength(buffer: object): int;
|
|
4039
|
+
|
|
4040
|
+
export const resolveWriteLength = (
|
|
4041
|
+
buffer: object,
|
|
4042
|
+
offset: int,
|
|
4043
|
+
lengthOrEncoding?: int | string
|
|
4044
|
+
): int =>
|
|
4045
|
+
lengthOrEncoding === undefined ||
|
|
4046
|
+
typeof lengthOrEncoding === "string"
|
|
4047
|
+
? ((getBufferLength(buffer) - offset) as int)
|
|
4048
|
+
: lengthOrEncoding;
|
|
4049
|
+
`, "/test/test.ts", { surface: "@tsonic/js" });
|
|
4050
|
+
expect(csharp).to.include("(lengthOrEncoding.As1())");
|
|
4051
|
+
expect(csharp).not.to.include("(lengthOrEncoding.As1())).Value");
|
|
4052
|
+
expect(csharp).not.to.include("(lengthOrEncoding.As1()).Value");
|
|
4053
|
+
});
|
|
4054
|
+
it("probes optional runtime-union members before instanceof projection", () => {
|
|
4055
|
+
const csharp = compileToCSharp(`
|
|
4056
|
+
import { Uint8Array } from "@tsonic/js/Uint8Array.js";
|
|
4057
|
+
import type { int } from "@tsonic/core/types.js";
|
|
4058
|
+
|
|
4059
|
+
export function choose(value?: number | Uint8Array | string): int {
|
|
4060
|
+
if (value instanceof Uint8Array) {
|
|
4061
|
+
return value.length as int;
|
|
4062
|
+
}
|
|
4063
|
+
return -1;
|
|
4064
|
+
}
|
|
4065
|
+
`, "/test/test.ts", { surface: "@tsonic/js" });
|
|
4066
|
+
expect(csharp).to.include("value)) != null && value.Is1()");
|
|
4067
|
+
expect(csharp).not.to.include("(value.As1()) is global::js.Uint8Array");
|
|
4068
|
+
});
|
|
4069
|
+
it("maps bare void value-slot members to object storage", () => {
|
|
4070
|
+
const csharp = compileToCSharp(`
|
|
4071
|
+
type Ok<T> = { success: true; data: T };
|
|
4072
|
+
|
|
4073
|
+
export function run(): Ok<void> {
|
|
4074
|
+
return { success: true, data: undefined };
|
|
4075
|
+
}
|
|
4076
|
+
`);
|
|
4077
|
+
expect(csharp).to.include("public required object data { get; set; }");
|
|
4078
|
+
expect(csharp).to.include("data = default(object)");
|
|
4079
|
+
expect(csharp).not.to.include("required void data");
|
|
4080
|
+
expect(csharp).not.to.include("default(void)");
|
|
4081
|
+
});
|
|
4082
|
+
it("wraps empty array callback arguments through a concrete union array arm", () => {
|
|
4083
|
+
const csharp = compileToCSharp(`
|
|
4084
|
+
import type { int } from "@tsonic/core/types.js";
|
|
4085
|
+
|
|
4086
|
+
interface RecordWithTtl {
|
|
4087
|
+
address: string;
|
|
4088
|
+
ttl: int;
|
|
4089
|
+
}
|
|
4090
|
+
|
|
4091
|
+
type ResolveCallback = (
|
|
4092
|
+
error: Error | null,
|
|
4093
|
+
records: string[] | RecordWithTtl[]
|
|
4094
|
+
) => void;
|
|
4095
|
+
|
|
4096
|
+
export function run(callback: ResolveCallback): void {
|
|
4097
|
+
callback(new Error("ECANCELLED"), []);
|
|
4098
|
+
}
|
|
4099
|
+
`, "/test/test.ts", { surface: "@tsonic/js" });
|
|
4100
|
+
expect(csharp).to.match(/From[12]\(global::System\.Array\.Empty<(?:string|global::Test\.RecordWithTtl)>\(\)\)/);
|
|
4101
|
+
expect(csharp).not.to.include('callback(new global::js.Error("ECANCELLED"), global::System.Array.Empty<double>())');
|
|
4102
|
+
expect(csharp).not.to.include('callback(new global::js.Error("ECANCELLED"), global::System.Array.Empty');
|
|
4103
|
+
});
|
|
4104
|
+
it("keeps integral conditional branches in assignment storage", () => {
|
|
4105
|
+
const csharp = compileToCSharp(`
|
|
4106
|
+
import type { int } from "@tsonic/core/types.js";
|
|
4107
|
+
|
|
4108
|
+
export function run(flag: boolean, value: int, polynomial: int): int {
|
|
4109
|
+
let crc = value;
|
|
4110
|
+
crc = flag ? (crc >>> 1) ^ polynomial : crc >>> 1;
|
|
4111
|
+
return crc;
|
|
4112
|
+
}
|
|
4113
|
+
`, "/test/test.ts", { surface: "@tsonic/js" });
|
|
4114
|
+
expect(csharp).to.include("public static int run(bool flag, int value, int polynomial)");
|
|
4115
|
+
expect(csharp).to.include(": (int)crc >>> (int)1");
|
|
4116
|
+
expect(csharp).not.to.include(": (global::System.Double)((int)crc >>> (int)1)");
|
|
4117
|
+
expect(csharp).not.to.include("crc = (int)(flag ?");
|
|
4118
|
+
});
|
|
4119
|
+
it("materializes union array arms to broad object arrays without throwing", () => {
|
|
4120
|
+
const csharp = compileToCSharp(`
|
|
4121
|
+
import type { int, JsValue } from "@tsonic/core/types.js";
|
|
4122
|
+
|
|
4123
|
+
interface RecordWithTtl {
|
|
4124
|
+
address: string;
|
|
4125
|
+
ttl: int;
|
|
4126
|
+
}
|
|
4127
|
+
|
|
4128
|
+
export function run(result: string[] | RecordWithTtl[]): number {
|
|
4129
|
+
const values = result as Array<JsValue>;
|
|
4130
|
+
return values.length;
|
|
4131
|
+
}
|
|
4132
|
+
`, "/test/test.ts", { surface: "@tsonic/js" });
|
|
4133
|
+
expect(csharp).to.include("result.Match<object?[]>");
|
|
4134
|
+
expect(csharp).to.match(/global::System\.Linq\.Enumerable\.Select<(?:global::Test\.)?RecordWithTtl, object\?>/);
|
|
4135
|
+
expect(csharp).not.to.include("Cannot materialize runtime union arrayType to arrayType");
|
|
4136
|
+
});
|
|
4137
|
+
});
|
|
4138
|
+
});
|
|
4139
|
+
//# sourceMappingURL=regression-coverage-c.test.js.map
|