MIRROR: javascript for ๐Ÿœ's, a tiny runtime with big ambitions
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

add coroutine settlement and suspension handling

+88 -12
+29 -12
src/sugar.c
··· 255 255 return promise; 256 256 } 257 257 258 + static inline void settle_coroutine(coroutine_t *coro, jsval_t *args, int nargs, bool is_error) { 259 + coro->result = nargs > 0 ? args[0] : js_mkundef(); 260 + coro->is_settled = true; 261 + coro->is_error = is_error; 262 + coro->is_ready = true; 263 + } 264 + 265 + static void resume_coroutine_if_suspended(struct js *js, coroutine_t *coro) { 266 + if (!coro || !coro->mco || mco_status(coro->mco) != MCO_SUSPENDED) return; 267 + 268 + remove_coroutine(coro); 269 + coro_saved_state_t saved = coro_enter(js, coro); 270 + mco_result res = mco_resume(coro->mco); 271 + coro_leave(js, coro, saved); 272 + 273 + if (res == MCO_SUCCESS && mco_status(coro->mco) != MCO_DEAD) { 274 + coro->is_ready = false; 275 + enqueue_coroutine(coro); 276 + } else free_coroutine(coro); 277 + } 278 + 258 279 jsval_t resume_coroutine_wrapper(struct js *js, jsval_t *args, int nargs) { 259 280 jsval_t me = js->current_func; 260 281 jsval_t coro_val = js_get_slot(js, me, SLOT_CORO); ··· 262 283 263 284 coroutine_t *coro = (coroutine_t *)(uintptr_t)tod(coro_val); 264 285 if (!coro) return js_mkundef(); 265 - 266 - coro->result = nargs > 0 ? args[0] : js_mkundef(); 267 - coro->is_settled = true; 268 - coro->is_error = false; 269 - coro->is_ready = true; 270 - 286 + 287 + settle_coroutine(coro, args, nargs, false); 288 + resume_coroutine_if_suspended(js, coro); 289 + 271 290 return js_mkundef(); 272 291 } 273 292 ··· 279 298 280 299 coroutine_t *coro = (coroutine_t *)(uintptr_t)tod(coro_val); 281 300 if (!coro) return js_mkundef(); 282 - 283 - coro->result = nargs > 0 ? args[0] : js_mkundef(); 284 - coro->is_settled = true; 285 - coro->is_error = true; 286 - coro->is_ready = true; 287 - 301 + 302 + settle_coroutine(coro, args, nargs, true); 303 + resume_coroutine_if_suspended(js, coro); 304 + 288 305 return js_mkundef(); 289 306 }
+59
tests/test_async_await_microtask.cjs
··· 1 + var jobQueue = []; 2 + 3 + function setTimeout(cb, time, cbarg) { 4 + var speedup = 10; 5 + var runTime = Date.now() + time / speedup; 6 + if (!jobQueue[runTime]) { 7 + jobQueue[runTime] = []; 8 + } 9 + jobQueue[runTime].push(function () { 10 + cb(cbarg); 11 + }); 12 + } 13 + 14 + function flushQueue() { 15 + var curTime = Date.now(); 16 + var empty = true; 17 + for (var runTime in jobQueue) { 18 + empty = false; 19 + if (curTime >= runTime) { 20 + var jobs = jobQueue[runTime]; 21 + delete jobQueue[runTime]; 22 + jobs.forEach(function (job) { 23 + job(); 24 + }); 25 + } 26 + } 27 + if (!empty) { 28 + Promise.resolve().then(flushQueue); 29 + } 30 + } 31 + 32 + function asyncTestPassed() { 33 + console.log('test_async_await_microtask.cjs: OK'); 34 + } 35 + 36 + function testCode() { 37 + (async function () { 38 + await Promise.resolve(); 39 + console.log('after'); 40 + var a1 = await new Promise(function (resolve) { 41 + setTimeout(resolve, 800, 'foo'); 42 + }); 43 + var a2 = await new Promise(function (resolve) { 44 + setTimeout(resolve, 800, 'bar'); 45 + }); 46 + if (a1 + a2 === 'foobar') { 47 + asyncTestPassed(); 48 + } else { 49 + console.log('test_async_await_microtask.cjs: FAIL'); 50 + } 51 + })(); 52 + } 53 + 54 + try { 55 + testCode(); 56 + Promise.resolve().then(flushQueue); 57 + } catch (e) { 58 + console.log('test_async_await_microtask.cjs: exception: ' + e); 59 + }