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