Skip to content

Commit

Permalink
Fixes memory leak in decodeBuffer + destroys worker after 10 seconds …
Browse files Browse the repository at this point in the history
…of inactivity
  • Loading branch information
chebum committed Dec 10, 2021
1 parent c6fab0a commit 39327e2
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 3 deletions.
4 changes: 3 additions & 1 deletion build/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,9 @@ async function startBuild() {
).replace(
/(\\)/g,
"\\\\"
)}\n${worker}\n\`;\nvar blob = new Blob([workerString], {type: 'application/javascript'});\nwindow.__heic2any__worker = new Worker(URL.createObjectURL(blob));`;
)}\n${worker}\n\`;` +
"\nwindow.__heic2any__blob = new Blob([workerString], {type: 'application/javascript'});" +
"\nwindow.__heic2any__blob_url = URL.createObjectURL(window.__heic2any__blob);";

console.log("🔨 📄 Fixing main files");
main = worker + main;
Expand Down
25 changes: 23 additions & 2 deletions src/heic2any.ts
Original file line number Diff line number Diff line change
Expand Up @@ -194,15 +194,36 @@ const utils = {
},
};

function getWorker(): Worker {
if (!(window as any).__heic2any__worker)
(window as any).__heic2any__worker = new Worker((window as any).__heic2any__blob_url);
return (window as any).__heic2any__worker;
}

let pendingWorkerJobsCount = 0;

function scheduleWorkerDestruction() {
setTimeout(() => {
if ((window as any).__heic2any__worker && pendingWorkerJobsCount == 0) {
(window as any).__heic2any__worker.terminate();
delete (window as any).__heic2any__worker;
}
}, 10000);
}

function decodeBuffer(buffer: ArrayBuffer): Promise<ImageData[]> {
return new Promise((resolve, reject) => {
const id = (Math.random() * new Date().getTime()).toString();
const message = { id, buffer };
const worker = (window as any).__heic2any__worker as Worker;
const worker = getWorker();
pendingWorkerJobsCount++;
worker.postMessage(message);
const listener = (message: MessageEvent<any>) => {
const listener = (message: MessageEvent) => {
if (message.data.id === id) {
worker.removeEventListener("message", listener);
pendingWorkerJobsCount--;
if (pendingWorkerJobsCount == 0)
scheduleWorkerDestruction();
if (message.data.error)
reject(message.data.error);
else
Expand Down

0 comments on commit 39327e2

Please sign in to comment.