You only need an async executor to deal with threading issues; you can completely side-step it if everything's single-threaded (coöperative multi-tasking) or thread-agnostic (Send + Sync). And an executor like smol has no compatibility issues with anything; you just run it.
Python has an async executor, yes, but only to let you do things you can't do with coöperative multi-tasking.
JavaScript has an executor, too. The only difference is that you can't turn it off. It's actually less capable than (most of the) Rust implementations, because JavaScript's single-threaded. (Python's an in-between case, thanks to the Global Interpreter Lock; good JavaScript engines should be able to match Python's concurrency capabilities.)
Executors are only important for things like timers. JavaScript's promises rarely make use of them, except when they schedule their callbacks based on something external to the JavaScript (your “primitive” promises on top of which everything is built). Both Python and Rust work the same way.
The only difference with JavaScript is that it Just Works™ (or, rather, just works; because it does) – but that comes at the cost of sticking JavaScript with a permanently single-threaded runtime.