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 Map and Set

+410 -1
+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.0.7.17') 77 + version_conf.set('ANT_VERSION', '0.0.7.18') 78 78 version_conf.set('ANT_GIT_HASH', git_hash) 79 79 version_conf.set('ANT_BUILD_DATE', build_date) 80 80
+319
src/ant.c
··· 353 353 static jsval_t builtin_promise_finally(struct js *js, jsval_t *args, int nargs); 354 354 static jsval_t builtin_Date(struct js *js, jsval_t *args, int nargs); 355 355 static jsval_t builtin_Date_now(struct js *js, jsval_t *args, int nargs); 356 + static jsval_t builtin_Map(struct js *js, jsval_t *args, int nargs); 357 + static jsval_t builtin_Set(struct js *js, jsval_t *args, int nargs); 358 + static jsval_t map_set(struct js *js, jsval_t *args, int nargs); 359 + static jsval_t map_get(struct js *js, jsval_t *args, int nargs); 360 + static jsval_t map_has(struct js *js, jsval_t *args, int nargs); 361 + static jsval_t map_delete(struct js *js, jsval_t *args, int nargs); 362 + static jsval_t map_clear(struct js *js, jsval_t *args, int nargs); 363 + static jsval_t map_size(struct js *js, jsval_t *args, int nargs); 364 + static jsval_t map_entries(struct js *js, jsval_t *args, int nargs); 365 + static jsval_t map_keys(struct js *js, jsval_t *args, int nargs); 366 + static jsval_t map_values(struct js *js, jsval_t *args, int nargs); 367 + static jsval_t map_forEach(struct js *js, jsval_t *args, int nargs); 368 + static jsval_t set_add(struct js *js, jsval_t *args, int nargs); 369 + static jsval_t set_has(struct js *js, jsval_t *args, int nargs); 370 + static jsval_t set_delete(struct js *js, jsval_t *args, int nargs); 371 + static jsval_t set_clear(struct js *js, jsval_t *args, int nargs); 372 + static jsval_t set_size(struct js *js, jsval_t *args, int nargs); 373 + static jsval_t set_values(struct js *js, jsval_t *args, int nargs); 374 + static jsval_t set_forEach(struct js *js, jsval_t *args, int nargs); 356 375 357 376 static jsval_t call_js(struct js *js, const char *fn, jsoff_t fnlen, jsval_t closure_scope); 358 377 static jsval_t call_js_with_args(struct js *js, jsval_t func, jsval_t *args, int nargs); ··· 2123 2142 return js_mkfun(builtin_array_includes); 2124 2143 } else if (streq(ptr, codereflen(r), "every", 5)) { 2125 2144 return js_mkfun(builtin_array_every); 2145 + } 2146 + } 2147 + 2148 + if (vtype(l) == T_OBJ) { 2149 + jsoff_t map_off = lkp(js, l, "__map", 5); 2150 + if (map_off != 0) { 2151 + if (streq(ptr, codereflen(r), "set", 3)) { 2152 + return js_mkfun(map_set); 2153 + } else if (streq(ptr, codereflen(r), "get", 3)) { 2154 + return js_mkfun(map_get); 2155 + } else if (streq(ptr, codereflen(r), "has", 3)) { 2156 + return js_mkfun(map_has); 2157 + } else if (streq(ptr, codereflen(r), "delete", 6)) { 2158 + return js_mkfun(map_delete); 2159 + } else if (streq(ptr, codereflen(r), "clear", 5)) { 2160 + return js_mkfun(map_clear); 2161 + } else if (streq(ptr, codereflen(r), "size", 4)) { 2162 + return js_mkfun(map_size); 2163 + } 2164 + } 2165 + 2166 + jsoff_t set_off = lkp(js, l, "__set", 5); 2167 + if (set_off != 0) { 2168 + if (streq(ptr, codereflen(r), "add", 3)) { 2169 + return js_mkfun(set_add); 2170 + } else if (streq(ptr, codereflen(r), "has", 3)) { 2171 + return js_mkfun(set_has); 2172 + } else if (streq(ptr, codereflen(r), "delete", 6)) { 2173 + return js_mkfun(set_delete); 2174 + } else if (streq(ptr, codereflen(r), "clear", 5)) { 2175 + return js_mkfun(set_clear); 2176 + } else if (streq(ptr, codereflen(r), "size", 4)) { 2177 + return js_mkfun(set_size); 2178 + } 2126 2179 } 2127 2180 } 2128 2181 ··· 8274 8327 return js_mkerr(js, "Invalid export statement"); 8275 8328 } 8276 8329 8330 + typedef struct map_entry { 8331 + char *key; 8332 + jsval_t value; 8333 + UT_hash_handle hh; 8334 + } map_entry_t; 8335 + 8336 + typedef struct set_entry { 8337 + jsval_t value; 8338 + char *key; 8339 + UT_hash_handle hh; 8340 + } set_entry_t; 8341 + 8342 + static const char* jsval_to_key(struct js *js, jsval_t val) { 8343 + if (vtype(val) == T_STR) { 8344 + jsoff_t len; 8345 + jsoff_t off = vstr(js, val, &len); 8346 + return (char *)&js->mem[off]; 8347 + } else return js_str(js, val); 8348 + } 8349 + 8350 + static jsval_t builtin_Map(struct js *js, jsval_t *args, int nargs) { 8351 + jsval_t map_obj = mkobj(js, 0); 8352 + 8353 + map_entry_t **map_head = (map_entry_t **)ANT_GC_MALLOC(sizeof(map_entry_t *)); 8354 + if (!map_head) return js_mkerr(js, "out of memory"); 8355 + *map_head = NULL; 8356 + 8357 + jsval_t map_ptr = mkval(T_NUM, (size_t)map_head); 8358 + jsval_t map_key = js_mkstr(js, "__map", 5); 8359 + setprop(js, map_obj, map_key, map_ptr); 8360 + 8361 + return map_obj; 8362 + } 8363 + 8364 + static jsval_t builtin_Set(struct js *js, jsval_t *args, int nargs) { 8365 + jsval_t set_obj = mkobj(js, 0); 8366 + 8367 + set_entry_t **set_head = (set_entry_t **)ANT_GC_MALLOC(sizeof(set_entry_t *)); 8368 + if (!set_head) return js_mkerr(js, "out of memory"); 8369 + *set_head = NULL; 8370 + 8371 + jsval_t set_ptr = mkval(T_NUM, (size_t)set_head); 8372 + jsval_t set_key = js_mkstr(js, "__set", 5); 8373 + setprop(js, set_obj, set_key, set_ptr); 8374 + 8375 + return set_obj; 8376 + } 8377 + 8378 + static map_entry_t** get_map_from_obj(struct js *js, jsval_t obj) { 8379 + jsoff_t map_off = lkp(js, obj, "__map", 5); 8380 + if (map_off == 0) return NULL; 8381 + jsval_t map_val = resolveprop(js, mkval(T_PROP, map_off)); 8382 + if (vtype(map_val) != T_NUM) return NULL; 8383 + return (map_entry_t**)(size_t)vdata(map_val); 8384 + } 8385 + 8386 + static set_entry_t** get_set_from_obj(struct js *js, jsval_t obj) { 8387 + jsoff_t set_off = lkp(js, obj, "__set", 5); 8388 + if (set_off == 0) return NULL; 8389 + jsval_t set_val = resolveprop(js, mkval(T_PROP, set_off)); 8390 + if (vtype(set_val) != T_NUM) return NULL; 8391 + return (set_entry_t**)(size_t)vdata(set_val); 8392 + } 8393 + 8394 + static jsval_t map_set(struct js *js, jsval_t *args, int nargs) { 8395 + if (nargs < 2) return js_mkerr(js, "Map.set() requires 2 arguments"); 8396 + 8397 + jsval_t this_val = js->this_val; 8398 + map_entry_t **map_ptr = get_map_from_obj(js, this_val); 8399 + if (!map_ptr) return js_mkerr(js, "Invalid Map object"); 8400 + 8401 + const char *key_str; 8402 + if (vtype(args[0]) == T_STR) { 8403 + jsoff_t len; 8404 + jsoff_t off = vstr(js, args[0], &len); 8405 + key_str = (char *)&js->mem[off]; 8406 + } else key_str = js_str(js, args[0]); 8407 + 8408 + map_entry_t *entry; 8409 + HASH_FIND_STR(*map_ptr, key_str, entry); 8410 + if (entry) { 8411 + entry->value = args[1]; 8412 + } else { 8413 + entry = (map_entry_t *)ANT_GC_MALLOC(sizeof(map_entry_t)); 8414 + if (!entry) return js_mkerr(js, "out of memory"); 8415 + entry->key = strdup(key_str); 8416 + entry->value = args[1]; 8417 + HASH_ADD_STR(*map_ptr, key, entry); 8418 + } 8419 + 8420 + return this_val; 8421 + } 8422 + 8423 + static jsval_t map_get(struct js *js, jsval_t *args, int nargs) { 8424 + if (nargs < 1) return js_mkerr(js, "Map.get() requires 1 argument"); 8425 + 8426 + jsval_t this_val = js->this_val; 8427 + map_entry_t **map_ptr = get_map_from_obj(js, this_val); 8428 + if (!map_ptr) return js_mkundef(); 8429 + 8430 + const char *key_str; 8431 + if (vtype(args[0]) == T_STR) { 8432 + jsoff_t len; 8433 + jsoff_t off = vstr(js, args[0], &len); 8434 + key_str = (char *)&js->mem[off]; 8435 + } else key_str = js_str(js, args[0]); 8436 + 8437 + map_entry_t *entry; 8438 + HASH_FIND_STR(*map_ptr, key_str, entry); 8439 + return entry ? entry->value : js_mkundef(); 8440 + } 8441 + 8442 + static jsval_t map_has(struct js *js, jsval_t *args, int nargs) { 8443 + if (nargs < 1) return js_mkerr(js, "Map.has() requires 1 argument"); 8444 + 8445 + jsval_t this_val = js->this_val; 8446 + map_entry_t **map_ptr = get_map_from_obj(js, this_val); 8447 + if (!map_ptr) return mkval(T_BOOL, 0); 8448 + 8449 + const char *key_str; 8450 + if (vtype(args[0]) == T_STR) { 8451 + jsoff_t len; 8452 + jsoff_t off = vstr(js, args[0], &len); 8453 + key_str = (char *)&js->mem[off]; 8454 + } else key_str = js_str(js, args[0]); 8455 + 8456 + map_entry_t *entry; 8457 + HASH_FIND_STR(*map_ptr, key_str, entry); 8458 + return mkval(T_BOOL, entry ? 1 : 0); 8459 + } 8460 + 8461 + static jsval_t map_delete(struct js *js, jsval_t *args, int nargs) { 8462 + if (nargs < 1) return js_mkerr(js, "Map.delete() requires 1 argument"); 8463 + 8464 + jsval_t this_val = js->this_val; 8465 + map_entry_t **map_ptr = get_map_from_obj(js, this_val); 8466 + if (!map_ptr) return mkval(T_BOOL, 0); 8467 + 8468 + const char *key_str; 8469 + if (vtype(args[0]) == T_STR) { 8470 + jsoff_t len; 8471 + jsoff_t off = vstr(js, args[0], &len); 8472 + key_str = (char *)&js->mem[off]; 8473 + } else key_str = js_str(js, args[0]); 8474 + 8475 + map_entry_t *entry; 8476 + HASH_FIND_STR(*map_ptr, key_str, entry); 8477 + if (entry) { 8478 + HASH_DEL(*map_ptr, entry); 8479 + free(entry->key); 8480 + ANT_GC_FREE(entry); 8481 + return mkval(T_BOOL, 1); 8482 + } 8483 + return mkval(T_BOOL, 0); 8484 + } 8485 + 8486 + static jsval_t map_clear(struct js *js, jsval_t *args, int nargs) { 8487 + jsval_t this_val = js->this_val; 8488 + map_entry_t **map_ptr = get_map_from_obj(js, this_val); 8489 + if (!map_ptr) return js_mkundef(); 8490 + 8491 + map_entry_t *entry, *tmp; 8492 + HASH_ITER(hh, *map_ptr, entry, tmp) { 8493 + HASH_DEL(*map_ptr, entry); 8494 + free(entry->key); 8495 + ANT_GC_FREE(entry); 8496 + } 8497 + *map_ptr = NULL; 8498 + 8499 + return js_mkundef(); 8500 + } 8501 + 8502 + static jsval_t map_size(struct js *js, jsval_t *args, int nargs) { 8503 + jsval_t this_val = js->this_val; 8504 + map_entry_t **map_ptr = get_map_from_obj(js, this_val); 8505 + if (!map_ptr) return tov(0); 8506 + 8507 + size_t count = HASH_COUNT(*map_ptr); 8508 + return tov((double)count); 8509 + } 8510 + 8511 + static jsval_t set_add(struct js *js, jsval_t *args, int nargs) { 8512 + if (nargs < 1) return js_mkerr(js, "Set.add() requires 1 argument"); 8513 + 8514 + jsval_t this_val = js->this_val; 8515 + set_entry_t **set_ptr = get_set_from_obj(js, this_val); 8516 + if (!set_ptr) return js_mkerr(js, "Invalid Set object"); 8517 + 8518 + const char *key_str = jsval_to_key(js, args[0]); 8519 + 8520 + set_entry_t *entry; 8521 + HASH_FIND_STR(*set_ptr, key_str, entry); 8522 + 8523 + if (!entry) { 8524 + entry = (set_entry_t *)ANT_GC_MALLOC(sizeof(set_entry_t)); 8525 + if (!entry) return js_mkerr(js, "out of memory"); 8526 + entry->value = args[0]; 8527 + entry->key = strdup(key_str); 8528 + HASH_ADD_KEYPTR(hh, *set_ptr, entry->key, strlen(entry->key), entry); 8529 + } 8530 + 8531 + return this_val; 8532 + } 8533 + 8534 + static jsval_t set_has(struct js *js, jsval_t *args, int nargs) { 8535 + if (nargs < 1) return js_mkerr(js, "Set.has() requires 1 argument"); 8536 + 8537 + jsval_t this_val = js->this_val; 8538 + set_entry_t **set_ptr = get_set_from_obj(js, this_val); 8539 + if (!set_ptr) return mkval(T_BOOL, 0); 8540 + 8541 + const char *key_str = jsval_to_key(js, args[0]); 8542 + 8543 + set_entry_t *entry; 8544 + HASH_FIND_STR(*set_ptr, key_str, entry); 8545 + 8546 + return mkval(T_BOOL, entry ? 1 : 0); 8547 + } 8548 + 8549 + static jsval_t set_delete(struct js *js, jsval_t *args, int nargs) { 8550 + if (nargs < 1) return js_mkerr(js, "Set.delete() requires 1 argument"); 8551 + 8552 + jsval_t this_val = js->this_val; 8553 + set_entry_t **set_ptr = get_set_from_obj(js, this_val); 8554 + if (!set_ptr) return mkval(T_BOOL, 0); 8555 + 8556 + const char *key_str = jsval_to_key(js, args[0]); 8557 + set_entry_t *entry; 8558 + HASH_FIND_STR(*set_ptr, key_str, entry); 8559 + 8560 + if (entry) { 8561 + HASH_DEL(*set_ptr, entry); 8562 + free(entry->key); 8563 + ANT_GC_FREE(entry); 8564 + return mkval(T_BOOL, 1); 8565 + } 8566 + return mkval(T_BOOL, 0); 8567 + } 8568 + 8569 + static jsval_t set_clear(struct js *js, jsval_t *args, int nargs) { 8570 + jsval_t this_val = js->this_val; 8571 + set_entry_t **set_ptr = get_set_from_obj(js, this_val); 8572 + if (!set_ptr) return js_mkundef(); 8573 + 8574 + set_entry_t *entry, *tmp; 8575 + HASH_ITER(hh, *set_ptr, entry, tmp) { 8576 + HASH_DEL(*set_ptr, entry); 8577 + free(entry->key); 8578 + ANT_GC_FREE(entry); 8579 + } 8580 + *set_ptr = NULL; 8581 + 8582 + return js_mkundef(); 8583 + } 8584 + 8585 + static jsval_t set_size(struct js *js, jsval_t *args, int nargs) { 8586 + jsval_t this_val = js->this_val; 8587 + set_entry_t **set_ptr = get_set_from_obj(js, this_val); 8588 + if (!set_ptr) return tov(0); 8589 + 8590 + size_t count = HASH_COUNT(*set_ptr); 8591 + return tov((double)count); 8592 + } 8593 + 8277 8594 struct js *js_create(void *buf, size_t len) { 8278 8595 ANT_GC_INIT(); 8279 8596 init_free_list(); ··· 8313 8630 8314 8631 setprop(js, glob, js_mkstr(js, "Boolean", 7), js_mkfun(builtin_Boolean)); 8315 8632 setprop(js, glob, js_mkstr(js, "Array", 5), js_mkfun(builtin_Array)); 8633 + setprop(js, glob, js_mkstr(js, "Map", 3), js_mkfun(builtin_Map)); 8634 + setprop(js, glob, js_mkstr(js, "Set", 3), js_mkfun(builtin_Set)); 8316 8635 setprop(js, glob, js_mkstr(js, "Error", 5), js_mkfun(builtin_Error)); 8317 8636 setprop(js, glob, js_mkstr(js, "RegExp", 6), js_mkfun(builtin_RegExp)); 8318 8637 setprop(js, glob, js_mkstr(js, "parseInt", 8), js_mkfun(builtin_parseInt));
+42
tests/test_map.js
··· 1 + // Test Map functionality 2 + const map = new Map(); 3 + 4 + // Test basic set/get 5 + map.set('key1', 'value1'); 6 + map.set('key2', 42); 7 + map.set('key3', true); 8 + 9 + console.log('Map size:', map.size()); // Should be 3 10 + console.log('Get key1:', map.get('key1')); // Should be 'value1' 11 + console.log('Get key2:', map.get('key2')); // Should be 42 12 + console.log('Get key3:', map.get('key3')); // Should be true 13 + 14 + // Test has() 15 + console.log('Has key1:', map.has('key1')); // Should be true 16 + console.log('Has missing:', map.has('missing')); // Should be false 17 + 18 + // Test delete() 19 + console.log('Delete key2:', map.delete('key2')); // Should be true 20 + console.log('Has key2 after delete:', map.has('key2')); // Should be false 21 + console.log('Map size after delete:', map.size()); // Should be 2 22 + 23 + // Test overwrite 24 + map.set('key1', 'newvalue1'); 25 + console.log('Get key1 after overwrite:', map.get('key1')); // Should be 'newvalue1' 26 + 27 + // Test clear() 28 + map.clear(); 29 + console.log('Map size after clear:', map.size()); // Should be 0 30 + console.log('Has key1 after clear:', map.has('key1')); // Should be false 31 + 32 + // Test with different key types 33 + map.set(123, 'number key'); 34 + map.set(true, 'boolean key'); 35 + map.set(null, 'null key'); 36 + 37 + console.log('Get number key:', map.get(123)); // Should be 'number key' 38 + console.log('Get boolean key:', map.get(true)); // Should be 'boolean key' 39 + console.log('Get null key:', map.get(null)); // Should be 'null key' 40 + console.log('Final map size:', map.size()); // Should be 3 41 + 42 + console.log('Map tests completed!');
+48
tests/test_set.js
··· 1 + // Test Set functionality 2 + const set = new Set(); 3 + 4 + // Test basic add/has 5 + set.add('value1'); 6 + set.add('value2'); 7 + set.add(42); 8 + set.add(true); 9 + 10 + console.log('Set size:', set.size()); // Should be 4 11 + console.log('Has value1:', set.has('value1')); // Should be true 12 + console.log('Has value2:', set.has('value2')); // Should be true 13 + console.log('Has 42:', set.has(42)); // Should be true 14 + console.log('Has true:', set.has(true)); // Should be true 15 + console.log('Has missing:', set.has('missing')); // Should be false 16 + 17 + // Test delete() 18 + console.log('Delete value2:', set.delete('value2')); // Should be true 19 + console.log('Has value2 after delete:', set.has('value2')); // Should be false 20 + console.log('Set size after delete:', set.size()); // Should be 3 21 + 22 + // Test adding duplicates (should not increase size) 23 + set.add('value1'); // Adding duplicate 24 + console.log('Set size after duplicate add:', set.size()); // Should still be 3 25 + 26 + // Test with different value types 27 + set.add(123); 28 + set.add(null); 29 + set.add({key: 'object'}); 30 + 31 + console.log('Has 123:', set.has(123)); // Should be true 32 + console.log('Has null:', set.has(null)); // Should be true 33 + console.log('Has object:', set.has({key: 'object'})); // Should be true 34 + console.log('Final set size:', set.size()); // Should be 7 35 + 36 + // Test clear() 37 + set.clear(); 38 + console.log('Set size after clear:', set.size()); // Should be 0 39 + console.log('Has value1 after clear:', set.has('value1')); // Should be false 40 + 41 + // Test chaining 42 + set.add('a').add('b').add('c'); 43 + console.log('Set size after chaining:', set.size()); // Should be 3 44 + console.log('Has a:', set.has('a')); // Should be true 45 + console.log('Has b:', set.has('b')); // Should be true 46 + console.log('Has c:', set.has('c')); // Should be true 47 + 48 + console.log('Set tests completed!');