UNPKG

tc39-weakrefs-shim

Version:
121 lines 4.85 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const WeakRefJobs_js_1 = require("../internal/WeakRefJobs.js"); const FinalizationGroupJobs_js_1 = require("../internal/FinalizationGroupJobs.js"); const WeakRef_js_1 = require("../internal/WeakRef.js"); const FinalizationGroup_js_1 = require("../internal/FinalizationGroup.js"); const setImmediate_js_1 = require("../utils/tasks/setImmediate.js"); const gc_js_1 = require("../global/gc.js"); const targetToInfoMap = new WeakMap(); exports.observedAliveInfos = new Set(); let knownFinalizeCount = 0; let knownAliveObjectsCount = 0; const gcCheckIntervalMin = 100; const gcCheckIntervalMax = 5000; let gcCheckInterval = gcCheckIntervalMin; let gcCheckTaskId = 0; function stopCollectMonitor() { if (gcCheckTaskId === 0) return; console.log("Warn: Force stopping collection"); clearTimeout(gcCheckTaskId); gcCheckTaskId = 0; } exports.stopCollectMonitor = stopCollectMonitor; class ObjectInfo { constructor(target) { this.weakMap = new WeakMap(); this.isAlive = true; this.weakMap.set(target, undefined); } getTarget() { if (!this.isAlive) return undefined; const keys = nondeterministicGetWeakMapKeys(this.weakMap); if (keys.length === 0) { this.isAlive = false; return undefined; } return keys[0]; } } function getInfo(target) { let info = targetToInfoMap.get(target); if (!info) { info = new ObjectInfo(target); targetToInfoMap.set(target, info); knownAliveObjectsCount++; } return info; } function checkOnKnownObjects() { let previousKnownAliveObjectCount = knownAliveObjectsCount; let aliveObjects; const previousFinalizeCount = knownFinalizeCount; knownFinalizeCount = finalizeCount(); let start = gcCheckTaskId === 0; // If the marker is still there, assume no one else we track got collected if (!start && previousFinalizeCount != knownFinalizeCount) { if (knownFinalizeCount < previousFinalizeCount) { console.log("Warning: finalizeCount got reset"); } // Record the fact our marker got collected knownAliveObjectsCount--; previousKnownAliveObjectCount = knownAliveObjectsCount; // let's see which of our objects are still around aliveObjects = nondeterministicGetWeakMapKeys(targetToInfoMap); knownAliveObjectsCount = aliveObjects.length; if (previousKnownAliveObjectCount != knownAliveObjectsCount) { if (previousKnownAliveObjectCount < knownAliveObjectsCount) { console.log("Warning: found more objects alive than expected"); } const aliveInfos = new Set(aliveObjects.map(object => targetToInfoMap.get(object))); for (const info of exports.observedAliveInfos) { if (aliveInfos.has(info)) continue; exports.observedAliveInfos.delete(info); finalizationGroupJobs.setFinalized(info); } } } if (!start && previousKnownAliveObjectCount == knownAliveObjectsCount) { // Only our marker got collected, back off gcCheckInterval = Math.min(gcCheckInterval * 2, gcCheckIntervalMax); } else { gcCheckInterval = gcCheckIntervalMin; } if (exports.observedAliveInfos.size > 0) { if (start || previousFinalizeCount != knownFinalizeCount) { getInfo(makeFinalizeObserver()); } gcCheckTaskId = setTimeout(checkOnKnownObjects, gcCheckInterval); } else { clearTimeout(gcCheckTaskId); gcCheckTaskId = 0; } } const finalizationGroupJobs = FinalizationGroupJobs_js_1.createFinalizationGroupJobsForTaskQueue(setImmediate_js_1.setImmediate, { registerObjectInfo: info => { exports.observedAliveInfos.add(info); if (exports.observedAliveInfos.size == 1) checkOnKnownObjects(); }, unregisterObjectInfo: info => { const wasObserved = exports.observedAliveInfos.delete(info); if (wasObserved && exports.observedAliveInfos.size == 0) checkOnKnownObjects(); }, }); exports.WeakRef = WeakRef_js_1.createWeakRefClassShim(WeakRefJobs_js_1.createWeakRefJobsForTaskQueue(setImmediate_js_1.setImmediate), getInfo, info => info.getTarget())[0]; exports.FinalizationGroup = FinalizationGroup_js_1.createFinalizationGroupClassShim(finalizationGroupJobs, getInfo, info => exports.observedAliveInfos.has(info) && info.getTarget !== undefined); function spidermonkeyGc() { gc_js_1.gc(); if (gcCheckTaskId !== 0) { clearTimeout(gcCheckTaskId); checkOnKnownObjects(); } } exports.gc = gc_js_1.gc && spidermonkeyGc; //# sourceMappingURL=internal.js.map