The execution of the closure is needed to be guaranteed across the start to end; meaning that the values must be changed sequentially and non-asynchronously. Furthermore thread locals are accessible from non-async contexts: e.g. when the property getter (which cannot be forced to be async) is accessed.
That means that to accomplish the tracking we need a scope local (aka thread local) for tracking, and cannot force non-async getters to reach out to a task local. Plus there is an extra cost for rendering side that was quite delicate; thread locals in that case compile down to a single machine instruction on some architectures.