It's trivially polyfilled and is ultimately the main low-level job scheduling primitive. And before it got to the Web, it already had some precedent in Node's process.nextTask.
From an implementor's perspective, almost all the legwork already exists (example) and it's just adding another type of job. And unlike promises, this just schedules a job without all the surrounding ceremony, making it much cheaper.
Semantically, queueMicrotask(fn) (after type checking) should be equivalent to void (async () => { await null; fn() })(), as it is today.
I'll note that like the async approach, both are slightly different than queueMicrotask since an extra stack frame is present underneath fn. You could prevent it in the Promise.resolve case by using fn as the fulfilment handler, but that would be observable as an arguments.length === 1
That's the thing, the scheduling part itself is a host hook, so basically this would just be a thin wrapper around HostEnqueuePromiseJob to enqueue the job.
Also there is the question of naming. The 262 spec only talks about Promise Jobs, the Web talks about microtasks. Internally at my company we reference to these as "turns" (and "cranks" roughly for what the web calls "tasks").
Btw the fact queueMicrotask shares its queue with promise jobs is an implementation choice of the Web. For example in Node, "ticks" used to (still are?) a parallel queue to promise jobs, with the same priority. Each would be drained before draining the other, until both were drained to move to the I/O queue.
I agree however this is one of those things that from the programmer's pov seem like it should be in the language. Does WinterCG define queueMicrotask?
So, it's always been linked to promises from the start. Only other real difference is in errors being unconditionally reported (and typically not as unhandled rejections).
I also cited process.nextTick as precedent, and yes, they do currently use other queues. But, before ES6 promises, it used to be the only non-I/O task/job queue. Most high-performance Promises/A+ implementations used it for scheduling when available. So, back then, it was in practice the queueMicrotask equivalent in Node.