weakRefs.js (3138B)
1 // https://tc39.es/ecma262/#sec-addtokeptobjects 2 // When the abstract operation AddToKeptObjects is called with a target object 3 // reference, it adds the target to an identity Set that will point strongly at 4 // the target until the end of the current Job. 5 // 6 // https://tc39.es/proposal-weakrefs/#sec-weakref-invariants 7 // When WeakRef.prototype.deref is called, the referent (if it's not already 8 // dead) is kept alive so that subsequent, synchronous accesses also return the 9 // object. 10 11 function testSameCompartmentWeakRef( 12 targetReachable, 13 weakRefReachable) { 14 15 let target = {}; 16 17 let weakref = new WeakRef(target); 18 assertEq(weakref.deref(), target); 19 20 if (!targetReachable) { 21 target = undefined; 22 } 23 24 if (!weakRefReachable) { 25 weakRef = undefined; 26 } 27 28 clearKeptObjects(); 29 gc(); 30 31 if (weakRefReachable) { 32 if (targetReachable) { 33 assertEq(weakref.deref(), target); 34 } else { 35 assertEq(weakref.deref(), undefined); 36 } 37 } 38 } 39 40 let serial = 0; 41 42 function testCrossCompartmentWeakRef( 43 targetReachable, 44 weakRefReachable, 45 collectTargetZone, 46 collectWeakRefZone, 47 sameZone) { 48 49 gc(); 50 51 let id = serial++; 52 let global = newGlobal(sameZone ? {sameZoneAs: this} : {newCompartment: true}); 53 global.eval('var target = {};'); 54 global.target.id = id; 55 56 let weakref = new WeakRef(global.target); 57 assertEq(weakref.deref(), global.target); 58 59 if (!targetReachable) { 60 global.target = undefined; 61 } 62 63 if (!weakRefReachable) { 64 weakRef = undefined; 65 } 66 67 if (collectTargetZone || collectWeakRefZone) { 68 clearKeptObjects(); 69 70 if (collectTargetZone) { 71 schedulezone(global); 72 } 73 if (collectWeakRefZone) { 74 schedulezone(this); 75 } 76 77 // Incremental GC so we use sweep groups. Shrinking GC to test updating 78 // pointers. 79 startgc(1, 'shrinking'); 80 while (gcstate() !== 'NotActive') { 81 gcslice(1000, {dontStart: true}); 82 } 83 } 84 85 if (!(collectWeakRefZone && !weakRefReachable)) { 86 if (collectTargetZone && !targetReachable) { 87 assertEq(weakref.deref(), undefined); 88 } else if (targetReachable) { 89 assertEq(weakref.deref(), global.target); 90 } else { 91 // Target is not strongly reachable but hasn't been collected yet. We 92 // can get it back through deref() but must check it based on properties. 93 assertEq(weakref.deref() !== undefined, true); 94 assertEq(weakref.deref().id, id); 95 } 96 } 97 } 98 99 gczeal(0); 100 101 for (let targetReachable of [true, false]) { 102 for (let weakRefReachable of [true, false]) { 103 testSameCompartmentWeakRef(targetReachable, weakRefReachable); 104 } 105 } 106 107 for (let targetReachable of [true, false]) { 108 for (let weakRefReachable of [true, false]) { 109 for (let collectTargetZone of [true, false]) { 110 for (let collectWeakRefZone of [true, false]) { 111 for (let sameZone of [true, false]) { 112 if (sameZone && (collectTargetZone != collectWeakRefZone)) { 113 continue; 114 } 115 116 testCrossCompartmentWeakRef(targetReachable, weakRefReachable, 117 collectTargetZone, collectWeakRefZone, sameZone); 118 } 119 } 120 } 121 } 122 }