Bug 265096

Summary: Provide ability to convert one type of NativePromise into another
Product: WebKit Reporter: Jean-Yves Avenard [:jya] <jean-yves.avenard>
Component: Web Template FrameworkAssignee: Jean-Yves Avenard [:jya] <jean-yves.avenard>
Status: RESOLVED DUPLICATE    
Severity: Normal CC: webkit-bug-importer
Priority: P2 Keywords: InRadar
Version: WebKit Nightly Build   
Hardware: Unspecified   
OS: Unspecified   
See Also: https://bugs.webkit.org/show_bug.cgi?id=264028
https://bugs.webkit.org/show_bug.cgi?id=265102

Description Jean-Yves Avenard [:jya] 2023-11-18 16:49:27 PST
The problem was mentioned in https://github.com/WebKit/WebKit/pull/20652#discussion_r1397622606

Where we did the following:
```
Ref<MediaPromise> SourceBufferPrivate::removeCodedFrames(const MediaTime& start, const MediaTime& end, const MediaTime& currentTime)
{
    MediaPromise::Producer producer;
    Ref promise = producer.promise();

    m_currentSourceBufferOperation = m_currentSourceBufferOperation->whenSettled(RunLoop::current(), [weakThis = WeakPtr { *this }, this, start, end, currentTime](auto&& result) mutable {
        if (!weakThis || !result)
            return MediaPromise::createAndReject(!result ? result.error() : PlatformMediaError::BufferRemoved);
        return removeCodedFramesInternal(start, end, currentTime);
    })->whenSettled(RunLoop::current(), [producer = WTFMove(producer)](auto&& result) mutable {
        producer.settle(result);
        return MediaPromise::createAndSettle(WTFMove(result));
    });
    return promise;
}
```

 m_currentSourceBufferOperation is a MediaPromise which is exclusive; you can only perform a single then/whenSettled on it. Exclusive promise are useful as it allows for move semantics and avoid needless copies of the resolved/rejected value.

So in the code above, we can't return m_currentSourceBufferOperation as it would mean you run then/whenSettled on it twice, which would assert.

One solution above would be to
1- make MediaPromise (NativePromise<void, PlatformMediaError>) a non-exclusive promise or
2- make m_currentSourceBufferOperation be a NonExclusive promise and allows to convert a non exclusive promise into an exclusive one.

Doing 1- would require changing all the MediaPromise use points to no longer expect a r-valued result (most are using `(auto&& result)` as their prototype
2- allows for less disruptive code and allow for rather more elegant code. It would also be a bit more efficient as you no longer require to dispatch a task

So the above could be written:
```
    m_currentSourceBufferOperation = m_currentSourceBufferOperation->whenSettled(RunLoop::current(), [weakThis = WeakPtr { *this }, this, start, end, currentTime](auto&& result) mutable {
        if (!weakThis || !result)
            return OperationPromise::createAndReject(!result ? result.error() : PlatformMediaError::BufferRemoved);
        return static_cast<Ref<OperationPromise>>(removeCodedFramesInternal(start, end, currentTime).get());
    });
    return m_currentSourceBufferOperation.get();
```
where m_currentSourceBufferOperation.get is now a non-exclusive promise.

Adopting solution 2, also gets us close to achieving bug 264028
Comment 1 Radar WebKit Bug Importer 2023-11-18 16:49:41 PST
<rdar://problem/118610126>
Comment 2 Jean-Yves Avenard [:jya] 2023-11-18 17:06:53 PST
Pull request: https://github.com/WebKit/WebKit/pull/20713
Comment 3 Jean-Yves Avenard [:jya] 2023-11-19 03:28:02 PST
Pull request: https://github.com/WebKit/WebKit/pull/20721
Comment 4 Jean-Yves Avenard [:jya] 2023-11-19 21:29:01 PST
Combined changes with bug 264028

*** This bug has been marked as a duplicate of bug 264028 ***