@sunshaobei/dsh-workflow 0.0.0-stage → 2.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +43 -2
- package/cordis.patch.yml +17 -0
- package/lib/client.js +14708 -0
- package/lib/core.js +137 -0
- package/lib/engine-adapter.js +1387 -0
- package/lib/host-driver.js +298 -0
- package/lib/index.js +536 -0
- package/lib/projection.js +159 -0
- package/lib/registry.js +218 -0
- package/lib/session-records.js +54 -0
- package/lib/submission-commit.js +34 -0
- package/lib/world-driver.js +275 -0
- package/package.json +67 -4
- package/vendor/PROVENANCE.md +9 -0
- package/vendor/dynamic-workflow/analysis/actor-graph.d.ts +47 -0
- package/vendor/dynamic-workflow/analysis/actor-graph.d.ts.map +1 -0
- package/vendor/dynamic-workflow/analysis/actor-graph.js +95 -0
- package/vendor/dynamic-workflow/analysis/actor-models.d.ts +60 -0
- package/vendor/dynamic-workflow/analysis/actor-models.d.ts.map +1 -0
- package/vendor/dynamic-workflow/analysis/actor-models.js +208 -0
- package/vendor/dynamic-workflow/analysis/actor-names.d.ts +56 -0
- package/vendor/dynamic-workflow/analysis/actor-names.d.ts.map +1 -0
- package/vendor/dynamic-workflow/analysis/actor-names.js +155 -0
- package/vendor/dynamic-workflow/analysis/analyze.d.ts +63 -0
- package/vendor/dynamic-workflow/analysis/analyze.d.ts.map +1 -0
- package/vendor/dynamic-workflow/analysis/analyze.js +92 -0
- package/vendor/dynamic-workflow/analysis/array-methods.d.ts +21 -0
- package/vendor/dynamic-workflow/analysis/array-methods.d.ts.map +1 -0
- package/vendor/dynamic-workflow/analysis/array-methods.js +132 -0
- package/vendor/dynamic-workflow/analysis/artifact-types.d.ts +39 -0
- package/vendor/dynamic-workflow/analysis/artifact-types.d.ts.map +1 -0
- package/vendor/dynamic-workflow/analysis/artifact-types.js +114 -0
- package/vendor/dynamic-workflow/analysis/artifacts.d.ts +67 -0
- package/vendor/dynamic-workflow/analysis/artifacts.d.ts.map +1 -0
- package/vendor/dynamic-workflow/analysis/artifacts.js +263 -0
- package/vendor/dynamic-workflow/analysis/assign.d.ts +42 -0
- package/vendor/dynamic-workflow/analysis/assign.d.ts.map +1 -0
- package/vendor/dynamic-workflow/analysis/assign.js +287 -0
- package/vendor/dynamic-workflow/analysis/callbacks.d.ts +71 -0
- package/vendor/dynamic-workflow/analysis/callbacks.d.ts.map +1 -0
- package/vendor/dynamic-workflow/analysis/callbacks.js +133 -0
- package/vendor/dynamic-workflow/analysis/calls.d.ts +40 -0
- package/vendor/dynamic-workflow/analysis/calls.d.ts.map +1 -0
- package/vendor/dynamic-workflow/analysis/calls.js +495 -0
- package/vendor/dynamic-workflow/analysis/causality-graph-lanes.d.ts +25 -0
- package/vendor/dynamic-workflow/analysis/causality-graph-lanes.d.ts.map +1 -0
- package/vendor/dynamic-workflow/analysis/causality-graph-lanes.js +161 -0
- package/vendor/dynamic-workflow/analysis/causality-graph-types.d.ts +163 -0
- package/vendor/dynamic-workflow/analysis/causality-graph-types.d.ts.map +1 -0
- package/vendor/dynamic-workflow/analysis/causality-graph-types.js +8 -0
- package/vendor/dynamic-workflow/analysis/causality-graph.d.ts +39 -0
- package/vendor/dynamic-workflow/analysis/causality-graph.d.ts.map +1 -0
- package/vendor/dynamic-workflow/analysis/causality-graph.js +530 -0
- package/vendor/dynamic-workflow/analysis/causality-order-calls.d.ts +29 -0
- package/vendor/dynamic-workflow/analysis/causality-order-calls.d.ts.map +1 -0
- package/vendor/dynamic-workflow/analysis/causality-order-calls.js +266 -0
- package/vendor/dynamic-workflow/analysis/causality-order-functions.d.ts +26 -0
- package/vendor/dynamic-workflow/analysis/causality-order-functions.d.ts.map +1 -0
- package/vendor/dynamic-workflow/analysis/causality-order-functions.js +116 -0
- package/vendor/dynamic-workflow/analysis/causality-order-loops.d.ts +5 -0
- package/vendor/dynamic-workflow/analysis/causality-order-loops.d.ts.map +1 -0
- package/vendor/dynamic-workflow/analysis/causality-order-loops.js +148 -0
- package/vendor/dynamic-workflow/analysis/causality-order-settle.d.ts +39 -0
- package/vendor/dynamic-workflow/analysis/causality-order-settle.d.ts.map +1 -0
- package/vendor/dynamic-workflow/analysis/causality-order-settle.js +263 -0
- package/vendor/dynamic-workflow/analysis/causality-order-state.d.ts +110 -0
- package/vendor/dynamic-workflow/analysis/causality-order-state.d.ts.map +1 -0
- package/vendor/dynamic-workflow/analysis/causality-order-state.js +162 -0
- package/vendor/dynamic-workflow/analysis/causality-order-strands.d.ts +79 -0
- package/vendor/dynamic-workflow/analysis/causality-order-strands.d.ts.map +1 -0
- package/vendor/dynamic-workflow/analysis/causality-order-strands.js +154 -0
- package/vendor/dynamic-workflow/analysis/causality-order-types.d.ts +174 -0
- package/vendor/dynamic-workflow/analysis/causality-order-types.d.ts.map +1 -0
- package/vendor/dynamic-workflow/analysis/causality-order-types.js +1 -0
- package/vendor/dynamic-workflow/analysis/causality-order-walk.d.ts +17 -0
- package/vendor/dynamic-workflow/analysis/causality-order-walk.d.ts.map +1 -0
- package/vendor/dynamic-workflow/analysis/causality-order-walk.js +282 -0
- package/vendor/dynamic-workflow/analysis/causality-order.d.ts +60 -0
- package/vendor/dynamic-workflow/analysis/causality-order.d.ts.map +1 -0
- package/vendor/dynamic-workflow/analysis/causality-order.js +110 -0
- package/vendor/dynamic-workflow/analysis/causality-reduce.d.ts +60 -0
- package/vendor/dynamic-workflow/analysis/causality-reduce.d.ts.map +1 -0
- package/vendor/dynamic-workflow/analysis/causality-reduce.js +198 -0
- package/vendor/dynamic-workflow/analysis/classes.d.ts +47 -0
- package/vendor/dynamic-workflow/analysis/classes.d.ts.map +1 -0
- package/vendor/dynamic-workflow/analysis/classes.js +264 -0
- package/vendor/dynamic-workflow/analysis/constants.d.ts +35 -0
- package/vendor/dynamic-workflow/analysis/constants.d.ts.map +1 -0
- package/vendor/dynamic-workflow/analysis/constants.js +23 -0
- package/vendor/dynamic-workflow/analysis/control-flow.d.ts +26 -0
- package/vendor/dynamic-workflow/analysis/control-flow.d.ts.map +1 -0
- package/vendor/dynamic-workflow/analysis/control-flow.js +132 -0
- package/vendor/dynamic-workflow/analysis/core-json.d.ts +45 -0
- package/vendor/dynamic-workflow/analysis/core-json.d.ts.map +1 -0
- package/vendor/dynamic-workflow/analysis/core-json.js +49 -0
- package/vendor/dynamic-workflow/analysis/core.d.ts +194 -0
- package/vendor/dynamic-workflow/analysis/core.d.ts.map +1 -0
- package/vendor/dynamic-workflow/analysis/core.js +204 -0
- package/vendor/dynamic-workflow/analysis/domain.d.ts +269 -0
- package/vendor/dynamic-workflow/analysis/domain.d.ts.map +1 -0
- package/vendor/dynamic-workflow/analysis/domain.js +523 -0
- package/vendor/dynamic-workflow/analysis/facade-misuse.d.ts +56 -0
- package/vendor/dynamic-workflow/analysis/facade-misuse.d.ts.map +1 -0
- package/vendor/dynamic-workflow/analysis/facade-misuse.js +350 -0
- package/vendor/dynamic-workflow/analysis/fanout-cardinality.d.ts +11 -0
- package/vendor/dynamic-workflow/analysis/fanout-cardinality.d.ts.map +1 -0
- package/vendor/dynamic-workflow/analysis/fanout-cardinality.js +121 -0
- package/vendor/dynamic-workflow/analysis/flow-graph.d.ts +113 -0
- package/vendor/dynamic-workflow/analysis/flow-graph.d.ts.map +1 -0
- package/vendor/dynamic-workflow/analysis/flow-graph.js +411 -0
- package/vendor/dynamic-workflow/analysis/flow-phase.d.ts +28 -0
- package/vendor/dynamic-workflow/analysis/flow-phase.d.ts.map +1 -0
- package/vendor/dynamic-workflow/analysis/flow-phase.js +104 -0
- package/vendor/dynamic-workflow/analysis/flow-strands.d.ts +39 -0
- package/vendor/dynamic-workflow/analysis/flow-strands.d.ts.map +1 -0
- package/vendor/dynamic-workflow/analysis/flow-strands.js +47 -0
- package/vendor/dynamic-workflow/analysis/flow-tree.d.ts +35 -0
- package/vendor/dynamic-workflow/analysis/flow-tree.d.ts.map +1 -0
- package/vendor/dynamic-workflow/analysis/flow-tree.js +33 -0
- package/vendor/dynamic-workflow/analysis/graph.d.ts +5 -0
- package/vendor/dynamic-workflow/analysis/graph.d.ts.map +1 -0
- package/vendor/dynamic-workflow/analysis/graph.js +199 -0
- package/vendor/dynamic-workflow/analysis/handoff-graph.d.ts +48 -0
- package/vendor/dynamic-workflow/analysis/handoff-graph.d.ts.map +1 -0
- package/vendor/dynamic-workflow/analysis/handoff-graph.js +0 -0
- package/vendor/dynamic-workflow/analysis/heap-ops.d.ts +14 -0
- package/vendor/dynamic-workflow/analysis/heap-ops.d.ts.map +1 -0
- package/vendor/dynamic-workflow/analysis/heap-ops.js +70 -0
- package/vendor/dynamic-workflow/analysis/hole-id.d.ts +28 -0
- package/vendor/dynamic-workflow/analysis/hole-id.d.ts.map +1 -0
- package/vendor/dynamic-workflow/analysis/hole-id.js +41 -0
- package/vendor/dynamic-workflow/analysis/hole-sites.d.ts +32 -0
- package/vendor/dynamic-workflow/analysis/hole-sites.d.ts.map +1 -0
- package/vendor/dynamic-workflow/analysis/hole-sites.js +215 -0
- package/vendor/dynamic-workflow/analysis/hole-splice.d.ts +45 -0
- package/vendor/dynamic-workflow/analysis/hole-splice.d.ts.map +1 -0
- package/vendor/dynamic-workflow/analysis/hole-splice.js +100 -0
- package/vendor/dynamic-workflow/analysis/interpret.d.ts +26 -0
- package/vendor/dynamic-workflow/analysis/interpret.d.ts.map +1 -0
- package/vendor/dynamic-workflow/analysis/interpret.js +200 -0
- package/vendor/dynamic-workflow/analysis/literals.d.ts +18 -0
- package/vendor/dynamic-workflow/analysis/literals.d.ts.map +1 -0
- package/vendor/dynamic-workflow/analysis/literals.js +125 -0
- package/vendor/dynamic-workflow/analysis/mermaid.d.ts +60 -0
- package/vendor/dynamic-workflow/analysis/mermaid.d.ts.map +1 -0
- package/vendor/dynamic-workflow/analysis/mermaid.js +477 -0
- package/vendor/dynamic-workflow/analysis/patterns.d.ts +31 -0
- package/vendor/dynamic-workflow/analysis/patterns.d.ts.map +1 -0
- package/vendor/dynamic-workflow/analysis/patterns.js +94 -0
- package/vendor/dynamic-workflow/analysis/phase-graph.d.ts +47 -0
- package/vendor/dynamic-workflow/analysis/phase-graph.d.ts.map +1 -0
- package/vendor/dynamic-workflow/analysis/phase-graph.js +334 -0
- package/vendor/dynamic-workflow/analysis/phases.d.ts +24 -0
- package/vendor/dynamic-workflow/analysis/phases.d.ts.map +1 -0
- package/vendor/dynamic-workflow/analysis/phases.js +54 -0
- package/vendor/dynamic-workflow/analysis/promise-ops.d.ts +52 -0
- package/vendor/dynamic-workflow/analysis/promise-ops.d.ts.map +1 -0
- package/vendor/dynamic-workflow/analysis/promise-ops.js +123 -0
- package/vendor/dynamic-workflow/analysis/relays.d.ts +12 -0
- package/vendor/dynamic-workflow/analysis/relays.d.ts.map +1 -0
- package/vendor/dynamic-workflow/analysis/relays.js +78 -0
- package/vendor/dynamic-workflow/analysis/serialize.d.ts +125 -0
- package/vendor/dynamic-workflow/analysis/serialize.d.ts.map +1 -0
- package/vendor/dynamic-workflow/analysis/serialize.js +321 -0
- package/vendor/dynamic-workflow/analysis/site-phases.d.ts +32 -0
- package/vendor/dynamic-workflow/analysis/site-phases.d.ts.map +1 -0
- package/vendor/dynamic-workflow/analysis/site-phases.js +69 -0
- package/vendor/dynamic-workflow/analysis/sites-labels.d.ts +71 -0
- package/vendor/dynamic-workflow/analysis/sites-labels.d.ts.map +1 -0
- package/vendor/dynamic-workflow/analysis/sites-labels.js +189 -0
- package/vendor/dynamic-workflow/analysis/sites.d.ts +267 -0
- package/vendor/dynamic-workflow/analysis/sites.d.ts.map +1 -0
- package/vendor/dynamic-workflow/analysis/sites.js +225 -0
- package/vendor/dynamic-workflow/analysis/state.d.ts +254 -0
- package/vendor/dynamic-workflow/analysis/state.d.ts.map +1 -0
- package/vendor/dynamic-workflow/analysis/state.js +569 -0
- package/vendor/dynamic-workflow/analysis/taint.d.ts +97 -0
- package/vendor/dynamic-workflow/analysis/taint.d.ts.map +1 -0
- package/vendor/dynamic-workflow/analysis/taint.js +649 -0
- package/vendor/dynamic-workflow/analysis/types.d.ts +100 -0
- package/vendor/dynamic-workflow/analysis/types.d.ts.map +1 -0
- package/vendor/dynamic-workflow/analysis/types.js +1 -0
- package/vendor/dynamic-workflow/analysis/world-run.d.ts +27 -0
- package/vendor/dynamic-workflow/analysis/world-run.d.ts.map +1 -0
- package/vendor/dynamic-workflow/analysis/world-run.js +44 -0
- package/vendor/dynamic-workflow/compiler/compile.d.ts +59 -0
- package/vendor/dynamic-workflow/compiler/compile.d.ts.map +1 -0
- package/vendor/dynamic-workflow/compiler/compile.js +159 -0
- package/vendor/dynamic-workflow/compiler/libs.generated.d.ts +3 -0
- package/vendor/dynamic-workflow/compiler/libs.generated.d.ts.map +1 -0
- package/vendor/dynamic-workflow/compiler/libs.generated.js +64 -0
- package/vendor/dynamic-workflow/engine/artifact-spec.d.ts +26 -0
- package/vendor/dynamic-workflow/engine/artifact-spec.d.ts.map +1 -0
- package/vendor/dynamic-workflow/engine/artifact-spec.js +173 -0
- package/vendor/dynamic-workflow/engine/ask-observation-types.d.ts +54 -0
- package/vendor/dynamic-workflow/engine/ask-observation-types.d.ts.map +1 -0
- package/vendor/dynamic-workflow/engine/ask-observation-types.js +19 -0
- package/vendor/dynamic-workflow/engine/cached-ask-facts.d.ts +28 -0
- package/vendor/dynamic-workflow/engine/cached-ask-facts.d.ts.map +1 -0
- package/vendor/dynamic-workflow/engine/cached-ask-facts.js +35 -0
- package/vendor/dynamic-workflow/engine/concurrency.d.ts +151 -0
- package/vendor/dynamic-workflow/engine/concurrency.d.ts.map +1 -0
- package/vendor/dynamic-workflow/engine/concurrency.js +282 -0
- package/vendor/dynamic-workflow/engine/engine-artifacts-primary.d.ts +17 -0
- package/vendor/dynamic-workflow/engine/engine-artifacts-primary.d.ts.map +1 -0
- package/vendor/dynamic-workflow/engine/engine-artifacts-primary.js +29 -0
- package/vendor/dynamic-workflow/engine/engine-artifacts.d.ts +55 -0
- package/vendor/dynamic-workflow/engine/engine-artifacts.d.ts.map +1 -0
- package/vendor/dynamic-workflow/engine/engine-artifacts.js +367 -0
- package/vendor/dynamic-workflow/engine/engine-config.d.ts +90 -0
- package/vendor/dynamic-workflow/engine/engine-config.d.ts.map +1 -0
- package/vendor/dynamic-workflow/engine/engine-config.js +6 -0
- package/vendor/dynamic-workflow/engine/engine-holes.d.ts +116 -0
- package/vendor/dynamic-workflow/engine/engine-holes.d.ts.map +1 -0
- package/vendor/dynamic-workflow/engine/engine-holes.js +142 -0
- package/vendor/dynamic-workflow/engine/engine-launch.d.ts +34 -0
- package/vendor/dynamic-workflow/engine/engine-launch.d.ts.map +1 -0
- package/vendor/dynamic-workflow/engine/engine-launch.js +26 -0
- package/vendor/dynamic-workflow/engine/engine-phase-stamp.d.ts +35 -0
- package/vendor/dynamic-workflow/engine/engine-phase-stamp.d.ts.map +1 -0
- package/vendor/dynamic-workflow/engine/engine-phase-stamp.js +74 -0
- package/vendor/dynamic-workflow/engine/engine-report.d.ts +27 -0
- package/vendor/dynamic-workflow/engine/engine-report.d.ts.map +1 -0
- package/vendor/dynamic-workflow/engine/engine-report.js +151 -0
- package/vendor/dynamic-workflow/engine/engine-resume.d.ts +18 -0
- package/vendor/dynamic-workflow/engine/engine-resume.d.ts.map +1 -0
- package/vendor/dynamic-workflow/engine/engine-resume.js +38 -0
- package/vendor/dynamic-workflow/engine/engine-settlement.d.ts +30 -0
- package/vendor/dynamic-workflow/engine/engine-settlement.d.ts.map +1 -0
- package/vendor/dynamic-workflow/engine/engine-settlement.js +79 -0
- package/vendor/dynamic-workflow/engine/engine-state.d.ts +99 -0
- package/vendor/dynamic-workflow/engine/engine-state.d.ts.map +1 -0
- package/vendor/dynamic-workflow/engine/engine-state.js +13 -0
- package/vendor/dynamic-workflow/engine/engine-world.d.ts +36 -0
- package/vendor/dynamic-workflow/engine/engine-world.d.ts.map +1 -0
- package/vendor/dynamic-workflow/engine/engine-world.js +189 -0
- package/vendor/dynamic-workflow/engine/engine.d.ts +263 -0
- package/vendor/dynamic-workflow/engine/engine.d.ts.map +1 -0
- package/vendor/dynamic-workflow/engine/engine.js +602 -0
- package/vendor/dynamic-workflow/engine/errors.d.ts +87 -0
- package/vendor/dynamic-workflow/engine/errors.d.ts.map +1 -0
- package/vendor/dynamic-workflow/engine/errors.js +56 -0
- package/vendor/dynamic-workflow/engine/hash-mismatch.d.ts +10 -0
- package/vendor/dynamic-workflow/engine/hash-mismatch.d.ts.map +1 -0
- package/vendor/dynamic-workflow/engine/hash-mismatch.js +15 -0
- package/vendor/dynamic-workflow/engine/hash.d.ts +16 -0
- package/vendor/dynamic-workflow/engine/hash.d.ts.map +1 -0
- package/vendor/dynamic-workflow/engine/hash.js +48 -0
- package/vendor/dynamic-workflow/engine/imported-cache-types.d.ts +96 -0
- package/vendor/dynamic-workflow/engine/imported-cache-types.d.ts.map +1 -0
- package/vendor/dynamic-workflow/engine/imported-cache-types.js +6 -0
- package/vendor/dynamic-workflow/engine/imported-cache.d.ts +127 -0
- package/vendor/dynamic-workflow/engine/imported-cache.d.ts.map +1 -0
- package/vendor/dynamic-workflow/engine/imported-cache.js +244 -0
- package/vendor/dynamic-workflow/engine/index.d.ts +11 -0
- package/vendor/dynamic-workflow/engine/index.d.ts.map +1 -0
- package/vendor/dynamic-workflow/engine/index.js +10 -0
- package/vendor/dynamic-workflow/engine/journal-memory.d.ts +32 -0
- package/vendor/dynamic-workflow/engine/journal-memory.d.ts.map +1 -0
- package/vendor/dynamic-workflow/engine/journal-memory.js +243 -0
- package/vendor/dynamic-workflow/engine/journal-read-types.d.ts +72 -0
- package/vendor/dynamic-workflow/engine/journal-read-types.d.ts.map +1 -0
- package/vendor/dynamic-workflow/engine/journal-read-types.js +28 -0
- package/vendor/dynamic-workflow/engine/persona.d.ts +20 -0
- package/vendor/dynamic-workflow/engine/persona.d.ts.map +1 -0
- package/vendor/dynamic-workflow/engine/persona.js +43 -0
- package/vendor/dynamic-workflow/engine/replay-order.d.ts +96 -0
- package/vendor/dynamic-workflow/engine/replay-order.d.ts.map +1 -0
- package/vendor/dynamic-workflow/engine/replay-order.js +229 -0
- package/vendor/dynamic-workflow/engine/run-terminal.d.ts +35 -0
- package/vendor/dynamic-workflow/engine/run-terminal.d.ts.map +1 -0
- package/vendor/dynamic-workflow/engine/run-terminal.js +7 -0
- package/vendor/dynamic-workflow/engine/scheduler-submit.d.ts +22 -0
- package/vendor/dynamic-workflow/engine/scheduler-submit.d.ts.map +1 -0
- package/vendor/dynamic-workflow/engine/scheduler-submit.js +84 -0
- package/vendor/dynamic-workflow/engine/scheduler-types.d.ts +105 -0
- package/vendor/dynamic-workflow/engine/scheduler-types.d.ts.map +1 -0
- package/vendor/dynamic-workflow/engine/scheduler-types.js +17 -0
- package/vendor/dynamic-workflow/engine/scheduler.d.ts +113 -0
- package/vendor/dynamic-workflow/engine/scheduler.d.ts.map +1 -0
- package/vendor/dynamic-workflow/engine/scheduler.js +484 -0
- package/vendor/dynamic-workflow/engine/types.d.ts +979 -0
- package/vendor/dynamic-workflow/engine/types.d.ts.map +1 -0
- package/vendor/dynamic-workflow/engine/types.js +26 -0
- package/vendor/dynamic-workflow/engine/world-read-input.d.ts +10 -0
- package/vendor/dynamic-workflow/engine/world-read-input.d.ts.map +1 -0
- package/vendor/dynamic-workflow/engine/world-read-input.js +55 -0
- package/vendor/dynamic-workflow/facade/artifact-caps.d.ts +48 -0
- package/vendor/dynamic-workflow/facade/artifact-caps.d.ts.map +1 -0
- package/vendor/dynamic-workflow/facade/artifact-caps.js +47 -0
- package/vendor/dynamic-workflow/facade/dts-hole.d.ts +16 -0
- package/vendor/dynamic-workflow/facade/dts-hole.d.ts.map +1 -0
- package/vendor/dynamic-workflow/facade/dts-hole.js +26 -0
- package/vendor/dynamic-workflow/facade/dts-model.d.ts +11 -0
- package/vendor/dynamic-workflow/facade/dts-model.d.ts.map +1 -0
- package/vendor/dynamic-workflow/facade/dts-model.js +18 -0
- package/vendor/dynamic-workflow/facade/dts-stream.d.ts +15 -0
- package/vendor/dynamic-workflow/facade/dts-stream.d.ts.map +1 -0
- package/vendor/dynamic-workflow/facade/dts-stream.js +41 -0
- package/vendor/dynamic-workflow/facade/dts.d.ts +29 -0
- package/vendor/dynamic-workflow/facade/dts.d.ts.map +1 -0
- package/vendor/dynamic-workflow/facade/dts.js +324 -0
- package/vendor/dynamic-workflow/facade/registry.d.ts +218 -0
- package/vendor/dynamic-workflow/facade/registry.d.ts.map +1 -0
- package/vendor/dynamic-workflow/facade/registry.js +203 -0
- package/vendor/dynamic-workflow/facade/report-caps.d.ts +40 -0
- package/vendor/dynamic-workflow/facade/report-caps.d.ts.map +1 -0
- package/vendor/dynamic-workflow/facade/report-caps.js +39 -0
- package/vendor/dynamic-workflow/facade/world-read-caps.d.ts +37 -0
- package/vendor/dynamic-workflow/facade/world-read-caps.d.ts.map +1 -0
- package/vendor/dynamic-workflow/facade/world-read-caps.js +36 -0
- package/vendor/dynamic-workflow/index.d.ts +41 -0
- package/vendor/dynamic-workflow/index.d.ts.map +1 -0
- package/vendor/dynamic-workflow/index.js +51 -0
- package/vendor/dynamic-workflow/lowering/index.d.ts +2 -0
- package/vendor/dynamic-workflow/lowering/index.d.ts.map +1 -0
- package/vendor/dynamic-workflow/lowering/index.js +1 -0
- package/vendor/dynamic-workflow/lowering/lower-hole.d.ts +16 -0
- package/vendor/dynamic-workflow/lowering/lower-hole.d.ts.map +1 -0
- package/vendor/dynamic-workflow/lowering/lower-hole.js +63 -0
- package/vendor/dynamic-workflow/lowering/lower.d.ts +82 -0
- package/vendor/dynamic-workflow/lowering/lower.d.ts.map +1 -0
- package/vendor/dynamic-workflow/lowering/lower.js +333 -0
- package/vendor/dynamic-workflow/projections.d.ts +26 -0
- package/vendor/dynamic-workflow/projections.d.ts.map +1 -0
- package/vendor/dynamic-workflow/projections.js +23 -0
- package/vendor/dynamic-workflow/schema/actor-submit-profiles.d.ts +49 -0
- package/vendor/dynamic-workflow/schema/actor-submit-profiles.d.ts.map +1 -0
- package/vendor/dynamic-workflow/schema/actor-submit-profiles.js +69 -0
- package/vendor/dynamic-workflow/schema/emit.d.ts +55 -0
- package/vendor/dynamic-workflow/schema/emit.d.ts.map +1 -0
- package/vendor/dynamic-workflow/schema/emit.js +325 -0
- package/vendor/dynamic-workflow/schema/jsdoc.d.ts +10 -0
- package/vendor/dynamic-workflow/schema/jsdoc.d.ts.map +1 -0
- package/vendor/dynamic-workflow/schema/jsdoc.js +83 -0
- package/vendor/dynamic-workflow/schema/serialize.d.ts +8 -0
- package/vendor/dynamic-workflow/schema/serialize.d.ts.map +1 -0
- package/vendor/dynamic-workflow/schema/serialize.js +20 -0
- package/vendor/dynamic-workflow/schema/synthesize.d.ts +48 -0
- package/vendor/dynamic-workflow/schema/synthesize.d.ts.map +1 -0
- package/vendor/dynamic-workflow/schema/synthesize.js +138 -0
- package/vendor/dynamic-workflow/schema/types.d.ts +67 -0
- package/vendor/dynamic-workflow/schema/types.d.ts.map +1 -0
- package/vendor/dynamic-workflow/schema/types.js +18 -0
- package/vendor/dynamic-workflow/schema/validate.d.ts +15 -0
- package/vendor/dynamic-workflow/schema/validate.d.ts.map +1 -0
- package/vendor/dynamic-workflow/schema/validate.js +213 -0
- package/vendor/dynamic-workflow/testing/index.d.ts +6 -0
- package/vendor/dynamic-workflow/testing/index.d.ts.map +1 -0
- package/vendor/dynamic-workflow/testing/index.js +5 -0
- package/vendor/dynamic-workflow/testing/journal-contract-artifacts.d.ts +9 -0
- package/vendor/dynamic-workflow/testing/journal-contract-artifacts.d.ts.map +1 -0
- package/vendor/dynamic-workflow/testing/journal-contract-artifacts.js +195 -0
- package/vendor/dynamic-workflow/testing/journal-contract-events.d.ts +9 -0
- package/vendor/dynamic-workflow/testing/journal-contract-events.d.ts.map +1 -0
- package/vendor/dynamic-workflow/testing/journal-contract-events.js +163 -0
- package/vendor/dynamic-workflow/testing/journal-contract-helpers.d.ts +9 -0
- package/vendor/dynamic-workflow/testing/journal-contract-helpers.d.ts.map +1 -0
- package/vendor/dynamic-workflow/testing/journal-contract-helpers.js +12 -0
- package/vendor/dynamic-workflow/testing/journal-contract-isolation.d.ts +9 -0
- package/vendor/dynamic-workflow/testing/journal-contract-isolation.d.ts.map +1 -0
- package/vendor/dynamic-workflow/testing/journal-contract-isolation.js +46 -0
- package/vendor/dynamic-workflow/testing/journal-contract-nodes.d.ts +9 -0
- package/vendor/dynamic-workflow/testing/journal-contract-nodes.d.ts.map +1 -0
- package/vendor/dynamic-workflow/testing/journal-contract-nodes.js +234 -0
- package/vendor/dynamic-workflow/testing/journal-contract-reads.d.ts +11 -0
- package/vendor/dynamic-workflow/testing/journal-contract-reads.d.ts.map +1 -0
- package/vendor/dynamic-workflow/testing/journal-contract-reads.js +281 -0
- package/vendor/dynamic-workflow/testing/journal-contract-runs.d.ts +9 -0
- package/vendor/dynamic-workflow/testing/journal-contract-runs.d.ts.map +1 -0
- package/vendor/dynamic-workflow/testing/journal-contract-runs.js +396 -0
- package/vendor/dynamic-workflow/testing/journal-contract-script.d.ts +12 -0
- package/vendor/dynamic-workflow/testing/journal-contract-script.d.ts.map +1 -0
- package/vendor/dynamic-workflow/testing/journal-contract-script.js +82 -0
- package/vendor/dynamic-workflow/testing/journal-contract.d.ts +15 -0
- package/vendor/dynamic-workflow/testing/journal-contract.d.ts.map +1 -0
- package/vendor/dynamic-workflow/testing/journal-contract.js +31 -0
- package/vendor/dynamic-workflow-runtime/child-cell-streams.js +128 -0
- package/vendor/dynamic-workflow-runtime/child-entry-file.js +43 -0
- package/vendor/dynamic-workflow-runtime/child-source.js +299 -0
- package/vendor/dynamic-workflow-runtime/harness.js +302 -0
- package/vendor/dynamic-workflow-runtime/index.js +4 -0
- package/vendor/dynamic-workflow-runtime/protocol.js +2 -0
- package/vendor/mcode-host/dynamic-workflow-import.js +269 -0
- package/vendor/mcode-host/workflow-git-world-read.js +183 -0
- package/vendor/mcode-host/workflow-world-read.js +282 -0
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 产物(artifact)的编译期收集与诊断。
|
|
3
|
+
*
|
|
4
|
+
* ⚠ 术语:本模块的 artifact 是**用户面产物**——脚本经 `artifact.*` 发布给用户看的文件 /
|
|
5
|
+
* markdown / 预置看板。同目录下的 `artifact-types.ts` 说的是**另一个** artifact:站点的
|
|
6
|
+
* 类型化输出值(给模型看的)。两者不相干。
|
|
7
|
+
*
|
|
8
|
+
* 产物两件:
|
|
9
|
+
*
|
|
10
|
+
* 1. `declaredArtifacts`(编译产物,照 `collectWorldRunCommands` 的 `commands`):脚本声明的
|
|
11
|
+
* 产物清单 `[{id, kind}]`,去重、按 id 排序。中枢与检视器据它在**运行前**就能说出这个
|
|
12
|
+
* 工作流会产出什么。
|
|
13
|
+
* 2. 定位诊断(facade-misuse 同族):id 必须是编译期字面量,标签必须指向一个已声明的预置,
|
|
14
|
+
* 同一个 id 不能横跨两个成员种类,预置声明不该长在循环体 / 回调 / 条件分支里。
|
|
15
|
+
*
|
|
16
|
+
* 为什么 id 必须是编译期字面量(与 `world.run` 的 cmd、`phase` 的 name 同一姿态):一个运行期
|
|
17
|
+
* 才成形的 id 没有可展示的对象——它既进不了「将产出」清单,也让「同 id 两种种类」这类规则
|
|
18
|
+
* 只剩运行期一条路。教改写发生在便宜的那一侧。
|
|
19
|
+
*
|
|
20
|
+
* 与运行期的分工:这一趟只做**字面量能看穿的那一半**。真正的门在引擎——`ArtifactKindMismatch`
|
|
21
|
+
* /`ArtifactRedeclared`/`ArtifactUndeclared`/`ArtifactCapExceeded` 都在运行期兜底,因为
|
|
22
|
+
* 声明的**执行顺序**(哪个先跑到)静态看不出来。所以本模块**只会漏报、不会误报**,
|
|
23
|
+
* 唯一的例外是提升诊断(见 {@link ARTIFACT_HOISTING_CODE})。
|
|
24
|
+
*/
|
|
25
|
+
import ts from "typescript";
|
|
26
|
+
import { ARTIFACT_CAPS, ARTIFACT_ID_PATTERN } from "../facade/artifact-caps.js";
|
|
27
|
+
import { isArtifactPresetOp } from "../facade/registry.js";
|
|
28
|
+
import { findWorkflowBody } from "./sites.js";
|
|
29
|
+
/**
|
|
30
|
+
* 产物的编译期诊断码(9001 = facade-siting、9002 = schema、9003 = world-run、9004 = phase、
|
|
31
|
+
* 9005/9006 = actor 名,顺延)。覆盖:非字面量 / 空 / 超长 / 非法字符的 id、同 id 跨种类复用、
|
|
32
|
+
* `report` 标签的三种错法。全部是**静态确定**的错误——没有一条会误伤一份合法脚本。
|
|
33
|
+
*/
|
|
34
|
+
export const ARTIFACT_DECLARATION_CODE = 9007;
|
|
35
|
+
/**
|
|
36
|
+
* 预置声明长在循环体 / 回调 / 条件分支里(「声明提到顶层,一次即可」),单独一个码而不是
|
|
37
|
+
* 复用 9007,理由与 9005/9006 的分家完全相同:**确定性不同**。
|
|
38
|
+
*
|
|
39
|
+
* 循环里以**相同 spec** 重复声明在运行期其实是幂等 no-op,所以这条子句理论上会误报。接受它
|
|
40
|
+
* 的理由是代价不对称——修复是免费的(把声明挪到脚本顶部),而不报的代价是一个看板声明藏在
|
|
41
|
+
* 第三层回调里,读者要跑一遍才知道它到底声明了没有。读端(fixture 语料、未来的宽松档)
|
|
42
|
+
* 因此需要能把它与 9007 区分开,而按错误文本分流是本仓库处处禁止的。
|
|
43
|
+
*/
|
|
44
|
+
export const ARTIFACT_HOISTING_CODE = 9008;
|
|
45
|
+
/**
|
|
46
|
+
* 两个**不同的** id 都写了字面量 `primary: true`。
|
|
47
|
+
* 与 9008 同一种确定性:互斥分支里各标一个在运行期跑得通,但卡与侧板只会带头一个交付物,
|
|
48
|
+
* 说不清哪个是的脚本没写完。只认字面量 `true`;算出来的旗子留给引擎的 `ArtifactPrimaryConflict`。
|
|
49
|
+
*/
|
|
50
|
+
export const ARTIFACT_PRIMARY_CONFLICT_CODE = 9009;
|
|
51
|
+
const HOISTING_MESSAGE = {
|
|
52
|
+
callback: "a preset artifact declared inside a callback: hoist it to the top level and declare it once. " +
|
|
53
|
+
"A preset is a declaration, not a step — it says how the items tagged with its id are drawn, " +
|
|
54
|
+
"and the tagged report() calls are what fill it in. Declaring it where the callback runs " +
|
|
55
|
+
'buries it: move artifact.<kind>("<id>", spec) to the head of the script and keep only ' +
|
|
56
|
+
'report(item, "<id>") in the callback.',
|
|
57
|
+
conditional: "a preset artifact declared inside a conditional branch: hoist it to the top level and declare " +
|
|
58
|
+
"it once. The card should exist from the moment the run starts (it is legitimately empty until " +
|
|
59
|
+
"the first tagged report arrives), and a declaration that may or may not have run is a card " +
|
|
60
|
+
"that may or may not exist. Declare it unconditionally and let the branch decide what to report.",
|
|
61
|
+
loop: "a preset artifact declared inside a loop: hoist it to the top level and declare it once. " +
|
|
62
|
+
"A preset is declared once and fed many times — the loop body is where report(item, \"<id>\") " +
|
|
63
|
+
"belongs, not the declaration. Re-declaring the same spec is a no-op, but re-declaring it with " +
|
|
64
|
+
"a different spec fails the whole run, so the loop is the wrong place for it either way.",
|
|
65
|
+
};
|
|
66
|
+
const NON_LITERAL_ID_MESSAGE = "an artifact id must be a compile-time string literal (\"report\" or a no-substitution template): " +
|
|
67
|
+
"the set of artifacts a run can publish is fixed when the script is submitted, so it can be listed " +
|
|
68
|
+
"before anything runs. Write the id inline; put the runtime value in the title instead " +
|
|
69
|
+
'(artifact.file("report", path, { title: `Report for ${name}` })).';
|
|
70
|
+
const EMPTY_ID_MESSAGE = "an artifact id must not be empty: it is the identity the card, the version history and the " +
|
|
71
|
+
'report tag all key off. Give it a short stable name ("book", "perf", "coverage").';
|
|
72
|
+
/**
|
|
73
|
+
* 收集产物清单与诊断。非空诊断即脚本不可提交(`analyzeWorkflowScript` 与 world.run / phase /
|
|
74
|
+
* actor 名的编译期规则同席)。
|
|
75
|
+
*/
|
|
76
|
+
export function collectArtifactDeclarations(workflow, table) {
|
|
77
|
+
const diagnostics = [];
|
|
78
|
+
const push = (code, loc, message) => {
|
|
79
|
+
diagnostics.push({ code, column: loc.column, line: loc.line, message });
|
|
80
|
+
};
|
|
81
|
+
const locOf = (node) => workflow.toScriptLoc(node.getStart(workflow.scriptFile));
|
|
82
|
+
const body = findWorkflowBody(workflow.scriptFile);
|
|
83
|
+
/** 已补全留白的函数体:不是回调,提升诊断看穿它们(见 {@link hoistingContextOf})。 */
|
|
84
|
+
const holeBodies = new Set(table.holes.flatMap((hole) => hole.body ?? []));
|
|
85
|
+
/** id → 第一个用它的站点(种类冲突时用来指认前一处)。 */
|
|
86
|
+
const claimed = new Map();
|
|
87
|
+
/** 第一个写了字面量 `primary: true` 的站点;第二个不同 id 再写就是 9009。 */
|
|
88
|
+
let primaryClaim;
|
|
89
|
+
const declared = [];
|
|
90
|
+
for (const site of table.artifacts) {
|
|
91
|
+
// id 的诊断落在**出问题的那个表达式**上(缺席时退回站点位置,同 world-run 的处理:
|
|
92
|
+
// 元数错误由类型检查先拦,但诊断收集不该依赖那条推断)。
|
|
93
|
+
const idLoc = site.artifactIdExpr === undefined ? site.loc : locOf(site.artifactIdExpr);
|
|
94
|
+
if (site.artifactId === undefined) {
|
|
95
|
+
push(ARTIFACT_DECLARATION_CODE, idLoc, NON_LITERAL_ID_MESSAGE);
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
const id = site.artifactId;
|
|
99
|
+
if (id === "") {
|
|
100
|
+
push(ARTIFACT_DECLARATION_CODE, idLoc, EMPTY_ID_MESSAGE);
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
if (id.length > ARTIFACT_CAPS.maxIdLength) {
|
|
104
|
+
push(ARTIFACT_DECLARATION_CODE, idLoc, `artifact id "${id}" is ${id.length} characters; the limit is ${ARTIFACT_CAPS.maxIdLength}. ` +
|
|
105
|
+
"The id is a key, not a description — put the prose in the title.");
|
|
106
|
+
continue;
|
|
107
|
+
}
|
|
108
|
+
if (!ARTIFACT_ID_PATTERN.test(id)) {
|
|
109
|
+
push(ARTIFACT_DECLARATION_CODE, idLoc, `artifact id "${id}" contains characters outside [A-Za-z0-9_.-]. The id is carried verbatim ` +
|
|
110
|
+
"through the journal, the artifact store and the side pane, so it is restricted to " +
|
|
111
|
+
'characters that need no escaping anywhere ("build-log", "perf.p95").');
|
|
112
|
+
continue;
|
|
113
|
+
}
|
|
114
|
+
// 跨成员种类复用(诊断 4):诊断落在**后一处**——先出现的那个种类是既有事实。
|
|
115
|
+
const first = claimed.get(id);
|
|
116
|
+
if (first === undefined) {
|
|
117
|
+
claimed.set(id, site);
|
|
118
|
+
declared.push({ id, kind: site.op });
|
|
119
|
+
}
|
|
120
|
+
else if (first.op !== site.op) {
|
|
121
|
+
push(ARTIFACT_DECLARATION_CODE, site.loc, `artifact id "${id}" is used with two different kinds: artifact.${first.op} on line ` +
|
|
122
|
+
`${first.loc.line} and artifact.${site.op} here. Within one run an id belongs to exactly ` +
|
|
123
|
+
"one kind — publishing it again is what mints the next VERSION, and a version cannot " +
|
|
124
|
+
"change what the thing is. Give this one its own id.");
|
|
125
|
+
}
|
|
126
|
+
// 交付物唯一(9009):诊断落在**后一处**的 `primary` 属性上——先标的那个是既有事实。
|
|
127
|
+
const primaryNode = primaryLiteralOf(site);
|
|
128
|
+
if (primaryNode !== undefined) {
|
|
129
|
+
if (primaryClaim === undefined)
|
|
130
|
+
primaryClaim = { id, site };
|
|
131
|
+
else if (primaryClaim.id !== id) {
|
|
132
|
+
push(ARTIFACT_PRIMARY_CONFLICT_CODE, locOf(primaryNode), `artifact "${id}" is marked primary, but "${primaryClaim.id}" already is (artifact.` +
|
|
133
|
+
`${primaryClaim.site.op} on line ${primaryClaim.site.loc.line}). A run has one ` +
|
|
134
|
+
"deliverable — the card and the run pane lead with it. Drop primary from one of them, " +
|
|
135
|
+
"or publish this content as a new version of the other id.");
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
// 提升诊断(预置族专属):内容成员反而**常常**该出现在循环 / 条件里(每轮发布一版、
|
|
139
|
+
// 失败时补一版),所以这条子句绝不能扩到那一族。
|
|
140
|
+
if (isArtifactPresetOp(site.op)) {
|
|
141
|
+
const context = hoistingContextOf(site.call, body, holeBodies);
|
|
142
|
+
if (context !== undefined) {
|
|
143
|
+
push(ARTIFACT_HOISTING_CODE, site.loc, HOISTING_MESSAGE[context]);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
// 已声明的**预置** id(标签的合法目标集)与内容 id,两张表分开:标签指向内容 id 有专门
|
|
148
|
+
// 的一条文案(它不是「没这个东西」,而是「这个东西没有数据面」)。
|
|
149
|
+
const presetIds = declared.filter((entry) => isArtifactPresetOp(entry.kind)).map((e) => e.id);
|
|
150
|
+
const contentIds = new Set(declared.filter((entry) => !isArtifactPresetOp(entry.kind)).map((e) => e.id));
|
|
151
|
+
for (const site of table.reports) {
|
|
152
|
+
if (site.artifactIdExpr === undefined)
|
|
153
|
+
continue; // 无标签的 report 照旧
|
|
154
|
+
const tagLoc = locOf(site.artifactIdExpr);
|
|
155
|
+
if (site.artifactId === undefined) {
|
|
156
|
+
push(ARTIFACT_DECLARATION_CODE, tagLoc, "report()'s artifact tag must be a compile-time string literal naming a preset artifact " +
|
|
157
|
+
"declared in this script: the tag is how an item finds its dashboard, and a tag that only " +
|
|
158
|
+
"exists at run time cannot be checked against the declarations. Write the id inline.");
|
|
159
|
+
continue;
|
|
160
|
+
}
|
|
161
|
+
const tag = site.artifactId;
|
|
162
|
+
if (presetIds.includes(tag))
|
|
163
|
+
continue;
|
|
164
|
+
if (contentIds.has(tag)) {
|
|
165
|
+
push(ARTIFACT_DECLARATION_CODE, tagLoc, `report()'s tag "${tag}" names a file/markdown artifact, which holds content rather than a ` +
|
|
166
|
+
"stream of items — there is nothing for this item to become. Tag the item with a preset " +
|
|
167
|
+
"artifact (chart / table / metrics / board), or drop the tag and let the item go to the " +
|
|
168
|
+
"run's Results.");
|
|
169
|
+
continue;
|
|
170
|
+
}
|
|
171
|
+
push(ARTIFACT_DECLARATION_CODE, tagLoc, `report()'s tag "${tag}" names no preset artifact declared in this script${describePresets(presetIds)}. ` +
|
|
172
|
+
'Declare it first — artifact.chart("' +
|
|
173
|
+
tag +
|
|
174
|
+
'", { x, y }) at the top of the script — or drop the tag.');
|
|
175
|
+
}
|
|
176
|
+
return { declaredArtifacts: sortDeclared(declared), diagnostics };
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* 站点 opts / spec 实参里字面量写着 `primary: true` 的那个属性;没有、不是对象字面量、不是
|
|
180
|
+
* 字面量 `true`(算出来的、展开进来的)都算没有——那一半留给引擎。
|
|
181
|
+
*/
|
|
182
|
+
function primaryLiteralOf(site) {
|
|
183
|
+
const arg = site.call.arguments[isArtifactPresetOp(site.op) ? 1 : 2];
|
|
184
|
+
if (arg === undefined || !ts.isObjectLiteralExpression(arg))
|
|
185
|
+
return undefined;
|
|
186
|
+
for (const property of arg.properties) {
|
|
187
|
+
if (!ts.isPropertyAssignment(property))
|
|
188
|
+
continue;
|
|
189
|
+
const name = property.name;
|
|
190
|
+
const key = ts.isIdentifier(name) || ts.isStringLiteral(name) ? name.text : undefined;
|
|
191
|
+
if (key !== "primary")
|
|
192
|
+
continue;
|
|
193
|
+
return property.initializer.kind === ts.SyntaxKind.TrueKeyword ? property : undefined;
|
|
194
|
+
}
|
|
195
|
+
return undefined;
|
|
196
|
+
}
|
|
197
|
+
/** 「已声明的预置有:…」的尾巴;一个都没有时说得更直白。 */
|
|
198
|
+
function describePresets(presetIds) {
|
|
199
|
+
if (presetIds.length === 0)
|
|
200
|
+
return " (this script declares no preset artifacts at all)";
|
|
201
|
+
return ` (declared presets: ${[...presetIds].sort().map((id) => `"${id}"`).join(", ")})`;
|
|
202
|
+
}
|
|
203
|
+
/** 去重(同 id 同种类只留一条)、按 id 字典序。 */
|
|
204
|
+
function sortDeclared(declared) {
|
|
205
|
+
const seen = new Set();
|
|
206
|
+
const unique = [];
|
|
207
|
+
for (const entry of declared) {
|
|
208
|
+
const key = `${entry.id}${entry.kind}`;
|
|
209
|
+
if (seen.has(key))
|
|
210
|
+
continue;
|
|
211
|
+
seen.add(key);
|
|
212
|
+
unique.push(entry);
|
|
213
|
+
}
|
|
214
|
+
return unique.sort((a, b) => (a.id === b.id ? a.kind.localeCompare(b.kind) : a.id < b.id ? -1 : 1));
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* 该调用**词法上**待在哪种不该待的位置里,从调用向外走到脚本体为止;都不是则 undefined。
|
|
218
|
+
* 报最内层的那一个:它离作者要改的那一行最近,文案也最具体。
|
|
219
|
+
*
|
|
220
|
+
* 刻意**不**把普通函数声明算作回调:`function setup() { artifact.chart(...) }` 后跟一次
|
|
221
|
+
* `setup()` 是一份合法的顶层声明,只是换了个写法。箭头函数与函数表达式则几乎总是回调
|
|
222
|
+
* (`.map(...)`、`.then(...)`),所以它们算。代价是「在具名 helper 里声明、而 helper 被
|
|
223
|
+
* 循环调用」这一形状漏报——那是漏报方向,与本模块的保守取向一致(引擎的
|
|
224
|
+
* `ArtifactRedeclared` 仍然兜底)。
|
|
225
|
+
*
|
|
226
|
+
* 已补全留白的函数体(`holeBodies`)**不算**回调:它被拼在留白所在的位置、每次到达跑一遍,与
|
|
227
|
+
* 周围的语句同级,所以这里看穿它,继续往外找——留白自己待在循环 / 分支里时照样报。
|
|
228
|
+
* 修复原因(2026-09-29 testfield 实测):此前一切箭头都算回调,补全体恰好是箭头,于是没有一次
|
|
229
|
+
* 补全能为它写下的那一段声明看板,主代理只能放弃。
|
|
230
|
+
*/
|
|
231
|
+
function hoistingContextOf(call, body, holeBodies) {
|
|
232
|
+
let child = call;
|
|
233
|
+
for (let node = call.parent; node !== undefined; node = node.parent) {
|
|
234
|
+
if (node === body)
|
|
235
|
+
return undefined;
|
|
236
|
+
if (holeBodies.has(node)) {
|
|
237
|
+
child = node;
|
|
238
|
+
continue;
|
|
239
|
+
}
|
|
240
|
+
if (ts.isArrowFunction(node) || ts.isFunctionExpression(node) || ts.isMethodDeclaration(node)) {
|
|
241
|
+
return "callback";
|
|
242
|
+
}
|
|
243
|
+
if (ts.isForStatement(node) ||
|
|
244
|
+
ts.isForOfStatement(node) ||
|
|
245
|
+
ts.isForInStatement(node) ||
|
|
246
|
+
ts.isWhileStatement(node) ||
|
|
247
|
+
ts.isDoStatement(node)) {
|
|
248
|
+
return "loop";
|
|
249
|
+
}
|
|
250
|
+
// if / ternary:只有**分支**算条件位置,条件表达式本身不算——`if (artifact.chart(...))`
|
|
251
|
+
// 无条件求值,它的问题是别的(一个 void 当条件用),不该借这条文案说。
|
|
252
|
+
if (ts.isIfStatement(node) && (node.thenStatement === child || node.elseStatement === child)) {
|
|
253
|
+
return "conditional";
|
|
254
|
+
}
|
|
255
|
+
if (ts.isConditionalExpression(node) && (node.whenTrue === child || node.whenFalse === child)) {
|
|
256
|
+
return "conditional";
|
|
257
|
+
}
|
|
258
|
+
if (ts.isCaseClause(node) || ts.isDefaultClause(node))
|
|
259
|
+
return "conditional";
|
|
260
|
+
child = node;
|
|
261
|
+
}
|
|
262
|
+
return undefined;
|
|
263
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import ts from "typescript";
|
|
2
|
+
import { type AbstractValue } from "./domain.js";
|
|
3
|
+
import { type EvalContext, type Evaluator } from "./taint.js";
|
|
4
|
+
/**
|
|
5
|
+
* Assignment transfer rules: plain `=`, compound / logical assignments (`+=`, `||=`,
|
|
6
|
+
* `??=`, …), and destructuring assignment EXPRESSIONS (`[a, b] = xs`, `({ x } = o)`).
|
|
7
|
+
* These live apart from the core evaluator (taint.ts) but operate on the same
|
|
8
|
+
* `Evaluator` instance.
|
|
9
|
+
*/
|
|
10
|
+
/** `target = value`: bind the target (destructuring pattern or lvalue), yield value. */
|
|
11
|
+
export declare function handleAssignment(ev: Evaluator, node: ts.BinaryExpression, ctx: EvalContext): AbstractValue;
|
|
12
|
+
/**
|
|
13
|
+
* `x += rhs` (and every compound / logical assignment): weak-merge the RHS into the
|
|
14
|
+
* target through the same paths as plain assignment (gen-only has no kills, so the
|
|
15
|
+
* old value stays), and yield the union of the target's prior value and the RHS.
|
|
16
|
+
* evalBinary special-cased only `=`, so `+=`/`||=`/`??=`/… computed the value
|
|
17
|
+
* but never wrote it back — the target kept its pre-op taint.
|
|
18
|
+
*/
|
|
19
|
+
export declare function handleCompoundAssignment(ev: Evaluator, node: ts.BinaryExpression, ctx: EvalContext): AbstractValue;
|
|
20
|
+
/**
|
|
21
|
+
* Bind a for-in / for-of loop variable to `value` through the EXISTING binding machinery
|
|
22
|
+
* (no parallel path): the declaration form (`for (const k … )`) routes through bindPattern,
|
|
23
|
+
* the assignment form (`for (k … )` or a destructuring assignment target) through
|
|
24
|
+
* bindAssignmentTarget. The loop value is derived (not a place), so value semantics — no
|
|
25
|
+
* aliasing sourcePlace. Previously for-of bound only the declaration form and
|
|
26
|
+
* for-in bound nothing at all, dropping element / key taint into every read
|
|
27
|
+
* of the loop variable.
|
|
28
|
+
*/
|
|
29
|
+
export declare function bindForInitializer(ev: Evaluator, initializer: ts.ForInitializer, value: AbstractValue, ctx: EvalContext): void;
|
|
30
|
+
/**
|
|
31
|
+
* Weak-merge `collapse(value)` into the leftmost identifier of a member-access chain.
|
|
32
|
+
* A nested assignment target (`a.b.c = x`, `a[i].f = x`) has a member-access
|
|
33
|
+
* receiver rather than a plain identifier, so the field-sensitive branches above find
|
|
34
|
+
* no `receiverSymbol` and used to drop x's taint silently. Folding into the root symbol
|
|
35
|
+
* is a field-insensitive over-approximation, which a may-flow analysis must prefer over
|
|
36
|
+
* under-approximating (dropping) the flow. Shared with the heap-mutator transfer
|
|
37
|
+
* (heap-ops.ts), whose unresolvable receivers fall back the same way. A chain rooted in
|
|
38
|
+
* a non-identifier (a call result: `log().push(x)`) still has no slot to fold into — the
|
|
39
|
+
* known residual of the place model (function returns are summaries, not heap objects).
|
|
40
|
+
*/
|
|
41
|
+
export declare function mergeIntoRootIdentifier(ev: Evaluator, expr: ts.Expression, value: AbstractValue): void;
|
|
42
|
+
//# sourceMappingURL=assign.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"assign.d.ts","sourceRoot":"","sources":["../../src/analysis/assign.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,YAAY,CAAC;AAC5B,OAAO,EAOL,KAAK,aAAa,EACnB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,KAAK,WAAW,EAAE,KAAK,SAAS,EAAE,MAAM,YAAY,CAAC;AAE9D;;;;;GAKG;AAEH,wFAAwF;AACxF,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,EAAE,CAAC,gBAAgB,EAAE,GAAG,EAAE,WAAW,GAAG,aAAa,CAgB1G;AAED;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,EAAE,CAAC,gBAAgB,EAAE,GAAG,EAAE,WAAW,GAAG,aAAa,CAMlH;AAwJD;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAChC,EAAE,EAAE,SAAS,EACb,WAAW,EAAE,EAAE,CAAC,cAAc,EAC9B,KAAK,EAAE,aAAa,EACpB,GAAG,EAAE,WAAW,GACf,IAAI,CAON;AA4BD;;;;;;;;;;GAUG;AACH,wBAAgB,uBAAuB,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,EAAE,CAAC,UAAU,EAAE,KAAK,EAAE,aAAa,GAAG,IAAI,CAiBtG"}
|
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
import ts from "typescript";
|
|
2
|
+
import { collapse, liveField, mergeInto, replayMayAliasWrite, staticIndexKey, unionValues, } from "./domain.js";
|
|
3
|
+
/**
|
|
4
|
+
* Assignment transfer rules: plain `=`, compound / logical assignments (`+=`, `||=`,
|
|
5
|
+
* `??=`, …), and destructuring assignment EXPRESSIONS (`[a, b] = xs`, `({ x } = o)`).
|
|
6
|
+
* These live apart from the core evaluator (taint.ts) but operate on the same
|
|
7
|
+
* `Evaluator` instance.
|
|
8
|
+
*/
|
|
9
|
+
/** `target = value`: bind the target (destructuring pattern or lvalue), yield value. */
|
|
10
|
+
export function handleAssignment(ev, node, ctx) {
|
|
11
|
+
const value = ev.evalExpr(node.right, ctx);
|
|
12
|
+
// When the RHS is a place, the assignment aliases (shares the live reference) rather
|
|
13
|
+
// than snapshotting, so a later write through either side is seen through both. For a
|
|
14
|
+
// destructuring target the place is the source each element aliases a live field of.
|
|
15
|
+
const rhsPlace = ev.resolvePlace(node.right);
|
|
16
|
+
const target = peelParens(node.left);
|
|
17
|
+
// Destructuring assignment expressions bind exactly like destructuring declarations.
|
|
18
|
+
// Previously handleAssignment matched only identifier/property/element
|
|
19
|
+
// targets, so these bound nothing (bindPattern was wired only to declarations/for-of).
|
|
20
|
+
if (ts.isArrayLiteralExpression(target) || ts.isObjectLiteralExpression(target)) {
|
|
21
|
+
bindAssignmentPattern(ev, target, value, ctx, rhsPlace);
|
|
22
|
+
return value;
|
|
23
|
+
}
|
|
24
|
+
writeTarget(ev, target, value, ctx, rhsPlace);
|
|
25
|
+
return value;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* `x += rhs` (and every compound / logical assignment): weak-merge the RHS into the
|
|
29
|
+
* target through the same paths as plain assignment (gen-only has no kills, so the
|
|
30
|
+
* old value stays), and yield the union of the target's prior value and the RHS.
|
|
31
|
+
* evalBinary special-cased only `=`, so `+=`/`||=`/`??=`/… computed the value
|
|
32
|
+
* but never wrote it back — the target kept its pre-op taint.
|
|
33
|
+
*/
|
|
34
|
+
export function handleCompoundAssignment(ev, node, ctx) {
|
|
35
|
+
const rhs = ev.evalExpr(node.right, ctx);
|
|
36
|
+
const prior = ev.evalExpr(node.left, ctx);
|
|
37
|
+
// A read-modify-write keeps the target's own identity (no aliasing): merge, not adopt.
|
|
38
|
+
writeTarget(ev, peelParens(node.left), rhs, ctx);
|
|
39
|
+
return unionValues(prior, rhs);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Weak-merge (or alias, when `rhsPlace` is given) `value` into an assignment target.
|
|
43
|
+
* Property / element receivers are resolved to their LIVE value via `resolvePlace`, so
|
|
44
|
+
* `wrap.o.f = t`, `arr[0].f = t`, and writes through extracted sub-objects mutate the
|
|
45
|
+
* SHARED field object — visible through every alias. Unresolvable receivers (a computed
|
|
46
|
+
* index somewhere in the chain) fall back to smearing into the root identifier.
|
|
47
|
+
*/
|
|
48
|
+
function writeTarget(ev, target, value, ctx, rhsPlace) {
|
|
49
|
+
if (ts.isIdentifier(target)) {
|
|
50
|
+
const sym = ev.checker.getSymbolAtLocation(target);
|
|
51
|
+
if (sym !== undefined)
|
|
52
|
+
ev.s.bindSymbol(sym, rhsPlace ?? value);
|
|
53
|
+
}
|
|
54
|
+
else if (ts.isPropertyAccessExpression(target)) {
|
|
55
|
+
const recv = ev.resolvePlace(target.expression, true);
|
|
56
|
+
if (recv !== undefined)
|
|
57
|
+
writeField(ev, recv, target.name.text, value, rhsPlace);
|
|
58
|
+
else
|
|
59
|
+
mergeIntoRootIdentifier(ev, target.expression, value);
|
|
60
|
+
recordSetterWrite(ev, target.name.text, value);
|
|
61
|
+
}
|
|
62
|
+
else if (ts.isElementAccessExpression(target)) {
|
|
63
|
+
const key = staticIndexKey(target.argumentExpression);
|
|
64
|
+
const recv = ev.resolvePlace(target.expression, true);
|
|
65
|
+
if (key !== undefined) {
|
|
66
|
+
// Static index: field-sensitive write into the live container (aliasing if a place).
|
|
67
|
+
if (recv !== undefined)
|
|
68
|
+
writeField(ev, recv, key, value, rhsPlace);
|
|
69
|
+
else
|
|
70
|
+
mergeIntoRootIdentifier(ev, target.expression, value);
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
// Computed index: the key expression must be evaluated (a facade sink can sit in it, e.g.
|
|
74
|
+
// `o[await ask()] = v`) AND its taint becomes an observable property NAME (surfaced by
|
|
75
|
+
// `for..in` / `Object.keys`, "strings launder nothing"), so it joins the container
|
|
76
|
+
// alongside the value. Previously the key was never evaluated and its taint never
|
|
77
|
+
// recorded, so both the sink and the key-derived flow were dropped.
|
|
78
|
+
const keyTaint = collapse(ev.evalExpr(target.argumentExpression, ctx));
|
|
79
|
+
if (recv !== undefined) {
|
|
80
|
+
if (mergeInto(recv, keyTaint))
|
|
81
|
+
ev.s.changed = true;
|
|
82
|
+
if (mergeInto(recv, collapse(value)))
|
|
83
|
+
ev.s.changed = true;
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
mergeIntoRootIdentifier(ev, target.expression, keyTaint);
|
|
87
|
+
mergeIntoRootIdentifier(ev, target.expression, value);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Write a value into a live container field. A place RHS ADOPTS the shared reference
|
|
93
|
+
* when the field slot is fresh (so the field and the RHS name are one aliased object);
|
|
94
|
+
* an existing slot or a non-place value weak-merges. Mirrors bindSymbol's adopt-vs-merge.
|
|
95
|
+
*/
|
|
96
|
+
function writeField(ev, container, key, value, rhsPlace) {
|
|
97
|
+
if (rhsPlace !== undefined && !container.fields.has(key)) {
|
|
98
|
+
container.fields.set(key, rhsPlace);
|
|
99
|
+
ev.s.changed = true;
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
const field = liveField(container, key);
|
|
103
|
+
if (field !== (rhsPlace ?? value) && mergeInto(field, rhsPlace ?? value))
|
|
104
|
+
ev.s.changed = true;
|
|
105
|
+
// Aliasing assignment onto an ALREADY-materialized field slot: the slot and the RHS
|
|
106
|
+
// place are the same runtime object, so a write already sitting in the slot must also
|
|
107
|
+
// reach the RHS place (and vice versa, above). This arises when a guarded write
|
|
108
|
+
// fabricates the slot BEFORE the alias assignment in source order and a loop carries
|
|
109
|
+
// the flow (`wrap.box.f = t` then `wrap.box = box`): re-pointing the slot to the place
|
|
110
|
+
// would strand the fabricated slot's taint, so merge it back weakly instead.
|
|
111
|
+
// Previously the merge only ran one direction, so the fabricated slot's
|
|
112
|
+
// `ask#1` never reached the box.
|
|
113
|
+
if (rhsPlace !== undefined && field !== rhsPlace && mergeInto(rhsPlace, field))
|
|
114
|
+
ev.s.changed = true;
|
|
115
|
+
// May-alias replay: a conditional-binding / join-element container's write reaches every
|
|
116
|
+
// candidate place it may BE (weak, inexact — the write lands on one arm only).
|
|
117
|
+
if (replayMayAliasWrite(container, key, rhsPlace ?? value))
|
|
118
|
+
ev.s.changed = true;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* An object-literal set accessor is registered globally by property name; any write to
|
|
122
|
+
* a property of that name records the assigned value as the setter's param-0 actual.
|
|
123
|
+
* Deliberately crude (name-based, ignores the receiver object) — a sound
|
|
124
|
+
* over-approximation so the setter body's flow is observed at all.
|
|
125
|
+
*/
|
|
126
|
+
function recordSetterWrite(ev, name, value) {
|
|
127
|
+
const setters = ev.s.settersByProp.get(name);
|
|
128
|
+
if (setters === undefined)
|
|
129
|
+
return;
|
|
130
|
+
const actual = collapse(value);
|
|
131
|
+
for (const id of setters)
|
|
132
|
+
ev.s.addParamActual(id, 0, actual);
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Bind an assignment-expression destructuring pattern (an array/object literal on an
|
|
136
|
+
* lvalue). The expression-flavored mirror of `bindPattern`: targets are expressions
|
|
137
|
+
* (identifiers, property/element accesses, nested patterns), not BindingNames, and
|
|
138
|
+
* property/element targets go through the weak heap-write paths. When `sourcePlace` is a
|
|
139
|
+
* live place, each element aliases a live field of it (via {@link Evaluator.extractField}),
|
|
140
|
+
* mirroring the declaration path; rest/spread and non-place sources keep value semantics.
|
|
141
|
+
*/
|
|
142
|
+
function bindAssignmentPattern(ev, target, value, ctx, sourcePlace) {
|
|
143
|
+
if (ts.isArrayLiteralExpression(target)) {
|
|
144
|
+
let index = 0;
|
|
145
|
+
for (const element of target.elements) {
|
|
146
|
+
if (ts.isOmittedExpression(element)) {
|
|
147
|
+
index += 1;
|
|
148
|
+
continue;
|
|
149
|
+
}
|
|
150
|
+
if (ts.isSpreadElement(element)) {
|
|
151
|
+
bindAssignmentTarget(ev, element.expression, collapse(value), ctx); // rest: value semantics
|
|
152
|
+
continue;
|
|
153
|
+
}
|
|
154
|
+
if (sourcePlace !== undefined) {
|
|
155
|
+
const field = ev.extractField(sourcePlace, String(index));
|
|
156
|
+
bindAssignmentTarget(ev, element, field, ctx, field);
|
|
157
|
+
}
|
|
158
|
+
else {
|
|
159
|
+
bindAssignmentTarget(ev, element, ev.selectField(value, String(index)), ctx);
|
|
160
|
+
}
|
|
161
|
+
index += 1;
|
|
162
|
+
}
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
if (!ts.isObjectLiteralExpression(target))
|
|
166
|
+
return;
|
|
167
|
+
for (const prop of target.properties) {
|
|
168
|
+
if (ts.isSpreadAssignment(prop)) {
|
|
169
|
+
bindAssignmentTarget(ev, prop.expression, collapse(value), ctx);
|
|
170
|
+
}
|
|
171
|
+
else if (ts.isShorthandPropertyAssignment(prop)) {
|
|
172
|
+
if (sourcePlace !== undefined) {
|
|
173
|
+
const field = ev.extractField(sourcePlace, prop.name.text);
|
|
174
|
+
// Default (`{ x = d }`) weak-merges into the live field, keeping the alias.
|
|
175
|
+
if (prop.objectAssignmentInitializer !== undefined) {
|
|
176
|
+
if (mergeInto(field, ev.evalExpr(prop.objectAssignmentInitializer, ctx)))
|
|
177
|
+
ev.s.changed = true;
|
|
178
|
+
}
|
|
179
|
+
writeTarget(ev, prop.name, field, ctx, field);
|
|
180
|
+
}
|
|
181
|
+
else {
|
|
182
|
+
let elemValue = ev.selectField(value, prop.name.text);
|
|
183
|
+
if (prop.objectAssignmentInitializer !== undefined) {
|
|
184
|
+
elemValue = unionValues(elemValue, ev.evalExpr(prop.objectAssignmentInitializer, ctx));
|
|
185
|
+
}
|
|
186
|
+
writeTarget(ev, prop.name, elemValue, ctx);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
else if (ts.isPropertyAssignment(prop) && !ts.isComputedPropertyName(prop.name)) {
|
|
190
|
+
const key = prop.name.getText(ev.s.scriptFile);
|
|
191
|
+
if (sourcePlace !== undefined) {
|
|
192
|
+
const field = ev.extractField(sourcePlace, key);
|
|
193
|
+
bindAssignmentTarget(ev, prop.initializer, field, ctx, field);
|
|
194
|
+
}
|
|
195
|
+
else {
|
|
196
|
+
bindAssignmentTarget(ev, prop.initializer, ev.selectField(value, key), ctx);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
else if (ts.isPropertyAssignment(prop)) {
|
|
200
|
+
bindAssignmentTarget(ev, prop.initializer, collapse(value), ctx); // computed key: value semantics
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Bind a for-in / for-of loop variable to `value` through the EXISTING binding machinery
|
|
206
|
+
* (no parallel path): the declaration form (`for (const k … )`) routes through bindPattern,
|
|
207
|
+
* the assignment form (`for (k … )` or a destructuring assignment target) through
|
|
208
|
+
* bindAssignmentTarget. The loop value is derived (not a place), so value semantics — no
|
|
209
|
+
* aliasing sourcePlace. Previously for-of bound only the declaration form and
|
|
210
|
+
* for-in bound nothing at all, dropping element / key taint into every read
|
|
211
|
+
* of the loop variable.
|
|
212
|
+
*/
|
|
213
|
+
export function bindForInitializer(ev, initializer, value, ctx) {
|
|
214
|
+
if (!ts.isVariableDeclarationList(initializer)) {
|
|
215
|
+
bindAssignmentTarget(ev, initializer, value, ctx);
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
const decl = initializer.declarations[0];
|
|
219
|
+
if (decl !== undefined)
|
|
220
|
+
ev.bindPattern(decl.name, value, ctx);
|
|
221
|
+
}
|
|
222
|
+
/** One target of an assignment pattern: a nested pattern, a default, or an lvalue. */
|
|
223
|
+
function bindAssignmentTarget(ev, target, value, ctx, sourcePlace) {
|
|
224
|
+
let t = peelParens(target);
|
|
225
|
+
if (ts.isBinaryExpression(t) && t.operatorToken.kind === ts.SyntaxKind.EqualsToken) {
|
|
226
|
+
// `[a = d]` / `{ x: a = d }`: the default joins in (it may carry taint). When aliasing,
|
|
227
|
+
// `value` IS the live field, so merge the default into it in place to keep the alias.
|
|
228
|
+
if (sourcePlace !== undefined) {
|
|
229
|
+
if (mergeInto(value, ev.evalExpr(t.right, ctx)))
|
|
230
|
+
ev.s.changed = true;
|
|
231
|
+
}
|
|
232
|
+
else {
|
|
233
|
+
value = unionValues(value, ev.evalExpr(t.right, ctx));
|
|
234
|
+
}
|
|
235
|
+
t = peelParens(t.left);
|
|
236
|
+
}
|
|
237
|
+
if (ts.isArrayLiteralExpression(t) || ts.isObjectLiteralExpression(t)) {
|
|
238
|
+
bindAssignmentPattern(ev, t, value, ctx, sourcePlace);
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
writeTarget(ev, t, value, ctx, sourcePlace);
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Weak-merge `collapse(value)` into the leftmost identifier of a member-access chain.
|
|
245
|
+
* A nested assignment target (`a.b.c = x`, `a[i].f = x`) has a member-access
|
|
246
|
+
* receiver rather than a plain identifier, so the field-sensitive branches above find
|
|
247
|
+
* no `receiverSymbol` and used to drop x's taint silently. Folding into the root symbol
|
|
248
|
+
* is a field-insensitive over-approximation, which a may-flow analysis must prefer over
|
|
249
|
+
* under-approximating (dropping) the flow. Shared with the heap-mutator transfer
|
|
250
|
+
* (heap-ops.ts), whose unresolvable receivers fall back the same way. A chain rooted in
|
|
251
|
+
* a non-identifier (a call result: `log().push(x)`) still has no slot to fold into — the
|
|
252
|
+
* known residual of the place model (function returns are summaries, not heap objects).
|
|
253
|
+
*/
|
|
254
|
+
export function mergeIntoRootIdentifier(ev, expr, value) {
|
|
255
|
+
let cur = expr;
|
|
256
|
+
while (true) {
|
|
257
|
+
if (ts.isParenthesizedExpression(cur))
|
|
258
|
+
cur = cur.expression;
|
|
259
|
+
else if (ts.isPropertyAccessExpression(cur))
|
|
260
|
+
cur = cur.expression;
|
|
261
|
+
else if (ts.isElementAccessExpression(cur))
|
|
262
|
+
cur = cur.expression;
|
|
263
|
+
// Peel the value-preserving wrappers that can sit on an lvalue chain
|
|
264
|
+
// (`report!.sections.intro = x`, `(report as T).sections = x`) so the walk still
|
|
265
|
+
// reaches the root identifier instead of stopping short and dropping x.
|
|
266
|
+
else if (ts.isNonNullExpression(cur))
|
|
267
|
+
cur = cur.expression;
|
|
268
|
+
else if (ts.isAsExpression(cur) || ts.isSatisfiesExpression(cur))
|
|
269
|
+
cur = cur.expression;
|
|
270
|
+
else if (ts.isTypeAssertionExpression(cur))
|
|
271
|
+
cur = cur.expression;
|
|
272
|
+
else
|
|
273
|
+
break;
|
|
274
|
+
}
|
|
275
|
+
if (!ts.isIdentifier(cur))
|
|
276
|
+
return;
|
|
277
|
+
const sym = ev.checker.getSymbolAtLocation(cur);
|
|
278
|
+
if (sym !== undefined && mergeInto(ev.s.envSlot(sym), collapse(value)))
|
|
279
|
+
ev.s.changed = true;
|
|
280
|
+
}
|
|
281
|
+
/** Peel parentheses off an lvalue expression. */
|
|
282
|
+
function peelParens(expr) {
|
|
283
|
+
let cur = expr;
|
|
284
|
+
while (ts.isParenthesizedExpression(cur))
|
|
285
|
+
cur = cur.expression;
|
|
286
|
+
return cur;
|
|
287
|
+
}
|