title: Javascript img.onload() not firing and/or promises always pending on firefox but not chrome
body: <p>I'm loading one or multiple pictures from local storage and putting it to a canvas on top of another picture.</p>
  <p>In the code below I first collect all the loading images in promises that only resolve after the image has loaded. Second after all the promises have resolved I send the created image data.</p>
  <pre><code>var Promises = [];
          for (const selectedOverlayImage of selectedOverlayImages.values()) {
              Promises.push(new Promise((resolve, reject) =&gt; {
                  const overlayImg = new Image();
                  overlayImg.onerror = () =&gt; { console.log(`Image ${selectedImage.value} loading error`); reject(); };
                  overlayImg.onload = () =&gt; {
                      canvasContext.drawImage(overlayImg, 0, 0, canvas.width, canvas.height);
                      resolve();
                  };
                  overlayImg.src = `overlayImages/${selectedOverlayImage.value}.png`;
                  console.log(selectedOverlayImage.value);
              }));
          }
  
          console.log(&quot;1&quot;);
          var ret = Promise.all(Promises).then(() =&gt; {
              console.log(&quot;IN&quot;);
              let imageData = canvas.toDataURL('image/png');
              fetch(&quot;http://localhost:8000/picture-editing.php&quot;, { //Call php to create picture in database
                  method: &quot;POST&quot;,
                  headers: {&quot;Content-Type&quot;: &quot;application/x-www-form-urlencoded; charset=UTF-8&quot;},
                          body: `imageData=${imageData}`
              });
              alert('Images successfully loaded!'); //This creates a gain of time before the refresh, allowing the new picture to be present more often after refresh
              window.location.reload();
          }).catch((error) =&gt; {console.log(error);});
          console.log(&quot;2&quot;);
          console.log(ret);
          setTimeout(() =&gt; {
          console.log('the queue is now empty');
          console.log(ret);
          });
      });
  </code></pre>
  <p>On Chrome I am able to create one image consisting of multiple pictures.<br>
  <a href="https://i.stack.imgur.com/fL6s2.png" rel="nofollow noreferrer">Console logs when successfully creating picture with wine as overlay-image, we can see the Promise.all function gets entered</a></p>
  <p>On firefox I am not able to create one image of multiple pictures.<br>
  <a href="https://i.stack.imgur.com/bGQP8.png" rel="nofollow noreferrer">We can see the code never enters Promise.all while Promise.all never resolves</a></p>
  <p>Thank you for your help!</p>
  <p><strong>Reproduce the error</strong></p>
  <p>Set the following in index.php.</p>
  <pre><code>&lt;h1 class=&quot;pageTitle&quot;&gt;Create Picture&lt;/h1&gt;
  &lt;form method=&quot;get&quot;&gt;
      &lt;input name=&quot;modeOfPicture&quot; type=&quot;submit&quot; value=&quot;webcam&quot;/&gt;
          &lt;input name=&quot;modeOfPicture&quot; type=&quot;submit&quot; value=&quot;upload&quot;/&gt;
  &lt;/form&gt;
  &lt;div class=&quot;wrapperPictureEditing&quot;&gt;
  &lt;div id=&quot;getPicture&quot; class=&quot;block1PictureEditing&quot;&gt;&lt;/div&gt;
  &lt;canvas id=&quot;takePictureCanvas&quot; style=&quot;display:none;&quot; width=&quot;320&quot; height=&quot;240&quot;&gt;&lt;/canvas&gt;
  &lt;form id=&quot;takePictureButton&quot; class=&quot;block2PictureEditing&quot;&gt;
      &lt;p&gt;Choose Overlay Image:&lt;/p&gt;
      &lt;label&gt;&lt;input type=&quot;checkbox&quot; name=&quot;overlay&quot; value=&quot;wine&quot;&gt; Wine&lt;/label&gt;&lt;br&gt;
      &lt;button type=&quot;submit&quot;&gt;Take photo&lt;/button&gt;&lt;br&gt;
  &lt;/form&gt;
  
  &lt;script&gt;
  function displaySelectedPicture(input) {
    var selectedPictureDisplay = document.getElementById('selectedPictureDisplay');
  
    if (input.files &amp;&amp; input.files[0]) {
      var reader = new FileReader();
  
      reader.onload = function (e) {
              selectedPictureDisplay.src = e.target.result;
      };
  
      reader.readAsDataURL(input.files[0]);
    } else { selectedPictureDisplay.removeAttribute('src') }
  }
  
  function takePicture(camera) {
      const takePictureButton = document.getElementById('takePictureButton');
  
      takePictureButton.addEventListener(&quot;submit&quot;, () =&gt; {
      let canvas = document.getElementById('takePictureCanvas');
          let canvasContext = canvas.getContext('2d');
          selectedOverlayImages = document.querySelectorAll('input[name=&quot;overlay&quot;]:checked');
          console.log(selectedOverlayImages);
  
          if (camera) {
              const stream = document.querySelector('video');
          canvasContext.drawImage(stream, 0, 0, canvas.width, canvas.height);
        } else {
              const selectedImage = document.getElementById('selectedPictureDisplay');
          canvasContext.drawImage(selectedImage, 0, 0, canvas.width, canvas.height);
        }
  
          var Promises = [];
          for (const selectedOverlayImage of selectedOverlayImages.values()) {
              Promises.push(new Promise((resolve, reject) =&gt; {
                  const overlayImg = new Image();
                  overlayImg.onerror = () =&gt; { console.log(`Image ${selectedImage.value} loading error`); reject(); };
                  overlayImg.onload = () =&gt; {
                      canvasContext.drawImage(overlayImg, 0, 0, canvas.width, canvas.height);
                      resolve();
                  };
                  overlayImg.src = `image.png`;
                  console.log(selectedOverlayImage.value);
              }));
          }
  
          console.log(&quot;1&quot;);
          var ret = Promise.all(Promises).then(() =&gt; {
              console.log(&quot;IN&quot;);
              let imageData = canvas.toDataURL('image/png');
              alert('Images successfully loaded!'); //This creates a gain of time before the refresh, allowing the new picture to be present more often after refresh
              window.location.reload();
          }).catch((error) =&gt; {console.log(error);});
          console.log(&quot;2&quot;);
          console.log(ret);
          setTimeout(() =&gt; {
          console.log('the queue is now empty');
          console.log(ret);
          });
      });
  }
  
  function setupVideoStream(stream) {
    const video = document.querySelector('video');
    video.srcObject = stream;
    video.play();
  }
  
  function errorMsg(msg, error) {
    const errorElement = document.getElementById('error');
    errorElement.innerHTML += `${msg}`;
    if (typeof error !== 'undefined') {
      console.error(error);
    }
  }
  
  function streamError(error) {
    if (error.name === 'NotAllowedError') {
      errorMsg('Permissions have not been granted to use your camera' +
        ', you need to allow the page access to your camera in ' +
        'order to take pictures. Instead you can upload an image.');
      } else if (error.name === &quot;NotFoundError&quot;) {
          errorMsg('No camera has been found on this device. ' +
              'Instead you can upload an image.');
    } else {
      errorMsg(`getUserMedia error: ${error.name}`, error);
    }
  }
  
  async function init() {
    var getPictureHTML = document.getElementById('getPicture');
      var modeOfPicture = (new URLSearchParams(document.location.search)).get('modeOfPicture');
  
      if (modeOfPicture === null || modeOfPicture === &quot;webcam&quot;) {
        try {
          const stream = await navigator.mediaDevices.getUserMedia({video: true});
          getPictureHTML.insertAdjacentHTML('afterbegin',
              &quot;&lt;video width='320' height='240' autoplay&gt;&lt;/video&gt;&lt;br&gt;&quot;);
              setupVideoStream(stream);
              takePicture(true);
        } catch (error) {
              getPictureHTML.insertAdjacentHTML('afterbegin',
                  &quot;&lt;p id='error' class='error'&gt;&lt;/p&gt;&quot; +
                  &quot;&lt;label&gt;&lt;input type='file' name='selectedPicture' accept='image/*' &quot; +
                  &quot;onchange='displaySelectedPicture(this);'&gt;&lt;br&gt;Upload image&lt;br&gt;&lt;/label&gt;&quot; +
                  &quot;&lt;br&gt;&lt;img id='selectedPictureDisplay' width='320' height='240'/&gt;&quot;);
              streamError(error);
          takePicture(false);
        }
      } else {
          getPictureHTML.insertAdjacentHTML('afterbegin',
              &quot;&lt;label&gt;&lt;input type='file' name='selectedPicture' accept='image/*' &quot; +
              &quot;onchange='displaySelectedPicture(this);'&gt;&lt;br&gt;Upload image&lt;br&gt;&lt;/label&gt;&quot; +
              &quot;&lt;br&gt;&lt;img id='selectedPictureDisplay' width='320' height='240'/&gt;&quot;);
          takePicture(false);
      }
  }
  
  init();
  &lt;/script&gt;
  </code></pre>
  <p>In same directory put an image named image.png, such as this one <a href="https://i.stack.imgur.com/Zrwi6.png" rel="nofollow noreferrer">image example</a></p>
  <p>Then run the server with this command in same directory:<br>
  <code>php -S localhost:8000</code><br>
  Visit localhost:8000 in Chrome and Firefox, see the console, on success &quot;IN&quot; should appear after taking a picture with wine overlay image.</p>