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.

event emitter

+288 -1
+2
.gitignore
··· 7 7 *.dll 8 8 9 9 /build 10 + /javascript-zoo 11 + 10 12 /subprojects/*/ 11 13 /subprojects/.wraplock 12 14 !/subprojects/packagefiles
+3
include/modules/events.h
··· 1 1 #ifndef EVENTS_H 2 2 #define EVENTS_H 3 3 4 + #include "ant.h" 5 + 4 6 void init_events_module(void); 7 + jsval_t events_library(struct js *js); 5 8 6 9 #endif
+1 -1
meson.build
··· 74 74 build_date = run_command('date', '+%Y-%m-%d', check: true).stdout().strip() 75 75 76 76 version_conf = configuration_data() 77 - version_conf.set('ANT_VERSION', '0.1.1.12') 77 + version_conf.set('ANT_VERSION', '0.1.1.13') 78 78 version_conf.set('ANT_GIT_HASH', git_hash) 79 79 version_conf.set('ANT_BUILD_DATE', build_date) 80 80
+1
src/main.c
··· 206 206 ant_register_library(path_library, "ant:path", "node:path", NULL); 207 207 ant_register_library(fs_library, "ant:fs", "node:fs", NULL); 208 208 ant_register_library(crypto_library, "ant:crypto", "node:crypto", NULL); 209 + ant_register_library(events_library, "ant:events", "node:events", NULL); 209 210 210 211 #ifndef ANT_SNAPSHOT_GENERATOR 211 212 jsval_t snapshot_result = ant_load_snapshot(js);
+281
src/modules/events.c
··· 29 29 } TargetEvents; 30 30 31 31 static TargetEvents *target_events_map = NULL; 32 + static uint64_t next_emitter_id = 1; 32 33 33 34 static TargetEvents *get_or_create_target_events(jsval_t target) { 34 35 uint64_t target_id = target; ··· 44 45 } 45 46 46 47 return te; 48 + } 49 + 50 + static TargetEvents *get_or_create_emitter_events(struct js *js, jsval_t this_obj) { 51 + jsval_t id_val = js_get(js, this_obj, "_emitter_id"); 52 + uint64_t emitter_id; 53 + TargetEvents *te = NULL; 54 + 55 + if (js_type(id_val) != JS_NUM) { 56 + emitter_id = next_emitter_id++; 57 + js_set(js, this_obj, "_emitter_id", js_mknum((double)emitter_id)); 58 + 59 + te = malloc(sizeof(TargetEvents)); 60 + te->target_id = emitter_id; 61 + te->events = NULL; 62 + HASH_ADD(hh, target_events_map, target_id, sizeof(uint64_t), te); 63 + return te; 64 + } 65 + 66 + emitter_id = (uint64_t)js_getnum(id_val); 67 + HASH_FIND(hh, target_events_map, &emitter_id, sizeof(uint64_t), te); 68 + return te; 69 + } 70 + 71 + static EventType *find_emitter_event_type(struct js *js, jsval_t this_obj, const char *event_type) { 72 + TargetEvents *te = get_or_create_emitter_events(js, this_obj); 73 + if (te == NULL) return NULL; 74 + 75 + EventType *evt = NULL; 76 + HASH_FIND_STR(te->events, event_type, evt); 77 + return evt; 78 + } 79 + 80 + static EventType *find_or_create_emitter_event_type(struct js *js, jsval_t this_obj, const char *event_type) { 81 + TargetEvents *te = get_or_create_emitter_events(js, this_obj); 82 + if (te == NULL) return NULL; 83 + 84 + EventType *evt = NULL; 85 + HASH_FIND_STR(te->events, event_type, evt); 86 + 87 + if (evt == NULL) { 88 + evt = malloc(sizeof(EventType)); 89 + evt->event_type = strdup(event_type); 90 + evt->listener_count = 0; 91 + HASH_ADD_KEYPTR(hh, te->events, evt->event_type, strlen(evt->event_type), evt); 92 + } 93 + 94 + return evt; 47 95 } 48 96 49 97 static EventType *find_or_create_event_type(jsval_t target, const char *event_type) { ··· 351 399 } 352 400 353 401 return result; 402 + } 403 + 404 + // EventEmitter.prototype.on(event, listener) 405 + static jsval_t js_eventemitter_on(struct js *js, jsval_t *args, int nargs) { 406 + jsval_t this_obj = js_getthis(js); 407 + 408 + if (nargs < 2) { 409 + return js_mkerr(js, "on requires 2 arguments (event, listener)"); 410 + } 411 + 412 + char *event_type = js_getstr(js, args[0], NULL); 413 + if (event_type == NULL) { 414 + return js_mkerr(js, "event must be a string"); 415 + } 416 + 417 + if (js_type(args[1]) != JS_FUNC) { 418 + return js_mkerr(js, "listener must be a function"); 419 + } 420 + 421 + EventType *evt = find_or_create_emitter_event_type(js, this_obj, event_type); 422 + if (evt == NULL) { 423 + return js_mkerr(js, "failed to create event type"); 424 + } 425 + 426 + if (evt->listener_count >= MAX_LISTENERS_PER_EVENT) { 427 + return js_mkerr(js, "maximum number of listeners for event '%s' reached", event_type); 428 + } 429 + 430 + EventListener *listener = &evt->listeners[evt->listener_count++]; 431 + listener->listener = args[1]; 432 + listener->once = false; 433 + 434 + return this_obj; 435 + } 436 + 437 + // EventEmitter.prototype.once(event, listener) 438 + static jsval_t js_eventemitter_once(struct js *js, jsval_t *args, int nargs) { 439 + jsval_t this_obj = js_getthis(js); 440 + 441 + if (nargs < 2) { 442 + return js_mkerr(js, "once requires 2 arguments (event, listener)"); 443 + } 444 + 445 + char *event_type = js_getstr(js, args[0], NULL); 446 + if (event_type == NULL) { 447 + return js_mkerr(js, "event must be a string"); 448 + } 449 + 450 + if (js_type(args[1]) != JS_FUNC) { 451 + return js_mkerr(js, "listener must be a function"); 452 + } 453 + 454 + EventType *evt = find_or_create_emitter_event_type(js, this_obj, event_type); 455 + if (evt == NULL) { 456 + return js_mkerr(js, "failed to create event type"); 457 + } 458 + 459 + if (evt->listener_count >= MAX_LISTENERS_PER_EVENT) { 460 + return js_mkerr(js, "maximum number of listeners for event '%s' reached", event_type); 461 + } 462 + 463 + EventListener *listener = &evt->listeners[evt->listener_count++]; 464 + listener->listener = args[1]; 465 + listener->once = true; 466 + 467 + return this_obj; 468 + } 469 + 470 + // EventEmitter.prototype.off(event, listener) 471 + static jsval_t js_eventemitter_off(struct js *js, jsval_t *args, int nargs) { 472 + jsval_t this_obj = js_getthis(js); 473 + 474 + if (nargs < 2) { 475 + return js_mkerr(js, "off requires 2 arguments (event, listener)"); 476 + } 477 + 478 + char *event_type = js_getstr(js, args[0], NULL); 479 + if (event_type == NULL) { 480 + return js_mkerr(js, "event must be a string"); 481 + } 482 + 483 + EventType *evt = find_emitter_event_type(js, this_obj, event_type); 484 + if (evt == NULL) { 485 + return this_obj; 486 + } 487 + 488 + for (int i = 0; i < evt->listener_count; i++) { 489 + if (evt->listeners[i].listener == args[1]) { 490 + for (int j = i; j < evt->listener_count - 1; j++) { 491 + evt->listeners[j] = evt->listeners[j + 1]; 492 + } 493 + evt->listener_count--; 494 + break; 495 + } 496 + } 497 + 498 + return this_obj; 499 + } 500 + 501 + // EventEmitter.prototype.emit(event, ...args) 502 + static jsval_t js_eventemitter_emit(struct js *js, jsval_t *args, int nargs) { 503 + jsval_t this_obj = js_getthis(js); 504 + 505 + if (nargs < 1) { 506 + return js_mkerr(js, "emit requires at least 1 argument (event)"); 507 + } 508 + 509 + char *event_type = js_getstr(js, args[0], NULL); 510 + if (event_type == NULL) { 511 + return js_mkerr(js, "event must be a string"); 512 + } 513 + 514 + EventType *evt = find_emitter_event_type(js, this_obj, event_type); 515 + if (evt == NULL || evt->listener_count == 0) { 516 + return js_mkfalse(); 517 + } 518 + 519 + int listener_nargs = nargs - 1; 520 + jsval_t *listener_args = (listener_nargs > 0) ? &args[1] : NULL; 521 + 522 + int i = 0; 523 + while (i < evt->listener_count) { 524 + EventListener *listener = &evt->listeners[i]; 525 + jsval_t result = js_call(js, listener->listener, listener_args, listener_nargs); 526 + 527 + if (js_type(result) == JS_ERR) { 528 + fprintf(stderr, "Error in event listener for '%s': %s\n", event_type, js_str(js, result)); 529 + } 530 + 531 + if (listener->once) { 532 + for (int j = i; j < evt->listener_count - 1; j++) { 533 + evt->listeners[j] = evt->listeners[j + 1]; 534 + } 535 + evt->listener_count--; 536 + } else { 537 + i++; 538 + } 539 + } 540 + 541 + return js_mktrue(); 542 + } 543 + 544 + // EventEmitter.prototype.removeAllListeners(event) 545 + static jsval_t js_eventemitter_removeAllListeners(struct js *js, jsval_t *args, int nargs) { 546 + jsval_t this_obj = js_getthis(js); 547 + 548 + if (nargs < 1) { 549 + return this_obj; 550 + } 551 + 552 + char *event_type = js_getstr(js, args[0], NULL); 553 + if (event_type == NULL) { 554 + return this_obj; 555 + } 556 + 557 + EventType *evt = find_emitter_event_type(js, this_obj, event_type); 558 + if (evt != NULL) { 559 + evt->listener_count = 0; 560 + } 561 + 562 + return this_obj; 563 + } 564 + 565 + // EventEmitter.prototype.listenerCount(event) 566 + static jsval_t js_eventemitter_listenerCount(struct js *js, jsval_t *args, int nargs) { 567 + jsval_t this_obj = js_getthis(js); 568 + 569 + if (nargs < 1) { 570 + return js_mknum(0); 571 + } 572 + 573 + char *event_type = js_getstr(js, args[0], NULL); 574 + if (event_type == NULL) { 575 + return js_mknum(0); 576 + } 577 + 578 + EventType *evt = find_emitter_event_type(js, this_obj, event_type); 579 + if (evt == NULL) { 580 + return js_mknum(0); 581 + } 582 + 583 + return js_mknum(evt->listener_count); 584 + } 585 + 586 + // EventEmitter.prototype.eventNames() 587 + static jsval_t js_eventemitter_eventNames(struct js *js, jsval_t *args, int nargs) { 588 + (void)args; (void)nargs; 589 + jsval_t this_obj = js_getthis(js); 590 + 591 + jsval_t result = js_mkarr(js); 592 + 593 + TargetEvents *te = get_or_create_emitter_events(js, this_obj); 594 + 595 + if (te != NULL && te->events != NULL) { 596 + EventType *evt, *tmp; 597 + HASH_ITER(hh, te->events, evt, tmp) { 598 + if (evt->listener_count > 0) { 599 + jsval_t name = js_mkstr(js, evt->event_type, strlen(evt->event_type)); 600 + js_arr_push(js, result, name); 601 + } 602 + } 603 + } 604 + 605 + return result; 606 + } 607 + 608 + // EventEmitter constructor 609 + static jsval_t js_eventemitter_constructor(struct js *js, jsval_t *args, int nargs) { 610 + (void)args; (void)nargs; 611 + 612 + jsval_t obj = js_mkobj(js); 613 + 614 + js_set(js, obj, "on", js_mkfun(js_eventemitter_on)); 615 + js_set(js, obj, "addListener", js_mkfun(js_eventemitter_on)); 616 + js_set(js, obj, "once", js_mkfun(js_eventemitter_once)); 617 + js_set(js, obj, "off", js_mkfun(js_eventemitter_off)); 618 + js_set(js, obj, "removeListener", js_mkfun(js_eventemitter_off)); 619 + js_set(js, obj, "emit", js_mkfun(js_eventemitter_emit)); 620 + js_set(js, obj, "removeAllListeners", js_mkfun(js_eventemitter_removeAllListeners)); 621 + js_set(js, obj, "listenerCount", js_mkfun(js_eventemitter_listenerCount)); 622 + js_set(js, obj, "eventNames", js_mkfun(js_eventemitter_eventNames)); 623 + js_set(js, obj, "@@toStringTag", js_mkstr(js, "EventEmitter", 12)); 624 + 625 + return obj; 626 + } 627 + 628 + jsval_t events_library(struct js *js) { 629 + jsval_t lib = js_mkobj(js); 630 + 631 + js_set(js, lib, "EventEmitter", js_mkfun(js_eventemitter_constructor)); 632 + js_set(js, lib, "@@toStringTag", js_mkstr(js, "events", 6)); 633 + 634 + return lib; 354 635 } 355 636 356 637 void init_events_module() {