I draw the line at whether the interleaving granule is under the programmer’s control or not.
For example, I can say that when a task executes on an event loop, no other tasks are executing concurrently to it because the event loop executes tasks sequentially.
Not quite. Consider a component in your code that does this:
for (let blah of things)
foo(blah);
In an event loop, if things has a lot of stuff in it, this can block the event loop. Other things in the event loop won't be able to run until this completes.
Your definition of concurrency is not correct. Concurrency usually implies that the work is chopped up into very small interleavable bits. A while function call with a loop of unbounded length being the default granule of interleaving is definitely not part of the definition of concurrency.
The term "concurrency" subsumes both event loop style concurrency and two-cores-running-code-at-the-same time concurrency.
Yes, it is. The JavaScript event loop is a very lazy scheduler than does no preemption. It's a very primitive concurrency model. It's up to the users of the language to break their tasks down into sufficiently small components or yield to allow for interleaving of work.
Just because concurrency and parallelism are different does not meant that concurrency and event loops are the same.