Changeset 273224 in webkit


Ignore:
Timestamp:
Feb 21, 2021 1:54:24 PM (17 months ago)
Author:
ysuzuki@apple.com
Message:

Support modules in service workers
https://bugs.webkit.org/show_bug.cgi?id=222155

Reviewed by Saam Barati.

LayoutTests/imported/w3c:

  • web-platform-tests/html/semantics/scripting-1/the-script-element/json-module/json-module-service-worker-test.https.tentative-expected.txt:
  • web-platform-tests/service-workers/service-worker/clients-matchall-client-types.https-expected.txt:
  • web-platform-tests/service-workers/service-worker/import-module-scripts.https-expected.txt:
  • web-platform-tests/service-workers/service-worker/performance-timeline.https-expected.txt:
  • web-platform-tests/service-workers/service-worker/update-registration-with-type.https-expected.txt:
  • web-platform-tests/service-workers/service-worker/update.https-expected.txt:
  • web-platform-tests/service-workers/service-worker/worker-client-id.https-expected.txt:

Source/WebCore:

This patch adds module support to service-workers. Basically this just plumbs the type: "module" information to
service worker's job as described in the spec[1]: Each SW job should have workerType, and this is passed.
And we sometimes compare newestWorker->type() with this job.workerType (as defined in the spec). And we spawn
the SW with this job.workerType. Since Worker already supports "module" evaluation, this is automatically evaluated
as modules if we spawn SW thread with "module" type.

When using, we can pass "module" type to the register method as follows.

navigator.serviceWorker.register('script.mjs', {

type: "module"

});

[1]: https://w3c.github.io/ServiceWorker/

  • workers/service/ServiceWorker.h:
  • workers/service/ServiceWorkerContainer.cpp:

(WebCore::ServiceWorkerContainer::addRegistration):
(WebCore::ServiceWorkerContainer::updateRegistration):

  • workers/service/ServiceWorkerJobData.cpp:

(WebCore::ServiceWorkerJobData::isolatedCopy const):
(WebCore::ServiceWorkerJobData::isEquivalent const):

  • workers/service/ServiceWorkerJobData.h:

(WebCore::ServiceWorkerJobData::encode const):
(WebCore::ServiceWorkerJobData::decode):

  • workers/service/ServiceWorkerRegistration.cpp:

(WebCore::ServiceWorkerRegistration::update):

  • workers/service/context/ServiceWorkerThread.cpp:

(WebCore::ServiceWorkerThread::ServiceWorkerThread):

  • workers/service/server/SWServer.cpp:

(WebCore::SWServer::softUpdate):

  • workers/service/server/SWServerJobQueue.cpp:

(WebCore::SWServerJobQueue::scriptFetchFinished):
(WebCore::SWServerJobQueue::runRegisterJob):
(WebCore::SWServerJobQueue::runUpdateJob):

Location:
trunk
Files:
17 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/imported/w3c/ChangeLog

    r273206 r273224  
     12021-02-20  Yusuke Suzuki  <ysuzuki@apple.com>
     2
     3        Support modules in service workers
     4        https://bugs.webkit.org/show_bug.cgi?id=222155
     5
     6        Reviewed by Saam Barati.
     7
     8        * web-platform-tests/html/semantics/scripting-1/the-script-element/json-module/json-module-service-worker-test.https.tentative-expected.txt:
     9        * web-platform-tests/service-workers/service-worker/clients-matchall-client-types.https-expected.txt:
     10        * web-platform-tests/service-workers/service-worker/import-module-scripts.https-expected.txt:
     11        * web-platform-tests/service-workers/service-worker/performance-timeline.https-expected.txt:
     12        * web-platform-tests/service-workers/service-worker/update-registration-with-type.https-expected.txt:
     13        * web-platform-tests/service-workers/service-worker/update.https-expected.txt:
     14        * web-platform-tests/service-workers/service-worker/worker-client-id.https-expected.txt:
     15
    1162021-02-20  Rob Buis  <rbuis@igalia.com>
    217
  • trunk/LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-script-element/json-module/json-module-service-worker-test.https.tentative-expected.txt

    r267646 r273224  
    11
    2 FAIL Javascript importing JSON Module should load within the context of a service worker promise_test: Unhandled rejection with value: object "TypeError: SyntaxError: Unexpected string literal './module.json'. import call expects exactly one argument."
     2FAIL Javascript importing JSON Module should load within the context of a service worker promise_test: Unhandled rejection with value: object "TypeError: TypeError: 'application/json' is not a valid JavaScript MIME type."
    33FAIL JSON Modules should load within the context of a service worker promise_test: Unhandled rejection with value: object "SecurityError: MIME Type is not a JavaScript MIME type"
    44PASS JSON Module dynamic import should not load within the context of a service worker
  • trunk/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/clients-matchall-client-types.https-expected.txt

    r267647 r273224  
    1 
    21
    32PASS Verify matchAll() with window client type
  • trunk/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/import-module-scripts.https-expected.txt

    r273203 r273224  
    11
    2 FAIL Static import. promise_test: Unhandled rejection with value: object "TypeError: SyntaxError: Unexpected token '*'. import call expects exactly one argument."
    3 FAIL Nested static import. promise_test: Unhandled rejection with value: object "TypeError: SyntaxError: Unexpected token '*'. import call expects exactly one argument."
    4 FAIL Static import and then dynamic import. promise_test: Unhandled rejection with value: object "TypeError: SyntaxError: Unexpected token '*'. import call expects exactly one argument."
     2PASS Static import.
     3PASS Nested static import.
     4PASS Static import and then dynamic import.
    55PASS Dynamic import.
    66PASS Nested dynamic import.
  • trunk/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/performance-timeline.https-expected.txt

    r267647 r273224  
    22
    33PASS Test Performance Timeline API in Service Worker
    4 FAIL empty service worker fetch event included in performance timings assert_greater_than: Slow service worker request should measure increased delay. expected a number greater than 1012 but got 12
     4FAIL empty service worker fetch event included in performance timings assert_greater_than: Slow service worker request should measure increased delay. expected a number greater than 1136 but got 135
    55PASS User Timing
    6 FAIL Resource Timing assert_equals: expected 2 but got 1
     6PASS Resource Timing
    77
  • trunk/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/update-registration-with-type.https-expected.txt

    r267647 r273224  
    11
    2 FAIL Update the registration with a different script type (classic => module). promise_test: Unhandled rejection with value: object "TypeError: null is not an object (evaluating 'secondWorker.postMessage')"
    3 FAIL Update the registration with a different script type (module => classic). promise_test: Unhandled rejection with value: object "TypeError: SyntaxError: Unexpected token '*'. import call expects exactly one argument."
     2PASS Update the registration with a different script type (classic => module).
     3PASS Update the registration with a different script type (module => classic).
    44PASS Update the registration with a different script type (classic => module) and with a same main script.
    55PASS Update the registration with a different script type (module => classic) and with a same main script.
    66PASS Does not update the registration with the same script type and the same main script.
    7 FAIL Update the registration with a different script type (classic => module) and with a same main script. Expect evaluation failed. assert_unreached: Should have rejected: Registering with invalid evaluation should be failed. Reached unreachable code
    8 FAIL Update the registration with a different script type (module => classic) and with a same main script. Expect evaluation failed. promise_test: Unhandled rejection with value: object "TypeError: SyntaxError: Unexpected token '*'. import call expects exactly one argument."
     7PASS Update the registration with a different script type (classic => module) and with a same main script. Expect evaluation failed.
     8PASS Update the registration with a different script type (module => classic) and with a same main script. Expect evaluation failed.
    99
  • trunk/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/update.https-expected.txt

    r267647 r273224  
    22PASS update() should succeed when new script is available.
    33PASS update() should fail when mime type is invalid.
    4 FAIL update() should fail when a response for the main script is redirect. assert_throws: function "function () { throw e }" threw object "SecurityError: Script https://localhost:9443/service-workers/service-worker/resources/update-worker.py?Key=53187c6b-e588-48ee-ad9b-272fe38aa9b8&Mode=redirect load failed" ("SecurityError") expected object "TypeError" ("TypeError")
     4FAIL update() should fail when a response for the main script is redirect. promise_rejects_js: function "function () { throw e }" threw object "SecurityError: Script https://localhost:9443/service-workers/service-worker/resources/update-worker.py?Key=48e2907e-b632-491a-b285-2fd2b666386a&Mode=redirect load failed" ("SecurityError") expected instance of function "function TypeError() {
     5    [native code]
     6}" ("TypeError")
    57PASS update() should fail when a new script contains a syntax error.
    68PASS update() should resolve when the install event throws.
  • trunk/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/worker-client-id.https-expected.txt

    r253704 r273224  
    11
    2 FAIL Verify workers have a unique client id separate from their owning documents window assert_not_equals: frame and worker client ids should be different got disallowed value "102-1083"
     2FAIL Verify workers have a unique client id separate from their owning documents window assert_not_equals: frame and worker client ids should be different got disallowed value "12-358"
    33
  • trunk/Source/WebCore/ChangeLog

    r273223 r273224  
     12021-02-20  Yusuke Suzuki  <ysuzuki@apple.com>
     2
     3        Support modules in service workers
     4        https://bugs.webkit.org/show_bug.cgi?id=222155
     5
     6        Reviewed by Saam Barati.
     7
     8        This patch adds module support to service-workers. Basically this just plumbs the type: "module" information to
     9        service worker's job as described in the spec[1]: Each SW job should have workerType, and this is passed.
     10        And we sometimes compare newestWorker->type() with this job.workerType (as defined in the spec). And we spawn
     11        the SW with this job.workerType. Since Worker already supports "module" evaluation, this is automatically evaluated
     12        as modules if we spawn SW thread with "module" type.
     13
     14        When using, we can pass "module" type to the register method as follows.
     15
     16            navigator.serviceWorker.register('script.mjs', {
     17                type: "module"
     18            });
     19
     20        [1]: https://w3c.github.io/ServiceWorker/
     21
     22        * workers/service/ServiceWorker.h:
     23        * workers/service/ServiceWorkerContainer.cpp:
     24        (WebCore::ServiceWorkerContainer::addRegistration):
     25        (WebCore::ServiceWorkerContainer::updateRegistration):
     26        * workers/service/ServiceWorkerJobData.cpp:
     27        (WebCore::ServiceWorkerJobData::isolatedCopy const):
     28        (WebCore::ServiceWorkerJobData::isEquivalent const):
     29        * workers/service/ServiceWorkerJobData.h:
     30        (WebCore::ServiceWorkerJobData::encode const):
     31        (WebCore::ServiceWorkerJobData::decode):
     32        * workers/service/ServiceWorkerRegistration.cpp:
     33        (WebCore::ServiceWorkerRegistration::update):
     34        * workers/service/context/ServiceWorkerThread.cpp:
     35        (WebCore::ServiceWorkerThread::ServiceWorkerThread):
     36        * workers/service/server/SWServer.cpp:
     37        (WebCore::SWServer::softUpdate):
     38        * workers/service/server/SWServerJobQueue.cpp:
     39        (WebCore::SWServerJobQueue::scriptFetchFinished):
     40        (WebCore::SWServerJobQueue::runRegisterJob):
     41        (WebCore::SWServerJobQueue::runUpdateJob):
     42
    1432021-02-21  Zalan Bujtas  <zalan@apple.com>
    244
  • trunk/Source/WebCore/workers/service/ServiceWorker.h

    r253812 r273224  
    6565    ServiceWorkerIdentifier identifier() const { return m_data.identifier; }
    6666    ServiceWorkerRegistrationIdentifier registrationIdentifier() const { return m_data.registrationIdentifier; }
     67    WorkerType workerType() const { return m_data.type; }
    6768
    6869    using RefCounted::ref;
  • trunk/Source/WebCore/workers/service/ServiceWorkerContainer.cpp

    r273183 r273224  
    185185    jobData.clientCreationURL = context->url();
    186186    jobData.topOrigin = context->topOrigin().data();
     187    jobData.workerType = options.type;
    187188    jobData.type = ServiceWorkerJobType::Register;
    188189    jobData.registrationOptions = options;
     
    206207}
    207208
    208 void ServiceWorkerContainer::updateRegistration(const URL& scopeURL, const URL& scriptURL, WorkerType, RefPtr<DeferredPromise>&& promise)
     209void ServiceWorkerContainer::updateRegistration(const URL& scopeURL, const URL& scriptURL, WorkerType workerType, RefPtr<DeferredPromise>&& promise)
    209210{
    210211    ASSERT(!m_isStopped);
     
    222223    jobData.clientCreationURL = context.url();
    223224    jobData.topOrigin = context.topOrigin().data();
     225    jobData.workerType = workerType;
    224226    jobData.type = ServiceWorkerJobType::Update;
    225227    jobData.scopeURL = scopeURL;
  • trunk/Source/WebCore/workers/service/ServiceWorkerJobData.cpp

    r256664 r273224  
    6464    result.m_identifier = identifier();
    6565    result.sourceContext = sourceContext;
     66    result.workerType = workerType;
    6667    result.type = type;
    6768
     
    8687        return scopeURL == job.scopeURL
    8788            && scriptURL == job.scriptURL
    88             && registrationOptions.type == job.registrationOptions.type
     89            && workerType == job.workerType
    8990            && registrationOptions.updateViaCache == job.registrationOptions.updateViaCache;
    9091    case ServiceWorkerJobType::Unregister:
  • trunk/Source/WebCore/workers/service/ServiceWorkerJobData.h

    r262994 r273224  
    5353    URL scopeURL;
    5454    ServiceWorkerOrClientIdentifier sourceContext;
     55    WorkerType workerType;
    5556    ServiceWorkerJobType type;
    5657
     
    7374void ServiceWorkerJobData::encode(Encoder& encoder) const
    7475{
    75     encoder << identifier() << scriptURL << clientCreationURL << topOrigin << scopeURL << sourceContext;
     76    encoder << identifier() << scriptURL << clientCreationURL << topOrigin << scopeURL << sourceContext << workerType;
    7677    encoder << type;
    7778    switch (type) {
     
    111112    if (!decoder.decode(jobData.sourceContext))
    112113        return WTF::nullopt;
     114    if (!decoder.decode(jobData.workerType))
     115        return WTF::nullopt;
    113116    if (!decoder.decode(jobData.type))
    114117        return WTF::nullopt;
  • trunk/Source/WebCore/workers/service/ServiceWorkerRegistration.cpp

    r273183 r273224  
    149149    }
    150150
    151     // FIXME: Support worker types.
    152     m_container->updateRegistration(m_registrationData.scopeURL, newestWorker->scriptURL(), WorkerType::Classic, WTFMove(promise));
     151    m_container->updateRegistration(m_registrationData.scopeURL, newestWorker->scriptURL(), newestWorker->workerType(), WTFMove(promise));
    153152}
    154153
  • trunk/Source/WebCore/workers/service/context/ServiceWorkerThread.cpp

    r273203 r273224  
    7474// FIXME: Use valid runtime flags
    7575
    76 // FIXME: Support modules in service-workers.
    77 // https://bugs.webkit.org/show_bug.cgi?id=222155
    7876ServiceWorkerThread::ServiceWorkerThread(const ServiceWorkerContextData& data, String&& userAgent, const Settings::Values& settingsValues, WorkerLoaderProxy& loaderProxy, WorkerDebuggerProxy& debuggerProxy, IDBClient::IDBConnectionProxy* idbConnectionProxy, SocketProvider* socketProvider)
    79     : WorkerThread({ data.scriptURL, emptyString(), "serviceworker:" + Inspector::IdentifiersFactory::createIdentifier(), WTFMove(userAgent), platformStrategies()->loaderStrategy()->isOnLine(), data.contentSecurityPolicy, false, MonotonicTime::now(), { }, WorkerType::Classic, FetchRequestCredentials::SameOrigin, settingsValues }, data.script, loaderProxy, debuggerProxy, DummyServiceWorkerThreadProxy::shared(), WorkerThreadStartMode::Normal, data.registration.key.topOrigin().securityOrigin().get(), idbConnectionProxy, socketProvider, JSC::RuntimeFlags::createAllEnabled())
     77    : WorkerThread({ data.scriptURL, emptyString(), "serviceworker:" + Inspector::IdentifiersFactory::createIdentifier(), WTFMove(userAgent), platformStrategies()->loaderStrategy()->isOnLine(), data.contentSecurityPolicy, false, MonotonicTime::now(), { }, data.workerType, FetchRequestCredentials::Omit, settingsValues }, data.script, loaderProxy, debuggerProxy, DummyServiceWorkerThreadProxy::shared(), WorkerThreadStartMode::Normal, data.registration.key.topOrigin().securityOrigin().get(), idbConnectionProxy, socketProvider, JSC::RuntimeFlags::createAllEnabled())
    8078    , m_data(data.isolatedCopy())
    8179    , m_workerObjectProxy(DummyServiceWorkerThreadProxy::shared())
  • trunk/Source/WebCore/workers/service/server/SWServer.cpp

    r266157 r273224  
    10961096void SWServer::softUpdate(SWServerRegistration& registration)
    10971097{
     1098    // Let newestWorker be the result of running Get Newest Worker algorithm passing registration as its argument.
     1099    // If newestWorker is null, abort these steps.
     1100    auto* newestWorker = registration.getNewestWorker();
     1101    if (!newestWorker)
     1102        return;
     1103
    10981104    ServiceWorkerJobData jobData(Process::identifier(), ServiceWorkerIdentifier::generate());
    10991105    jobData.scriptURL = registration.scriptURL();
    11001106    jobData.topOrigin = registration.key().topOrigin();
    11011107    jobData.scopeURL = registration.scopeURLWithoutFragment();
     1108    jobData.workerType = newestWorker->type();
    11021109    jobData.type = ServiceWorkerJobType::Update;
    11031110    scheduleJob(WTFMove(jobData));
  • trunk/Source/WebCore/workers/service/server/SWServerJobQueue.cpp

    r273183 r273224  
    101101    // flag set, and script's source text is a byte-for-byte match with newestWorker's script resource's source
    102102    // text, then:
    103     if (newestWorker && equalIgnoringFragmentIdentifier(newestWorker->scriptURL(), job.scriptURL) && result.script == newestWorker->script() && doCertificatesMatch(result.certificateInfo, newestWorker->certificateInfo())) {
     103    if (newestWorker && equalIgnoringFragmentIdentifier(newestWorker->scriptURL(), job.scriptURL) && newestWorker->type() == job.workerType && result.script == newestWorker->script() && doCertificatesMatch(result.certificateInfo, newestWorker->certificateInfo())) {
    104104        RELEASE_LOG(ServiceWorker, "%p - SWServerJobQueue::scriptFetchFinished, script and certificate are matching for registrationID=%llu", this, registration->identifier().toUInt64());
    105105        // FIXME: for non classic scripts, check the script’s module record's [[ECMAScriptCode]].
     
    115115    // FIXME: Update all the imported scripts as per spec. For now, we just do as if there is none.
    116116
    117     // FIXME: Support the proper worker type (classic vs module)
    118     m_server.updateWorker(job.identifier(), *registration, job.scriptURL, result.script, result.certificateInfo, result.contentSecurityPolicy, result.referrerPolicy, WorkerType::Classic, { });
     117    m_server.updateWorker(job.identifier(), *registration, job.scriptURL, result.script, result.certificateInfo, result.contentSecurityPolicy, result.referrerPolicy, job.workerType, { });
    119118}
    120119
     
    288287    if (auto* registration = m_server.getRegistration(m_registrationKey)) {
    289288        auto* newestWorker = registration->getNewestWorker();
    290         if (newestWorker && equalIgnoringFragmentIdentifier(job.scriptURL, newestWorker->scriptURL()) && job.registrationOptions.updateViaCache == registration->updateViaCache()) {
     289        if (newestWorker && equalIgnoringFragmentIdentifier(job.scriptURL, newestWorker->scriptURL()) && job.workerType == newestWorker->type() && job.registrationOptions.updateViaCache == registration->updateViaCache()) {
    291290            RELEASE_LOG(ServiceWorker, "%p - SWServerJobQueue::runRegisterJob: Found directly reusable registration %llu for job %s (DONE)", this, registration->identifier().toUInt64(), job.identifier().loggingString().utf8().data());
    292291            m_server.resolveRegistrationJob(job, registration->data(), ShouldNotifyWhenResolved::No);
     
    350349    auto* newestWorker = registration->getNewestWorker();
    351350
    352     // If job's type is update, and newestWorker's script url does not equal job's script url with the exclude fragments flag set, then:
     351    // If job’s type is update, and newestWorker is not null and its script url does not equal job’s script url, then:
    353352    if (job.type == ServiceWorkerJobType::Update && newestWorker && !equalIgnoringFragmentIdentifier(job.scriptURL, newestWorker->scriptURL()))
    354353        return rejectCurrentJob(ExceptionData { TypeError, "Cannot update a service worker with a requested script URL whose newest worker has a different script URL"_s });
Note: See TracChangeset for help on using the changeset viewer.