While investigating ContextVar in pallets/werkzeug#2436, I realized that there's no reason to use a LocalStack now to manage RequestContext and AppContext.
LocalStack incurs some performance and memory overhead on every push and pop because it uses a mutable list as the value of the ContextVar. Since we can never know if this context was copied by asyncio or asgiref into a child context, we always have to copy the list before mutating it, then set it again, otherwise mutations would be unsafe.
RequestContext and AppContext already have their own internal thread-unsafe state to track how many times they've been pushed, and implicit app contexts for request contexts.
Now, the contexts keep an internal stack of contextvars.Token objects, appending a new token when pushed. This allows resetting the context var to the previous value when the context is popped. Essentially, this makes the contexts singly-linked lists instead of stacks.
This does mean that _app_ctx_stack.top and _request_ctx_stack.top will no longer exist. Currently, there is a fake object that keeps the API around, since it's used by extensions to store state. However, importing them or accessing them will show deprecation warnings. Docs now encourage using g instead of the internal contexts for extension state. I added app_ctx and request_ctx objects that are proxies to the current objects, in case existing extensions want a less drastic change.
This bumps the minimum version of Werkzeug to 2.2 (currently 2.2.0a1) to take advantage of changes to its implementation of LocalProxy.