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 better hash for library imports

+104 -151
+1 -1
meson.build
··· 68 68 build_date = run_command('date', '+%Y-%m-%d', check: true).stdout().strip() 69 69 70 70 version_conf = configuration_data() 71 - version_conf.set('ANT_VERSION', '0.0.7.5') 71 + version_conf.set('ANT_VERSION', '0.0.7.7') 72 72 version_conf.set('ANT_GIT_HASH', git_hash) 73 73 version_conf.set('ANT_BUILD_DATE', build_date) 74 74
+37 -56
src/ant.c
··· 15 15 #include <libgen.h> 16 16 #include <sys/stat.h> 17 17 #include <utarray.h> 18 + #include <uthash.h> 18 19 19 20 #include "ant.h" 20 21 #include "config.h" ··· 131 132 } esm_module_cache_t; 132 133 133 134 typedef struct ant_library { 134 - char *name; 135 + char name[256]; 135 136 ant_library_init_fn init_fn; 136 - struct ant_library *next; 137 + UT_hash_handle hh; 137 138 } ant_library_t; 138 139 139 140 static ant_library_t *library_registry = NULL; ··· 148 149 ant_library_t *lib = (ant_library_t *)ANT_GC_MALLOC(sizeof(ant_library_t)); 149 150 if (!lib) return; 150 151 151 - size_t name_len = strlen(name) + 1; 152 - lib->name = (char *)ANT_GC_MALLOC_ATOMIC(name_len); 153 - if (lib->name) memcpy(lib->name, name, name_len); 152 + strncpy(lib->name, name, sizeof(lib->name) - 1); 153 + lib->name[sizeof(lib->name) - 1] = '\0'; 154 + lib->init_fn = init_fn; 154 155 155 - lib->init_fn = init_fn; 156 - lib->next = library_registry; 157 - library_registry = lib; 156 + HASH_ADD_STR(library_registry, name, lib); 157 + } 158 + 159 + static ant_library_t* find_library(const char *specifier, size_t spec_len) { 160 + ant_library_t *lib = NULL; 161 + 162 + char key[256]; 163 + if (spec_len >= sizeof(key)) return NULL; 164 + memcpy(key, specifier, spec_len); 165 + key[spec_len] = '\0'; 166 + 167 + HASH_FIND_STR(library_registry, key, lib); 168 + return lib; 158 169 } 159 170 160 171 struct js { ··· 7455 7466 jsoff_t spec_off = vstr(js, args[0], &spec_len); 7456 7467 const char *specifier = (char *)&js->mem[spec_off]; 7457 7468 7458 - ant_library_t *lib = library_registry; 7459 - while (lib) { 7460 - if (strlen(lib->name) == spec_len && memcmp(lib->name, specifier, spec_len) == 0) { 7461 - jsval_t lib_obj = lib->init_fn(js); 7462 - if (is_err(lib_obj)) return builtin_Promise_reject(js, &lib_obj, 1); 7463 - jsval_t promise_args[] = { lib_obj }; 7464 - return builtin_Promise_resolve(js, promise_args, 1); 7465 - } 7466 - lib = lib->next; 7469 + ant_library_t *lib = find_library(specifier, spec_len); 7470 + if (lib) { 7471 + jsval_t lib_obj = lib->init_fn(js); 7472 + if (is_err(lib_obj)) return builtin_Promise_reject(js, &lib_obj, 1); 7473 + jsval_t promise_args[] = { lib_obj }; 7474 + return builtin_Promise_resolve(js, promise_args, 1); 7467 7475 } 7468 7476 7469 7477 const char *base_path = js->filename ? js->filename : "."; ··· 7600 7608 const char *specifier = (char *)&js->mem[spec_off]; 7601 7609 7602 7610 jsval_t ns = js_mkundef(); 7603 - bool is_library = false; 7604 - 7605 - ant_library_t *lib = library_registry; 7606 - while (lib) { 7607 - if (strlen(lib->name) == spec_len && memcmp(lib->name, specifier, spec_len) == 0) { 7608 - ns = lib->init_fn(js); 7609 - is_library = true; 7610 - break; 7611 - } 7612 - lib = lib->next; 7613 - } 7614 - 7615 - if (!is_library) { 7611 + ant_library_t *lib = find_library(specifier, spec_len); 7612 + if (lib) { 7613 + ns = lib->init_fn(js); 7614 + } else { 7616 7615 const char *base_path = js->filename ? js->filename : "."; 7617 7616 char *resolved_path = esm_resolve_path(specifier, base_path); 7618 7617 if (!resolved_path) { ··· 7663 7662 const char *specifier = (char *)&js->mem[spec_off]; 7664 7663 7665 7664 jsval_t ns = js_mkundef(); 7666 - bool is_library = false; 7667 - 7668 - ant_library_t *lib = library_registry; 7669 - while (lib) { 7670 - if (strlen(lib->name) == spec_len && memcmp(lib->name, specifier, spec_len) == 0) { 7671 - ns = lib->init_fn(js); 7672 - is_library = true; 7673 - break; 7674 - } 7675 - lib = lib->next; 7676 - } 7677 - 7678 - if (!is_library) { 7665 + ant_library_t *lib = find_library(specifier, spec_len); 7666 + if (lib) { 7667 + ns = lib->init_fn(js); 7668 + } else { 7679 7669 const char *base_path = js->filename ? js->filename : "."; 7680 7670 char *resolved_path = esm_resolve_path(specifier, base_path); 7681 7671 if (!resolved_path) { ··· 7764 7754 const char *specifier = (char *)&js->mem[spec_off]; 7765 7755 7766 7756 jsval_t ns = js_mkundef(); 7767 - bool is_library = false; 7768 - 7769 - ant_library_t *lib = library_registry; 7770 - while (lib) { 7771 - if (strlen(lib->name) == spec_len && memcmp(lib->name, specifier, spec_len) == 0) { 7772 - ns = lib->init_fn(js); 7773 - is_library = true; 7774 - break; 7775 - } 7776 - lib = lib->next; 7777 - } 7778 - 7779 - if (!is_library) { 7757 + ant_library_t *lib = find_library(specifier, spec_len); 7758 + if (lib) { 7759 + ns = lib->init_fn(js); 7760 + } else { 7780 7761 const char *base_path = js->filename ? js->filename : "."; 7781 7762 char *resolved_path = esm_resolve_path(specifier, base_path); 7782 7763 if (!resolved_path) return js_mkerr(js, "Cannot resolve module: %.*s", (int)spec_len, specifier);
-22
test_minimal.cjs
··· 1 - console.log('Testing recursive string assignment with objects'); 2 - 3 - function testRecursion(depth, params) { 4 - if (depth >= 10) return 'done'; 5 - 6 - let paramValue = ''; 7 - // This assignment causes parser corruption in certain contexts 8 - paramValue = 'test'; 9 - 10 - if (paramValue !== '') { 11 - params['test' + depth] = paramValue; 12 - const result = testRecursion(depth + 1, params); 13 - delete params['test' + depth]; 14 - return result; 15 - } 16 - 17 - return 'failed'; 18 - } 19 - 20 - const params = {}; 21 - const result = testRecursion(0, params); 22 - console.log('Result:', result);
-72
tests/test_gc.cjs
··· 1 - // Test Ant.gc(), Ant.alloc(), and Ant.stats() 2 - 3 - console.log("=== Testing Ant.alloc() ==="); 4 - let alloc1 = Ant.alloc(); 5 - console.log("Initial allocation:"); 6 - console.log(" used:", alloc1.used); 7 - console.log(" minFree:", alloc1.minFree); 8 - 9 - console.log("\n=== Creating objects to allocate memory ==="); 10 - let arr = []; 11 - for (let i = 0; i < 100; i = i + 1) { 12 - arr.push({ value: i, name: "item" + i }); 13 - } 14 - console.log("Created array with 100 objects"); 15 - 16 - let alloc2 = Ant.alloc(); 17 - console.log("After allocation:"); 18 - console.log(" used:", alloc2.used); 19 - console.log(" minFree:", alloc2.minFree); 20 - console.log(" increase:", alloc2.used - alloc1.used); 21 - 22 - console.log("\n=== Testing Ant.stats() ==="); 23 - let stats1 = Ant.stats(); 24 - console.log("Memory stats:"); 25 - console.log(" used:", stats1.used); 26 - console.log(" minFree:", stats1.minFree); 27 - console.log(" cstack:", stats1.cstack); 28 - 29 - console.log("\n=== Testing Ant.gc() ==="); 30 - // Clear reference to allow GC 31 - arr = null; 32 - 33 - let gcResult = Ant.gc(); 34 - console.log("GC result:"); 35 - console.log(" before break:", gcResult.before); 36 - console.log(" after break:", gcResult.after); 37 - console.log(" freed bytes:", gcResult.freed); 38 - 39 - console.log("\n=== Verifying memory after GC ==="); 40 - let alloc3 = Ant.alloc(); 41 - console.log("After GC:"); 42 - console.log(" used:", alloc3.used); 43 - console.log(" minFree:", alloc3.minFree); 44 - 45 - console.log("\n=== Testing multiple GC cycles ==="); 46 - // Allocate and free multiple times 47 - for (let cycle = 0; cycle < 3; cycle = cycle + 1) { 48 - console.log("Cycle", cycle + 1); 49 - 50 - // Allocate 51 - let temp = []; 52 - for (let i = 0; i < 50; i = i + 1) { 53 - temp.push({ data: "test data " + i }); 54 - } 55 - let beforeGc = Ant.alloc(); 56 - console.log(" Before GC - used:", beforeGc.used); 57 - 58 - // Clear and collect 59 - temp = null; 60 - let gc = Ant.gc(); 61 - console.log(" After GC - used:", gc.after, "freed bytes:", gc.freed); 62 - } 63 - 64 - console.log("\n=== Testing stats consistency ==="); 65 - let statsA = Ant.stats(); 66 - let allocA = Ant.alloc(); 67 - console.log("Stats and alloc should match:"); 68 - console.log(" stats.used:", statsA.used); 69 - console.log(" alloc.used:", allocA.used); 70 - console.log(" match:", statsA.used === allocA.used); 71 - 72 - console.log("\n=== Test complete ===");
+66
tests/test_gc.js
··· 1 + console.log('=== Testing Ant.alloc() ==='); 2 + let alloc1 = Ant.alloc(); 3 + console.log('Initial allocation:'); 4 + console.log(' used:', alloc1.used); 5 + console.log(' minFree:', alloc1.minFree); 6 + 7 + console.log('\n=== Creating objects to allocate memory ==='); 8 + let arr = []; 9 + for (let i = 0; i < 100; i = i + 1) { 10 + arr.push({ value: i, name: 'item' + i }); 11 + } 12 + console.log('Created array with 100 objects'); 13 + 14 + let alloc2 = Ant.alloc(); 15 + console.log('After allocation:'); 16 + console.log(' used:', alloc2.used); 17 + console.log(' minFree:', alloc2.minFree); 18 + console.log(' increase:', alloc2.used - alloc1.used); 19 + 20 + console.log('\n=== Testing Ant.stats() ==='); 21 + let stats1 = Ant.stats(); 22 + console.log('Memory stats:'); 23 + console.log(' used:', stats1.used); 24 + console.log(' minFree:', stats1.minFree); 25 + console.log(' cstack:', stats1.cstack); 26 + 27 + console.log('\n=== Testing Ant.gc() ==='); 28 + arr = null; 29 + 30 + let gcResult = Ant.gc(); 31 + console.log('GC result:'); 32 + console.log(' before break:', gcResult.before); 33 + console.log(' after break:', gcResult.after); 34 + console.log(' freed bytes:', gcResult.freed); 35 + 36 + console.log('\n=== Verifying memory after GC ==='); 37 + let alloc3 = Ant.alloc(); 38 + console.log('After GC:'); 39 + console.log(' used:', alloc3.used); 40 + console.log(' minFree:', alloc3.minFree); 41 + 42 + console.log('\n=== Testing multiple GC cycles ==='); 43 + for (let cycle = 0; cycle < 3; cycle = cycle + 1) { 44 + console.log('Cycle', cycle + 1); 45 + 46 + let temp = []; 47 + for (let i = 0; i < 50; i = i + 1) { 48 + temp.push({ data: 'test data ' + i }); 49 + } 50 + let beforeGc = Ant.alloc(); 51 + console.log(' Before GC - used:', beforeGc.used); 52 + 53 + temp = null; 54 + let gc = Ant.gc(); 55 + console.log(' After GC - used:', gc.after, 'freed bytes:', gc.freed); 56 + } 57 + 58 + console.log('\n=== Testing stats consistency ==='); 59 + let statsA = Ant.stats(); 60 + let allocA = Ant.alloc(); 61 + console.log('Stats and alloc should match:'); 62 + console.log(' stats.used:', statsA.used); 63 + console.log(' alloc.used:', allocA.used); 64 + console.log(' match:', statsA.used === allocA.used); 65 + 66 + console.log('\n=== Test complete ===');