Description
The problem
Today, the iteration semantics for relative scopes differs from the semantics for "every" and ordinal scopes. The latter first expand to iteration scope (if input target has no explicit range), and then get a list of all top-level scopes in that iteration scope. The former iterate directly from the input target, with no knowledge of iteration scopes. These semantics lead to the following problems:
- Reevaluate iteration order for scopes that start or end at the same position #1597
- Relative exclusive scope should skip containing #2110
- @josharian's riddle of "take scope take next scope take scope" not being equivalent to "take scope"
The solution
If the scope has no iteration scope, maybe we just leave today's behaviour?
Otherwise, we first want to find the proper iteration scope in which to iterate:
- For relative exclusive, we expand input target to smallest containing iteration scope
- For relative inclusive, we expand input target to smallest containing scope, then expand from there to smallest containing iteration scope. That handles the case where you're between scopes in the very smallest iteration scope, eg
if (true) { console.log(1) | console.log(2) } console.log(2)
Then we do the same thing we do with "every" / ordinal, where we construct a list of all scopes in the iteration scope. These are the scopes we use instead of directly working with the scope handler.
Note that if when iterating through the returned scopes, we run out, I think we move up to grand iteration scope and start over. Repeat that as many times as necessary