title: Are RTCDataChannels guaranteed to open after the ICE state becomes connected?
body: <p>During high CPU load, in Firefox, an RTCDataChannel's <code>onopen</code> event fires before the RTCPeerConnection's <code>oniceconnectionstatechange</code>. I'm wondering if there is anything in the spec regarding the order in which the two events fire, and how to ensure that <code>oniceconnectionstatechange</code> fires first.</p>
  <pre><code>              | Chrome 88                         | Firefox 85
  --------------+-----------------------------------+------------------------------------
  Low CPU load  | oniceconnectionstatechange first  | oniceconnectionstatechange first
                | onopen second                     | onopen second
  --------------+-----------------------------------+------------------------------------
  High CPU load | oniceconnectionstatechange first  | onopen first?
                | onopen second                     | oniceconnectionstatechange second
  </code></pre>
  <p>This is the code I'm using to test:</p>
  <pre><code>(async function()
  {
      var p1 = new RTCPeerConnection();
      var p2 = new RTCPeerConnection();
      
      p1.channel = p1.createDataChannel(&quot;channel&quot;, { negotiated: true, id: 88 });
      p2.channel = p2.createDataChannel(&quot;channel&quot;, { negotiated: true, id: 88 });
      
      p1.onicecandidate = function(e)
      {
          if(e.candidate)
              p2.addIceCandidate(e.candidate);
      };
      
      p2.onicecandidate = function(e)
      {
          if(e.candidate)
              p1.addIceCandidate(e.candidate);
      };
      
      p1.oniceconnectionstatechange = function()
      {
          if(p1.iceConnectionState === &quot;connected&quot;)
              console.log(&quot;P1 PeerConnection connected&quot;);
      };
      
      p2.oniceconnectionstatechange = function()
      {
          if(p2.iceConnectionState === &quot;connected&quot;)
              console.log(&quot;P2 PeerConnection connected&quot;);
      };
      
      p1.channel.onopen = function()
      {
          console.log(&quot;P1 DataChannel opened&quot;);
      };
      
      p2.channel.onopen = function()
      {
          console.log(&quot;P2 DataChannel opened&quot;);
      };
      
      var offer = await p1.createOffer();
      await p1.setLocalDescription(offer);
      await p2.setRemoteDescription(offer);
      
      var answer = await p2.createAnswer();
      await p2.setLocalDescription(answer);
      await p1.setRemoteDescription(answer);
  })();
  
  //create some load
  requestAnimationFrame(renderingLoopTest); //comment this line for no load
  function renderingLoopTest()
  {
      var lag = Date.now();
      while(Date.now() - lag &lt; 60);
      requestAnimationFrame(renderingLoopTest);
  }
  </code></pre>