-
Notifications
You must be signed in to change notification settings - Fork 35
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
editorial: Tidy up uses of "in parallel". #299
Conversation
While you are here fixing the "in parallel" sections this specification should be updated to define a task source onto which the tasks returning to main thread are queued. |
Do you think it's better to come up with a new task source, or would it make sense to use the user interaction task source? |
Per w3c/presentation-api#360 and w3ctag/design-principles#38 it looks like it makes more sense to define another task source. |
Some thoughts:
In parallel usage otherwise seems reasonable from a quick skim. (If you're still not too sure about it, HTML has a bunch of guidance language for it, it's basically akin to a thread/process. Also happy to chat at https://whatwg.org/irc or equivalent.) Questions:
|
da7e759
to
8dc5d6a
Compare
Thanks for the review, @annevk. I've pushed some new commits addressing some of the points you've brought up.
I was hoping to get rid of the algorithm altogether in #298, but in the meantime I've dropped the "in parallel" bit in this PR.
Done.
Is there any particular reason for using "global" here? I recently defined a task source in #301 and was using the regular "queue a task" language with it.
Hmm, I wonder if the algorithms in "handling document loss of {full activity, visibility}" could set some flag that could be checked in the parallel steps of
Would it be OK (from an idiomatic perspective) to remove the check altogether and sort of under-specify the behavior by leaving it up to each implementation to determine whether to ask the platform for a lock?
Thanks, done.
I'm trying to determine if there's some general guidance here. If it's basically "fire events away and only queue a task to fire them if necessary", then I'm fine with the changes being done here. |
Yes, it helps ensure the task is queued on the correct event loop and all the relevant bits are set correctly. (Though @domenic has been suggesting that we have some kind of ambient global available for constructing objects we could also repurpose here perhaps...)
Maybe, not sure. It seems easy enough to add some boolean that you can use to prevent this, no?
It depends on the cause and the target, I think here it's fine. If it was in response to a DOM mutation I'd ask for a change. |
* @annevk says in w3c#299 that, as a general rule, invoking IDL members from algorithms, like we were doing with `document.hidden`, is not recommended. Instead, invoke the "determine the visibility state" steps defined in the Page Visibility spec directly. * Clean up the "Dependencies" section; for now we only need one term that is not exported by the latest Page Visibility TR (this is fixed in the ED): the "now hidden algorithm". The steps described in the "Handling document loss of visibility" steps now explicitly run after that algorithm, which runs when the top-level browsing context's Document becomes hidden. More generally, these changes should also make it more clear that the visibility state checks only apply to the top-level browsing context (according to the Page Visibility spec itself). Although we were previously checking if a given `Document` was `hidden` even if it did not belong to a top-level browsing context, that was simply invalid.
8dc5d6a
to
56b7230
Compare
@annevk I've pushed a few more commits. I think I've managed to solve everything, but I am not entirely sure doing things from a queued global task is enough to avoid race conditions and not being allowed to refer to global objects:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some drive by feedback...
…#306) * @annevk says in #299 that, as a general rule, invoking IDL members from algorithms, like we were doing with `document.hidden`, is not recommended. Instead, invoke the "determine the visibility state" steps defined in the Page Visibility spec directly. * Clean up the "Dependencies" section; for now we only need one term that is not exported by the latest Page Visibility TR (this is fixed in the ED): the "now hidden algorithm". The steps described in the "Handling document loss of visibility" steps now explicitly run after that algorithm, which runs when the top-level browsing context's Document becomes hidden. More generally, these changes should also make it more clear that the visibility state checks only apply to the top-level browsing context (according to the Page Visibility spec itself). Although we were previously checking if a given `Document` was `hidden` even if it did not belong to a top-level browsing context, that was simply invalid.
6e19ace
to
2074bdb
Compare
<li>Let |document:Document| be the [=environment settings object / | ||
responsible document=] of the <a>current settings object</a>. | ||
responsible document=] of <a>this</a>' <a>relevant settings | ||
object</a>. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Domenic just used "
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it makes sense to clean this up in #307 rather than here, as it's part of the effort to stop mentioning "responsible document" altogether.
@annevk @domenic @kenchris @marcoscaceres I think this PR is finally ready. All uses of "in parallel" have been audited, I think There are further cleanups that @domenic is doing in #307 related to the use of "responsible document"; I think it makes sense to land them separately there. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking very solid; just some minor issues with nesting.
Incorporate suggestions made by @domenic in w3c#299: * Steps 1.1 and 1.2 which checked `document` should not be substeps of step 1, but siblings just like other subsequent steps that also check `document`. * Checking the value of `state` should be done at the same nesting level of the step that sets `state`, not as a nested substep. These changes should have no user-visible effects.
Incorporate suggestions made by @domenic in w3c#299: * Steps 1.1 and 1.2 which checked `document` should not be substeps of step 1, but siblings just like other subsequent steps that also check `document`. * Checking the value of `state` should be done at the same nesting level of the step that sets `state`, not as a nested substep. These changes should have no user-visible effects.
…#308) Incorporate suggestions made by @domenic in #299: * Steps 1.1 and 1.2 which checked `document` should not be substeps of step 1, but siblings just like other subsequent steps that also check `document`. * Checking the value of `state` should be done at the same nesting level of the step that sets `state`, not as a nested substep. These changes should have no user-visible effects.
c69a539
to
c87c077
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM.
@rakuco, any blockers or anything you need help with here? |
Nope, thanks a lot for reviewing and accepting the PR, and sorry I haven't merged it yet. I've been dragged into other stuff but will try to check if any tests need to be adjusted and merge it today or tomorrow. |
Great to hear! thanks for the update, @rakuco! |
Besides tidying up uses of "in parallel" in algorithms, that spec change also makes the "release wake lock" algorithm fire the "release" event and change the `[[Released]]` slot immediately rather than in a queued task. Adjust some tests to make sure the new behavior is properly verified here.
Besides tidying up uses of "in parallel" in algorithms, that spec change also makes the "release wake lock" algorithm fire the "release" event and change the `[[Released]]` slot immediately rather than in a queued task. Adjust some tests to make sure the new behavior is properly verified here.
Steps that run "in parallel" need to take several extra restrictions into account: we do not have access to documents or global objects, cannot create IDL interfaces or manipulate promises, for example, all of which we had been doing, along with needlessly running nested "in parallel" steps. This change attempts to rectify the situation by only running things in parallel when absolutely necessary (i.e. when reaching out to the OS), and queuing global tasks (emphasis on "global" given whatwg/html#4980 and whatwg/html#5653) from there when we need to manipulate promises or create objects. "Obtain permission" algorithm: * Stop running in parallel. Callers should be responsible for choosing whether it should be run in parallel or not. `WakeLock.request()`: * Separate returning a promise and running steps in parallel. This style is more usual. * Refer to the "relevant settings object" rather than the "current settings object", as we are inside a method of an IDL interface and can rely on it being defined. I do not think this is a user-visible change, and it looks cleaner. * Queue a global task to reject `|promise|` when the permission request run in parallel is denied. * Manipulate the `[[ActiveLocks]]` internal slot, check page visibility, invoke "acquire a wake lock", create a new WakeLockSentinel and resolve the returned promise in a queued global task. `WakeLockSentinel.release()`: * Do not run the "release a wake lock" algorithm in parallel (see the changes to the algorithm itself below). * Just return a resolved promise once the rest of the steps run. The returned promise does not have much use, but has been kept to avoid breaking API compatibility. * One user-visible consequence is that the "release" event is fired synchronously and before the function returns. "Acquire wake lock" algorithm: * Stop running everything in parallel. * Move all `[[ActiveLocks]]` manipulation to `WakeLock.request()` itself, and make the algorithm just ask the platform for a wake lock. "Release wake lock" algorithm: * Stop running everything in parallel. The only steps that still need to run in parallel are the ones asking the platform to release the wake lock. * Consequently, stop queueing a task to change `[[Released]]` and fire the "release" event, and do it directly in the algorithm instead. Big thanks to Anne van Kesteren, Domenic Denicola and Marcos Cáceres for their input. Fixes w3c#293.
c87c077
to
7ac57c1
Compare
I'd like to thank everyone once again for reviewing this patch and for all the discussions. I've updated the PR message and included links to the Chromium bug and WPT PR that this change has originated. Since there have been no objections and the PR in WPT is close to being merged, I'm finally going to merge this one. |
Besides tidying up uses of "in parallel" in algorithms, that spec change also makes the "release wake lock" algorithm fire the "release" event and change the `[[Released]]` slot immediately rather than in a queued task. Adjust some tests to make sure the new behavior is properly verified here.
…ke-lock#299, a=testonly Automatic update from web-platform-tests screen-wake-lock: Adapt to w3c/screen-wake-lock#299 (#28148) Besides tidying up uses of "in parallel" in algorithms, that spec change also makes the "release wake lock" algorithm fire the "release" event and change the `[[Released]]` slot immediately rather than in a queued task. Adjust some tests to make sure the new behavior is properly verified here. -- wpt-commits: 36aa2a490d8aabdb15436e62910fe87111fddbdf wpt-pr: 28148
This spec change reworked the way "in parallel" is used in normative text. In terms of implementation, the only thing that needs to change is the way we set WakeLockSentinel::released_ and fire the "release" event. This is now done synchronously rather than from a queued task, which means WakeLockSentinel.release() will immediately perform those actions rather than return a promise first. The promise is not really necessary, but it has been kept in the spec to avoid making a backwards-incompatible change. The corresponding test changes are being landed directly in WPT and once they are imported the new -expected.txt will be removed automatically: web-platform-tests/wpt#28148 Bug: 1190110 Change-Id: Ia9fc0174d36f70a7f7c8ede90c5992b07e1c69ec Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2778411 Reviewed-by: Reilly Grant <[email protected]> Commit-Queue: Raphael Kubo da Costa <[email protected]> Cr-Commit-Position: refs/heads/master@{#867272}
This spec change reworked the way "in parallel" is used in normative text. In terms of implementation, the only thing that needs to change is the way we set WakeLockSentinel::released_ and fire the "release" event. This is now done synchronously rather than from a queued task, which means WakeLockSentinel.release() will immediately perform those actions rather than return a promise first. The promise is not really necessary, but it has been kept in the spec to avoid making a backwards-incompatible change. The corresponding test changes are being landed directly in WPT and once they are imported the new -expected.txt will be removed automatically: web-platform-tests/wpt#28148 Bug: 1190110 Change-Id: Ia9fc0174d36f70a7f7c8ede90c5992b07e1c69ec Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2778411 Reviewed-by: Reilly Grant <[email protected]> Commit-Queue: Raphael Kubo da Costa <[email protected]> Cr-Commit-Position: refs/heads/master@{#867272} GitOrigin-RevId: dcfc63084215ecd3292e911eefe07fddcf30aed0
Steps that run "in parallel" need to take several extra restrictions into
account: we do not have access to documents or global objects, cannot create
IDL interfaces or manipulate promises, for example, all of which we had been
doing, along with needlessly running nested "in parallel" steps.
This change attempts to rectify the situation by only running things in
parallel when absolutely necessary (i.e. when reaching out to the OS), and
queuing global tasks (emphasis on "global" given whatwg/html#4980 and
whatwg/html#5653) from there when we need to manipulate promises or create
objects.
"Obtain permission" algorithm:
whether it should be run in parallel or not.
WakeLock.request()
:more usual.
object", as we are inside a method of an IDL interface and can rely on it
being defined. I do not think this is a user-visible change, and it looks
cleaner.
|promise|
when the permission request runin parallel is denied.
[[ActiveLocks]]
internal slot, check page visibility,invoke "acquire a wake lock", create a new WakeLockSentinel and resolve
the returned promise in a queued global task.
WakeLockSentinel.release()
:changes to the algorithm itself below).
returned promise does not have much use, but has been kept to avoid
breaking API compatibility.
synchronously and before the function returns.
"Acquire wake lock" algorithm:
[[ActiveLocks]]
manipulation toWakeLock.request()
itself,and make the algorithm just ask the platform for a wake lock.
"Release wake lock" algorithm:
in parallel are the ones asking the platform to release the wake lock.
[[Released]]
and fire the"release" event, and do it directly in the algorithm instead.
Big thanks to Anne van Kesteren, Domenic Denicola and Marcos Cáceres for
their input.
Fixes #293.
Open items:
|document|
is hidden inWakeLock.request()
's parallel steps? Or, more generally speaking, how can we avoid reaching the steps where we ask the platform for a lock if the page was hidden, for example?WakeLock.request()
: does it make sense to have to separate "in parallel" steps to first acquire a platform lock and then manipulate[[ActiveLocks]]
?WakeLock.request()
: does manipulating[[ActiveLocks]]
from a queued task leave the algorithm open to race conditions?WakeLockSentinel.release()
: the Web Platform Design Principles say "events should fire before Promises resolve". Do the changes make sense here? We are changing[[Released]]
and firing the "released" event "synchronously" in the event loop before even creating the resolved promise we are returning. This feels a bit odd, but on the other hand I'm not sure how to avoid running the "release wake lock" algorithm in parallel if we create the promise first.[[Released]]
be changed synchronously though, so that e.g. when we are navigating to another page, should.released
is true in the "visibilitychange" event handler even though the "release" event has not been dispatched?The following tasks have been completed:
Implementation commitment:
Preview | Diff