title: Memory Leak with pdf.js and iron-list
body: <p>While developing some custom elements with polymer and pdf.js to show pdf files I noticed a memory leak while displaying and switching between two pdf files. The consumed memory grows and I can't seem to figure out the reason. To observe the memory changes I use heap snapshots in google chrome. The idea is to have a iron-list display the individual pages, which are wrapped inside another custom element.</p>
  
  <p>Here is the element which should load a pdf document, show it as list and propagate the pdfpageproxys loaded to a another custom element, which then should display it:</p>
  
  <p><strong>pdf-list-viewer.html</strong></p>
  
  <pre><code>&lt;link rel="import" href="../polymer/polymer-element.html"&gt;
  &lt;link rel="import" href="../iron-list/iron-list.html"&gt;
  &lt;link rel="import" href="../layer-view/layer-view.html"&gt;
  &lt;link rel="import" href="../pdf-page-viewer/pdf-page-viewer.html"&gt;
  
  &lt;dom-module id="pdf-list-viewer"&gt;
    &lt;template&gt;
      &lt;style&gt;
        iron-list {
          width: 400ox;
          height: 800px;
        }
  
        layer-view {
          width: 100%;
          min-height: 100%;
        }
      &lt;/style&gt;
  
      &lt;iron-list items="[[pages]]" as="page"&gt;
        &lt;template&gt;
            &lt;pdf-page-viewer pdf-page="[[page]]" canvas-width="800" /&gt;
        &lt;/template&gt;
      &lt;/iron-list&gt;
    &lt;/template&gt;
  
    &lt;script&gt;
      /**
       * `pdf-list-viewer`
       * Shows a pdf file as a scrollable list of individual pages
       *
       * @customElement
       * @polymer
       * @demo demo/index.html
       */
      class PdfListViewer extends Polymer.Element {
        static get is() { return 'pdf-list-viewer'; }
        static get properties() {
          return {
            pdfUrl: {
              type: Object,
              observer: '_pdfUrlChanged'
            },
            pages: {
              type: Array,
              value: []
            },
            _loadingTask: Object
          };
        }
  
        _pdfUrlChanged(newValue, oldValue) {
          var self = this;
          // Remove old pages
          var destroyPromise = null;
          if (this.pages.length !== 0) {
            destroyPromise = this._loadingTask.destroy();
          }
          if(destroyPromise === null){
            this._loadPdf(newValue);
          } else{
            destroyPromise.then(function(){
              self._loadPdf(newValue);
            });
          }
  
        }
  
        _loadPdf(newUrl){
          var self = this;
          this.pdfUrl = newUrl;
  
          this._loadingTask = PDFJS.getDocument({ url: newUrl });
          this._loadingTask.then(function (pdfDoc) {
            var pagePromises = Array.from(new Array(pdfDoc.numPages), (_, index) =&gt; pdfDoc.getPage(index + 1));
            Promise.all(pagePromises).then(function (values) {
              self.splice('pages', 0, self.pages.length, ...values);
            });
          }).catch(function (error) {
            // TODO: handle error
            alert(error.message);
          });
        }
      }
  
      window.customElements.define(PdfListViewer.is, PdfListViewer);
    &lt;/script&gt;
  &lt;/dom-module&gt;
  </code></pre>
  
  <p>Here is the element which only needs to display the pdf on a canvas and handle zoom (which is not important for now):</p>
  
  <p><strong>pdf-page-viewer.html</strong></p>
  
  <pre><code>&lt;link rel="import" href="../polymer/polymer-element.html"&gt;
  &lt;linkrel="import" href="../paper-spinner/paper-spinner.html"&gt;
  &lt;link rel="import" href="pdfjs.html"&gt;
  
    &lt;dom-module id="pdf-page-viewer"&gt;
      &lt;template&gt;
        &lt;style&gt;
        &lt;/style&gt;
        &lt;canvas id="pageCanvas" width="[[canvasWidth]]"&gt;&lt;/canvas&gt;
        &lt;!-- Here should be a circular loading bar displaying that page is rendering --&gt;
      &lt;/template&gt;
  
      &lt;script&gt;
        /**
         * `pdf-page-viewer`
         * Viewer to display a single pdf page using mozillas pdf.js library
         *
         * @customElement
         * @polymer
         * @demo demo/index.html
         */
        class PdfPageViewer extends Polymer.Element {
          static get is() { return 'pdf-page-viewer'; }
          static get properties() {
            return {
              /**
               * Page object as defined in pdfjs-dist library in lib/core/document.js. 
               */
              pdfPage: {
                type: Object,
                observer: '_pageChanged'
              },
              /**
               * Width of the page canvas in pixel. Height will be calculated when showing the page.
               */
              canvasWidth: Number,
              _zoom: Number,
              /**
               * Displays wether or not a page rendering is being processed.
               */
              pageRenderingInProgress: {
                type: Boolean,
                value: false,
              }
            };
          }
          constructor(){
            super();
            this._boundChangeListener = this.zoom.bind(this);
          }
  
          connectedCallback() {
            super.connectedCallback();
  
            window.addEventListener('zoom', this._boundChangeListener);
          }
  
          disconnectedCallback(){
            super.disconnectedCallback();
  
            window.removeEventListener('zoom', this._boundChangeListener);
          }
  
          _pageChanged(newValue, oldValue) {
            this.pdfPage = newValue;
            this._showPage();
          }
  
  
          // Load and render a specific page of the PDF
          _showPage() {
            this.pageRenderingInProgress = true;
            var self = this;
            // As the canvas is of a fixed width we need to set the scale of the viewport accordingly
            var scale_required = this.$.pageCanvas.width / this.pdfPage.getViewport(1).width;
  
            // Get viewport of the page at required scale
            var viewport = this.pdfPage.getViewport(scale_required);
  
            // Set canvas height
            this.$.pageCanvas.height = viewport.height;
  
            var renderContext = {
              canvasContext: self.$.pageCanvas.getContext('2d'),
              viewport: viewport
            };
  
            // Render the page contents in the canvas
            this.dispatchEvent(new CustomEvent('pageRenderingStarted'));
            this.pdfPage.render(renderContext).then(function () {
              self.pageRenderingInProgress = false;
              self.dispatchEvent(new CustomEvent('pageRenderingFinished'));
            });
          }
  
          zoom(event) {
            this._zoom = event.detail.newValue;
            this.$.pageCanvas.width = this.canvasWidth * this._zoom;
  
            this._showPage();
          }
        }
  
        window.customElements.define(PdfPageViewer.is, PdfPageViewer);
      &lt;/script&gt;
    &lt;/dom-module&gt;
  </code></pre>
  
  <p>Please bear in mind, that I'm a newbi in web development (and polymer and pdf.js) so feel free to critizise every little strange thing you find, so that I may improve in that regard.
  Every help would be very much appreciated!</p>
  
  <p><strong>EDIT:</strong></p>
  
  <p>I monitored the memory usage of the pdf-viewer demo in <a href="https://www.webcomponents.org/element/telecomsante/pdf-viewer" rel="nofollow noreferrer">this webcomponent</a> with chrome dev tools and noticed the same memory leak when taking snapshots of the memory heap. Just go to <a href="https://www.webcomponents.org/element/telecomsante/pdf-viewer/demo/demo/index.html" rel="nofollow noreferrer">https://www.webcomponents.org/element/telecomsante/pdf-viewer/demo/demo/index.html</a>, click through the 367 page pdf file, switch to antoher pdf in the dropbox and switch back to the 367 pdf document. After going through them again you'll se the following increase:</p>
  
  <p>22,5 MB (Page 1/367 opened) -> </p>
  
  <p>52,7 MB (Clicked thorugh every page of the document) -> </p>
  
  <p>55,5 MB (Opened another document in the list and clicked through the pages) -></p>
  
  <p>69,8 MB (Opened the 367 pages pdf and clicked through all of them again)</p>
  
  <p>Any ideas?
  To recreate this, just </p>