Changeset 224584 in webkit


Ignore:
Timestamp:
Nov 8, 2017 9:26:22 AM (6 years ago)
Author:
Chris Dumez
Message:

[Service Workers] Support waitUntil() on the 'install' event
https://bugs.webkit.org/show_bug.cgi?id=179396

Reviewed by Brady Eidson.

LayoutTests/imported/w3c:

Rebaseline a few WPT tests.

  • web-platform-tests/service-workers/service-worker/oninstall-script-error.https-expected.txt:
  • web-platform-tests/service-workers/service-worker/register-wait-forever-in-install-worker.https-expected.txt:

Source/WebCore:

Support waitUntil() on the 'install' event:

Tests: http/tests/workers/service/basic-install-event-waitUntil-multiple-promises.html

http/tests/workers/service/basic-install-event-waitUntil-reject.html
http/tests/workers/service/basic-install-event-waitUntil-resolve.html

  • testing/Internals.cpp:
  • testing/Internals.h:
  • testing/Internals.idl:
  • workers/service/ExtendableEvent.cpp:

(WebCore::ExtendableEvent::waitUntil):
(WebCore::ExtendableEvent::addExtendLifetimePromise):
(WebCore::ExtendableEvent::whenAllExtendLifetimePromisesAreSettled):

  • workers/service/ExtendableEvent.h:

(WebCore::ExtendableEvent::pendingPromiseCount const):

  • workers/service/FetchEvent.cpp:

(WebCore::FetchEvent::respondWith):

  • workers/service/ServiceWorkerContainer.cpp:

(WebCore::ServiceWorkerContainer::addRegistration):
(WebCore::ServiceWorkerContainer::removeRegistration):

  • workers/service/ServiceWorkerContainer.h:
  • workers/service/context/ServiceWorkerThread.cpp:

(WebCore::ServiceWorkerThread::fireInstallEvent):

  • workers/service/server/SWClientConnection.h:
  • workers/service/server/SWServerJobQueue.cpp:

(WebCore::SWServerJobQueue::didFinishInstall):

  • workers/service/server/SWServerRegistration.cpp:

(WebCore::SWServerRegistration::firePostInstallEvents):

LayoutTests:

Add layout test coverage.

  • http/tests/workers/service/basic-install-event-waitUntil-multiple-promises-expected.txt: Added.
  • http/tests/workers/service/basic-install-event-waitUntil-multiple-promises.html: Added.
  • http/tests/workers/service/basic-install-event-waitUntil-reject-expected.txt: Added.
  • http/tests/workers/service/basic-install-event-waitUntil-reject.html: Added.
  • http/tests/workers/service/basic-install-event-waitUntil-resolve-expected.txt: Added.
  • http/tests/workers/service/basic-install-event-waitUntil-resolve.html: Added.
  • http/tests/workers/service/resources/basic-install-event-waitUntil-multiple-promises-worker.js: Added.

(event.i.event.waitUntil.new.Promise):

  • http/tests/workers/service/resources/basic-install-event-waitUntil-reject-worker.js: Added.

(event.event.waitUntil.new.Promise):

  • http/tests/workers/service/resources/basic-install-event-waitUntil-resolve-worker.js: Added.

(event.event.waitUntil.new.Promise):

  • http/wpt/service-workers/extendableEvent.https-expected.txt:
  • http/wpt/service-workers/extendableEvent.https.html:
Location:
trunk
Files:
9 added
19 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r224582 r224584  
     12017-11-08  Chris Dumez  <cdumez@apple.com>
     2
     3        [Service Workers] Support waitUntil() on the 'install' event
     4        https://bugs.webkit.org/show_bug.cgi?id=179396
     5
     6        Reviewed by Brady Eidson.
     7
     8        Add layout test coverage.
     9
     10        * http/tests/workers/service/basic-install-event-waitUntil-multiple-promises-expected.txt: Added.
     11        * http/tests/workers/service/basic-install-event-waitUntil-multiple-promises.html: Added.
     12        * http/tests/workers/service/basic-install-event-waitUntil-reject-expected.txt: Added.
     13        * http/tests/workers/service/basic-install-event-waitUntil-reject.html: Added.
     14        * http/tests/workers/service/basic-install-event-waitUntil-resolve-expected.txt: Added.
     15        * http/tests/workers/service/basic-install-event-waitUntil-resolve.html: Added.
     16        * http/tests/workers/service/resources/basic-install-event-waitUntil-multiple-promises-worker.js: Added.
     17        (event.i.event.waitUntil.new.Promise):
     18        * http/tests/workers/service/resources/basic-install-event-waitUntil-reject-worker.js: Added.
     19        (event.event.waitUntil.new.Promise):
     20        * http/tests/workers/service/resources/basic-install-event-waitUntil-resolve-worker.js: Added.
     21        (event.event.waitUntil.new.Promise):
     22        * http/wpt/service-workers/extendableEvent.https-expected.txt:
     23        * http/wpt/service-workers/extendableEvent.https.html:
     24
    1252017-11-08  David Hyatt  <hyatt@apple.com>
    226
  • trunk/LayoutTests/http/wpt/service-workers/extendableEvent.https-expected.txt

    r223562 r224584  
    11
    22PASS ExtendableEvent waitUntil should support non promise parameters
    3 PASS ExtendableEvent should wait for given promise to resolve
    4 PASS ExtendableEvent should wait for given promise to reject
    53PASS Event constructors
    64
  • trunk/LayoutTests/http/wpt/service-workers/extendableEvent.https.html

    r223562 r224584  
    1111    assert_throws('InvalidStateError', () => event.waitUntil(new Request('')));
    1212}, "ExtendableEvent waitUntil should support non promise parameters");
    13 
    14 promise_test(async t => {
    15     if (!window.internals)
    16         return Promise.reject("test require internals");
    17     var event = internals.createTrustedExtendableEvent();
    18     var promise = internals.waitForExtendableEventToFinish(event);
    19     var shouldWait = true;
    20     event.waitUntil(new Promise((resolve, reject) => {
    21         setTimeout(() => {
    22             shouldWait = false;
    23             resolve(new Request(''));
    24         }, 50);
    25     }));
    26     await promise;
    27     assert_false(shouldWait);
    28 }, "ExtendableEvent should wait for given promise to resolve");
    29 
    30 promise_test(async t => {
    31     if (!window.internals)
    32         return Promise.reject("test require internals");
    33     var event = internals.createTrustedExtendableEvent();
    34     var promise = internals.waitForExtendableEventToFinish(event);
    35     var shouldWait = true;
    36     event.waitUntil(new Promise((resolve, reject) => {
    37         setTimeout(() => {
    38             shouldWait = false;
    39             reject(new Request(''));
    40         }, 50);
    41     }));
    42     await promise;
    43     assert_false(shouldWait);
    44 }, "ExtendableEvent should wait for given promise to reject");
    4513
    4614test(function() {
  • trunk/LayoutTests/imported/w3c/ChangeLog

    r224581 r224584  
     12017-11-08  Chris Dumez  <cdumez@apple.com>
     2
     3        [Service Workers] Support waitUntil() on the 'install' event
     4        https://bugs.webkit.org/show_bug.cgi?id=179396
     5
     6        Reviewed by Brady Eidson.
     7
     8        Rebaseline a few WPT tests.
     9
     10        * web-platform-tests/service-workers/service-worker/oninstall-script-error.https-expected.txt:
     11        * web-platform-tests/service-workers/service-worker/register-wait-forever-in-install-worker.https-expected.txt:
     12
    1132017-11-08  Ms2ger  <Ms2ger@igalia.com>
    214
  • trunk/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/oninstall-script-error.https-expected.txt

    r224218 r224584  
    33PASS install handler throws an error, error handler does not cancel
    44PASS install handler dispatches an event that throws an error
    5 FAIL install handler throws an error in the waitUntil assert_equals: The worker was installed expected false but got true
     5PASS install handler throws an error in the waitUntil
    66PASS install handler throws an error that is cancelled
    77PASS install handler throws an error and prevents default
  • trunk/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/register-wait-forever-in-install-worker.https-expected.txt

    r224132 r224584  
    11
    2 FAIL register worker that calls waitUntil with a promise that never resolves in oninstall promise_test: Unhandled rejection with value: object "TypeError: null is not an object (evaluating 'registration.installing.scriptURL')"
     2FAIL register worker that calls waitUntil with a promise that never resolves in oninstall assert_equals: expected "https://localhost:9443/service-workers/service-worker/resources/empty-worker.js" but got "https://localhost:9443/service-workers/service-worker/resources/wait-forever-in-install-worker.js"
    33
  • trunk/Source/WebCore/ChangeLog

    r224583 r224584  
     12017-11-08  Chris Dumez  <cdumez@apple.com>
     2
     3        [Service Workers] Support waitUntil() on the 'install' event
     4        https://bugs.webkit.org/show_bug.cgi?id=179396
     5
     6        Reviewed by Brady Eidson.
     7
     8        Support waitUntil() on the 'install' event:
     9        - https://w3c.github.io/ServiceWorker/#installation-algorithm (step 10.4)
     10        - https://w3c.github.io/ServiceWorker/#wait-until-method
     11
     12        Tests: http/tests/workers/service/basic-install-event-waitUntil-multiple-promises.html
     13               http/tests/workers/service/basic-install-event-waitUntil-reject.html
     14               http/tests/workers/service/basic-install-event-waitUntil-resolve.html
     15
     16        * testing/Internals.cpp:
     17        * testing/Internals.h:
     18        * testing/Internals.idl:
     19        * workers/service/ExtendableEvent.cpp:
     20        (WebCore::ExtendableEvent::waitUntil):
     21        (WebCore::ExtendableEvent::addExtendLifetimePromise):
     22        (WebCore::ExtendableEvent::whenAllExtendLifetimePromisesAreSettled):
     23        * workers/service/ExtendableEvent.h:
     24        (WebCore::ExtendableEvent::pendingPromiseCount const):
     25        * workers/service/FetchEvent.cpp:
     26        (WebCore::FetchEvent::respondWith):
     27        * workers/service/ServiceWorkerContainer.cpp:
     28        (WebCore::ServiceWorkerContainer::addRegistration):
     29        (WebCore::ServiceWorkerContainer::removeRegistration):
     30        * workers/service/ServiceWorkerContainer.h:
     31        * workers/service/context/ServiceWorkerThread.cpp:
     32        (WebCore::ServiceWorkerThread::fireInstallEvent):
     33        * workers/service/server/SWClientConnection.h:
     34        * workers/service/server/SWServerJobQueue.cpp:
     35        (WebCore::SWServerJobQueue::didFinishInstall):
     36        * workers/service/server/SWServerRegistration.cpp:
     37        (WebCore::SWServerRegistration::firePostInstallEvents):
     38
    1392017-11-08  Antti Koivisto  <antti@apple.com>
    240
  • trunk/Source/WebCore/testing/Internals.cpp

    r224582 r224584  
    42594259}
    42604260
    4261 void Internals::waitForExtendableEventToFinish(ExtendableEvent& event, DOMPromiseDeferred<void>&& promise)
    4262 {
    4263     event.onFinishedWaitingForTesting([promise = WTFMove(promise)] () mutable {
    4264         promise.resolve();
    4265     });
    4266 }
    4267 
    4268 Ref<ExtendableEvent> Internals::createTrustedExtendableEvent()
    4269 {
    4270     return ExtendableEvent::create("ExtendableEvent", { }, Event::IsTrusted::Yes);
    4271 }
    4272 
    42734261Ref<FetchEvent> Internals::createBeingDispatchedFetchEvent(ScriptExecutionContext& context)
    42744262{
  • trunk/Source/WebCore/testing/Internals.h

    r224582 r224584  
    618618#if ENABLE(SERVICE_WORKER)
    619619    void waitForFetchEventToFinish(FetchEvent&, DOMPromiseDeferred<IDLInterface<FetchResponse>>&&);
    620     void waitForExtendableEventToFinish(ExtendableEvent&, DOMPromiseDeferred<void>&&);
    621620    Ref<FetchEvent> createBeingDispatchedFetchEvent(ScriptExecutionContext&);
    622     Ref<ExtendableEvent> createTrustedExtendableEvent();
    623621    using HasRegistrationPromise = DOMPromiseDeferred<IDLBoolean>;
    624622    void hasServiceWorkerRegistration(const String& clientURL, HasRegistrationPromise&&);
  • trunk/Source/WebCore/testing/Internals.idl

    r224582 r224584  
    564564
    565565    [Conditional=SERVICE_WORKER] Promise<Response> waitForFetchEventToFinish(FetchEvent event);
    566     [Conditional=SERVICE_WORKER] Promise<void> waitForExtendableEventToFinish(ExtendableEvent event);
    567566    [Conditional=SERVICE_WORKER, CallWith=ScriptExecutionContext] FetchEvent createBeingDispatchedFetchEvent();
    568     [Conditional=SERVICE_WORKER] ExtendableEvent createTrustedExtendableEvent();
    569567    [Conditional=SERVICE_WORKER] Promise<boolean> hasServiceWorkerRegistration(DOMString scopeURL);
    570568
  • trunk/Source/WebCore/workers/service/ExtendableEvent.cpp

    r223922 r224584  
    4747}
    4848
     49// https://w3c.github.io/ServiceWorker/#dom-extendableevent-waituntil
    4950ExceptionOr<void> ExtendableEvent::waitUntil(Ref<DOMPromise>&& promise)
    5051{
     
    5253        return Exception { InvalidStateError, ASCIILiteral("Event is not trusted") };
    5354
    54     if (m_pendingPromises.isEmpty() && isBeingDispatched())
    55         return Exception { InvalidStateError, ASCIILiteral("Event is being dispatched") };
     55    // If the pending promises count is zero and the dispatch flag is unset, throw an "InvalidStateError" DOMException.
     56    if (!m_pendingPromiseCount && !isBeingDispatched())
     57        return Exception { InvalidStateError, ASCIILiteral("Event is no longer being dispatched and has no pending promises") };
    5658
    57     addPendingPromise(WTFMove(promise));
     59    addExtendLifetimePromise(WTFMove(promise));
    5860    return { };
    5961}
    6062
    61 void ExtendableEvent::onFinishedWaitingForTesting(WTF::Function<void()>&& callback)
     63void ExtendableEvent::addExtendLifetimePromise(Ref<DOMPromise>&& promise)
    6264{
    63     ASSERT(!m_onFinishedWaitingForTesting);
    64     m_onFinishedWaitingForTesting = WTFMove(callback);
     65    promise->whenSettled([this, protectedThis = makeRefPtr(this), settledPromise = promise.ptr()] () {
     66        --m_pendingPromiseCount;
     67
     68        // FIXME: Let registration be the context object's relevant global object's associated service worker's containing service worker registration.
     69        // FIXME: If registration's uninstalling flag is set, invoke Try Clear Registration with registration.
     70        // FIXME: If registration is not null, invoke Try Activate with registration.
     71
     72        if (m_pendingPromiseCount)
     73            return;
     74
     75        auto settledPromises = WTFMove(m_extendLifetimePromises);
     76        if (auto handler = WTFMove(m_whenAllExtendLifetimePromisesAreSettledHandler))
     77            handler(WTFMove(settledPromises));
     78    });
     79
     80    m_extendLifetimePromises.add(WTFMove(promise));
     81    ++m_pendingPromiseCount;
    6582}
    6683
    67 void ExtendableEvent::addPendingPromise(Ref<DOMPromise>&& promise)
     84void ExtendableEvent::whenAllExtendLifetimePromisesAreSettled(WTF::Function<void(HashSet<Ref<DOMPromise>>&&)>&& handler)
    6885{
    69     promise->whenSettled([this, weakThis = createWeakPtr(), settledPromise = promise.ptr()] () {
    70         if (!weakThis)
    71             return;
     86    ASSERT_WITH_MESSAGE(target(), "Event has not been dispatched yet");
     87    ASSERT(!m_whenAllExtendLifetimePromisesAreSettledHandler);
    7288
    73         auto promise = m_pendingPromises.take(*settledPromise);
     89    if (!m_pendingPromiseCount) {
     90        handler(WTFMove(m_extendLifetimePromises));
     91        return;
     92    }
    7493
    75         // FIXME: Implement registration handling as per https://w3c.github.io/ServiceWorker/v1/#dom-extendableevent-waituntil.
    76 
    77         if (!m_pendingPromises.isEmpty())
    78             return;
    79 
    80         if (auto callback = WTFMove(m_onFinishedWaitingForTesting))
    81             callback();
    82     });
    83     m_pendingPromises.add(WTFMove(promise));
     94    m_whenAllExtendLifetimePromisesAreSettledHandler = WTFMove(handler);
    8495}
    8596
  • trunk/Source/WebCore/workers/service/ExtendableEvent.h

    r223922 r224584  
    4848
    4949    ExceptionOr<void> waitUntil(Ref<DOMPromise>&&);
     50    unsigned pendingPromiseCount() const { return m_pendingPromiseCount; }
    5051
    51     WEBCORE_EXPORT void onFinishedWaitingForTesting(WTF::Function<void()>&&);
     52    WEBCORE_EXPORT void whenAllExtendLifetimePromisesAreSettled(WTF::Function<void(HashSet<Ref<DOMPromise>>&&)>&&);
    5253
    5354protected:
     
    5758    WeakPtr<ExtendableEvent> createWeakPtr() { return m_weakPtrFactory.createWeakPtr(*this); }
    5859
    59     void addPendingPromise(Ref<DOMPromise>&&);
     60    void addExtendLifetimePromise(Ref<DOMPromise>&&);
    6061
    6162private:
    62     HashSet<Ref<DOMPromise>> m_pendingPromises;
     63    unsigned m_pendingPromiseCount { 0 };
     64    HashSet<Ref<DOMPromise>> m_extendLifetimePromises;
    6365    WeakPtrFactory<ExtendableEvent> m_weakPtrFactory;
    64     WTF::Function<void()> m_onFinishedWaitingForTesting;
     66    WTF::Function<void(HashSet<Ref<DOMPromise>>&&)> m_whenAllExtendLifetimePromisesAreSettledHandler;
    6567};
    6668
  • trunk/Source/WebCore/workers/service/FetchEvent.cpp

    r223839 r224584  
    6565
    6666    m_respondPromise = WTFMove(promise);
    67     addPendingPromise(*m_respondPromise);
     67    addExtendLifetimePromise(*m_respondPromise);
    6868
    6969    m_respondPromise->whenSettled([this, weakThis = createWeakPtr()] () {
  • trunk/Source/WebCore/workers/service/ServiceWorkerContainer.cpp

    r224553 r224584  
    450450}
    451451
     452void ServiceWorkerContainer::addRegistration(ServiceWorkerRegistration& registration)
     453{
     454    m_swConnection->addServiceWorkerRegistrationInServer(registration.data().key, registration.identifier());
     455    m_registrations.add(registration.data().key, &registration);
     456}
     457
     458void ServiceWorkerContainer::removeRegistration(ServiceWorkerRegistration& registration)
     459{
     460    m_swConnection->removeServiceWorkerRegistrationInServer(registration.data().key, registration.identifier());
     461    m_registrations.remove(registration.data().key);
     462}
     463
    452464} // namespace WebCore
    453465
  • trunk/Source/WebCore/workers/service/ServiceWorkerContainer.h

    r224553 r224584  
    7373    void getRegistrations(RegistrationsPromise&&);
    7474
    75     void addRegistration(ServiceWorkerRegistration& registration) { m_registrations.add(registration.data().key, &registration); }
    76     void removeRegistration(ServiceWorkerRegistration& registration)  { m_registrations.remove(registration.data().key); }
     75    void addRegistration(ServiceWorkerRegistration&);
     76    void removeRegistration(ServiceWorkerRegistration&);
    7777
    7878    void startMessages();
  • trunk/Source/WebCore/workers/service/context/ServiceWorkerThread.cpp

    r224542 r224584  
    3333#include "EventNames.h"
    3434#include "ExtendableMessageEvent.h"
     35#include "JSDOMPromise.h"
    3536#include "SecurityOrigin.h"
    3637#include "ServiceWorkerFetch.h"
     
    123124        serviceWorkerGlobalScope.dispatchEvent(installEvent);
    124125
    125         // FIXME: We are supposed to wait for all installEvent's extend lifetime promises.
    126         callOnMainThread([serviceWorkerIdentifier] () mutable {
    127             if (auto* connection = SWContextManager::singleton().connection())
    128                 connection->didFinishInstall(serviceWorkerIdentifier, true);
     126        installEvent->whenAllExtendLifetimePromisesAreSettled([serviceWorkerIdentifier](HashSet<Ref<DOMPromise>>&& extendLifetimePromises) {
     127            bool hasRejectedAnyPromise = false;
     128            for (auto& promise : extendLifetimePromises) {
     129                if (promise->status() == DOMPromise::Status::Rejected) {
     130                    hasRejectedAnyPromise = true;
     131                    break;
     132                }
     133            }
     134            callOnMainThread([serviceWorkerIdentifier, hasRejectedAnyPromise] () mutable {
     135                if (auto* connection = SWContextManager::singleton().connection())
     136                    connection->didFinishInstall(serviceWorkerIdentifier, !hasRejectedAnyPromise);
     137            });
    129138        });
    130139    });
  • trunk/Source/WebCore/workers/service/server/SWClientConnection.h

    r224553 r224584  
    5353    virtual void matchRegistration(const SecurityOrigin& topOrigin, const URL& clientURL, RegistrationCallback&&) = 0;
    5454
     55    virtual void addServiceWorkerRegistrationInServer(const ServiceWorkerRegistrationKey&, uint64_t registrationIdentifier) = 0;
     56    virtual void removeServiceWorkerRegistrationInServer(const ServiceWorkerRegistrationKey&, uint64_t registrationIdentifier) = 0;
     57
    5558    void scheduleJob(ServiceWorkerJob&);
    5659    void finishedFetchingScript(ServiceWorkerJob&, const String&);
     
    7780    virtual void scheduleJobInServer(const ServiceWorkerJobData&) = 0;
    7881    virtual void finishFetchingScriptInServer(const ServiceWorkerFetchResult&) = 0;
    79     virtual void addServiceWorkerRegistrationInServer(const ServiceWorkerRegistrationKey&, uint64_t registrationIdentifier) = 0;
    80     virtual void removeServiceWorkerRegistrationInServer(const ServiceWorkerRegistrationKey&, uint64_t registrationIdentifier) = 0;
    8182    void forEachContainer(const WTF::Function<void(ServiceWorkerContainer&)>& apply);
    8283
  • trunk/Source/WebCore/workers/service/server/SWServerJobQueue.cpp

    r224553 r224584  
    132132
    133133// https://w3c.github.io/ServiceWorker/#install
    134 void SWServerJobQueue::didFinishInstall(SWServer::Connection&, ServiceWorkerIdentifier, bool wasSuccessful)
     134void SWServerJobQueue::didFinishInstall(SWServer::Connection&, ServiceWorkerIdentifier identifier, bool wasSuccessful)
    135135{
    136136    auto* registration = m_server.getRegistration(m_registrationKey);
     
    138138
    139139    if (!wasSuccessful) {
    140         // FIXME: Run the Update Worker State algorithm passing registration's installing worker and redundant as the arguments.
    141         // FIXME: Run the Update Registration State algorithm passing registration, "installing" and null as the arguments.
     140        auto* worker = m_server.workerByID(identifier);
     141        RELEASE_ASSERT(worker);
     142
     143        // Run the Update Worker State algorithm passing registration's installing worker and redundant as the arguments.
     144        registration->updateWorkerState(*worker, ServiceWorkerState::Redundant);
     145        // Run the Update Registration State algorithm passing registration, "installing" and null as the arguments.
     146        registration->updateRegistrationState(ServiceWorkerRegistrationState::Installing, nullptr);
    142147
    143148        // If newestWorker is null, invoke Clear Registration algorithm passing registration as its argument.
  • trunk/Source/WebCore/workers/service/server/SWServerRegistration.cpp

    r224553 r224584  
    123123
    124124    for (auto& connectionIdentifierWithClients : m_clientRegistrationsByConnection.keys()) {
     125        if (connectionIdentifierWithClients == connectionIdentifier)
     126            continue;
     127
    125128        if (auto* connection = m_server.getConnection(connectionIdentifierWithClients))
    126129            connection->firePostInstallEvents(m_registrationKey);
Note: See TracChangeset for help on using the changeset viewer.