@scriptc/compiler 0.2.7 → 0.2.8
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/ambient/scriptc-node-fallback.d.ts +2 -0
- package/dist/backend/llvm/alloc.d.ts +3 -0
- package/dist/backend/llvm/alloc.js +54 -13
- package/dist/backend/llvm/alloc.js.map +1 -1
- package/dist/backend/llvm/blocks.d.ts +9 -0
- package/dist/backend/llvm/blocks.js +9 -0
- package/dist/backend/llvm/blocks.js.map +1 -1
- package/dist/backend/llvm/borrowed-receivers.d.ts +7 -0
- package/dist/backend/llvm/borrowed-receivers.js +39 -0
- package/dist/backend/llvm/borrowed-receivers.js.map +1 -1
- package/dist/backend/llvm/call-lifetimes.d.ts +4 -1
- package/dist/backend/llvm/call-lifetimes.js +14 -3
- package/dist/backend/llvm/call-lifetimes.js.map +1 -1
- package/dist/backend/llvm/call-lifetimes.test.js +8 -3
- package/dist/backend/llvm/call-lifetimes.test.js.map +1 -1
- package/dist/backend/llvm/checked-narrows.d.ts +24 -0
- package/dist/backend/llvm/checked-narrows.js +108 -0
- package/dist/backend/llvm/checked-narrows.js.map +1 -0
- package/dist/backend/llvm/checked-narrows.test.d.ts +1 -0
- package/dist/backend/llvm/checked-narrows.test.js +208 -0
- package/dist/backend/llvm/checked-narrows.test.js.map +1 -0
- package/dist/backend/llvm/classes.d.ts +13 -1
- package/dist/backend/llvm/classes.js +26 -18
- package/dist/backend/llvm/classes.js.map +1 -1
- package/dist/backend/llvm/classes.test.js +32 -3
- package/dist/backend/llvm/classes.test.js.map +1 -1
- package/dist/backend/llvm/debug-info.d.ts +6 -2
- package/dist/backend/llvm/debug-info.js +11 -1
- package/dist/backend/llvm/debug-info.js.map +1 -1
- package/dist/backend/llvm/dense-array-access.test.js +89 -0
- package/dist/backend/llvm/dense-array-access.test.js.map +1 -1
- package/dist/backend/llvm/dyn.d.ts +4 -0
- package/dist/backend/llvm/dyn.js +31 -20
- package/dist/backend/llvm/dyn.js.map +1 -1
- package/dist/backend/llvm/emitter.d.ts +184 -11
- package/dist/backend/llvm/emitter.js +1189 -125
- package/dist/backend/llvm/emitter.js.map +1 -1
- package/dist/backend/llvm/emitter.test.js +21 -1
- package/dist/backend/llvm/emitter.test.js.map +1 -1
- package/dist/backend/llvm/expr-async.js +4 -4
- package/dist/backend/llvm/expr-async.js.map +1 -1
- package/dist/backend/llvm/expr-bytes.d.ts +1 -1
- package/dist/backend/llvm/expr-bytes.js +85 -8
- package/dist/backend/llvm/expr-bytes.js.map +1 -1
- package/dist/backend/llvm/expr-callbacks.js +29 -21
- package/dist/backend/llvm/expr-callbacks.js.map +1 -1
- package/dist/backend/llvm/expr-calls.d.ts +5 -0
- package/dist/backend/llvm/expr-calls.js +55 -10
- package/dist/backend/llvm/expr-calls.js.map +1 -1
- package/dist/backend/llvm/expr-containers.d.ts +7 -1
- package/dist/backend/llvm/expr-containers.js +230 -27
- package/dist/backend/llvm/expr-containers.js.map +1 -1
- package/dist/backend/llvm/expr-control.js +25 -10
- package/dist/backend/llvm/expr-control.js.map +1 -1
- package/dist/backend/llvm/expr-dynamic.js +72 -21
- package/dist/backend/llvm/expr-dynamic.js.map +1 -1
- package/dist/backend/llvm/expr-island.js +3 -8
- package/dist/backend/llvm/expr-island.js.map +1 -1
- package/dist/backend/llvm/expr-primitives.js +41 -12
- package/dist/backend/llvm/expr-primitives.js.map +1 -1
- package/dist/backend/llvm/expr-primitives.test.js +50 -2
- package/dist/backend/llvm/expr-primitives.test.js.map +1 -1
- package/dist/backend/llvm/expr-records.js +28 -14
- package/dist/backend/llvm/expr-records.js.map +1 -1
- package/dist/backend/llvm/expr-stream-bridges.js +41 -31
- package/dist/backend/llvm/expr-stream-bridges.js.map +1 -1
- package/dist/backend/llvm/expr-stream-callbacks.js +6 -3
- package/dist/backend/llvm/expr-stream-callbacks.js.map +1 -1
- package/dist/backend/llvm/layouts.d.ts +2 -1
- package/dist/backend/llvm/layouts.js +2 -2
- package/dist/backend/llvm/layouts.js.map +1 -1
- package/dist/backend/llvm/lib-abi.js +10 -0
- package/dist/backend/llvm/lib-abi.js.map +1 -1
- package/dist/backend/llvm/lib-filesystem.js +7 -11
- package/dist/backend/llvm/lib-filesystem.js.map +1 -1
- package/dist/backend/llvm/lib-process.js +8 -8
- package/dist/backend/llvm/lib-process.js.map +1 -1
- package/dist/backend/llvm/lib-shared.js +1 -0
- package/dist/backend/llvm/lib-shared.js.map +1 -1
- package/dist/backend/llvm/local-array-reads.js +73 -13
- package/dist/backend/llvm/local-array-reads.js.map +1 -1
- package/dist/backend/llvm/local-array-reads.test.js +7 -3
- package/dist/backend/llvm/local-array-reads.test.js.map +1 -1
- package/dist/backend/llvm/local-union-storage.js +10 -6
- package/dist/backend/llvm/local-union-storage.js.map +1 -1
- package/dist/backend/llvm/local-union-storage.test.js +3 -2
- package/dist/backend/llvm/local-union-storage.test.js.map +1 -1
- package/dist/backend/llvm/map-number-lookup.d.ts +18 -0
- package/dist/backend/llvm/map-number-lookup.js +62 -0
- package/dist/backend/llvm/map-number-lookup.js.map +1 -0
- package/dist/backend/llvm/map-read-lifetimes.d.ts +6 -0
- package/dist/backend/llvm/map-read-lifetimes.js +24 -3
- package/dist/backend/llvm/map-read-lifetimes.js.map +1 -1
- package/dist/backend/llvm/map-read-lifetimes.test.js +38 -19
- package/dist/backend/llvm/map-read-lifetimes.test.js.map +1 -1
- package/dist/backend/llvm/nullable-unions.d.ts +68 -0
- package/dist/backend/llvm/nullable-unions.js +132 -0
- package/dist/backend/llvm/nullable-unions.js.map +1 -0
- package/dist/backend/llvm/publish.d.ts +58 -0
- package/dist/backend/llvm/publish.js +286 -0
- package/dist/backend/llvm/publish.js.map +1 -0
- package/dist/backend/llvm/rebound-parameters.d.ts +12 -0
- package/dist/backend/llvm/rebound-parameters.js +72 -0
- package/dist/backend/llvm/rebound-parameters.js.map +1 -0
- package/dist/backend/llvm/rebound-parameters.test.d.ts +1 -0
- package/dist/backend/llvm/rebound-parameters.test.js +67 -0
- package/dist/backend/llvm/rebound-parameters.test.js.map +1 -0
- package/dist/backend/llvm/reference-effects.d.ts +18 -2
- package/dist/backend/llvm/reference-effects.js +106 -16
- package/dist/backend/llvm/reference-effects.js.map +1 -1
- package/dist/backend/llvm/reference-effects.test.js +52 -1
- package/dist/backend/llvm/reference-effects.test.js.map +1 -1
- package/dist/backend/llvm/shapes.d.ts +45 -17
- package/dist/backend/llvm/shapes.js +131 -53
- package/dist/backend/llvm/shapes.js.map +1 -1
- package/dist/backend/llvm/shapes.test.js +33 -8
- package/dist/backend/llvm/shapes.test.js.map +1 -1
- package/dist/backend/llvm/stack-unions.test.js +5 -2
- package/dist/backend/llvm/stack-unions.test.js.map +1 -1
- package/dist/backend/llvm/string-construction.d.ts +10 -0
- package/dist/backend/llvm/string-construction.js +42 -0
- package/dist/backend/llvm/string-construction.js.map +1 -1
- package/dist/backend/llvm/string-key-hash.d.ts +9 -2
- package/dist/backend/llvm/string-key-hash.js +20 -3
- package/dist/backend/llvm/string-key-hash.js.map +1 -1
- package/dist/backend/llvm/string-key-hash.test.js +14 -3
- package/dist/backend/llvm/string-key-hash.test.js.map +1 -1
- package/dist/backend/llvm/string-lifetimes.test.js +24 -11
- package/dist/backend/llvm/string-lifetimes.test.js.map +1 -1
- package/dist/backend/llvm/string-reads.d.ts +7 -0
- package/dist/backend/llvm/string-reads.js +76 -0
- package/dist/backend/llvm/string-reads.js.map +1 -0
- package/dist/backend/llvm/switch-dispatch.test.js +1 -1
- package/dist/backend/llvm/switch-dispatch.test.js.map +1 -1
- package/dist/backend/llvm/test-boxed-unions.d.ts +5 -0
- package/dist/backend/llvm/test-boxed-unions.js +13 -0
- package/dist/backend/llvm/test-boxed-unions.js.map +1 -0
- package/dist/backend/llvm/union-repr.d.ts +15 -0
- package/dist/backend/llvm/union-repr.js +89 -0
- package/dist/backend/llvm/union-repr.js.map +1 -0
- package/dist/backend/llvm/virtual-borrows.d.ts +31 -0
- package/dist/backend/llvm/virtual-borrows.js +82 -0
- package/dist/backend/llvm/virtual-borrows.js.map +1 -0
- package/dist/backend/llvm/walk-borrows.d.ts +43 -0
- package/dist/backend/llvm/walk-borrows.js +150 -0
- package/dist/backend/llvm/walk-borrows.js.map +1 -0
- package/dist/backend/llvm/walk-borrows.test.d.ts +1 -0
- package/dist/backend/llvm/walk-borrows.test.js +119 -0
- package/dist/backend/llvm/walk-borrows.test.js.map +1 -0
- package/dist/backend/llvm/walkers.d.ts +5 -1
- package/dist/backend/llvm/walkers.js +24 -21
- package/dist/backend/llvm/walkers.js.map +1 -1
- package/dist/backend/may-throw.d.ts +29 -1
- package/dist/backend/may-throw.js +346 -3
- package/dist/backend/may-throw.js.map +1 -1
- package/dist/backend/may-throw.test.js +113 -1
- package/dist/backend/may-throw.test.js.map +1 -1
- package/dist/backend/native/runtime-inputs.d.ts +1 -1
- package/dist/backend/native/runtime-inputs.js +1 -0
- package/dist/backend/native/runtime-inputs.js.map +1 -1
- package/dist/backend/native-codegen-core.d.ts +7 -5
- package/dist/backend/native-codegen-core.js +14 -9
- package/dist/backend/native-codegen-core.js.map +1 -1
- package/dist/backend/native-codegen.d.ts +4 -0
- package/dist/backend/native-codegen.js +49 -2
- package/dist/backend/native-codegen.js.map +1 -1
- package/dist/backend/native-codegen.test.js +41 -10
- package/dist/backend/native-codegen.test.js.map +1 -1
- package/dist/backend/native-tools.d.ts +2 -0
- package/dist/backend/native-tools.js +3 -0
- package/dist/backend/native-tools.js.map +1 -1
- package/dist/backend/publication.d.ts +28 -0
- package/dist/backend/publication.js +155 -0
- package/dist/backend/publication.js.map +1 -0
- package/dist/backend/publication.test.d.ts +1 -0
- package/dist/backend/publication.test.js +72 -0
- package/dist/backend/publication.test.js.map +1 -0
- package/dist/backend/runtime-abi.d.ts +2 -2
- package/dist/backend/runtime-abi.js +2 -2
- package/dist/backend/runtime-pack-targets.test.js +1 -1
- package/dist/backend/runtime-pack.test.js +1 -1
- package/dist/cli/command.js +70 -7
- package/dist/cli/command.js.map +1 -1
- package/dist/cli/usage.d.ts +4 -1
- package/dist/cli/usage.js +8 -1
- package/dist/cli/usage.js.map +1 -1
- package/dist/compile-types.d.ts +12 -3
- package/dist/coverage/report.d.ts +25 -2
- package/dist/coverage/report.js +161 -33
- package/dist/coverage/report.js.map +1 -1
- package/dist/coverage/verdict-cache.d.ts +63 -0
- package/dist/coverage/verdict-cache.js +193 -0
- package/dist/coverage/verdict-cache.js.map +1 -0
- package/dist/coverage/verdict-cache.test.d.ts +1 -0
- package/dist/coverage/verdict-cache.test.js +52 -0
- package/dist/coverage/verdict-cache.test.js.map +1 -0
- package/dist/coverage/verdict-semantic.d.ts +2 -0
- package/dist/coverage/verdict-semantic.js +24 -0
- package/dist/coverage/verdict-semantic.js.map +1 -0
- package/dist/coverage/verdict-startup.d.ts +15 -0
- package/dist/coverage/verdict-startup.js +66 -0
- package/dist/coverage/verdict-startup.js.map +1 -0
- package/dist/diagnostics/diagnostic.d.ts +29 -1
- package/dist/diagnostics/diagnostic.js +74 -4
- package/dist/diagnostics/diagnostic.js.map +1 -1
- package/dist/diagnostics/envelope.d.ts +130 -0
- package/dist/diagnostics/envelope.js +257 -0
- package/dist/diagnostics/envelope.js.map +1 -0
- package/dist/diagnostics/envelope.test.d.ts +1 -0
- package/dist/diagnostics/envelope.test.js +91 -0
- package/dist/diagnostics/envelope.test.js.map +1 -0
- package/dist/diagnostics/render.d.ts +3 -0
- package/dist/diagnostics/render.js +13 -2
- package/dist/diagnostics/render.js.map +1 -1
- package/dist/executable/prepare.d.ts +4 -0
- package/dist/executable/prepare.js +7 -1
- package/dist/executable/prepare.js.map +1 -1
- package/dist/frontend/analysis.js +1 -0
- package/dist/frontend/analysis.js.map +1 -1
- package/dist/frontend/lowering/array-values.d.ts +7 -0
- package/dist/frontend/lowering/array-values.js +120 -4
- package/dist/frontend/lowering/array-values.js.map +1 -1
- package/dist/frontend/lowering/builtins/numbers.js +29 -1
- package/dist/frontend/lowering/builtins/numbers.js.map +1 -1
- package/dist/frontend/lowering/builtins/process.d.ts +4 -0
- package/dist/frontend/lowering/builtins/process.js +10 -0
- package/dist/frontend/lowering/builtins/process.js.map +1 -1
- package/dist/frontend/lowering/builtins/workers.js +4 -2
- package/dist/frontend/lowering/builtins/workers.js.map +1 -1
- package/dist/frontend/lowering/class-assertions.d.ts +8 -0
- package/dist/frontend/lowering/class-assertions.js +217 -1
- package/dist/frontend/lowering/class-assertions.js.map +1 -1
- package/dist/frontend/lowering/class-dynamic-dispatch.js +8 -5
- package/dist/frontend/lowering/class-dynamic-dispatch.js.map +1 -1
- package/dist/frontend/lowering/coercions/state.d.ts +6 -0
- package/dist/frontend/lowering/coercions/state.js +2 -0
- package/dist/frontend/lowering/coercions/state.js.map +1 -1
- package/dist/frontend/lowering/coercions/unions.d.ts +8 -0
- package/dist/frontend/lowering/coercions/unions.js +67 -2
- package/dist/frontend/lowering/coercions/unions.js.map +1 -1
- package/dist/frontend/lowering/collation-repertoire.d.ts +1 -0
- package/dist/frontend/lowering/collation-repertoire.js +19 -0
- package/dist/frontend/lowering/collation-repertoire.js.map +1 -0
- package/dist/frontend/lowering/construction-escapes.d.ts +38 -0
- package/dist/frontend/lowering/construction-escapes.js +146 -0
- package/dist/frontend/lowering/construction-escapes.js.map +1 -0
- package/dist/frontend/lowering/construction-escapes.test.d.ts +1 -0
- package/dist/frontend/lowering/construction-escapes.test.js +150 -0
- package/dist/frontend/lowering/construction-escapes.test.js.map +1 -0
- package/dist/frontend/lowering/containers/array-callbacks.js +81 -44
- package/dist/frontend/lowering/containers/array-callbacks.js.map +1 -1
- package/dist/frontend/lowering/containers/array-construction.js +15 -2
- package/dist/frontend/lowering/containers/array-construction.js.map +1 -1
- package/dist/frontend/lowering/containers/array-methods.js +231 -12
- package/dist/frontend/lowering/containers/array-methods.js.map +1 -1
- package/dist/frontend/lowering/containers/callback-arguments.js +43 -1
- package/dist/frontend/lowering/containers/callback-arguments.js.map +1 -1
- package/dist/frontend/lowering/containers/string-and-regexp.js +7 -63
- package/dist/frontend/lowering/containers/string-and-regexp.js.map +1 -1
- package/dist/frontend/lowering/cycle-initialization.d.ts +6 -1
- package/dist/frontend/lowering/cycle-initialization.js +59 -33
- package/dist/frontend/lowering/cycle-initialization.js.map +1 -1
- package/dist/frontend/lowering/divergences.d.ts +9 -0
- package/dist/frontend/lowering/divergences.js +630 -0
- package/dist/frontend/lowering/divergences.js.map +1 -0
- package/dist/frontend/lowering/expressions/object-literals.js +40 -2
- package/dist/frontend/lowering/expressions/object-literals.js.map +1 -1
- package/dist/frontend/lowering/lower-calls.d.ts +5 -0
- package/dist/frontend/lowering/lower-calls.js +226 -157
- package/dist/frontend/lowering/lower-calls.js.map +1 -1
- package/dist/frontend/lowering/lower-classes.d.ts +4 -0
- package/dist/frontend/lowering/lower-classes.js +72 -22
- package/dist/frontend/lowering/lower-classes.js.map +1 -1
- package/dist/frontend/lowering/lower-exprs.d.ts +13 -0
- package/dist/frontend/lowering/lower-exprs.js +431 -107
- package/dist/frontend/lowering/lower-exprs.js.map +1 -1
- package/dist/frontend/lowering/lower-generators.d.ts +19 -13
- package/dist/frontend/lowering/lower-generators.js +67 -44
- package/dist/frontend/lowering/lower-generators.js.map +1 -1
- package/dist/frontend/lowering/lower-inspect.js +3 -2
- package/dist/frontend/lowering/lower-inspect.js.map +1 -1
- package/dist/frontend/lowering/lower-island.d.ts +1 -1
- package/dist/frontend/lowering/lower-island.js +24 -7
- package/dist/frontend/lowering/lower-island.js.map +1 -1
- package/dist/frontend/lowering/lower-modules.js +90 -1
- package/dist/frontend/lowering/lower-modules.js.map +1 -1
- package/dist/frontend/lowering/lower-stmts.js +36 -6
- package/dist/frontend/lowering/lower-stmts.js.map +1 -1
- package/dist/frontend/lowering/lowerer.d.ts +78 -2
- package/dist/frontend/lowering/lowerer.js +986 -73
- package/dist/frontend/lowering/lowerer.js.map +1 -1
- package/dist/frontend/lowering/runtime-optional-bounds.d.ts +19 -0
- package/dist/frontend/lowering/runtime-optional-bounds.js +354 -0
- package/dist/frontend/lowering/runtime-optional-bounds.js.map +1 -0
- package/dist/frontend/lowering/runtime-optional-bounds.test.d.ts +1 -0
- package/dist/frontend/lowering/runtime-optional-bounds.test.js +66 -0
- package/dist/frontend/lowering/runtime-optional-bounds.test.js.map +1 -0
- package/dist/frontend/lowering/runtime-optional-elements.d.ts +117 -0
- package/dist/frontend/lowering/runtime-optional-elements.js +738 -0
- package/dist/frontend/lowering/runtime-optional-elements.js.map +1 -0
- package/dist/frontend/lowering/runtime-optional-guards.d.ts +36 -0
- package/dist/frontend/lowering/runtime-optional-guards.js +375 -0
- package/dist/frontend/lowering/runtime-optional-guards.js.map +1 -0
- package/dist/frontend/lowering/runtime-optional-guards.test.d.ts +1 -0
- package/dist/frontend/lowering/runtime-optional-guards.test.js +92 -0
- package/dist/frontend/lowering/runtime-optional-guards.test.js.map +1 -0
- package/dist/frontend/lowering/runtime-optional-ownership.d.ts +63 -0
- package/dist/frontend/lowering/runtime-optional-ownership.js +382 -0
- package/dist/frontend/lowering/runtime-optional-ownership.js.map +1 -0
- package/dist/frontend/lowering/runtime-optional-provenance.d.ts +2 -1
- package/dist/frontend/lowering/runtime-optional-provenance.js +2 -1
- package/dist/frontend/lowering/runtime-optional-provenance.js.map +1 -1
- package/dist/frontend/lowering/string-index-bounds.d.ts +36 -0
- package/dist/frontend/lowering/string-index-bounds.js +537 -0
- package/dist/frontend/lowering/string-index-bounds.js.map +1 -0
- package/dist/frontend/lowering/string-index-bounds.test.d.ts +1 -0
- package/dist/frontend/lowering/string-index-bounds.test.js +223 -0
- package/dist/frontend/lowering/string-index-bounds.test.js.map +1 -0
- package/dist/frontend/lowering/union-narrow.d.ts +2 -0
- package/dist/frontend/lowering/union-narrow.js +10 -6
- package/dist/frontend/lowering/union-narrow.js.map +1 -1
- package/dist/frontend/program-analysis.d.ts +10 -0
- package/dist/frontend/program-analysis.js +7 -0
- package/dist/frontend/program-analysis.js.map +1 -1
- package/dist/frontend/program.d.ts +25 -0
- package/dist/frontend/program.js +613 -17
- package/dist/frontend/program.js.map +1 -1
- package/dist/frontend/program.test.js +64 -1
- package/dist/frontend/program.test.js.map +1 -1
- package/dist/frontend/resolve.d.ts +6 -0
- package/dist/frontend/resolve.js +14 -0
- package/dist/frontend/resolve.js.map +1 -1
- package/dist/frontend/threads-import.d.ts +5 -0
- package/dist/frontend/threads-import.js +21 -0
- package/dist/frontend/threads-import.js.map +1 -0
- package/dist/frontend/type-mapper.d.ts +3 -0
- package/dist/frontend/type-mapper.js +72 -6
- package/dist/frontend/type-mapper.js.map +1 -1
- package/dist/frontend/worker-target.d.ts +4 -0
- package/dist/frontend/worker-target.js +8 -1
- package/dist/frontend/worker-target.js.map +1 -1
- package/dist/index.d.ts +6 -1
- package/dist/index.js +47 -9
- package/dist/index.js.map +1 -1
- package/dist/ir/build.d.ts +5 -0
- package/dist/ir/build.js +7 -0
- package/dist/ir/build.js.map +1 -1
- package/dist/ir/builtin-signatures.d.ts +1 -1
- package/dist/ir/builtin-signatures.js +3 -0
- package/dist/ir/builtin-signatures.js.map +1 -1
- package/dist/ir/int32-slots.d.ts +72 -0
- package/dist/ir/int32-slots.js +837 -0
- package/dist/ir/int32-slots.js.map +1 -0
- package/dist/ir/int32-slots.test.d.ts +1 -0
- package/dist/ir/int32-slots.test.js +222 -0
- package/dist/ir/int32-slots.test.js.map +1 -0
- package/dist/ir/integer-ranges.d.ts +19 -3
- package/dist/ir/integer-ranges.js +168 -23
- package/dist/ir/integer-ranges.js.map +1 -1
- package/dist/ir/integer-ranges.test.js +74 -2
- package/dist/ir/integer-ranges.test.js.map +1 -1
- package/dist/ir/ir.d.ts +24 -6
- package/dist/ir/ir.js.map +1 -1
- package/dist/ir/validate.js +21 -2
- package/dist/ir/validate.js.map +1 -1
- package/dist/ir/validate.test.js +39 -0
- package/dist/ir/validate.test.js.map +1 -1
- package/dist/native/cache.d.ts +3 -0
- package/dist/native/cache.js +49 -1
- package/dist/native/cache.js.map +1 -1
- package/dist/native/cache.test.js +21 -1
- package/dist/native/cache.test.js.map +1 -1
- package/dist/native/cli.js +1 -1
- package/dist/native/cli.js.map +1 -1
- package/dist/native/compiler.d.ts +5 -0
- package/dist/native/compiler.js +51 -4
- package/dist/native/compiler.js.map +1 -1
- package/dist/native/prepare.d.ts +4 -0
- package/dist/native/prepare.js +2 -1
- package/dist/native/prepare.js.map +1 -1
- package/dist/startup-cache.d.ts +2 -0
- package/dist/startup-cache.js +2 -0
- package/dist/startup-cache.js.map +1 -1
- package/package.json +20 -20
- package/surface-manifest.json +1 -1
|
@@ -0,0 +1,630 @@
|
|
|
1
|
+
/* Divergence scan: compile-time-detectable places where a program that
|
|
2
|
+
* compiles will behave differently natively than under Node. Each finding
|
|
3
|
+
* is an SC6xxx warning — never a build failure (`scriptc coverage
|
|
4
|
+
* --fail-on=divergences` opts into failing on them).
|
|
5
|
+
*
|
|
6
|
+
* The scan is deliberately narrow: a finding needs both the construct that
|
|
7
|
+
* differs AND evidence in the program that the difference is observable
|
|
8
|
+
* (a write or identity comparison through a copied object, an
|
|
9
|
+
* order-observing call on the type whose literal is reordered, ...).
|
|
10
|
+
* Ordinary code produces no findings. Syntactic prefilters run first so the
|
|
11
|
+
* checker is only consulted for candidate sites.
|
|
12
|
+
*/
|
|
13
|
+
import * as ts from "../ts7/adapter.js";
|
|
14
|
+
import { locOf } from "../program.js";
|
|
15
|
+
import { isNodeModulesPath } from "../resolve.js";
|
|
16
|
+
import { dateLiteralDivergenceDiag, keyOrderDivergenceDiag, localeCompareDivergenceDiag, unrelatedClassCastDivergenceDiag, widthCopyDivergenceDiag, } from "../../diagnostics/diagnostic.js";
|
|
17
|
+
import { isCollationCovered } from "./collation-repertoire.js";
|
|
18
|
+
export function scanDivergences(lowerer, files) {
|
|
19
|
+
const own = files.filter((sf) => !sf.isDeclarationFile && !sf.fileName.endsWith(".json") && !isNodeModulesPath(sf.fileName));
|
|
20
|
+
const out = [];
|
|
21
|
+
const checker = lowerer.checker;
|
|
22
|
+
// ── pass 1: syntactic collection ────────────────────────────────────
|
|
23
|
+
const fnsByName = new Map();
|
|
24
|
+
const calls = [];
|
|
25
|
+
const typedDecls = [];
|
|
26
|
+
const literals = [];
|
|
27
|
+
const observers = [];
|
|
28
|
+
const casts = [];
|
|
29
|
+
const dates = [];
|
|
30
|
+
const localeCompares = [];
|
|
31
|
+
/** binding name → member names assigned through it (`q.a = 2`). */
|
|
32
|
+
const assignedMembers = new Map();
|
|
33
|
+
const visit = (node) => {
|
|
34
|
+
if ((ts.isFunctionDeclaration(node) || ts.isMethodDeclaration(node)) &&
|
|
35
|
+
node.body !== undefined &&
|
|
36
|
+
node.name !== undefined &&
|
|
37
|
+
ts.isIdentifier(node.name) &&
|
|
38
|
+
node.parameters.length > 0) {
|
|
39
|
+
const list = fnsByName.get(node.name.text) ?? [];
|
|
40
|
+
list.push(node);
|
|
41
|
+
fnsByName.set(node.name.text, list);
|
|
42
|
+
}
|
|
43
|
+
if (ts.isCallExpression(node)) {
|
|
44
|
+
calls.push(node);
|
|
45
|
+
const callee = node.expression;
|
|
46
|
+
if (ts.isPropertyAccessExpression(callee)) {
|
|
47
|
+
const member = callee.name.text;
|
|
48
|
+
if (member === "localeCompare" && node.arguments.length === 1)
|
|
49
|
+
localeCompares.push(node);
|
|
50
|
+
const recv = callee.expression;
|
|
51
|
+
if (ts.isIdentifier(recv)) {
|
|
52
|
+
if ((recv.text === "JSON" && member === "stringify") ||
|
|
53
|
+
(recv.text === "Object" &&
|
|
54
|
+
(member === "keys" || member === "values" || member === "entries"))) {
|
|
55
|
+
if (node.arguments[0] !== undefined)
|
|
56
|
+
observers.push(node.arguments[0]);
|
|
57
|
+
}
|
|
58
|
+
else if (recv.text === "console" &&
|
|
59
|
+
(member === "log" ||
|
|
60
|
+
member === "info" ||
|
|
61
|
+
member === "warn" ||
|
|
62
|
+
member === "error" ||
|
|
63
|
+
member === "debug" ||
|
|
64
|
+
member === "dir")) {
|
|
65
|
+
for (const a of node.arguments)
|
|
66
|
+
if (!isLiteralLike(a))
|
|
67
|
+
observers.push(a);
|
|
68
|
+
}
|
|
69
|
+
else if (recv.text === "Date" && member === "parse") {
|
|
70
|
+
if (node.arguments[0] !== undefined)
|
|
71
|
+
dates.push({ call: node, arg: node.arguments[0] });
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
else if (ts.isNewExpression(node)) {
|
|
77
|
+
if (ts.isIdentifier(node.expression) &&
|
|
78
|
+
node.expression.text === "Date" &&
|
|
79
|
+
node.arguments?.length === 1) {
|
|
80
|
+
dates.push({ call: node, arg: node.arguments[0] });
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
else if (ts.isForInStatement(node)) {
|
|
84
|
+
observers.push(node.expression);
|
|
85
|
+
}
|
|
86
|
+
else if (ts.isVariableDeclaration(node)) {
|
|
87
|
+
if (node.type !== undefined &&
|
|
88
|
+
node.initializer !== undefined &&
|
|
89
|
+
isExistingObjectExpression(node.initializer) &&
|
|
90
|
+
ts.isIdentifier(node.name))
|
|
91
|
+
typedDecls.push(node);
|
|
92
|
+
}
|
|
93
|
+
else if (ts.isObjectLiteralExpression(node)) {
|
|
94
|
+
if (node.properties.length >= 1 && node.properties.every(isPlainProperty))
|
|
95
|
+
literals.push(node);
|
|
96
|
+
}
|
|
97
|
+
else if (ts.isAsExpression(node) || ts.isTypeAssertion(node)) {
|
|
98
|
+
casts.push(node);
|
|
99
|
+
}
|
|
100
|
+
else if (ts.isBinaryExpression(node) &&
|
|
101
|
+
node.operatorToken.kind === ts.SyntaxKind.EqualsToken &&
|
|
102
|
+
ts.isPropertyAccessExpression(node.left) &&
|
|
103
|
+
ts.isIdentifier(node.left.expression)) {
|
|
104
|
+
const names = assignedMembers.get(node.left.expression.text) ?? new Set();
|
|
105
|
+
names.add(node.left.name.text);
|
|
106
|
+
assignedMembers.set(node.left.expression.text, names);
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
// Iterative: absurdly deep nesting must reach the lowering's own fence.
|
|
110
|
+
for (const sf of own)
|
|
111
|
+
ts.walkPreorder(sf, visit);
|
|
112
|
+
// ── width copies: writes or identity comparisons through a copy ─────
|
|
113
|
+
const usesByFn = new Map();
|
|
114
|
+
const identityUsesOf = (fn) => {
|
|
115
|
+
let uses = usesByFn.get(fn);
|
|
116
|
+
if (uses === undefined) {
|
|
117
|
+
uses = fn.parameters.map((p) => ts.isIdentifier(p.name) && fn.body !== undefined ? identityUse(fn.body, p.name.text) : null);
|
|
118
|
+
usesByFn.set(fn, uses);
|
|
119
|
+
}
|
|
120
|
+
return uses;
|
|
121
|
+
};
|
|
122
|
+
for (const call of calls) {
|
|
123
|
+
const name = calleeName(call);
|
|
124
|
+
if (name === null)
|
|
125
|
+
continue;
|
|
126
|
+
const candidates = fnsByName.get(name);
|
|
127
|
+
if (candidates === undefined)
|
|
128
|
+
continue;
|
|
129
|
+
if (!candidates.some((fn) => identityUsesOf(fn).some((u) => u !== null)))
|
|
130
|
+
continue;
|
|
131
|
+
const signature = safely(() => checker.getResolvedSignature(call));
|
|
132
|
+
if (signature === undefined)
|
|
133
|
+
continue;
|
|
134
|
+
const decl = safely(() => checker.signatureDeclaration(signature));
|
|
135
|
+
if (decl === undefined || !candidates.includes(decl))
|
|
136
|
+
continue;
|
|
137
|
+
const fn = decl;
|
|
138
|
+
const uses = identityUsesOf(fn);
|
|
139
|
+
call.arguments.forEach((arg, i) => {
|
|
140
|
+
const use = uses[i];
|
|
141
|
+
const param = fn.parameters[i];
|
|
142
|
+
if (use === null || use === undefined || param === undefined || param.type === undefined)
|
|
143
|
+
return;
|
|
144
|
+
if (!isExistingObjectExpression(arg))
|
|
145
|
+
return;
|
|
146
|
+
const copy = safely(() => widthCopyBetween(lowerer, arg, param.type));
|
|
147
|
+
if (copy === undefined || copy === null)
|
|
148
|
+
return;
|
|
149
|
+
out.push(widthCopyDivergenceDiag(copy.source, copy.target, use.kind, use.text, "call", locOf(arg)));
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
for (const decl of typedDecls) {
|
|
153
|
+
const name = decl.name.text;
|
|
154
|
+
const scope = enclosingScope(decl);
|
|
155
|
+
if (scope === undefined)
|
|
156
|
+
continue;
|
|
157
|
+
const use = identityUse(scope, name, decl.end);
|
|
158
|
+
if (use === null)
|
|
159
|
+
continue;
|
|
160
|
+
const copy = safely(() => widthCopyBetween(lowerer, decl.initializer, decl.type));
|
|
161
|
+
if (copy === undefined || copy === null)
|
|
162
|
+
continue;
|
|
163
|
+
out.push(widthCopyDivergenceDiag(copy.source, copy.target, use.kind, use.text, "declaration", locOf(decl.initializer)));
|
|
164
|
+
}
|
|
165
|
+
// ── key order: a reordered literal that reaches an order observer ───
|
|
166
|
+
// Local flow only: the observer's argument is the literal itself, or a
|
|
167
|
+
// const/let binding initialized with it in the same file. A type that
|
|
168
|
+
// some other value of it is observed elsewhere is not evidence.
|
|
169
|
+
if (observers.length > 0) {
|
|
170
|
+
const reported = new Set();
|
|
171
|
+
for (const expr of observers) {
|
|
172
|
+
let inner = expr;
|
|
173
|
+
while (ts.isParenthesizedExpression(inner) || ts.isAsExpression(inner))
|
|
174
|
+
inner = inner.expression;
|
|
175
|
+
let lit = null;
|
|
176
|
+
let binding = null;
|
|
177
|
+
if (ts.isObjectLiteralExpression(inner))
|
|
178
|
+
lit = inner;
|
|
179
|
+
else if (ts.isIdentifier(inner)) {
|
|
180
|
+
const symbol = safely(() => checker.getSymbolAtLocation(inner));
|
|
181
|
+
const decl = symbol === undefined ? undefined : checker.valueDeclarationOf(symbol);
|
|
182
|
+
if (decl !== undefined &&
|
|
183
|
+
ts.isVariableDeclaration(decl) &&
|
|
184
|
+
decl.initializer !== undefined &&
|
|
185
|
+
ts.isObjectLiteralExpression(decl.initializer) &&
|
|
186
|
+
decl.getSourceFile() === inner.getSourceFile()) {
|
|
187
|
+
lit = decl.initializer;
|
|
188
|
+
binding = inner.text;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
if (lit === null || reported.has(lit) || !literals.includes(lit))
|
|
192
|
+
continue;
|
|
193
|
+
const contextual = safely(() => checker.getContextualType(lit));
|
|
194
|
+
if (contextual === undefined)
|
|
195
|
+
continue;
|
|
196
|
+
if (namedObjectDeclaration(checker, contextual) === null)
|
|
197
|
+
continue;
|
|
198
|
+
const declared = safely(() => checker.getPropertiesOfType(contextual).map((p) => p.name));
|
|
199
|
+
if (declared === undefined)
|
|
200
|
+
continue;
|
|
201
|
+
const written = lit.properties.map((p) => propertyNameText(p));
|
|
202
|
+
const assigned = binding === null ? new Set() : (assignedMembers.get(binding) ?? new Set());
|
|
203
|
+
const finding = keyOrderFinding(lowerer, contextual, declared, written, assigned);
|
|
204
|
+
if (finding === null)
|
|
205
|
+
continue;
|
|
206
|
+
reported.add(lit);
|
|
207
|
+
out.push(keyOrderDivergenceDiag(checker.typeToString(contextual), finding.node, finding.native, finding.detail, locOf(lit)));
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
// ── one-argument localeCompare over text outside the collation table ─
|
|
211
|
+
for (const call of localeCompares) {
|
|
212
|
+
const access = call.expression;
|
|
213
|
+
for (const operand of [access.expression, call.arguments[0]]) {
|
|
214
|
+
const text = stringLiteralText(operand);
|
|
215
|
+
if (text !== null && !isCollationCovered(text)) {
|
|
216
|
+
out.push(localeCompareDivergenceDiag(text, locOf(operand)));
|
|
217
|
+
break;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
// ── downcasts a call provably feeds a sibling class ────────────────
|
|
222
|
+
// `function read(n: Base) { (n as A).x }` called with a `B` (B extends
|
|
223
|
+
// Base, unrelated to A): Node reads the member structurally, natively
|
|
224
|
+
// the checked class cast throws a TypeError.
|
|
225
|
+
const downcasts = new Map();
|
|
226
|
+
for (const cast of casts) {
|
|
227
|
+
let inner = cast.expression;
|
|
228
|
+
while (ts.isParenthesizedExpression(inner))
|
|
229
|
+
inner = inner.expression;
|
|
230
|
+
if (!ts.isIdentifier(inner))
|
|
231
|
+
continue;
|
|
232
|
+
let fn = cast.parent;
|
|
233
|
+
while (fn !== undefined && !ts.isFunctionLike(fn))
|
|
234
|
+
fn = fn.parent;
|
|
235
|
+
if (fn === undefined || !ts.isFunctionLike(fn))
|
|
236
|
+
continue;
|
|
237
|
+
const index = fn.parameters.findIndex((p) => ts.isIdentifier(p.name) && p.name.text === inner.text);
|
|
238
|
+
if (index < 0)
|
|
239
|
+
continue;
|
|
240
|
+
const target = safely(() => classDeclarationOfTypeNode(lowerer, cast.type));
|
|
241
|
+
if (target === undefined || target === null)
|
|
242
|
+
continue;
|
|
243
|
+
// A function that tests the parameter with instanceof guards its casts.
|
|
244
|
+
if (fn.body !== undefined && testsInstanceof(fn.body, inner.text))
|
|
245
|
+
continue;
|
|
246
|
+
// The member read through the cast: `(p as A).member`.
|
|
247
|
+
let use = cast;
|
|
248
|
+
while (use.parent !== undefined && ts.isParenthesizedExpression(use.parent))
|
|
249
|
+
use = use.parent;
|
|
250
|
+
const access = use.parent;
|
|
251
|
+
if (access === undefined || !ts.isPropertyAccessExpression(access) || access.expression !== use)
|
|
252
|
+
continue;
|
|
253
|
+
const list = downcasts.get(fn) ?? [];
|
|
254
|
+
list.push({ index, target, cast, member: access.name.text });
|
|
255
|
+
downcasts.set(fn, list);
|
|
256
|
+
}
|
|
257
|
+
if (downcasts.size > 0) {
|
|
258
|
+
for (const call of calls) {
|
|
259
|
+
const name = calleeName(call);
|
|
260
|
+
if (name === null || !fnsByName.has(name))
|
|
261
|
+
continue;
|
|
262
|
+
const signature = safely(() => checker.getResolvedSignature(call));
|
|
263
|
+
const decl = signature === undefined ? undefined : safely(() => checker.signatureDeclaration(signature));
|
|
264
|
+
const sites = decl === undefined ? undefined : downcasts.get(decl);
|
|
265
|
+
if (sites === undefined)
|
|
266
|
+
continue;
|
|
267
|
+
for (const site of sites) {
|
|
268
|
+
const arg = call.arguments[site.index];
|
|
269
|
+
if (arg === undefined)
|
|
270
|
+
continue;
|
|
271
|
+
const argType = safely(() => checker.getTypeAtLocation(arg));
|
|
272
|
+
const source = argType === undefined ? null : classDeclarationOfType(checker, argType);
|
|
273
|
+
if (source === null || source === site.target)
|
|
274
|
+
continue;
|
|
275
|
+
if (classExtends(lowerer, source, site.target) ||
|
|
276
|
+
classExtends(lowerer, site.target, source))
|
|
277
|
+
continue;
|
|
278
|
+
// Node's structural read succeeds only when the instance has the
|
|
279
|
+
// member; a missing method fails under Node too.
|
|
280
|
+
if (argType === undefined || checker.getPropertyOfType(argType, site.member) === undefined)
|
|
281
|
+
continue;
|
|
282
|
+
out.push(unrelatedClassCastDivergenceDiag(className(source), className(site.target), locOf(arg)));
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
// ── Date strings the native parser does not accept ────────────────
|
|
287
|
+
for (const { call, arg } of dates) {
|
|
288
|
+
const callee = ts.isNewExpression(call)
|
|
289
|
+
? call.expression
|
|
290
|
+
: ts.isPropertyAccessExpression(call.expression)
|
|
291
|
+
? call.expression.expression
|
|
292
|
+
: undefined;
|
|
293
|
+
if (callee === undefined || !lowerer.isStdlibGlobal(callee, "Date"))
|
|
294
|
+
continue;
|
|
295
|
+
for (const literal of dateStringLiterals(checker, arg)) {
|
|
296
|
+
const text = stringLiteralText(literal);
|
|
297
|
+
if (nativeDateParses(text) || !/\d/.test(text))
|
|
298
|
+
continue;
|
|
299
|
+
out.push(dateLiteralDivergenceDiag(text, locOf(literal)));
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
return out;
|
|
303
|
+
}
|
|
304
|
+
/** The string literals a Date argument can be: the literal itself, or
|
|
305
|
+
* each element of a const array of literals a for-of binding iterates. */
|
|
306
|
+
function dateStringLiterals(checker, arg) {
|
|
307
|
+
if (stringLiteralText(arg) !== null)
|
|
308
|
+
return [arg];
|
|
309
|
+
if (!ts.isIdentifier(arg))
|
|
310
|
+
return [];
|
|
311
|
+
const symbol = safely(() => checker.getSymbolAtLocation(arg));
|
|
312
|
+
const decl = symbol === undefined ? undefined : checker.valueDeclarationOf(symbol);
|
|
313
|
+
const list = decl?.parent;
|
|
314
|
+
const loop = list?.parent;
|
|
315
|
+
if (decl === undefined ||
|
|
316
|
+
!ts.isVariableDeclaration(decl) ||
|
|
317
|
+
list === undefined ||
|
|
318
|
+
loop === undefined ||
|
|
319
|
+
!ts.isForOfStatement(loop) ||
|
|
320
|
+
loop.initializer !== list)
|
|
321
|
+
return [];
|
|
322
|
+
let iterated = loop.expression;
|
|
323
|
+
if (ts.isIdentifier(iterated)) {
|
|
324
|
+
const source = safely(() => checker.getSymbolAtLocation(iterated));
|
|
325
|
+
const init = source === undefined ? undefined : checker.valueDeclarationOf(source);
|
|
326
|
+
if (init === undefined || !ts.isVariableDeclaration(init) || init.initializer === undefined)
|
|
327
|
+
return [];
|
|
328
|
+
if (init.parent === undefined || (init.parent.flags & ts.NodeFlags.Const) === 0)
|
|
329
|
+
return [];
|
|
330
|
+
iterated = init.initializer;
|
|
331
|
+
}
|
|
332
|
+
if (!ts.isArrayLiteralExpression(iterated))
|
|
333
|
+
return [];
|
|
334
|
+
return iterated.elements.filter((e) => stringLiteralText(e) !== null);
|
|
335
|
+
}
|
|
336
|
+
/** A checker query that fails here only loses a warning. */
|
|
337
|
+
function safely(f) {
|
|
338
|
+
try {
|
|
339
|
+
return f();
|
|
340
|
+
}
|
|
341
|
+
catch {
|
|
342
|
+
return undefined;
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
function isLiteralLike(node) {
|
|
346
|
+
return (ts.isStringLiteral(node) ||
|
|
347
|
+
ts.isNumericLiteral(node) ||
|
|
348
|
+
ts.isNoSubstitutionTemplateLiteral(node) ||
|
|
349
|
+
ts.isTemplateExpression(node));
|
|
350
|
+
}
|
|
351
|
+
function stringLiteralText(node) {
|
|
352
|
+
if (node === undefined)
|
|
353
|
+
return null;
|
|
354
|
+
if (ts.isStringLiteral(node) || ts.isNoSubstitutionTemplateLiteral(node))
|
|
355
|
+
return node.text;
|
|
356
|
+
return null;
|
|
357
|
+
}
|
|
358
|
+
/** An expression that denotes an object that already exists (and so has
|
|
359
|
+
* other references a copy would not update), not a fresh value. */
|
|
360
|
+
function isExistingObjectExpression(node) {
|
|
361
|
+
while (ts.isParenthesizedExpression(node) || ts.isNonNullExpression(node))
|
|
362
|
+
node = node.expression;
|
|
363
|
+
return (ts.isIdentifier(node) ||
|
|
364
|
+
ts.isPropertyAccessExpression(node) ||
|
|
365
|
+
ts.isElementAccessExpression(node) ||
|
|
366
|
+
node.kind === ts.SyntaxKind.ThisKeyword);
|
|
367
|
+
}
|
|
368
|
+
function isPlainProperty(p) {
|
|
369
|
+
return ((ts.isPropertyAssignment(p) || ts.isShorthandPropertyAssignment(p)) &&
|
|
370
|
+
propertyNameText(p) !== null);
|
|
371
|
+
}
|
|
372
|
+
function propertyNameText(p) {
|
|
373
|
+
if (!ts.isPropertyAssignment(p) && !ts.isShorthandPropertyAssignment(p))
|
|
374
|
+
return null;
|
|
375
|
+
const name = p.name;
|
|
376
|
+
if (ts.isIdentifier(name) || ts.isStringLiteral(name))
|
|
377
|
+
return name.text;
|
|
378
|
+
return null;
|
|
379
|
+
}
|
|
380
|
+
function calleeName(call) {
|
|
381
|
+
const callee = call.expression;
|
|
382
|
+
if (ts.isIdentifier(callee))
|
|
383
|
+
return callee.text;
|
|
384
|
+
if (ts.isPropertyAccessExpression(callee))
|
|
385
|
+
return callee.name.text;
|
|
386
|
+
return null;
|
|
387
|
+
}
|
|
388
|
+
/** The first write through, or identity comparison of, the binding `name`
|
|
389
|
+
* inside `root` (after `from`, when given). Name-based: a nested function
|
|
390
|
+
* that rebinds the name is skipped. */
|
|
391
|
+
function identityUse(root, name, from = -1) {
|
|
392
|
+
let found = null;
|
|
393
|
+
const isRef = (node) => {
|
|
394
|
+
while (ts.isParenthesizedExpression(node) || ts.isNonNullExpression(node))
|
|
395
|
+
node = node.expression;
|
|
396
|
+
return ts.isIdentifier(node) && node.text === name;
|
|
397
|
+
};
|
|
398
|
+
const rootOf = (node) => {
|
|
399
|
+
let cur = node;
|
|
400
|
+
while (ts.isPropertyAccessExpression(cur) || ts.isElementAccessExpression(cur))
|
|
401
|
+
cur = cur.expression;
|
|
402
|
+
return cur;
|
|
403
|
+
};
|
|
404
|
+
const textOf = (node) => {
|
|
405
|
+
const text = node.getText();
|
|
406
|
+
return text.length > 60 ? `${text.slice(0, 57)}...` : text;
|
|
407
|
+
};
|
|
408
|
+
const visit = (node) => {
|
|
409
|
+
if (found !== null)
|
|
410
|
+
return "stop";
|
|
411
|
+
if (node.pos < from)
|
|
412
|
+
return node.end > from ? undefined : "skip";
|
|
413
|
+
if (node !== root &&
|
|
414
|
+
ts.isFunctionLike(node) &&
|
|
415
|
+
node.parameters.some((p) => ts.isIdentifier(p.name) && p.name.text === name))
|
|
416
|
+
return "skip";
|
|
417
|
+
if (ts.isBinaryExpression(node)) {
|
|
418
|
+
const op = node.operatorToken.kind;
|
|
419
|
+
if ((op === ts.SyntaxKind.EqualsEqualsEqualsToken ||
|
|
420
|
+
op === ts.SyntaxKind.ExclamationEqualsEqualsToken ||
|
|
421
|
+
op === ts.SyntaxKind.EqualsEqualsToken ||
|
|
422
|
+
op === ts.SyntaxKind.ExclamationEqualsToken) &&
|
|
423
|
+
(isRef(node.left) || isRef(node.right)) &&
|
|
424
|
+
!isNullish(node.left) &&
|
|
425
|
+
!isNullish(node.right)) {
|
|
426
|
+
found = { kind: "compare", text: textOf(node) };
|
|
427
|
+
return "stop";
|
|
428
|
+
}
|
|
429
|
+
if (op >= ts.SyntaxKind.FirstAssignment &&
|
|
430
|
+
op <= ts.SyntaxKind.LastAssignment &&
|
|
431
|
+
(ts.isPropertyAccessExpression(node.left) || ts.isElementAccessExpression(node.left)) &&
|
|
432
|
+
isRef(rootOf(node.left))) {
|
|
433
|
+
found = { kind: "write", text: textOf(node.left) };
|
|
434
|
+
return "stop";
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
if ((ts.isPrefixUnaryExpression(node) || ts.isPostfixUnaryExpression(node)) &&
|
|
438
|
+
(node.operator === ts.SyntaxKind.PlusPlusToken ||
|
|
439
|
+
node.operator === ts.SyntaxKind.MinusMinusToken) &&
|
|
440
|
+
(ts.isPropertyAccessExpression(node.operand) || ts.isElementAccessExpression(node.operand)) &&
|
|
441
|
+
isRef(rootOf(node.operand))) {
|
|
442
|
+
found = { kind: "write", text: textOf(node.operand) };
|
|
443
|
+
return "stop";
|
|
444
|
+
}
|
|
445
|
+
if (ts.isDeleteExpression(node) &&
|
|
446
|
+
(ts.isPropertyAccessExpression(node.expression) ||
|
|
447
|
+
ts.isElementAccessExpression(node.expression)) &&
|
|
448
|
+
isRef(rootOf(node.expression))) {
|
|
449
|
+
found = { kind: "write", text: textOf(node.expression) };
|
|
450
|
+
return "stop";
|
|
451
|
+
}
|
|
452
|
+
return undefined;
|
|
453
|
+
};
|
|
454
|
+
ts.walkPreorder(root, visit);
|
|
455
|
+
return found;
|
|
456
|
+
}
|
|
457
|
+
function testsInstanceof(root, name) {
|
|
458
|
+
let found = false;
|
|
459
|
+
ts.walkPreorder(root, (node) => {
|
|
460
|
+
if (ts.isBinaryExpression(node) &&
|
|
461
|
+
node.operatorToken.kind === ts.SyntaxKind.InstanceOfKeyword &&
|
|
462
|
+
ts.isIdentifier(node.left) &&
|
|
463
|
+
node.left.text === name) {
|
|
464
|
+
found = true;
|
|
465
|
+
return "stop";
|
|
466
|
+
}
|
|
467
|
+
return undefined;
|
|
468
|
+
});
|
|
469
|
+
return found;
|
|
470
|
+
}
|
|
471
|
+
function isNullish(node) {
|
|
472
|
+
return (node.kind === ts.SyntaxKind.NullKeyword ||
|
|
473
|
+
(ts.isIdentifier(node) && node.text === "undefined") ||
|
|
474
|
+
ts.isVoidExpression(node));
|
|
475
|
+
}
|
|
476
|
+
function enclosingScope(node) {
|
|
477
|
+
let cur = node.parent;
|
|
478
|
+
while (cur !== undefined && !ts.isBlock(cur) && !ts.isSourceFile(cur))
|
|
479
|
+
cur = cur.parent;
|
|
480
|
+
return cur;
|
|
481
|
+
}
|
|
482
|
+
/** A plain-record width copy between the value at `source` and the
|
|
483
|
+
* declared `targetNode` type: both are object types that are not class
|
|
484
|
+
* instances, arrays, functions or built-in containers, and the target's
|
|
485
|
+
* properties are a strict subset of the source's — the shape scriptc
|
|
486
|
+
* compiles as a field copy. */
|
|
487
|
+
function widthCopyBetween(lowerer, source, targetNode) {
|
|
488
|
+
const checker = lowerer.checker;
|
|
489
|
+
const s = checker.getTypeAtLocation(source);
|
|
490
|
+
const t = checker.getTypeFromTypeNode(targetNode);
|
|
491
|
+
if (!isPlainRecordType(checker, s) || !isPlainRecordType(checker, t))
|
|
492
|
+
return null;
|
|
493
|
+
// Accessor members write through to captured state, so a copy of them
|
|
494
|
+
// still observes the same writes: no divergence to report.
|
|
495
|
+
const accessor = ts.SymbolFlags.GetAccessor | ts.SymbolFlags.SetAccessor;
|
|
496
|
+
if (checker.getPropertiesOfType(s).some((p) => (p.flags & accessor) !== 0))
|
|
497
|
+
return null;
|
|
498
|
+
const sourceProps = new Set(checker.getPropertiesOfType(s).map((p) => p.name));
|
|
499
|
+
const targetProps = checker.getPropertiesOfType(t).map((p) => p.name);
|
|
500
|
+
if (targetProps.length === 0 || targetProps.length >= sourceProps.size)
|
|
501
|
+
return null;
|
|
502
|
+
if (!targetProps.every((p) => sourceProps.has(p)))
|
|
503
|
+
return null;
|
|
504
|
+
return { source: checker.typeToString(s), target: checker.typeToString(t) };
|
|
505
|
+
}
|
|
506
|
+
function isPlainRecordType(checker, type) {
|
|
507
|
+
if ((type.flags & ts.TypeFlags.Object) === 0)
|
|
508
|
+
return false;
|
|
509
|
+
if (checker.isArrayType(type) || checker.isTupleType(type))
|
|
510
|
+
return false;
|
|
511
|
+
if (checker.getCallSignatures(type).length > 0)
|
|
512
|
+
return false;
|
|
513
|
+
if (checker.getConstructSignatures(type).length > 0)
|
|
514
|
+
return false;
|
|
515
|
+
if (checker.getIndexInfosOfType(type).length > 0)
|
|
516
|
+
return false;
|
|
517
|
+
const symbol = type.getSymbol();
|
|
518
|
+
if (symbol !== undefined && (symbol.flags & ts.SymbolFlags.Class) !== 0)
|
|
519
|
+
return false;
|
|
520
|
+
// Library-declared object types (Map, Date, Promise, ...) are not records.
|
|
521
|
+
const decls = symbol === undefined ? [] : checker.declarationsOf(symbol);
|
|
522
|
+
if (decls.some((d) => d.getSourceFile().isDeclarationFile))
|
|
523
|
+
return false;
|
|
524
|
+
return true;
|
|
525
|
+
}
|
|
526
|
+
/** The interface/type-alias/literal declaration that names an object type,
|
|
527
|
+
* or null for anything else (classes keep their own layout rules). */
|
|
528
|
+
function namedObjectDeclaration(checker, type) {
|
|
529
|
+
if ((type.flags & ts.TypeFlags.Object) === 0)
|
|
530
|
+
return null;
|
|
531
|
+
const alias = type.getAliasSymbol();
|
|
532
|
+
const symbol = alias ?? type.getSymbol();
|
|
533
|
+
if (symbol === undefined)
|
|
534
|
+
return null;
|
|
535
|
+
if ((symbol.flags & ts.SymbolFlags.Class) !== 0)
|
|
536
|
+
return null;
|
|
537
|
+
const decl = checker.declarationsOf(symbol)[0];
|
|
538
|
+
if (decl === undefined || decl.getSourceFile().isDeclarationFile)
|
|
539
|
+
return null;
|
|
540
|
+
return decl;
|
|
541
|
+
}
|
|
542
|
+
function keyOrderFinding(lowerer, contextual, declared, written, assignedNames) {
|
|
543
|
+
const present = declared.filter((name) => written.includes(name));
|
|
544
|
+
const writtenKnown = written.filter((name) => declared.includes(name));
|
|
545
|
+
if (present.join("\0") !== writtenKnown.join("\0") && writtenKnown.length >= 2) {
|
|
546
|
+
return { native: present.join(", "), node: writtenKnown.join(", "), detail: "reordered" };
|
|
547
|
+
}
|
|
548
|
+
// An optional property the literal leaves out but the program assigns
|
|
549
|
+
// later: Node appends it after the literal's keys; natively it keeps its
|
|
550
|
+
// declared slot ahead of them.
|
|
551
|
+
const checker = lowerer.checker;
|
|
552
|
+
for (let i = 0; i < declared.length; i++) {
|
|
553
|
+
const name = declared[i];
|
|
554
|
+
if (written.includes(name) || !assignedNames.has(name))
|
|
555
|
+
continue;
|
|
556
|
+
if (!declared.slice(i + 1).some((later) => written.includes(later)))
|
|
557
|
+
continue;
|
|
558
|
+
const prop = checker.getPropertyOfType(contextual, name);
|
|
559
|
+
if (prop === undefined || (prop.flags & ts.SymbolFlags.Optional) === 0)
|
|
560
|
+
continue;
|
|
561
|
+
const nodeOrder = [...writtenKnown, name];
|
|
562
|
+
const nativeOrder = declared.filter((d) => nodeOrder.includes(d));
|
|
563
|
+
return { native: nativeOrder.join(", "), node: nodeOrder.join(", "), detail: "added-later" };
|
|
564
|
+
}
|
|
565
|
+
return null;
|
|
566
|
+
}
|
|
567
|
+
function classDeclarationOfTypeNode(lowerer, node) {
|
|
568
|
+
if (!ts.isTypeReferenceNode(node) || !ts.isIdentifier(node.typeName))
|
|
569
|
+
return null;
|
|
570
|
+
const symbol = lowerer.checker.getSymbolAtLocation(node.typeName);
|
|
571
|
+
if (symbol === undefined || (symbol.flags & ts.SymbolFlags.Class) === 0)
|
|
572
|
+
return null;
|
|
573
|
+
const decl = lowerer.checker
|
|
574
|
+
.declarationsOf(symbol)
|
|
575
|
+
.find((d) => ts.isClassDeclaration(d) || ts.isClassExpression(d));
|
|
576
|
+
if (decl === undefined || decl.getSourceFile().isDeclarationFile)
|
|
577
|
+
return null;
|
|
578
|
+
return decl;
|
|
579
|
+
}
|
|
580
|
+
function classDeclarationOfType(checker, type) {
|
|
581
|
+
const symbol = type.getSymbol();
|
|
582
|
+
if (symbol === undefined || (symbol.flags & ts.SymbolFlags.Class) === 0)
|
|
583
|
+
return null;
|
|
584
|
+
const decl = checker
|
|
585
|
+
.declarationsOf(symbol)
|
|
586
|
+
.find((d) => ts.isClassDeclaration(d) || ts.isClassExpression(d));
|
|
587
|
+
if (decl === undefined || decl.getSourceFile().isDeclarationFile)
|
|
588
|
+
return null;
|
|
589
|
+
return decl;
|
|
590
|
+
}
|
|
591
|
+
/** Whether `sub` names `base` in its (transitive) extends chain. */
|
|
592
|
+
function classExtends(lowerer, sub, base) {
|
|
593
|
+
let cur = sub;
|
|
594
|
+
for (let guard = 0; cur !== null && guard < 64; guard++) {
|
|
595
|
+
if (cur === base)
|
|
596
|
+
return true;
|
|
597
|
+
const heritage = cur.heritageClauses?.find((h) => h.token === ts.SyntaxKind.ExtendsKeyword);
|
|
598
|
+
const expr = heritage?.types[0]?.expression;
|
|
599
|
+
if (expr === undefined)
|
|
600
|
+
return false;
|
|
601
|
+
const symbol = lowerer.checker.getSymbolAtLocation(expr);
|
|
602
|
+
if (symbol === undefined)
|
|
603
|
+
return false;
|
|
604
|
+
const resolved = (symbol.flags & ts.SymbolFlags.Alias) !== 0
|
|
605
|
+
? lowerer.checker.getAliasedSymbol(symbol)
|
|
606
|
+
: symbol;
|
|
607
|
+
const decl = lowerer.checker
|
|
608
|
+
.declarationsOf(resolved)
|
|
609
|
+
.find((d) => ts.isClassDeclaration(d) || ts.isClassExpression(d));
|
|
610
|
+
cur = decl === undefined ? null : decl;
|
|
611
|
+
}
|
|
612
|
+
return false;
|
|
613
|
+
}
|
|
614
|
+
function className(decl) {
|
|
615
|
+
return decl.name?.text ?? "(anonymous class)";
|
|
616
|
+
}
|
|
617
|
+
const MONTHS = ["jan", "feb", "mar", "apr", "may", "jun", "jul", "aug", "sep", "oct", "nov", "dec"];
|
|
618
|
+
/** The date-string grammar the native runtime accepts (scr_lib.c
|
|
619
|
+
* scr_date_parse_get_time): ECMAScript's date-time format with an explicit
|
|
620
|
+
* offset (date-only forms are UTC) and the certificate-time shape
|
|
621
|
+
* "Mon DD HH:MM:SS YYYY GMT". Everything else parses to NaN natively. */
|
|
622
|
+
export function nativeDateParses(text) {
|
|
623
|
+
const iso = /^(?:[+-]\d{6}|\d{4})(?:-(\d{2})(?:-(\d{2}))?)?$/.test(text) ||
|
|
624
|
+
/^(?:[+-]\d{6}|\d{4})-\d{2}-\d{2}T\d{2}:\d{2}(?::\d{2}(?:\.\d{3})?)?(?:Z|[+-]\d{2}:\d{2})$/.test(text);
|
|
625
|
+
if (iso)
|
|
626
|
+
return true;
|
|
627
|
+
const cert = /^([A-Za-z]{3}) {1,2}\d{1,2} \d{2}:\d{2}:\d{2} \d{4} GMT$/.exec(text);
|
|
628
|
+
return cert !== null && MONTHS.includes(cert[1].toLowerCase());
|
|
629
|
+
}
|
|
630
|
+
//# sourceMappingURL=divergences.js.map
|