collect_garbage.ts (1555B)
1 import { resolveOnTimeout } from './util.js'; 2 3 /* eslint-disable-next-line @typescript-eslint/no-explicit-any */ 4 declare const Components: any; 5 6 /** 7 * Attempts to trigger JavaScript garbage collection, either using explicit methods if exposed 8 * (may be available in testing environments with special browser runtime flags set), or using 9 * some weird tricks to incur GC pressure. Adopted from the WebGL CTS. 10 */ 11 export async function attemptGarbageCollection(): Promise<void> { 12 /* eslint-disable-next-line @typescript-eslint/no-explicit-any */ 13 const w: any = globalThis; 14 if (w.GCController) { 15 w.GCController.collect(); 16 return; 17 } 18 19 if (w.opera && w.opera.collect) { 20 w.opera.collect(); 21 return; 22 } 23 24 try { 25 w.QueryInterface(Components.interfaces.nsIInterfaceRequestor) 26 .getInterface(Components.interfaces.nsIDOMWindowUtils) 27 .garbageCollect(); 28 return; 29 } catch (e) { 30 // ignore any failure 31 } 32 33 if (w.gc) { 34 w.gc(); 35 return; 36 } 37 38 if (w.CollectGarbage) { 39 w.CollectGarbage(); 40 return; 41 } 42 43 let i: number; 44 function gcRec(n: number): void { 45 if (n < 1) return; 46 /* eslint-disable @typescript-eslint/restrict-plus-operands */ 47 let temp: object | string = { i: 'ab' + i + i / 100000 }; 48 /* eslint-disable @typescript-eslint/restrict-plus-operands */ 49 temp = temp + 'foo'; 50 temp; // dummy use of unused variable 51 gcRec(n - 1); 52 } 53 for (i = 0; i < 1000; i++) { 54 gcRec(10); 55 } 56 57 return resolveOnTimeout(35); // Let the event loop run a few frames in case it helps. 58 }