mirror of
https://gh.wpcy.net/https://github.com/discourse/discourse.git
synced 2026-05-29 06:46:14 +08:00
Three independent issues in `each`'s isolation, each surfacing as soon as the step is used outside the simplest shapes: 1. Nested `each` blocks crashed inside `with_isolation`'s `ensure`. The isolation kept its snapshot in a single slot that the inner call would overwrite then null, so the outer's cleanup ran against `nil`. The snapshot now lives on a stack, making isolation re-entrant. 2. ActiveRecord models in the context lost their primary key inside an `each` block. The snapshot used `deep_dup`, which recurses into AR objects via `dup` and AR's `dup` returns an unpersisted copy with `id == nil`. Basic shapes like `model :user; each :things do ... end` silently swapped the real user for a useless ghost. The deep copy was originally an attempt at mutation isolation for collections, but that contract was never documented, its supporting spec was removed before the original PR merged, and the rest of the framework already lets steps mutate what they receive. A shallow dup matches the documented "variables set inside the loop don't leak" guarantee and stops corrupting models. 3. Non-persisted state leaked between iterations. The whole loop ran inside one isolation, so iteration N could read scratch values iteration N-1 had left around. Each iteration now gets its own isolation. Steps inside the same iteration still share state freely (step 2 can act on what step 1 produced); only cross-iteration carry-over now requires `persist:`, which makes that dependency visible at the `each` declaration. |
||
|---|---|---|
| .. | ||
| base | ||
| contract_base_spec.rb | ||
| nested_contract_type_spec.rb | ||
| runner_spec.rb | ||
| steps_inspector_spec.rb | ||