Skip to content

Commit

Permalink
Fix races between tasks resolving/rejecting play promises and them be…
Browse files Browse the repository at this point in the history
…ing added

For example, if pause() is called, it creates a task to reject all
promises even if there is none around. If play() is called just after,
this task would reject the newly created promise.

This is fixing the issue by creating tasks rejecting/resolving a given
list of promises, copied for the task.

Closes #996.
  • Loading branch information
mounirlamouri authored and foolip committed Jun 2, 2016
1 parent 806bc62 commit 18be384
Showing 1 changed file with 49 additions and 35 deletions.
84 changes: 49 additions & 35 deletions source
Original file line number Diff line number Diff line change
Expand Up @@ -30835,8 +30835,8 @@ interface <dfn>HTMLMediaElement</dfn> : <span>HTMLElement</span> {
data-x="task queue">task queues</span>, then remove those tasks.</p>
-->

<p><span>Reject pending play promises</span> with an <span>"<code>AbortError</code>"</span>
<code>DOMException</code>.</p>
<p><span>Take pending play promises</span> and <span>reject pending play promises</span> with
the result and an <span>"<code>AbortError</code>"</span> <code>DOMException</code>.</p>

<p class="note">Basically, pending events and callbacks are discarded and pending promises are
rejected when the media element starts loading a new resource.</p>
Expand Down Expand Up @@ -31021,8 +31021,9 @@ interface <dfn>HTMLMediaElement</dfn> : <span>HTMLElement</span> {
aborting <em>this</em> one, then the load failed.</p></li>

<li><p><i>Failed with media provider</i>: Reaching this step indicates that the media
resource failed to load. <span>Queue a task</span> to run the <span>dedicated media source
failure steps</span>.</p></li>
resource failed to load. <span>Take pending play promises</span> and <span>queue a
task</span> to run the <span>dedicated media source failure steps</span> with the
result.</p></li>

<li><p>Wait for the <span data-x="concept-task">task</span> queued by the previous step to have
executed.</p></li>
Expand Down Expand Up @@ -31064,8 +31065,8 @@ interface <dfn>HTMLMediaElement</dfn> : <span>HTMLElement</span> {

<li><p><i>Failed with attribute</i>: Reaching this step indicates that the media resource
failed to load or that the given <span>URL</span> could not be <span data-x="parse a
url">parsed</span>. <span>Queue a task</span> to run the <span>dedicated media source
failure steps</span>.</p></li>
url">parsed</span>. <span>Take pending play promises</span> and <span>queue a task</span> to
run the <span>dedicated media source failure steps</span> with the result.</p></li>

<li><p>Wait for the <span data-x="concept-task">task</span> queued by the previous step to have
executed.</p></li>
Expand Down Expand Up @@ -31213,7 +31214,8 @@ interface <dfn>HTMLMediaElement</dfn> : <span>HTMLElement</span> {

</dl>

<p>The <dfn>dedicated media source failure steps</dfn> are the following steps:</p>
<p>The <dfn>dedicated media source failure steps</dfn> with a list of promises
<var>promises</var> are the following steps:</p>

<ol>

Expand All @@ -31232,7 +31234,7 @@ interface <dfn>HTMLMediaElement</dfn> : <span>HTMLElement</span> {
<li><p><span>Fire a simple event</span> named <code data-x="event-media-error">error</code> at
the <span>media element</span>.</p></li>

<li><p><span>Reject pending play promises</span> with a
<li><p><span>Reject pending play promises</span> with <var>promises</var> and a
<span>"<code>NotSupportedError</code>"</span> <code>DOMException</code>.</p></li>

<li><p>Set the element's <span>delaying-the-load-event flag</span> to false. This stops <span
Expand Down Expand Up @@ -32422,7 +32424,7 @@ interface <dfn>HTMLMediaElement</dfn> : <span>HTMLElement</span> {
<code data-x="event-media-canplay">canplay</code> at the element.</p>

<p>If the element's <code data-x="dom-media-paused">paused</code> attribute is false, the user
agent must <span>queue a task</span> to <span>notify about playing</span> for the element.</p>
agent must <span>notify about playing</span> for the element.</p>

</dd>

Expand All @@ -32436,8 +32438,8 @@ interface <dfn>HTMLMediaElement</dfn> : <span>HTMLElement</span> {
data-x="dom-media-HAVE_CURRENT_DATA">HAVE_CURRENT_DATA</code> or less, the user agent must
<span>queue a task</span> to <span>fire a simple event</span> named <code
data-x="event-media-canplay">canplay</code> at the element, and, if the element's <code
data-x="dom-media-paused">paused</code> attribute is false, <span>queue a task</span> to
<span>notify about playing</span> for the element.</p>
data-x="dom-media-paused">paused</code> attribute is false, <span>notify about playing</span>
for the element.</p>

<p>If the <span>autoplaying flag</span> is true, and the <code
data-x="dom-media-paused">paused</code> attribute is true, and the <span>media element</span>
Expand All @@ -32456,7 +32458,7 @@ interface <dfn>HTMLMediaElement</dfn> : <span>HTMLElement</span> {
<li><span>Queue a task</span> to <span>fire a simple event</span> named <code
data-x="event-media-play">play</code> at the element.</li>

<li><span>Queue a task</span> to <span>notify about playing</span> for the element.</li>
<li><span>Notify about playing</span> for the element.</li>

<li>Set the <span>autoplaying flag</span> to false.</li>

Expand Down Expand Up @@ -32777,41 +32779,49 @@ interface <dfn>HTMLMediaElement</dfn> : <span>HTMLElement</span> {
<p>Each <span>media element</span> has a <dfn>list of pending play promises</dfn>, which must
initially be empty.</p>

<p>To <dfn>resolve pending play promises</dfn> for a <span>media element</span>, the user agent
must run the following steps:</p>
<p>To <dfn>take pending play promises</dfn> for a <span>media element</span>, the user agent must
run the following steps:</p>

<ol>

<li><p>For each promise in the <span>media element</span>'s <span>list of pending play
promises</span>, resolve it with undefined.</p></li>
<li><p>Let <var>promises</var> be an empty list of promises.</p></li>

<li><p>Copy the <span>media element</span>'s <span>list of pending play promises</span> to
<var>promises</var>.</p></li>

<li><p>Clear the <span>media element</span>'s <span>list of pending play
promises</span>.</p></li>

</ol>

<p>To <dfn>reject pending play promises</dfn> for a <span>media element</span> with an exception
name <var>error</var>, the user agent must run the following steps:</p>

<ol>
<li>Return <var>promises</var>.</li>

<li><p>For each promise in the <span>media element</span>'s <span>list of pending play
promises</span>, reject it with an <var>error</var> exception.</p></li>
</ol>

<li><p>Clear the <span>media element</span>'s <span>list of pending play
promises</span>.</p></li>
<p>To <dfn>resolve pending play promises</dfn> for a <span>media element</span> with a list of
promises <var>promises</var>, the user agent must resolve each promise in <var>promises</var> with
undefined.</p>

</ol>
<p>To <dfn>reject pending play promises</dfn> for a <span>media element</span> with a list of
promise <var>promises</var> and an exception name <var>error</var>, the user agent must resolve
each promise in <var>promises</var> with <var>error</var>.</p>

<p>To <dfn>notify about playing</dfn> for a <span>media element</span>, the user agent must run
the following steps:</p>

<ol>

<li><p><span>Fire a simple event</span> named <code data-x="event-media-playing">playing</code>
at the element.</p></li>
<li><p><span>Take pending play promises</span> and let <var>promises</var> be the
result.</p></li>

<li><p><span>Queue a task</span> to:</p></li>

<ol>

<li><p><span>Fire a simple event</span> named <code
data-x="event-media-playing">playing</code> at the element.</p></li>

<li><p><span>Resolve pending play promises</span>.</p></li>
<li><p><span>Resolve pending play promises</span> with <var>promises</var>.</p></li>

</ol>

</ol>

Expand Down Expand Up @@ -32893,8 +32903,8 @@ interface <dfn>HTMLMediaElement</dfn> : <span>HTMLElement</span> {
<p>Otherwise, the <span>media element</span>'s <code
data-x="dom-media-readyState">readyState</code> attribute has the value <code
data-x="dom-media-HAVE_FUTURE_DATA">HAVE_FUTURE_DATA</code> or <code
data-x="dom-media-HAVE_ENOUGH_DATA">HAVE_ENOUGH_DATA</code>: <span>queue a task</span> to
<span>notify about playing</span> for the element.</p>
data-x="dom-media-HAVE_ENOUGH_DATA">HAVE_ENOUGH_DATA</code>: <span>notify about playing</span>
for the element.</p>

</li>

Expand All @@ -32907,8 +32917,9 @@ interface <dfn>HTMLMediaElement</dfn> : <span>HTMLElement</span> {
<p>Otherwise, if the <span>media element</span>'s <code
data-x="dom-media-readyState">readyState</code> attribute has the value <code
data-x="dom-media-HAVE_FUTURE_DATA">HAVE_FUTURE_DATA</code> or <code
data-x="dom-media-HAVE_ENOUGH_DATA">HAVE_ENOUGH_DATA</code>, <span>queue a task</span> to
<span>resolve pending play promises</span>.</p>
data-x="dom-media-HAVE_ENOUGH_DATA">HAVE_ENOUGH_DATA</code>, <span>take pending play
promises</span> and <span>queue a task</span> to <span>resolve pending play promises</span> with
the result.</p>

<p class="note">The media element is already playing. However, it's possible that
<var>promise</var> will be <span data-x="reject pending play promises">rejected</span> before
Expand Down Expand Up @@ -32952,6 +32963,9 @@ interface <dfn>HTMLMediaElement</dfn> : <span>HTMLElement</span> {

<li><p>Change the value of <code data-x="dom-media-paused">paused</code> to true.</p></li>

<li><p><span>Take pending play promises</span> and let <var>promises</var> be the
result.</p></li>

<li>

<p><span>Queue a task</span> to:</p>
Expand All @@ -32964,7 +32978,7 @@ interface <dfn>HTMLMediaElement</dfn> : <span>HTMLElement</span> {
<li><p><span>Fire a simple event</span> named <code data-x="event-media-pause">pause</code>
at the element.</p></li>

<li><p><span>Reject pending play promises</span> with an
<li><p><span>Reject pending play promises</span> with <var>promises</var> and an
<span>"<code>AbortError</code>"</span> <code>DOMException</code>.</p></li>

</ol>
Expand Down

0 comments on commit 18be384

Please sign in to comment.