Re: [w3c/screen-orientation] Promise for unlock()? (#104)

> Could you maybe explain the mess and how returning a promise helps resolve it?

Sure! 

## Problem 

The over problem with the design of the API is that it's designed to be "fire and forget". I think this was done originally (9 years ago) because some OSs didn't provide any signal about the success of the orientation change. 

That led to the current model:

```
(promise) `.lock()` -> IPC -> OS maybe does something -> IPC (success/fail) -> settle JS promise. 
```

And the assumption with `unlock()` was the it was "fire and forget" (hence no promise):

```
`.unlock()` -> IPC -> OS maybe does something but doesn't notify success. 
```

The above assumption is wrong, because `.unlock()` IPC SHOULD notify of success/failure. 

Thus, if one calls: 

```
p1 = lock();
unlock();
```

They race, because the IPC messages could end up out of order. Similarly:

```
.unlock();
.exitFullscreen();
```

Has the race condition, as noted by the OP. This leads to horrible hacks, like using `setTimeout()` and `requestAnimationFrame()` to provide enough time for the screen to actually unlock. 

The work around in WebKit's test framework is now to always basically do:

```
const initialOrientation = screen.orientation.type;
// ... test ....
// manually reset it
await .lock(initialOrientation);
.unlock(); // nothing happens at device because of call above
await .exitFullscreen();
```

## Addressing the issue

What should have actually happened in the API is that it should have been impossible to make call to .unlock() (or another .lock()) before the first call finishes (and the promise settles). 

```JS
const p1 = orientation.lock("any");
// InvalidStateError, p1 hasn't settled.
const p2 = orientation.lock("landscape");
// Unlock, InvalidStateError, p1 hasn't settled
const p3 = orientation.unlock();
```

Unfortunately, doing the above might no longer be web compatible... 

## What we should do... 

Unlocking should be treated exactly the same as .lock(). That is:

```
(promise) `.unlock()` -> IPC -> OS maybe does something -> IPC (success/fail) -> settle JS promise. 
```

That means that .unlock() will abort any pending `.lock()` promises (same as lock already does), and will have exactly the same behavior as `.lock()`. When used correctly by developers, the race conditions go away:

```
await .lock();
await .unlock();
await .anyOtherAPI();
```

> (One way out might be to make unlock() no-op and require exiting fullscreen instead. Not sure how compatible that is though.)

The problem is that the API can be used outside the context of the FS API (e.g., a web application that was installed that launched full screen). 

However, we should nonetheless integrate the two APIs as I proposed here:
https://github.com/whatwg/fullscreen/issues/202#issuecomment-1275546965






-- 
Reply to this email directly or view it on GitHub:
https://github.com/w3c/screen-orientation/issues/104#issuecomment-1276804083
You are receiving this because you are subscribed to this thread.

Message ID: <w3c/screen-orientation/issues/104/1276804083@github.com>

Received on Wednesday, 12 October 2022 22:39:06 UTC