Your problem is not with the getImageData function. This is the way that the variable getImageData assigned a variable that creates a leak .
The problem is that delete c will fail (deletion does not affect variable names), and the browser silently returns false.
MDN removal link
Try c = null instead. Try declaring the variable c outside the for loop to avoid recreating the variable at each step of the loop.
Here is the modified code:
function getImageData(){ var i = 0; var c; while(i++ < 100){ c = g.getImageData(0,0,1000, 1000); // c = null; // <= check UPDATE to see why this doesn't work as expected } } function toDataURL(){ var i = 0; var c; while(i++ < 100){ c = g.canvas.toDataURL(); // c = null; // <= check UPDATE to see why this doesn't work as expected } }
I tried the code exactly in the same browser and used the memory profile in the developer tools, I could see that the memory is perfectly cleared by the garbage collector.
Check the memory timeline in the developer tools ( Ctrl+Shift+i ).
To enable the memory profile, you need to run Chrome with the --enable-memory-info flag.
UPDATE:
As already mentioned in the comments, garbage collection works by restoring memory blocks (objects) that are no longer available.
When the function returns, the object that c points to is automatically available for garbage collection, because there is nothing left that has a link to it.
There are also misconceptions about how null works. Setting the object reference to null does not "null" the object. It sets the object reference to null.
So, in this case, the memory allocated to store each getImageData information remains there until the function returns. Since image data is a very large object, and it is larger in size of the canvas, in huge cycles (say, 500 cycles or higher, which depends on the machine), it will overflow the memory before the function returns and garbage collector will be launched.
I recommend the following article: Writing fast, memory efficient JavaScript . It is well explained and easy to read.
DECISION!!!
Now we know that the garbage collector starts only after the function returns, and one of the solutions that occurred to me is to defer the function that calls getImageData for a fraction of a millisecond. Thus, we guarantee that the function will be returned after each call to getImageData.
I tried the code below and it works even for 10,000 iterations! Spends a lot of time to complete, but it ends without memory leaks!)
Try it yourself:
<!DOCTYPE html> <html> <head> <title>CanvasRenderingContext2D#getImageData bug fixed</title> <script type="text/javascript"> var g; function init(){ g = document.getElementById('canvas').getContext('2d'); g.fillStyle = "blue"; g.fillRect(10, 10, 100, 100); g.fillStyle = "green"; g.fillRect(60, 60, 100, 100); } function getImageData(){ var c = g.getImageData(0,0,1000, 1000); } var total = 0; var iterations = 100; function test(){ var i = 0; while(i++ < iterations){ setTimeout(function(){ getImageData(); total++; //console.log(total); if(total == iterations){ alert("" + total+" getImageData functions were completed!!!") } }, 0.01); // defer } alert("" + (i-1) + " iterations completed. Wait for the return of all getImageData"); } </script> </head> <body onload="init()"> <button onclick="test()">call getImageData several times</button><br> <canvas id='canvas' width='600px' height='500px'/> </body> </html>