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 gc tests

+468 -3
+4 -1
tests/test_async_gc.js
··· 22 22 console.log('Done'); 23 23 } 24 24 25 - main(); 25 + main().then(() => { 26 + console.log('=== async done, calling gc ==='); 27 + console.log(Ant.gc()); 28 + });
+27 -2
tests/test_gc.js
··· 4 4 console.log(' heapSize:', alloc1.heapSize); 5 5 console.log(' usedBytes:', alloc1.usedBytes); 6 6 console.log(' freeBytes:', alloc1.freeBytes); 7 + console.log(' totalBytes:', alloc1.totalBytes); 7 8 8 9 console.log('\n=== Creating objects to allocate memory ==='); 9 10 let arr = []; ··· 16 17 console.log('After allocation:'); 17 18 console.log(' heapSize:', alloc2.heapSize); 18 19 console.log(' usedBytes:', alloc2.usedBytes); 19 - console.log(' increase:', alloc2.usedBytes - alloc1.usedBytes); 20 + console.log(' totalBytes:', alloc2.totalBytes); 21 + console.log(' totalBytes increase:', alloc2.totalBytes - alloc1.totalBytes); 20 22 21 23 console.log('\n=== Testing Ant.stats() ==='); 22 24 let stats1 = Ant.stats(); ··· 38 40 console.log(' usedBefore:', gcResult.usedBefore); 39 41 console.log(' usedAfter:', gcResult.usedAfter); 40 42 console.log(' freed:', gcResult.freed); 43 + console.log(' arenaBefore:', gcResult.arenaBefore); 44 + console.log(' arenaAfter:', gcResult.arenaAfter); 45 + console.log(' arenaFreed:', gcResult.arenaFreed); 46 + 47 + console.log('\n=== Testing Ant.stats() ==='); 48 + let stats2 = Ant.stats(); 49 + console.log('Memory stats:'); 50 + console.log(' arenaUsed:', stats2.arenaUsed); 51 + console.log(' arenaLwm:', stats2.arenaLwm); 52 + console.log(' cstack:', stats2.cstack); 53 + console.log(' gcHeapSize:', stats2.gcHeapSize); 54 + console.log(' gcUsedBytes:', stats2.gcUsedBytes); 55 + console.log(' gcFreeBytes:', stats2.gcFreeBytes); 41 56 42 57 console.log('\n=== Verifying memory after GC ==='); 43 58 let alloc3 = Ant.alloc(); ··· 59 74 60 75 temp = null; 61 76 let gc = Ant.gc(); 62 - console.log(' After GC - usedAfter:', gc.usedAfter, 'freed:', gc.freed); 77 + console.log(' After GC - usedAfter:', gc.usedAfter, 'freed:', gc.freed, 'arenaFreed:', gc.arenaFreed); 63 78 } 79 + 80 + console.log('\n=== Testing Ant.stats() ==='); 81 + let stats3 = Ant.stats(); 82 + console.log('Memory stats:'); 83 + console.log(' arenaUsed:', stats3.arenaUsed); 84 + console.log(' arenaLwm:', stats3.arenaLwm); 85 + console.log(' cstack:', stats3.cstack); 86 + console.log(' gcHeapSize:', stats3.gcHeapSize); 87 + console.log(' gcUsedBytes:', stats3.gcUsedBytes); 88 + console.log(' gcFreeBytes:', stats3.gcFreeBytes); 64 89 65 90 console.log('\n=== Testing stats consistency ==='); 66 91 let statsA = Ant.stats();
+191
tests/test_gc_comprehensive.js
··· 1 + console.log('=== Comprehensive GC Test ==='); 2 + console.log('Starting...\n'); 3 + 4 + let failures = 0; 5 + function assert(condition, msg) { 6 + if (!condition) { 7 + console.log('FAIL:', msg); 8 + failures = failures + 1; 9 + } 10 + } 11 + 12 + // Test 1: Basic objects and arrays survive GC 13 + console.log('Test 1: Objects and Arrays'); 14 + let obj1 = { name: 'test', value: 42, nested: { deep: 'value' } }; 15 + let arr1 = [1, 2, 3, { inner: 'object' }, 'string']; 16 + Ant.gc(); 17 + assert(obj1.name === 'test', 'obj1.name should be "test"'); 18 + assert(obj1.nested.deep === 'value', 'nested object should survive'); 19 + assert(arr1.length === 5, 'array length should be 5'); 20 + assert(arr1[3].inner === 'object', 'array nested object should survive'); 21 + console.log(' Objects and arrays: OK\n'); 22 + 23 + // Test 2: Map survives GC 24 + console.log('Test 2: Map'); 25 + let map = new Map(); 26 + map.set('key1', { data: 'value1' }); 27 + map.set('key2', [1, 2, 3]); 28 + map.set('key3', 'simple string'); 29 + Ant.gc(); 30 + assert(map.get('key1').data === 'value1', 'map value object should survive'); 31 + assert(map.get('key2')[1] === 2, 'map value array should survive'); 32 + assert(map.get('key3') === 'simple string', 'map value string should survive'); 33 + assert(map.size() === 3, 'map size should be 3'); 34 + console.log(' Map: OK\n'); 35 + 36 + // Test 3: Set survives GC 37 + console.log('Test 3: Set'); 38 + let set = new Set(); 39 + let setObj = { id: 123 }; 40 + set.add('value1'); 41 + set.add(42); 42 + set.add(setObj); 43 + Ant.gc(); 44 + assert(set.has('value1'), 'set should have "value1"'); 45 + assert(set.has(42), 'set should have 42'); 46 + assert(set.size() === 3, 'set size should be 3'); 47 + console.log(' Set: OK\n'); 48 + 49 + // Test 4: Property descriptors (getters/setters) survive GC 50 + console.log('Test 4: Property Descriptors'); 51 + let descObj = {}; 52 + let _hidden = 'initial'; 53 + Object.defineProperty(descObj, 'prop', { 54 + get: function() { return _hidden; }, 55 + set: function(v) { _hidden = v; }, 56 + enumerable: true, 57 + configurable: true 58 + }); 59 + descObj.prop = 'updated'; 60 + Ant.gc(); 61 + assert(descObj.prop === 'updated', 'getter should return updated value'); 62 + descObj.prop = 'after gc'; 63 + assert(descObj.prop === 'after gc', 'setter should work after GC'); 64 + console.log(' Property descriptors: OK\n'); 65 + 66 + // Test 5: Promises survive GC 67 + console.log('Test 5: Promises'); 68 + let promiseResolved = false; 69 + let promiseValue = null; 70 + let p = new Promise((resolve) => { 71 + resolve({ result: 'success' }); 72 + }); 73 + p.then((val) => { 74 + promiseResolved = true; 75 + promiseValue = val; 76 + }); 77 + Ant.gc(); 78 + // Run microtasks 79 + console.log(' Waiting for promise...'); 80 + 81 + // Test 6: Proxy survives GC 82 + console.log('Test 6: Proxy'); 83 + let proxyTarget = { x: 10, y: 20 }; 84 + let proxyHandler = { 85 + get: function(target, prop) { 86 + if (prop === 'sum') return target.x + target.y; 87 + return target[prop]; 88 + } 89 + }; 90 + let proxy = new Proxy(proxyTarget, proxyHandler); 91 + Ant.gc(); 92 + assert(proxy.x === 10, 'proxy.x should be 10'); 93 + assert(proxy.y === 20, 'proxy.y should be 20'); 94 + assert(proxy.sum === 30, 'proxy.sum should be 30'); 95 + console.log(' Proxy: OK\n'); 96 + 97 + // Test 7: Closures survive GC 98 + console.log('Test 7: Closures'); 99 + function makeCounter() { 100 + let count = 0; 101 + return { 102 + inc: function() { count = count + 1; return count; }, 103 + get: function() { return count; } 104 + }; 105 + } 106 + let counter = makeCounter(); 107 + counter.inc(); 108 + counter.inc(); 109 + Ant.gc(); 110 + assert(counter.get() === 2, 'closure should preserve count'); 111 + counter.inc(); 112 + assert(counter.get() === 3, 'closure should work after GC'); 113 + console.log(' Closures: OK\n'); 114 + 115 + // Test 8: Multiple GC cycles 116 + console.log('Test 8: Multiple GC Cycles'); 117 + let cycleData = { iteration: 0 }; 118 + for (let i = 0; i < 5; i = i + 1) { 119 + cycleData.iteration = i; 120 + cycleData['data' + i] = { value: i * 10 }; 121 + Ant.gc(); 122 + } 123 + assert(cycleData.iteration === 4, 'iteration should be 4'); 124 + assert(cycleData.data3.value === 30, 'data3.value should be 30'); 125 + console.log(' Multiple cycles: OK\n'); 126 + 127 + // Test 9: Large allocations + GC 128 + console.log('Test 9: Large Allocations'); 129 + let largeArr = []; 130 + for (let i = 0; i < 1000; i = i + 1) { 131 + largeArr.push({ index: i, data: 'item ' + i }); 132 + } 133 + let allocBefore = Ant.alloc(); 134 + Ant.gc(); 135 + let allocAfter = Ant.alloc(); 136 + assert(largeArr.length === 1000, 'large array should have 1000 elements'); 137 + assert(largeArr[500].index === 500, 'element 500 should be correct'); 138 + assert(largeArr[999].data === 'item 999', 'last element should be correct'); 139 + console.log(' Large allocations: OK\n'); 140 + 141 + // Test 10: Nested structures 142 + console.log('Test 10: Nested Structures'); 143 + let nested = { 144 + level1: { 145 + level2: { 146 + level3: { 147 + level4: { 148 + value: 'deep' 149 + } 150 + } 151 + } 152 + } 153 + }; 154 + let nestedArr = [[[[['innermost']]]]]; 155 + Ant.gc(); 156 + assert(nested.level1.level2.level3.level4.value === 'deep', 'deep nesting should survive'); 157 + assert(nestedArr[0][0][0][0][0] === 'innermost', 'nested array should survive'); 158 + console.log(' Nested structures: OK\n'); 159 + 160 + // Summary 161 + console.log('=== Test Summary ==='); 162 + if (failures === 0) { 163 + console.log('All tests passed!'); 164 + } else { 165 + console.log('Failures:', failures); 166 + } 167 + 168 + // Test async separately (needs event loop) 169 + console.log('\n=== Async GC Test ==='); 170 + async function testAsyncGC() { 171 + let asyncData = { value: 'before await' }; 172 + 173 + await new Promise(resolve => setTimeout(resolve, 10)); 174 + 175 + // GC inside coroutine (should skip compaction) 176 + Ant.gc(); 177 + 178 + asyncData.value = 'after first await'; 179 + 180 + await new Promise(resolve => setTimeout(resolve, 10)); 181 + 182 + assert(asyncData.value === 'after first await', 'async data should survive await'); 183 + 184 + console.log(' Async GC: OK'); 185 + return 'async complete'; 186 + } 187 + 188 + testAsyncGC().then((result) => { 189 + console.log(' Result:', result); 190 + console.log('\n=== All Tests Complete ==='); 191 + });
+18
tests/test_gc_cycles.js
··· 1 + console.log('=== Testing Multiple GC Cycles ===\n'); 2 + 3 + let cycleData = { iteration: 0 }; 4 + for (let i = 0; i < 5; i = i + 1) { 5 + console.log('Cycle', i); 6 + cycleData.iteration = i; 7 + cycleData['data' + i] = { value: i * 10 }; 8 + console.log(' Before GC - iteration:', cycleData.iteration); 9 + let result = Ant.gc(); 10 + console.log(' GC result - arenaFreed:', result.arenaFreed); 11 + console.log(' After GC - iteration:', cycleData.iteration); 12 + } 13 + 14 + console.log('\nFinal check:'); 15 + console.log(' iteration:', cycleData.iteration); 16 + console.log(' data3.value:', cycleData.data3.value); 17 + 18 + console.log('\n=== Done ===');
+78
tests/test_gc_debug.js
··· 1 + console.log('=== Debug GC Test ===\n'); 2 + 3 + // Test 1 4 + console.log('Test 1: Objects'); 5 + let obj1 = { name: 'test', value: 42, nested: { deep: 'value' } }; 6 + Ant.gc(); 7 + console.log(' OK\n'); 8 + 9 + // Test 2 10 + console.log('Test 2: Map'); 11 + let map = new Map(); 12 + map.set('key1', { data: 'value1' }); 13 + map.set('key2', [1, 2, 3]); 14 + Ant.gc(); 15 + console.log(' get key1:', map.get('key1')); 16 + console.log(' OK\n'); 17 + 18 + // Test 3 19 + console.log('Test 3: Set'); 20 + let set = new Set(); 21 + set.add('value1'); 22 + set.add(42); 23 + Ant.gc(); 24 + console.log(' OK\n'); 25 + 26 + // Test 4 27 + console.log('Test 4: Property Descriptors'); 28 + let descObj = {}; 29 + let _hidden = 'initial'; 30 + Object.defineProperty(descObj, 'prop', { 31 + get: function() { return _hidden; }, 32 + set: function(v) { _hidden = v; }, 33 + enumerable: true, 34 + configurable: true 35 + }); 36 + descObj.prop = 'updated'; 37 + Ant.gc(); 38 + console.log(' prop:', descObj.prop); 39 + console.log(' OK\n'); 40 + 41 + // Test 5 42 + console.log('Test 5: Promises'); 43 + let p = new Promise((resolve) => { 44 + resolve({ result: 'success' }); 45 + }); 46 + Ant.gc(); 47 + console.log(' OK\n'); 48 + 49 + // Test 6 50 + console.log('Test 6: Proxy'); 51 + let proxyTarget = { x: 10, y: 20 }; 52 + let proxyHandler = { 53 + get: function(target, prop) { 54 + if (prop === 'sum') return target.x + target.y; 55 + return target[prop]; 56 + } 57 + }; 58 + let proxy = new Proxy(proxyTarget, proxyHandler); 59 + Ant.gc(); 60 + console.log(' proxy.x:', proxy.x); 61 + console.log(' OK\n'); 62 + 63 + // Test 7 64 + console.log('Test 7: Closures'); 65 + function makeCounter() { 66 + let count = 0; 67 + return { 68 + inc: function() { count = count + 1; return count; }, 69 + get: function() { return count; } 70 + }; 71 + } 72 + let counter = makeCounter(); 73 + counter.inc(); 74 + Ant.gc(); 75 + console.log(' count:', counter.get()); 76 + console.log(' OK\n'); 77 + 78 + console.log('=== All tests passed ===');
+59
tests/test_gc_large.js
··· 1 + console.log('=== GC Test with Large Objects ===\n'); 2 + 3 + let alloc1 = Ant.alloc(); 4 + console.log('Initial:'); 5 + console.log(' heapSize:', alloc1.heapSize); 6 + console.log(' totalBytes:', alloc1.totalBytes); 7 + console.log(''); 8 + 9 + // Allocate large objects 10 + let largeObjects = []; 11 + for (let i = 0; i < 5; i++) { 12 + let arr = new Array(1024 * 128); 13 + for (let j = 0; j < arr.length; j += 1024) { 14 + arr[j] = i; 15 + } 16 + largeObjects.push(arr); 17 + } 18 + 19 + let alloc2 = Ant.alloc(); 20 + console.log('After allocating 5MB:'); 21 + console.log(' heapSize:', alloc2.heapSize); 22 + console.log(' totalBytes:', alloc2.totalBytes); 23 + console.log(''); 24 + 25 + // Free the objects 26 + largeObjects = null; 27 + 28 + let gc1 = Ant.gc(); 29 + console.log('GC 1: freed:', gc1.freed, 'arenaFreed:', gc1.arenaFreed); 30 + let gc2 = Ant.gc(); 31 + console.log('GC 2: freed:', gc2.freed, 'arenaFreed:', gc2.arenaFreed); 32 + let gc3 = Ant.gc(); 33 + console.log('GC 3: freed:', gc3.freed, 'arenaFreed:', gc3.arenaFreed); 34 + 35 + let alloc3 = Ant.alloc(); 36 + console.log('After 3x GC:'); 37 + console.log(' heapSize:', alloc3.heapSize); 38 + console.log(' totalBytes:', alloc3.totalBytes); 39 + console.log(''); 40 + 41 + // Allocate again - if GC worked, heap shouldn't grow much 42 + let moreObjects = []; 43 + for (let i = 0; i < 5; i++) { 44 + let arr = new Array(1024 * 128); 45 + for (let j = 0; j < arr.length; j += 1024) { 46 + arr[j] = i; 47 + } 48 + moreObjects.push(arr); 49 + } 50 + 51 + let alloc4 = Ant.alloc(); 52 + console.log('After allocating another 5MB:'); 53 + console.log(' heapSize:', alloc4.heapSize); 54 + console.log(' totalBytes:', alloc4.totalBytes); 55 + console.log(' heap increase from GC point:', alloc4.heapSize - alloc3.heapSize); 56 + console.log(''); 57 + 58 + console.log('If heapSize stayed same, GC reclaimed memory for reuse!'); 59 + console.log('=== Test Complete ===');
+42
tests/test_gc_minimal8.js
··· 1 + console.log('=== Minimal Test 8 ==='); 2 + console.log('Starting...'); 3 + 4 + // Simulate what comes before Test 8 5 + console.log('Creating Map...'); 6 + let map = new Map(); 7 + map.set('key1', { data: 'value1' }); 8 + Ant.gc(); 9 + 10 + let set = new Set(); 11 + set.add('value1'); 12 + Ant.gc(); 13 + 14 + let descObj = {}; 15 + Object.defineProperty(descObj, 'prop', { 16 + get: function() { return 'test'; }, 17 + set: function(v) { }, 18 + }); 19 + Ant.gc(); 20 + 21 + let proxyTarget = { x: 10 }; 22 + let proxy = new Proxy(proxyTarget, { get: function(t, p) { return t[p]; } }); 23 + Ant.gc(); 24 + 25 + function makeCounter() { 26 + let count = 0; 27 + return { inc: function() { count = count + 1; return count; } }; 28 + } 29 + let counter = makeCounter(); 30 + counter.inc(); 31 + Ant.gc(); 32 + 33 + // Now Test 8 34 + console.log('Test 8: Multiple GC Cycles'); 35 + let cycleData = { iteration: 0 }; 36 + for (let i = 0; i < 5; i = i + 1) { 37 + console.log('Cycle', i); 38 + cycleData.iteration = i; 39 + cycleData['data' + i] = { value: i * 10 }; 40 + Ant.gc(); 41 + } 42 + console.log('Done');
+18
tests/test_gc_simple.js
··· 1 + console.log('=== Simple GC Test ===\n'); 2 + 3 + // Test 1: Basic objects 4 + console.log('Test 1: Objects'); 5 + let obj1 = { name: 'test', value: 42 }; 6 + console.log('Before GC:', obj1.name); 7 + Ant.gc(); 8 + console.log('After GC:', obj1.name); 9 + 10 + // Test 2: Map 11 + console.log('\nTest 2: Map'); 12 + let map = new Map(); 13 + map.set('key1', 'value1'); 14 + console.log('Before GC:', map.get('key1')); 15 + Ant.gc(); 16 + console.log('After GC:', map.get('key1')); 17 + 18 + console.log('\n=== Done ===');
+31
tests/test_map_gc.js
··· 1 + console.log('=== Map GC Debug ===\n'); 2 + 3 + let map = new Map(); 4 + console.log('Created map'); 5 + 6 + map.set('key1', { data: 'value1' }); 7 + console.log('Set key1, size:', map.size); 8 + 9 + map.set('key2', [1, 2, 3]); 10 + console.log('Set key2, size:', map.size); 11 + 12 + map.set('key3', 'simple string'); 13 + console.log('Set key3, size:', map.size); 14 + 15 + console.log('\nBefore GC:'); 16 + console.log(' map.size:', map.size); 17 + console.log(' map.get("key1"):', map.get('key1')); 18 + console.log(' map.get("key2"):', map.get('key2')); 19 + console.log(' map.get("key3"):', map.get('key3')); 20 + 21 + let gc = Ant.gc(); 22 + console.log('\nGC result:'); 23 + console.log(' arenaFreed:', gc.arenaFreed); 24 + 25 + console.log('\nAfter GC:'); 26 + console.log(' map.size:', map.size); 27 + console.log(' map.get("key1"):', map.get('key1')); 28 + console.log(' map.get("key2"):', map.get('key2')); 29 + console.log(' map.get("key3"):', map.get('key3')); 30 + 31 + console.log('\n=== Done ===');