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 process.listeners

+177 -39
+43
examples/spec/process.js
··· 48 48 test('removeAllListeners is function', typeof process.removeAllListeners, 'function'); 49 49 test('emit is function', typeof process.emit, 'function'); 50 50 test('listenerCount is function', typeof process.listenerCount, 'function'); 51 + test('listeners is function', typeof process.listeners, 'function'); 52 + test('rawListeners is function', typeof process.rawListeners, 'function'); 53 + test('eventNames is function', typeof process.eventNames, 'function'); 54 + test('prependListener is function', typeof process.prependListener, 'function'); 55 + test('prependOnceListener is function', typeof process.prependOnceListener, 'function'); 51 56 test('setMaxListeners is function', typeof process.setMaxListeners, 'function'); 52 57 test('getMaxListeners is function', typeof process.getMaxListeners, 'function'); 53 58 ··· 100 105 test('listenerCount returns count', process.listenerCount('testCount'), 2); 101 106 process.removeAllListeners('testCount'); 102 107 test('removeAllListeners clears', process.listenerCount('testCount'), 0); 108 + 109 + const listenersSeen = []; 110 + const listenersFirst = () => { 111 + listenersSeen.push('first'); 112 + }; 113 + const listenersSecond = () => { 114 + listenersSeen.push('second'); 115 + }; 116 + process.on('testListeners', listenersFirst); 117 + process.prependListener('testListeners', listenersSecond); 118 + const processListeners = process.listeners('testListeners'); 119 + test('listeners returns array', Array.isArray(processListeners), true); 120 + test('listeners includes prepended handler first', processListeners[0], listenersSecond); 121 + test('listeners includes appended handler second', processListeners[1], listenersFirst); 122 + const processRawListeners = process.rawListeners('testListeners'); 123 + test('rawListeners returns array', Array.isArray(processRawListeners), true); 124 + test('rawListeners includes prepended handler first', processRawListeners[0], listenersSecond); 125 + test('rawListeners includes appended handler second', processRawListeners[1], listenersFirst); 126 + test('eventNames includes active process event', process.eventNames().includes('testListeners'), true); 127 + process.emit('testListeners'); 128 + test('prependListener affects emit order', listenersSeen.join(','), 'second,first'); 129 + process.removeAllListeners('testListeners'); 130 + test('eventNames excludes removed process event', process.eventNames().includes('testListeners'), false); 131 + 132 + let prependOnceCount = 0; 133 + const prependOnceMarker = []; 134 + process.on('testPrependOnce', () => { 135 + prependOnceMarker.push('on'); 136 + }); 137 + process.prependOnceListener('testPrependOnce', () => { 138 + prependOnceCount++; 139 + prependOnceMarker.push('once'); 140 + }); 141 + process.emit('testPrependOnce'); 142 + process.emit('testPrependOnce'); 143 + test('prependOnceListener fires once', prependOnceCount, 1); 144 + test('prependOnceListener runs before on listener', prependOnceMarker[0], 'once'); 145 + process.removeAllListeners('testPrependOnce'); 103 146 104 147 let receivedArg = null; 105 148 process.on('testArgs', arg => {
+88 -39
src/modules/process.c
··· 1532 1532 return js_mkundef(); 1533 1533 } 1534 1534 1535 - static ant_value_t process_on(ant_t *js, ant_value_t *args, int nargs) { 1536 - if (nargs < 2) return js_mkerr(js, "process.on requires 2 arguments"); 1537 - 1535 + static ant_value_t process_add(ant_t *js, ant_value_t *args, int nargs, bool once, bool prepend) { 1536 + if (nargs < 2) { 1537 + return js_mkerr(js, once ? "process.once requires 2 arguments" : "process.on requires 2 arguments"); 1538 + } 1539 + 1538 1540 char *event = js_getstr(js, args[0], NULL); 1539 1541 if (!event) return js_mkerr(js, "event must be a string"); 1540 - if (vtype(args[1]) != T_FUNC) return js_mkerr(js, "listener must be a function"); 1541 - 1542 - int signum = get_signal_number(event); 1543 - if (signum > 0) { 1544 - start_signal_watch(signum); 1542 + 1543 + uint8_t listener_type = vtype(args[1]); 1544 + if (listener_type != T_FUNC && listener_type != T_CFUNC) { 1545 + return js_mkerr(js, "listener must be a function"); 1545 1546 } 1546 - 1547 + 1548 + int signum = get_signal_number(event); 1549 + if (signum > 0) start_signal_watch(signum); 1550 + 1547 1551 ProcessEventType *evt = find_or_create_event(&process_events, event); 1548 - if (!ensure_listener_capacity(evt)) { 1549 - return js_mkerr(js, "failed to allocate listener"); 1552 + if (!ensure_listener_capacity(evt)) return js_mkerr(js, "failed to allocate listener"); 1553 + 1554 + if (prepend && evt->listener_count > 0) { 1555 + memmove( 1556 + &evt->listeners[1], 1557 + &evt->listeners[0], 1558 + (size_t)evt->listener_count * sizeof(ProcessEventListener) 1559 + ); 1560 + evt->listeners[0].listener = args[1]; 1561 + evt->listeners[0].once = once; 1562 + } else { 1563 + evt->listeners[evt->listener_count].listener = args[1]; 1564 + evt->listeners[evt->listener_count].once = once; 1550 1565 } 1551 - 1552 - evt->listeners[evt->listener_count].listener = args[1]; 1553 - evt->listeners[evt->listener_count].once = false; 1566 + 1554 1567 evt->listener_count++; 1555 - 1556 1568 check_listener_warning(event); 1557 - 1558 1569 return js_get(js, js_glob(js), "process"); 1559 1570 } 1560 1571 1572 + static ant_value_t process_on(ant_t *js, ant_value_t *args, int nargs) { 1573 + return process_add(js, args, nargs, false, false); 1574 + } 1575 + 1561 1576 static ant_value_t process_once(ant_t *js, ant_value_t *args, int nargs) { 1562 - if (nargs < 2) return js_mkerr(js, "process.once requires 2 arguments"); 1563 - 1564 - char *event = js_getstr(js, args[0], NULL); 1565 - if (!event) return js_mkerr(js, "event must be a string"); 1566 - if (vtype(args[1]) != T_FUNC) return js_mkerr(js, "listener must be a function"); 1567 - 1568 - int signum = get_signal_number(event); 1569 - if (signum > 0) { 1570 - start_signal_watch(signum); 1571 - } 1572 - 1573 - ProcessEventType *evt = find_or_create_event(&process_events, event); 1574 - if (!ensure_listener_capacity(evt)) { 1575 - return js_mkerr(js, "failed to allocate listener"); 1576 - } 1577 - 1578 - evt->listeners[evt->listener_count].listener = args[1]; 1579 - evt->listeners[evt->listener_count].once = true; 1580 - evt->listener_count++; 1581 - 1582 - check_listener_warning(event); 1583 - 1584 - return js_get(js, js_glob(js), "process"); 1577 + return process_add(js, args, nargs, true, false); 1578 + } 1579 + 1580 + static ant_value_t process_prepend_listener(ant_t *js, ant_value_t *args, int nargs) { 1581 + return process_add(js, args, nargs, false, true); 1582 + } 1583 + 1584 + static ant_value_t process_prepend_once_listener(ant_t *js, ant_value_t *args, int nargs) { 1585 + return process_add(js, args, nargs, true, true); 1585 1586 } 1586 1587 1587 1588 static ant_value_t process_off(ant_t *js, ant_value_t *args, int nargs) { ··· 1750 1751 return js_mknum(evt ? evt->listener_count : 0); 1751 1752 } 1752 1753 1754 + static ant_value_t process_listeners_impl(ant_t *js, ant_value_t *args, int nargs, bool raw) { 1755 + (void)raw; 1756 + ant_value_t result = js_mkarr(js); 1757 + if (nargs < 1) return result; 1758 + 1759 + char *event = js_getstr(js, args[0], NULL); 1760 + if (!event) return result; 1761 + 1762 + ProcessEventType *evt = NULL; 1763 + HASH_FIND_STR(process_events, event, evt); 1764 + if (!evt) return result; 1765 + 1766 + for (int i = 0; i < evt->listener_count; i++) { 1767 + js_arr_push(js, result, evt->listeners[i].listener); 1768 + } 1769 + 1770 + return result; 1771 + } 1772 + 1773 + static ant_value_t process_listeners(ant_t *js, ant_value_t *args, int nargs) { 1774 + return process_listeners_impl(js, args, nargs, false); 1775 + } 1776 + 1777 + static ant_value_t process_raw_listeners(ant_t *js, ant_value_t *args, int nargs) { 1778 + return process_listeners_impl(js, args, nargs, true); 1779 + } 1780 + 1781 + static ant_value_t process_event_names(ant_t *js, ant_value_t *args, int nargs) { 1782 + (void)args; 1783 + (void)nargs; 1784 + ant_value_t result = js_mkarr(js); 1785 + ProcessEventType *evt = NULL; 1786 + ProcessEventType *tmp = NULL; 1787 + 1788 + HASH_ITER(hh, process_events, evt, tmp) { 1789 + if (evt->listener_count > 0) { 1790 + js_arr_push(js, result, js_mkstr(js, evt->event_type, strlen(evt->event_type))); 1791 + } 1792 + } 1793 + 1794 + return result; 1795 + } 1796 + 1753 1797 static ant_value_t process_set_max_listeners(ant_t *js, ant_value_t *args, int nargs) { 1754 1798 if (nargs < 1) return js_mkerr(js, "setMaxListeners requires 1 argument"); 1755 1799 if (vtype(args[0]) != T_NUM) return js_mkerr(js, "n must be a number"); ··· 1803 1847 js_set(js, obj, "on", js_mkfun(process_on)); 1804 1848 js_set(js, obj, "addListener", js_mkfun(process_on)); 1805 1849 js_set(js, obj, "once", js_mkfun(process_once)); 1850 + js_set(js, obj, "prependListener", js_mkfun(process_prepend_listener)); 1851 + js_set(js, obj, "prependOnceListener", js_mkfun(process_prepend_once_listener)); 1806 1852 js_set(js, obj, "off", js_mkfun(process_off)); 1807 1853 js_set(js, obj, "removeListener", js_mkfun(process_off)); 1808 1854 js_set(js, obj, "removeAllListeners", js_mkfun(process_remove_all_listeners)); 1809 1855 js_set(js, obj, "emit", js_mkfun(process_emit)); 1810 1856 js_set(js, obj, "listenerCount", js_mkfun(process_listener_count)); 1857 + js_set(js, obj, "listeners", js_mkfun(process_listeners)); 1858 + js_set(js, obj, "rawListeners", js_mkfun(process_raw_listeners)); 1859 + js_set(js, obj, "eventNames", js_mkfun(process_event_names)); 1811 1860 js_set(js, obj, "setMaxListeners", js_mkfun(process_set_max_listeners)); 1812 1861 js_set(js, obj, "getMaxListeners", js_mkfun(process_get_max_listeners)); 1813 1862 }
+46
tests/test_process_event_api.cjs
··· 1 + const processEvents = []; 2 + 3 + function first() { 4 + processEvents.push('first'); 5 + } 6 + 7 + function second() { 8 + processEvents.push('second'); 9 + } 10 + 11 + process.removeAllListeners('codex-process-api'); 12 + process.on('codex-process-api', first); 13 + process.prependListener('codex-process-api', second); 14 + 15 + const listeners = process.listeners('codex-process-api'); 16 + if (!Array.isArray(listeners) || listeners.length !== 2) { 17 + console.log('FAIL: process.listeners should return the registered listeners'); 18 + process.exit(1); 19 + } 20 + 21 + if (listeners[0] !== second || listeners[1] !== first) { 22 + console.log('FAIL: process.prependListener should place the listener first'); 23 + process.exit(1); 24 + } 25 + 26 + const rawListeners = process.rawListeners('codex-process-api'); 27 + if (!Array.isArray(rawListeners) || rawListeners.length !== 2) { 28 + console.log('FAIL: process.rawListeners should mirror process.listeners for direct listeners'); 29 + process.exit(1); 30 + } 31 + 32 + const eventNames = process.eventNames(); 33 + if (!Array.isArray(eventNames) || eventNames.indexOf('codex-process-api') === -1) { 34 + console.log('FAIL: process.eventNames should include active events'); 35 + process.exit(1); 36 + } 37 + 38 + process.emit('codex-process-api'); 39 + 40 + if (processEvents.join(',') !== 'second,first') { 41 + console.log('FAIL: process.emit should honor prepended listener order'); 42 + process.exit(1); 43 + } 44 + 45 + process.removeAllListeners('codex-process-api'); 46 + console.log('PASS');