Your timeTakingFunc does all of its work synchronously, for two reasons:
- An asyncfunction's code is synchronous up until the firstawaitorreturn. That's so it can start whatever process it's going to complete asynchronously.
- The executor function you pass to new Promiseis run synchronously, running to completion before the new promise is returned to the code making the call — for the same reason that anasyncfunction starts out synchronous. (In fact, the beginning of anasyncfunction, before the firstawaitorreturn, is directly analogous to the body of a promise executor function.)
So there's nothing actually asynchronous about that function.
(Side note: There's no reason to use async on a function that never uses await and that explicitly creates its promise. It's redundant.)
If the function had any actual asynchronous work in it that took virtually any time to complete, you'd see the order of output you expect:
async function timeTakingFunc() {
    // This fetch fails, but it takes non-zero time to do so
    try {
        const response = await fetch("https://via.placeholder.com/150");
        if (response.ok) {
            await response.arrayBuffer();
        }
    } catch (e) {
    }
}
(async () => {
    try {
        setTimeout(() => console.log('next task'), 0);
        await timeTakingFunc();
        console.log('after waiting for timetaking function');
    } catch (error) {
        console.log(error.message);
    }
})();
 
 
But with that code, timeTakingFunc is synchronous:
async function timeTakingFunc() {
    const p = new Promise((resolve, error) => {
        console.log("Start of executor function");
        for (let t = 1; t < 100000; t++) {
            for (let k = 1; k < 100000; k++) {}
        }
        console.log("End of executor function");
        resolve();
    });
    console.log("timeTakingFunc returning promise");
    return p;
};
(async () => {
    try {
        setTimeout(() => console.log('next task'), 0);
        await timeTakingFunc();
        console.log('after waiting for timetaking function');
    } catch (error) {
        console.log(error.message);
    }
})();
 
 
...and the JavaScript engine does this:
- Sets the timer (which at some point will queue a task to run the timer callback)
- Runs the synchronous part of timeTakingFunction(which is all of it) to completion
- [Because of the await] Queues a microtask in the current task's microtask queue to run the remainder of the code
- Reaches the end of the current task
- Processes the microtask queue
- Runs the remainder of the code, logging "after waiting for timetaking function"
 
- Processes the next task in the task queue, which might be the timer callback (if not, it'll show up in the queue fairly soon)
- When the timer task is run, it logs "next task"
 
Which is why you see the  order you see, with a synchronous function.