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

Clean up yield inheritance #115

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
64 changes: 54 additions & 10 deletions spec/patches.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,30 @@ determine task execution order across [=scheduler task queues=] of the same {{Ta
all {{Scheduler}}s associated with the same [=event loop=]. A timestamp would also suffice as long
as it is guaranteed to be strictly increasing and unique.

Add: An [=event loop=] has a <dfn for="event loop">current scheduling state</dfn> (a [=scheduling
state=] or null), which is initialized to null.
Add: An [=event loop=] has a <dfn for="event loop">current continuation state</dfn> (a
[=continuation state=] or null), which is initially null.

Add the following algorithms:

<div algorithm>
To <dfn>set the continuation state value</dfn> for |key| to |value| given an |eventLoop| (an
[=event loop=]):

1. If |eventLoop|'s [=event loop/current continuation state=] is null, then set |eventLoop|'s
[=event loop/current continuation state=] to a new [=continuation state=].
1. Let |continuationState| be |eventLoop|'s [=event loop/current continuation state=].
1. Assert: |continuationState|'s [=continuation state/state map=][|key|] does not [=map/exist=].
1. Set |continuationState|'s [=continuation state/state map=][|key|] to |value|.
</div>

<div algorithm>
To <dfn>get the continuation state value</dfn> for |key| given an |eventLoop| (an [=event loop=]):

1. Let |continuationState| be |eventLoop|'s [=event loop/current continuation state=].
1. If |continuationState| is not null and |continuationState|'s
[=continuation state/state map=][|key|] [=map/exists=], then return |continuationState|'s
[=continuation state/state map=][|key|], otherwise return null.
</div>

### <a href="https://html.spec.whatwg.org/multipage/webappapis.html#event-loop-processing-model">Event loop: processing model</a> ### {#sec-patches-html-event-loop-processing}

Expand Down Expand Up @@ -80,33 +102,55 @@ Issue: The |taskQueue| in this step will either be a [=set=] of [=tasks=] or a [
*roughly* compatible. Ideally, there would be a common task queue interface that supports a `pop()`
method that would return a plain [=task=], but that would involve a fair amount of refactoring.

### <a href="https://html.spec.whatwg.org/#queuing-tasks">Event Loop: Queuing Tasks</a> ### {#sec-patches-html-queuing-tasks}

Change the <a href="">To queue a microtask</a> algorithm to accept an optional boolean
|ignoreContinuationState| (default false).

Change Step 5 to the following:

1. Let |continuationState| be |eventLoop|'s [=event loop/current continuation state=] if
|ignoreContinuationState| is false, otherwise null.
1. Set <var ignore=''>microtask</var>'s <a attribute for="task">steps</a> to the following:
1. If |ignoreContinuationState| is false, then set |eventLoop|'s
[=event loop/current continuation state=] to |continuationState|.
1. Run <var ignore=''>steps</var>.
1. If |ignoreContinuationState| is false, then set |eventLoop|'s
[=event loop/current continuation state=] to null.

### <a href="https://html.spec.whatwg.org/multipage/webappapis.html#hostmakejobcallback">HostMakeJobCallback(callable)</a> ### {#sec-patches-html-hostmakejobcallback}

Add the following before step 5:

1. Let |event loop| be <var ignore=''>incumbent settings<var>'s
[=environment settings object/realm=]'s [=realm/agent=]'s [=agent/event loop=].
1. Let |state| be |event loop|'s [=event loop/current scheduling state=].
1. Let |state| be |event loop|'s [=event loop/current continuation state=].

Modify step 5 to read:

1. Return the <span>JobCallback Record</span> { \[[Callback]]: <var ignore=''>callable</var>,
\[[HostDefined]]: { \[[IncumbentSettings]]: <var ignore=''>incumbent settings</var>,
\[[ActiveScriptContext]]: <var ignore=''>script execution context</var>,
\[[SchedulingState]]: |state| } }.
\[[ContinuationState]]: |state| } }.

### <a href="https://html.spec.whatwg.org/multipage/webappapis.html#hostcalljobcallback">HostCallJobCallback(callback, V, argumentsList)</a> ### {#sec-patches-html-hostcalljobcallback}

Add the following steps before step 5:

1. Let |event loop| be <var ignore=''>incumbent settings<var>'s
[=environment settings object/realm=]'s [=realm/agent=]'s [=agent/event loop=].
1. Set |event loop|'s [=event loop/current scheduling state=] to
<var ignore=''>callback</var>.\[[HostDefined]].\[[SchedulingState]].
1. Set |event loop|'s [=event loop/current continuation state=] to
<var ignore=''>callback</var>.\[[HostDefined]].\[[ContinuationState]].

Add the following after step 7:

1. Set |event loop|'s [=event loop/current scheduling state=] to null.
1. Set |event loop|'s [=event loop/current continuation state=] to null.

### <a href="https://html.spec.whatwg.org/multipage/webappapis.html#hostenqueuepromisejob">HostEnqueuePromiseJob(job, realm)</a> ### {#sec-patches-html-hostenqueuepromisejob}

Change step 2 to:

1. Queue a microtask to perform the following steps with |ignoreContinuationState| set to true:

## <a href="https://w3c.github.io/requestidlecallback/">`requestIdleCallback()`</a> ## {#sec-patches-requestidlecallback}

Expand All @@ -118,9 +162,9 @@ Add the following step before step 3.3:
1. Let |state| be a new [=scheduling state=].
1. Set |state|'s [=scheduling state/priority source=] to the result of [=creating a fixed priority
unabortable task signal=] given "{{TaskPriority/background}}" and |realm|.
1. Let |event loop| be |realm|'s [=realm/agent=]'s [=agent/event loop=].
1. Set |event loop|'s [=event loop/current scheduling state=] to |state|.
1. Let |scheduler| be the {{Scheduler}} whose [=relevant realm=] is |realm|.
1. [=Set the current scheduling state=] for |scheduler| to |state|.

Add the following after step 3.3:

1. Set |event loop|'s [=event loop/current scheduling state=] to null.
1. Set |event loop|'s [=event loop/current continuation state=] to null.
40 changes: 34 additions & 6 deletions spec/scheduling-tasks.md
Original file line number Diff line number Diff line change
Expand Up @@ -175,12 +175,22 @@ A <dfn>scheduler task queue</dfn> is a [=struct=] with the following [=struct/it
A <dfn>scheduling state</dfn> is a [=struct=] with the following [=struct/items=]:

: <dfn for="scheduling state">abort source</dfn>
:: An {{AbortSignal}} object or, initially null.
:: An {{AbortSignal}} object or null, initially null.
: <dfn for="scheduling state">priority source</dfn>
:: A {{TaskSignal}} object or null, initially null.

<br/>

A <dfn>continuation state</dfn> is a [=struct=] with the following [=struct/items=]:

: <dfn for="continuation state">state map</dfn>
:: An initially empty [=map=].

Note: The [=continuation state/state map=] can be implemented as weak map if its keys are
implemented as garbage collected objects.

<br/>

A <dfn>task handle</dfn> is a [=struct=] with the following [=struct/items=]:

: <dfn for="task handle">task</dfn>
Expand Down Expand Up @@ -289,6 +299,25 @@ A <dfn>task handle</dfn> is a [=struct=] with the following [=struct/items=]:

### Scheduling Tasks and Continuations ### {#sec-scheduler-alg-scheduling-tasks-and-continuations}

<div algorithm>
To <dfn>set the current scheduling state</dfn> for |scheduler| (a {{Scheduler}}) to |state| (a
[=scheduling state=]):

1. Let |eventLoop| be |scheduler|'s [=relevant agent=]'s [=agent/event loop=].
1. [=Set the continuation state value=] for |scheduler| to |state| given |eventLoop|.

Note: Any key can be used for the [=continuation state/state map=] as long as it is unique to the
{{Scheduler}}.
</div>

<div algorithm>
To <dfn>get the current scheduling state</dfn> for |scheduler| (a {{Scheduler}}):

1. Let |eventLoop| be |scheduler|'s [=relevant agent=]'s [=agent/event loop=].
1. Return the result of [=getting the continuation state value=] for |scheduler| given
|eventLoop|.
</div>

<div algorithm>
To <dfn>schedule a postTask task</dfn> for {{Scheduler}} |scheduler| given a
{{SchedulerPostTaskCallback}} |callback| and {{SchedulerPostTaskOptions}} |options|:
Expand Down Expand Up @@ -316,12 +345,12 @@ A <dfn>task handle</dfn> is a [=struct=] with the following [=struct/items=]:
for |scheduler| given |state|'s [=scheduling state/priority source=] and false.
1. [=Schedule a task to invoke an algorithm=] for |scheduler| given |handle| and the following
steps:
1. Let |event loop| be the |scheduler|'s [=relevant agent=]'s [=agent/event loop=].
1. Set |event loop|'s [=event loop/current scheduling state=] to |state|.
1. Let |eventLoop| be the |scheduler|'s [=relevant agent=]'s [=agent/event loop=].
1. [=Set the current scheduling state=] for |scheduler| to |state|.
1. Let |callbackResult| be the result of [=invoking=] |callback| with « » and "`rethrow`".
If that threw an exception, then [=reject=] |result| with that. Otherwise, [=resolve=]
|result| with |callbackResult|.
1. Set |event loop|'s [=event loop/current scheduling state=] to null.
1. Set |eventLoop|'s [=event loop/current continuation state=] to null.
1. Let |delay| be |options|["{{SchedulerPostTaskOptions/delay}}"].
1. If |delay| is greater than 0, then [=run steps after a timeout=] given |scheduler|'s [=relevant
global object=], "`scheduler-postTask`", |delay|, and the following steps:
Expand All @@ -340,8 +369,7 @@ Issue: [=Run steps after a timeout=] doesn't necessarily account for suspension;
To <dfn>schedule a yield continuation</dfn> for {{Scheduler}} |scheduler|:

1. Let |result| be [=a new promise=].
1. Let |inheritedState| be the |scheduler|'s [=relevant agent=]'s [=agent/event loop=]'s
[=event loop/current scheduling state=].
1. Let |inheritedState| be the result of [=getting the current scheduling state=] for |scheduler|.
1. Let |abortSource| be |inheritedState|'s [=scheduling state/abort source=] if |inheritedState|
is not null, or otherwise null.
1. If |abortSource| is not null and |abortSource| is [=AbortSignal/aborted=], then [=reject=]
Expand Down