I am aware that, as of 2022 Q2, JavaScript does not have destructors.
EDIT: the Accepted answer to that question is incorrect due to being out-of-date. See my answer, h/t UnholySheep, for an update from 2020.
However, it looks like my workaround in the following function to leverage closures' GC may have some compatibility impact.
function to_async(f) {
let src = f.toString();
let src_worker = [ // TODO: pass exceptions, too
"self.addEventListener('message', async e => { let arguments = e.data.arguments; let result = await (\n",
src,
"\n)(...arguments); self.postMessage({result: result}, [result].filter(x => typeof x === 'object')); }, {once: true});"
];
// MEMORY LEAK; ENABLE AT YOUR OWN RISK!!
//let src_worker_url = URL.createObjectURL(new Blob(src_worker, {type: 'application/javascript'}));
// Workaround / alternative implementation in case function is called non-finite number of times
let src_worker_url = 'data:application/javascript,' + encodeURIComponent(src_worker.join(""));
async function g() {
let w = new Worker(src_worker_url);
let p = new Promise(res => w.addEventListener('message', e => res(e.data.result), {once: true}));
w.postMessage({arguments: Array.from(arguments)}, Array.from(arguments).filter(x => typeof x === 'object'));
let result = await p;
return result;
}
return g;
}
I would like to set g[Symbol.destructor] = () => URL.revokeObjectURL(src_worker_url);
before returning it.
Is there any way I can achieve something like this in ES6? Or is my current workaround with let
-inside-a-closure of a data:
URI the best it gets for this use-case?