Native async/await functions use generator functions under the hood, which are an implementation of coroutines. Like all fully-fledged coroutine implementations, generators can suspend execution while preserving the stack by yielding control (hence the `yield` keyword). This requires interpreter (e.g. V8) support.
Desuguared Promise.then can't suspend the stack like that as a normal JS thread must run to completion and cannot yield to the scheduler; instead every call to `.then` pushes the new closure onto the event/microtask queue.