Skip to content

Instantly share code, notes, and snippets.

@mhofman
Last active May 26, 2022 03:52
Show Gist options
  • Save mhofman/94bd0f43fe598bdb3d580a652f32e450 to your computer and use it in GitHub Desktop.
Save mhofman/94bd0f43fe598bdb3d580a652f32e450 to your computer and use it in GitHub Desktop.
XS WeakMap memory leak
if (typeof console === "undefined") {
globalThis.console = {
log() {
print(...arguments);
},
};
}
let queueGCJob;
if (typeof setTimeout === "function") {
queueGCJob = function() {
return new Promise(function(resolve) {
setTimeout(resolve, 0);
});
};
} else if (typeof drainJobQueue === "function") {
queueGCJob = function() {
return new Promise(function(resolve) {
drainJobQueue();
resolve();
});
};
} else {
queueGCJob = function() {
return Promise.resolve();
};
}
let gc;
const setupGC = async () => {
gc = globalThis.gc || (typeof $262 !== "undefined" ? $262.gc : null);
if (!gc) {
try {
const [{ ["default"]: v8 }, { ["default"]: vm }] = await Promise.all([
import("v8"),
import("vm"),
]);
v8.setFlagsFromString("--expose_gc");
gc = vm.runInNewContext("gc");
v8.setFlagsFromString("--no-expose_gc");
} catch (err) {
gc = () => void Array.from({ length: 2 ** 24 }, () => Math.random());
}
}
globalThis.gc = gc;
};
// Hold map inside of key to make sure key is visited first by mark
const key = { map: new WeakMap() };
let refValue;
let refSentinel;
setupGC()
.then(() => {
const value = {};
const sentinel = {};
refValue = new WeakRef(value);
refSentinel = new WeakRef(sentinel);
key.map.set(key, value);
key.map.delete(key);
})
.then(async () => {
await queueGCJob();
gc();
})
.then(() => {
// Keep a reference to key throughout
void key;
console.log(!!refSentinel.deref(), !!refValue.deref());
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment