Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add TaskSignal.any() #72

Merged
merged 10 commits into from
May 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 66 additions & 11 deletions spec/controlling-tasks.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,14 @@ The `TaskSignal` Interface {#sec-task-signal}
---------------------

<pre class='idl'>
dictionary TaskSignalAnyInit {
(TaskPriority or TaskSignal) priority = "user-visible";
};

[Exposed=(Window, Worker)]
interface TaskSignal : AbortSignal {
[NewObject] static TaskSignal _any(sequence&lt;AbortSignal> signals, optional TaskSignalAnyInit init = {});

readonly attribute TaskPriority priority;

attribute EventHandler onprioritychange;
Expand All @@ -103,22 +109,38 @@ accept an {{AbortSignal}}. Additionally, {{Scheduler/postTask()}} accepts an
{{AbortSignal}}, which can be useful if dynamic prioritization is not needed.

<dl class="domintro non-normative">
<dt><code>TaskSignal . <a method for=TaskSignal lt="any(signals, init)">any</a>(|signals|, |init|)</code>
<dd>Returns a {{TaskSignal}} instance which will be aborted if any of |signals| is aborted. Its
[=AbortSignal/abort reason=] will be set to whichever one of |signals| caused it to be aborted.
The signal's [=TaskSignal/priority=] will be determined by |init|'s {{TaskSignalAnyInit/priority}},
which can either be a fixed {{TaskPriority}} or a {{TaskSignal}}, in which case the new signal's
[=TaskSignal/priority=] will change along with this signal.

<dt><code>signal . {{TaskSignal/priority}}</code>
<dd>
<p>Returns the {{TaskPriority}} of the signal.
</dd>
<dd><p>Returns the {{TaskPriority}} of the signal.
</dl>

A {{TaskSignal}} object has an associated {{TaskPriority}}
<dfn for=TaskSignal>priority</dfn>.
A {{TaskSignal}} object has an associated <dfn for=TaskSignal>priority</dfn> (a {{TaskPriority}}).

A {{TaskSignal}} object has an associated <dfn for=TaskSignal>priority changing</dfn>
[=boolean=], intially set to false.
A {{TaskSignal}} object has an associated <dfn for=TaskSignal>priority changing</dfn> (a
[=boolean=]), which is intially set to false.

A {{TaskSignal}} object has associated <dfn for=TaskSignal>priority change algorithms</dfn>,
which is a [=set=] of algorithms, initialized to a new empty [=set=]. These
algorithms are to be executed when its [=TaskSignal/priority changing=] value
is true.
(a [=set=] of algorithms that are to be executed when its [=TaskSignal/priority changing=] value
is true), which is initially empty.

A {{TaskSignal}} object has an associated <dfn for=TaskSignal>source signal</dfn> (a weak refernece
to a {{TaskSignal}} that the object is dependent on for its [=TaskSignal/priority=]), which is
initially null.

A {{TaskSignal}} object has associated <dfn for=TaskSignal>dependent signals</dfn> (a weak [=set=]
of {{TaskSignal}} objects that are dependent on the object for their [=TaskSignal/priority=]), which
is initially empty.

A {{TaskSignal}} object has an associated <dfn for=TaskSignal>dependent</dfn> (a
boolean), which is initially false.

<br>

The <dfn attribute for="TaskSignal">priority</dfn> getter steps are to return
[=this=]'s [=TaskSignal/priority=].
Expand All @@ -132,9 +154,34 @@ To <dfn for="TaskSignal">add a priority change algorithm</dfn> |algorithm| to a
{{TaskSignal}} object |signal|, [=set/append=] |algorithm| to |signal|'s
[=TaskSignal/priority change algorithms=].

<br>

A {{TaskSignal}} <dfn for=TaskSignal lt="has fixed priority|have fixed priority">has fixed priority</dfn>
if it is a [=TaskSignal/dependent=] signal with a null [=TaskSignal/source signal=].

<div algorithm>
The static <dfn method for=TaskSignal><code>any(|signals|, |init|)</code></dfn> method steps are:

1. Let |resultSignal| be the result of <a for=AbortSignal>creating a dependent signal</a> from
|signals| using the {{TaskSignal}} interface and the [=current realm=].
1. Set |resultSignal|'s [=TaskSignal/dependent=] to true.
1. If |init|["{{TaskSignalAnyInit/priority}}"] is a {{TaskPriority}}, then:
1. Set |resultSignal|'s [=TaskSignal/priority=] to |init|["{{TaskSignalAnyInit/priority}}"].
1. Otherwise:
1. Let |sourceSignal| be |init|["{{TaskSignalAnyInit/priority}}"].
1. Set |resultSignal|'s [=TaskSignal/priority=] to |sourceSignal|'s [=TaskSignal/priority=].
1. If |sourceSignal| does not [=TaskSignal/have fixed priority=], then:
1. If |sourceSignal|'s [=TaskSignal/dependent=] is true, then set |sourceSignal| to
|sourceSignal|'s [=TaskSignal/source signal=].
1. Assert: |sourceSignal| is not [=TaskSignal/dependent=].
1. Set |resultSignal|'s [=TaskSignal/source signal=] to a weak reference to |sourceSignal|.
1. [=set/Append=] |resultSignal| to |sourceSignal|'s [=TaskSignal/dependent signals=].
1. Return |resultSignal|.
</div>

<div algorithm>
To <dfn for="TaskSignal">signal priority change</dfn> on a {{TaskSignal}}
object |signal|, given a {{TaskPriority}} |priority|, run the following steps:
object |signal|, given a {{TaskPriority}} |priority|:

1. If |signal|'s [=TaskSignal/priority changing=] is true, then [=exception/throw=]
a "{{NotAllowedError!!exception}}" {{DOMException}}.
Expand All @@ -147,9 +194,17 @@ To <dfn for="TaskSignal">add a priority change algorithm</dfn> |algorithm| to a
1. [=Fire an event=] named {{TaskSignal/prioritychange}} at |signal| using
{{TaskPriorityChangeEvent}}, with its {{TaskPriorityChangeEvent/previousPriority}}
attribute initialized to |previousPriority|.
1. [=list/iterate|For each=] |dependentSignal| of |signal|'s [=TaskSignal/dependent signals=],
[=TaskSignal/signal priority change=] on |dependentSignal| with |priority|.
1. Set |signal|'s [=TaskSignal/priority changing=] to false.
</div>

### Garbage Collection ### {#sec-task-signal-garbage-collection}

A [=TaskSignal/dependent=] {{TaskSignal}} object must not be garbage collected while its
[=TaskSignal/source signal=] is non-null and it has registered event listeners for its
{{TaskSignal/prioritychange}} event or its [=TaskSignal/priority change algorithms=] is non-empty.

Examples {#sec-controlling-tasks-examples}
---------------------

Expand Down
6 changes: 5 additions & 1 deletion spec/index.bs
Original file line number Diff line number Diff line change
Expand Up @@ -89,12 +89,16 @@ spec: HTML; urlPrefix: https://html.spec.whatwg.org/multipage/;
text: associated Document; for:Window; url: window-object.html#concept-document-window
type: dfn
text: runnable; for:task; url: webappapis.html#concept-task-runnable
spec: dom; urlPrefix: https://dom.spec.whatwg.org/#;
spec: dom; urlPrefix: https://dom.spec.whatwg.org/#
type: dfn;
text: creating a dependent signal; for:AbortSignal; url: create-a-dependent-abort-signal
text: signal; for: AbortController; url: abortcontroller-signal
spec: requestidlecallback; urlPrefix: https://www.w3.org/TR/requestidlecallback/#;
type: method;
text: requestIdleCallback(); for: Window; url: dom-window-requestidlecallback
spec: ECMASCRIPT urlPrefix: https://tc39.es/ecma262/#;
type: dfn
text: current realm; url: current-realm
</pre>

<pre class=include>
Expand Down
7 changes: 5 additions & 2 deletions spec/scheduling-tasks.md
Original file line number Diff line number Diff line change
Expand Up @@ -264,8 +264,11 @@ see [whatwg/html#5925](https://github.com/whatwg/html/issues/5925).
for a {{Scheduler}} |scheduler| given an {{AbortSignal}} or null |signal|, and
a {{TaskPriority}} or null |priority|:

1. If |priority| is null and |signal| is not null and |signal| [=implements=]
the {{TaskSignal}} interface, then
1. If |priority| is null, |signal| is not null and [=implements=] the {{TaskSignal}} interface,
and |signal| [=TaskSignal/has fixed priority=], then set |priority| to |signal|'s
[=TaskSignal/priority=].
1. If |priority| is null and |signal| is not null and [=implements=] the {{TaskSignal}} interface,
then
1. If |scheduler|'s [=Scheduler/dynamic priority task queue map=] does not
[=map/contain=] |signal|, then
1. Let |queue| be the result of [=creating a scheduler task queue=] given
Expand Down