Title: [292799] trunk
Revision
292799
Author
[email protected]
Date
2022-04-12 21:27:16 -0700 (Tue, 12 Apr 2022)

Log Message

Allow Wasm import from a JS Worker module
https://bugs.webkit.org/show_bug.cgi?id=238291

Patch by Asumu Takikawa <[email protected]> on 2022-04-12
Reviewed by Yusuke Suzuki.

LayoutTests/imported/w3c:

Fixed worker test and updated expectation.

* web-platform-tests/wasm/webapi/esm-integration/resources/worker-helper.js:
(export.pm):
* web-platform-tests/wasm/webapi/esm-integration/worker-import.tentative-expected.txt:
* web-platform-tests/wasm/webapi/esm-integration/worker-import.tentative.html:

Source/WebCore:

Adds new source provider for Wasm module loading when imported via
a JS module running in a Worker. Also adjust how WorkerRunLoop
processes tasks for script module loading. In particular, during
the module parsing phase, Wasm modules schedule async tasks that
need to be run to produce a module record.

When a Wasm module is loaded (via the module loader's module parsing
step), the validation/compilation happens asynchronously and
completion callbacks are run via
DeferredWorkTimer::scheduleWorkSoon, which queues up microtasks
from the VM. These microtasks, however, don't get run in a Worker
run loop during module loading and therefore the Wasm module never
finishes loading.

This is because during non-default modes, the Worker run loop
does not install its set timer callback, and continues to wait for
a task to run (due to infinite timeout). This means the microtask
checkpoint is also not reached, so other microtasks cannot run.
In non-default modes, the run loop also ignores all tasks that were
not installed in that particular mode.

In addition, the Worker event loop cannot run either, as it posts
default mode tasks to the run loop to trigger its operation.

The current patch modifies the run loop to allow the run loop to time
out even in non-default modes if a `useTimeout` parameter is passed as
true (defaults to false). We set this to true for the Worker module
loading process. It also allows the timer notification callback to
post tasks to non-default run loops.

* WebCore.xcodeproj/project.pbxproj:
* bindings/js/ScriptBufferSourceProvider.h:
(WebCore::AbstractScriptBufferHolder::~AbstractScriptBufferHolder):
* bindings/js/ScriptModuleLoader.cpp:
(WebCore::ScriptModuleLoader::notifyFinished):
* bindings/js/WebAssemblyScriptBufferSourceProvider.h: Added.
* bindings/js/WebAssemblyScriptSourceCode.h:
(WebCore::WebAssemblyScriptSourceCode::WebAssemblyScriptSourceCode):
* workers/ScriptBuffer.cpp:
(WebCore::ScriptBuffer::append):
* workers/ScriptBuffer.h:
* workers/WorkerEventLoop.cpp:
(WebCore::WorkerEventLoop::scheduleToRun):
(WebCore::WorkerEventLoop::taskMode):
* workers/WorkerEventLoop.h:
* workers/WorkerOrWorkletGlobalScope.cpp:
(WebCore::WorkerOrWorkletGlobalScope::postTaskForMode):
* workers/WorkerOrWorkletGlobalScope.h:
* workers/WorkerOrWorkletScriptController.cpp:
(WebCore::WorkerOrWorkletScriptController::loadModuleSynchronously):
* workers/WorkerRunLoop.cpp:
(WebCore::ModePredicate::ModePredicate):
(WebCore::ModePredicate::mode const):
(WebCore::ModePredicate::operator() const):
(WebCore::WorkerDedicatedRunLoop::run):
(WebCore::WorkerDedicatedRunLoop::runInDebuggerMode):
(WebCore::WorkerDedicatedRunLoop::runInMode):
(WebCore::WorkerMainRunLoop::runInMode):
* workers/WorkerRunLoop.h:
* workers/WorkerScriptLoader.cpp:
(WebCore::WorkerScriptLoader::didReceiveData):

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/imported/w3c/ChangeLog (292798 => 292799)


--- trunk/LayoutTests/imported/w3c/ChangeLog	2022-04-13 04:25:34 UTC (rev 292798)
+++ trunk/LayoutTests/imported/w3c/ChangeLog	2022-04-13 04:27:16 UTC (rev 292799)
@@ -1,3 +1,17 @@
+2022-04-12  Asumu Takikawa  <[email protected]>
+
+        Allow Wasm import from a JS Worker module
+        https://bugs.webkit.org/show_bug.cgi?id=238291
+
+        Reviewed by Yusuke Suzuki.
+
+        Fixed worker test and updated expectation.
+
+        * web-platform-tests/wasm/webapi/esm-integration/resources/worker-helper.js:
+        (export.pm):
+        * web-platform-tests/wasm/webapi/esm-integration/worker-import.tentative-expected.txt:
+        * web-platform-tests/wasm/webapi/esm-integration/worker-import.tentative.html:
+
 2022-04-11  Antti Koivisto  <[email protected]>
 
         [CSS Container Queries] Update container shorthand order

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/wasm/webapi/esm-integration/resources/worker-helper.js (292798 => 292799)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/wasm/webapi/esm-integration/resources/worker-helper.js	2022-04-13 04:25:34 UTC (rev 292798)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/wasm/webapi/esm-integration/resources/worker-helper.js	2022-04-13 04:27:16 UTC (rev 292799)
@@ -1 +1 @@
-export const pm = DedicatedWorkerGlobalScope.postMessage;
+export function pm(x) { postMessage(x); }

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/wasm/webapi/esm-integration/worker-import.tentative-expected.txt (292798 => 292799)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/wasm/webapi/esm-integration/worker-import.tentative-expected.txt	2022-04-13 04:25:34 UTC (rev 292798)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/wasm/webapi/esm-integration/worker-import.tentative-expected.txt	2022-04-13 04:27:16 UTC (rev 292799)
@@ -1,4 +1,3 @@
-CONSOLE MESSAGE: TypeError: WebAssembly modules are not supported in workers yet.
 
-FAIL Testing import of WebAssembly from _javascript_ worker Script error.
+PASS Testing import of WebAssembly from _javascript_ worker
 

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/wasm/webapi/esm-integration/worker-import.tentative.html (292798 => 292799)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/wasm/webapi/esm-integration/worker-import.tentative.html	2022-04-13 04:25:34 UTC (rev 292798)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/wasm/webapi/esm-integration/worker-import.tentative.html	2022-04-13 04:27:16 UTC (rev 292799)
@@ -7,7 +7,7 @@
 setup({ single_test: true });
 const worker = new Worker("resources/worker.js", { type: "module" });
 worker._onmessage_ = (msg) => {
-  assert_equals(msg, 42);
+  assert_equals(msg.data, 42);
   done();
 }
 </script>

Modified: trunk/Source/WebCore/ChangeLog (292798 => 292799)


--- trunk/Source/WebCore/ChangeLog	2022-04-13 04:25:34 UTC (rev 292798)
+++ trunk/Source/WebCore/ChangeLog	2022-04-13 04:27:16 UTC (rev 292799)
@@ -1,3 +1,72 @@
+2022-04-12  Asumu Takikawa  <[email protected]>
+
+        Allow Wasm import from a JS Worker module
+        https://bugs.webkit.org/show_bug.cgi?id=238291
+
+        Reviewed by Yusuke Suzuki.
+
+        Adds new source provider for Wasm module loading when imported via
+        a JS module running in a Worker. Also adjust how WorkerRunLoop
+        processes tasks for script module loading. In particular, during
+        the module parsing phase, Wasm modules schedule async tasks that
+        need to be run to produce a module record.
+
+        When a Wasm module is loaded (via the module loader's module parsing
+        step), the validation/compilation happens asynchronously and
+        completion callbacks are run via
+        DeferredWorkTimer::scheduleWorkSoon, which queues up microtasks
+        from the VM. These microtasks, however, don't get run in a Worker
+        run loop during module loading and therefore the Wasm module never
+        finishes loading.
+
+        This is because during non-default modes, the Worker run loop
+        does not install its set timer callback, and continues to wait for
+        a task to run (due to infinite timeout). This means the microtask
+        checkpoint is also not reached, so other microtasks cannot run.
+        In non-default modes, the run loop also ignores all tasks that were
+        not installed in that particular mode.
+
+        In addition, the Worker event loop cannot run either, as it posts
+        default mode tasks to the run loop to trigger its operation.
+
+        The current patch modifies the run loop to allow the run loop to time
+        out even in non-default modes if a `useTimeout` parameter is passed as
+        true (defaults to false). We set this to true for the Worker module
+        loading process. It also allows the timer notification callback to
+        post tasks to non-default run loops.
+
+        * WebCore.xcodeproj/project.pbxproj:
+        * bindings/js/ScriptBufferSourceProvider.h:
+        (WebCore::AbstractScriptBufferHolder::~AbstractScriptBufferHolder):
+        * bindings/js/ScriptModuleLoader.cpp:
+        (WebCore::ScriptModuleLoader::notifyFinished):
+        * bindings/js/WebAssemblyScriptBufferSourceProvider.h: Added.
+        * bindings/js/WebAssemblyScriptSourceCode.h:
+        (WebCore::WebAssemblyScriptSourceCode::WebAssemblyScriptSourceCode):
+        * workers/ScriptBuffer.cpp:
+        (WebCore::ScriptBuffer::append):
+        * workers/ScriptBuffer.h:
+        * workers/WorkerEventLoop.cpp:
+        (WebCore::WorkerEventLoop::scheduleToRun):
+        (WebCore::WorkerEventLoop::taskMode):
+        * workers/WorkerEventLoop.h:
+        * workers/WorkerOrWorkletGlobalScope.cpp:
+        (WebCore::WorkerOrWorkletGlobalScope::postTaskForMode):
+        * workers/WorkerOrWorkletGlobalScope.h:
+        * workers/WorkerOrWorkletScriptController.cpp:
+        (WebCore::WorkerOrWorkletScriptController::loadModuleSynchronously):
+        * workers/WorkerRunLoop.cpp:
+        (WebCore::ModePredicate::ModePredicate):
+        (WebCore::ModePredicate::mode const):
+        (WebCore::ModePredicate::operator() const):
+        (WebCore::WorkerDedicatedRunLoop::run):
+        (WebCore::WorkerDedicatedRunLoop::runInDebuggerMode):
+        (WebCore::WorkerDedicatedRunLoop::runInMode):
+        (WebCore::WorkerMainRunLoop::runInMode):
+        * workers/WorkerRunLoop.h:
+        * workers/WorkerScriptLoader.cpp:
+        (WebCore::WorkerScriptLoader::didReceiveData):
+
 2022-04-12  Elliott Williams  <[email protected]>
 
         [Xcode] In open-source builds, disable bitcode in xcconfigs instead of build-webkit

Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (292798 => 292799)


--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2022-04-13 04:25:34 UTC (rev 292798)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2022-04-13 04:27:16 UTC (rev 292799)
@@ -10260,6 +10260,7 @@
 		550A0BC8085F6039007353D6 /* QualifiedName.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = QualifiedName.h; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
 		550F664522CA89BD000A3417 /* SVGSharedPrimitiveProperty.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SVGSharedPrimitiveProperty.h; sourceTree = "<group>"; };
 		55137B2C20379E550001004B /* SVGMarkerTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SVGMarkerTypes.h; sourceTree = "<group>"; };
+		5523B98B27ED194800ECA746 /* WebAssemblyScriptBufferSourceProvider.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = WebAssemblyScriptBufferSourceProvider.h; path = bindings/js/WebAssemblyScriptBufferSourceProvider.h; sourceTree = "<group>"; };
 		554675771FD1FC1A003B10B0 /* ImageSource.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ImageSource.cpp; sourceTree = "<group>"; };
 		554675781FD1FC1A003B10B0 /* ImageSource.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ImageSource.h; sourceTree = "<group>"; };
 		5550CB411E955E3C00111AA0 /* ImageTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageTypes.h; sourceTree = "<group>"; };
@@ -19027,6 +19028,7 @@
 		0867D691FE84028FC02AAC07 /* WebCore */ = {
 			isa = PBXGroup;
 			children = (
+				5523B98B27ED194800ECA746 /* WebAssemblyScriptBufferSourceProvider.h */,
 				DDB04F37278E5527008D3678 /* libWTF.a */,
 				1C09D04B1E31C32800725F18 /* PAL.xcodeproj */,
 				65C97AF208EA908800ACD273 /* config.h */,

Modified: trunk/Source/WebCore/bindings/js/ScriptBufferSourceProvider.h (292798 => 292799)


--- trunk/Source/WebCore/bindings/js/ScriptBufferSourceProvider.h	2022-04-13 04:25:34 UTC (rev 292798)
+++ trunk/Source/WebCore/bindings/js/ScriptBufferSourceProvider.h	2022-04-13 04:27:16 UTC (rev 292799)
@@ -31,7 +31,15 @@
 
 namespace WebCore {
 
-class ScriptBufferSourceProvider final : public JSC::SourceProvider, public CanMakeWeakPtr<ScriptBufferSourceProvider> {
+class AbstractScriptBufferHolder : public CanMakeWeakPtr<AbstractScriptBufferHolder> {
+public:
+    virtual void clearDecodedData() = 0;
+    virtual void tryReplaceScriptBuffer(const ScriptBuffer&) = 0;
+
+    virtual ~AbstractScriptBufferHolder() { }
+};
+
+class ScriptBufferSourceProvider final : public JSC::SourceProvider, public AbstractScriptBufferHolder {
     WTF_MAKE_FAST_ALLOCATED;
 public:
     static Ref<ScriptBufferSourceProvider> create(const ScriptBuffer& scriptBuffer, const JSC::SourceOrigin& sourceOrigin, String sourceURL, const TextPosition& startPosition = TextPosition(), JSC::SourceProviderSourceType sourceType = JSC::SourceProviderSourceType::Program)
@@ -70,12 +78,12 @@
         return m_cachedScriptString;
     }
 
-    void clearDecodedData()
+    void clearDecodedData() final
     {
         m_cachedScriptString = String();
     }
 
-    void tryReplaceScriptBuffer(const ScriptBuffer& scriptBuffer)
+    void tryReplaceScriptBuffer(const ScriptBuffer& scriptBuffer) final
     {
         // If this new file-mapped script buffer is identical to the one we have, then replace
         // ours to save dirty memory.

Modified: trunk/Source/WebCore/bindings/js/ScriptModuleLoader.cpp (292798 => 292799)


--- trunk/Source/WebCore/bindings/js/ScriptModuleLoader.cpp	2022-04-13 04:25:34 UTC (rev 292798)
+++ trunk/Source/WebCore/bindings/js/ScriptModuleLoader.cpp	2022-04-13 04:27:16 UTC (rev 292799)
@@ -482,12 +482,8 @@
         if (MIMETypeRegistry::isSupportedJavaScriptMIMEType(loader.responseMIMEType()))
             type = ModuleType::_javascript_;
 #if ENABLE(WEBASSEMBLY)
-        else if (context().settingsValues().webAssemblyESMIntegrationEnabled && MIMETypeRegistry::isSupportedWebAssemblyMIMEType(loader.responseMIMEType())) {
+        else if (context().settingsValues().webAssemblyESMIntegrationEnabled && MIMETypeRegistry::isSupportedWebAssemblyMIMEType(loader.responseMIMEType()))
             type = ModuleType::WebAssembly;
-            // FIXME: add worker support for Wasm/ESM integration.
-            rejectWithFetchError(promise.get(), TypeError, makeString("WebAssembly modules are not supported in workers yet."));
-            return;
-        }
 #endif
         else {
             // https://html.spec.whatwg.org/multipage/webappapis.html#fetch-a-single-module-script
@@ -518,7 +514,12 @@
                 return JSC::JSSourceCode::create(jsGlobalObject.vm(),
                     JSC::SourceCode { ScriptSourceCode { loader.script(), WTFMove(responseURL), { }, JSC::SourceProviderSourceType::Module, loader.scriptFetcher() }.jsSourceCode() });
                 break;
+#if ENABLE(WEBASSEMBLY)
             case ModuleType::WebAssembly:
+                return JSC::JSSourceCode::create(jsGlobalObject.vm(),
+                    JSC::SourceCode { WebAssemblyScriptSourceCode { loader.script(), WTFMove(responseURL), loader.scriptFetcher() }.jsSourceCode() });
+                break;
+#endif
             default:
                 RELEASE_ASSERT_NOT_REACHED();
             }

Added: trunk/Source/WebCore/bindings/js/WebAssemblyScriptBufferSourceProvider.h (0 => 292799)


--- trunk/Source/WebCore/bindings/js/WebAssemblyScriptBufferSourceProvider.h	                        (rev 0)
+++ trunk/Source/WebCore/bindings/js/WebAssemblyScriptBufferSourceProvider.h	2022-04-13 04:27:16 UTC (rev 292799)
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2022 Igalia S.L. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if ENABLE(WEBASSEMBLY)
+
+#include "ScriptBufferSourceProvider.h"
+#include <_javascript_Core/SourceProvider.h>
+
+namespace WebCore {
+
+class WebAssemblyScriptBufferSourceProvider final : public JSC::BaseWebAssemblySourceProvider, public AbstractScriptBufferHolder {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    static Ref<WebAssemblyScriptBufferSourceProvider> create(const ScriptBuffer& scriptBuffer, URL&& sourceURL, Ref<JSC::ScriptFetcher>&& scriptFetcher)
+    {
+        return adoptRef(*new WebAssemblyScriptBufferSourceProvider(scriptBuffer, JSC::SourceOrigin { WTFMove(sourceURL), WTFMove(scriptFetcher) }, sourceURL.string()));
+    }
+
+    unsigned hash() const final
+    {
+        return m_source.impl()->hash();
+    }
+
+    StringView source() const final
+    {
+        return m_source;
+    }
+
+    size_t size() const final { return m_buffer ? m_buffer->size() : 0; }
+
+    const uint8_t* data() final
+    {
+        if (!m_buffer)
+            return nullptr;
+
+        ASSERT(m_buffer->isContiguous());
+        return downcast<SharedBuffer>(*m_buffer).data();
+    }
+
+    void lockUnderlyingBuffer() final
+    {
+        ASSERT(!m_buffer);
+        m_buffer = m_scriptBuffer.buffer();
+
+        if (!m_buffer)
+            return;
+
+        if (!m_buffer->isContiguous())
+            m_buffer = m_buffer->makeContiguous();
+    }
+
+    void unlockUnderlyingBuffer() final
+    {
+        ASSERT(m_buffer);
+        m_buffer = nullptr;
+    }
+
+    void clearDecodedData() final { }
+
+    void tryReplaceScriptBuffer(const ScriptBuffer& scriptBuffer) final
+    {
+        if (m_scriptBuffer != scriptBuffer)
+            return;
+
+        m_scriptBuffer = scriptBuffer;
+    }
+
+private:
+    WebAssemblyScriptBufferSourceProvider(const ScriptBuffer& scriptBuffer, const JSC::SourceOrigin& sourceOrigin, String sourceURL)
+        : BaseWebAssemblySourceProvider(sourceOrigin, WTFMove(sourceURL))
+        , m_scriptBuffer(scriptBuffer)
+        , m_buffer(nullptr)
+        , m_source("[WebAssembly source]"_s)
+    {
+    }
+
+    ScriptBuffer m_scriptBuffer;
+    RefPtr<const FragmentedSharedBuffer> m_buffer;
+    String m_source;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(WEBASSEMBLY)

Modified: trunk/Source/WebCore/bindings/js/WebAssemblyScriptSourceCode.h (292798 => 292799)


--- trunk/Source/WebCore/bindings/js/WebAssemblyScriptSourceCode.h	2022-04-13 04:25:34 UTC (rev 292798)
+++ trunk/Source/WebCore/bindings/js/WebAssemblyScriptSourceCode.h	2022-04-13 04:27:16 UTC (rev 292799)
@@ -32,6 +32,7 @@
 #include "CachedScriptFetcher.h"
 #include "SharedBuffer.h"
 #include "WebAssemblyCachedScriptSourceProvider.h"
+#include "WebAssemblyScriptBufferSourceProvider.h"
 #include <_javascript_Core/SourceCode.h>
 #include <_javascript_Core/SourceProvider.h>
 #include <wtf/RefPtr.h>
@@ -48,6 +49,12 @@
     {
     }
 
+    WebAssemblyScriptSourceCode(const ScriptBuffer& source, URL&& url, Ref<JSC::ScriptFetcher>&& scriptFetcher)
+        : m_provider(WebAssemblyScriptBufferSourceProvider::create(source, WTFMove(url), WTFMove(scriptFetcher)))
+        , m_code(m_provider.copyRef())
+    {
+    }
+
     const JSC::SourceCode& jsSourceCode() const { return m_code; }
 
 private:

Modified: trunk/Source/WebCore/workers/ScriptBuffer.cpp (292798 => 292799)


--- trunk/Source/WebCore/workers/ScriptBuffer.cpp	2022-04-13 04:25:34 UTC (rev 292798)
+++ trunk/Source/WebCore/workers/ScriptBuffer.cpp	2022-04-13 04:27:16 UTC (rev 292799)
@@ -69,6 +69,11 @@
     m_buffer.append(utf8.data(), utf8.length());
 }
 
+void ScriptBuffer::append(const FragmentedSharedBuffer& buffer)
+{
+    m_buffer.append(buffer);
+}
+
 bool operator==(const ScriptBuffer& a, const ScriptBuffer& b)
 {
     if (a.buffer() == b.buffer())

Modified: trunk/Source/WebCore/workers/ScriptBuffer.h (292798 => 292799)


--- trunk/Source/WebCore/workers/ScriptBuffer.h	2022-04-13 04:25:34 UTC (rev 292798)
+++ trunk/Source/WebCore/workers/ScriptBuffer.h	2022-04-13 04:27:16 UTC (rev 292799)
@@ -56,6 +56,7 @@
 
     WEBCORE_EXPORT bool containsSingleFileMappedSegment() const;
     void append(const String&);
+    void append(const FragmentedSharedBuffer&);
 
 private:
     SharedBufferBuilder m_buffer; // Contains the UTF-8 encoded script.

Modified: trunk/Source/WebCore/workers/WorkerEventLoop.cpp (292798 => 292799)


--- trunk/Source/WebCore/workers/WorkerEventLoop.cpp	2022-04-13 04:25:34 UTC (rev 292798)
+++ trunk/Source/WebCore/workers/WorkerEventLoop.cpp	2022-04-13 04:27:16 UTC (rev 292799)
@@ -47,10 +47,13 @@
 
 void WorkerEventLoop::scheduleToRun()
 {
-    ASSERT(scriptExecutionContext());
-    scriptExecutionContext()->postTask([eventLoop = Ref { *this }] (ScriptExecutionContext&) {
+    auto* globalScope = downcast<WorkerOrWorkletGlobalScope>(scriptExecutionContext());
+    ASSERT(globalScope);
+    // Post this task with a special event mode, so that it can be separated from other
+    // kinds of tasks so that queued microtasks can run even if other tasks are ignored.
+    globalScope->postTaskForMode([eventLoop = Ref { *this }] (ScriptExecutionContext&) {
         eventLoop->run();
-    });
+    }, WorkerEventLoop::taskMode());
 }
 
 bool WorkerEventLoop::isContextThread() const
@@ -71,5 +74,9 @@
     m_microtaskQueue = nullptr;
 }
 
+const String WorkerEventLoop::taskMode()
+{
+    return "workerEventLoopTaskMode"_s;
+}
+
 } // namespace WebCore
-

Modified: trunk/Source/WebCore/workers/WorkerEventLoop.h (292798 => 292799)


--- trunk/Source/WebCore/workers/WorkerEventLoop.h	2022-04-13 04:25:34 UTC (rev 292798)
+++ trunk/Source/WebCore/workers/WorkerEventLoop.h	2022-04-13 04:27:16 UTC (rev 292799)
@@ -38,6 +38,7 @@
 
     virtual ~WorkerEventLoop();
 
+    static const String taskMode();
     // FIXME: This should be removed once MicrotaskQueue is integrated with EventLoopTaskGroup.
     void clearMicrotaskQueue();
 

Modified: trunk/Source/WebCore/workers/WorkerOrWorkletGlobalScope.cpp (292798 => 292799)


--- trunk/Source/WebCore/workers/WorkerOrWorkletGlobalScope.cpp	2022-04-13 04:25:34 UTC (rev 292798)
+++ trunk/Source/WebCore/workers/WorkerOrWorkletGlobalScope.cpp	2022-04-13 04:27:16 UTC (rev 292799)
@@ -120,4 +120,10 @@
     workerOrWorkletThread()->runLoop().postTask(WTFMove(task));
 }
 
+void WorkerOrWorkletGlobalScope::postTaskForMode(Task&& task, const String& mode)
+{
+    ASSERT(workerOrWorkletThread());
+    workerOrWorkletThread()->runLoop().postTaskForMode(WTFMove(task), mode);
+}
+
 } // namespace WebCore

Modified: trunk/Source/WebCore/workers/WorkerOrWorkletGlobalScope.h (292798 => 292799)


--- trunk/Source/WebCore/workers/WorkerOrWorkletGlobalScope.h	2022-04-13 04:25:34 UTC (rev 292798)
+++ trunk/Source/WebCore/workers/WorkerOrWorkletGlobalScope.h	2022-04-13 04:27:16 UTC (rev 292799)
@@ -65,6 +65,10 @@
     bool isContextThread() const final;
     void postTask(Task&&) final; // Executes the task on context's thread asynchronously.
 
+    // Defined specifcially for WorkerOrWorkletGlobalScope for cooperation with
+    // WorkerEventLoop and WorkerRunLoop, not part of ScriptExecutionContext.
+    void postTaskForMode(Task&&, const String&);
+
     virtual void prepareForDestruction();
 
     using RefCounted::ref;

Modified: trunk/Source/WebCore/workers/WorkerOrWorkletScriptController.cpp (292798 => 292799)


--- trunk/Source/WebCore/workers/WorkerOrWorkletScriptController.cpp	2022-04-13 04:25:34 UTC (rev 292798)
+++ trunk/Source/WebCore/workers/WorkerOrWorkletScriptController.cpp	2022-04-13 04:27:16 UTC (rev 292799)
@@ -364,9 +364,13 @@
     // task is queued in WorkerRunLoop before start running module scripts. This task should not be discarded
     // in the following driving of the RunLoop which mainly attempt to collect initial load of module scripts.
     String taskMode = WorkerModuleScriptLoader::taskMode();
+
+    // Allow tasks scheduled from the WorkerEventLoop.
+    constexpr bool allowEventLoopTasks = true;
+
     bool success = true;
     while ((!protector->isLoaded() && !protector->wasCanceled()) && success) {
-        success = runLoop.runInMode(m_globalScope, taskMode);
+        success = runLoop.runInMode(m_globalScope, taskMode, allowEventLoopTasks);
         if (success)
             m_globalScope->eventLoop().performMicrotaskCheckpoint();
     }

Modified: trunk/Source/WebCore/workers/WorkerRunLoop.cpp (292798 => 292799)


--- trunk/Source/WebCore/workers/WorkerRunLoop.cpp	2022-04-13 04:25:34 UTC (rev 292798)
+++ trunk/Source/WebCore/workers/WorkerRunLoop.cpp	2022-04-13 04:27:16 UTC (rev 292799)
@@ -36,6 +36,7 @@
 #include "SharedTimer.h"
 #include "ThreadGlobalData.h"
 #include "ThreadTimers.h"
+#include "WorkerEventLoop.h"
 #include "WorkerOrWorkletGlobalScope.h"
 #include "WorkerOrWorkletScriptController.h"
 #include "WorkerThread.h"
@@ -65,12 +66,18 @@
 
 class ModePredicate {
 public:
-    explicit ModePredicate(String&& mode)
+    explicit ModePredicate(String&& mode, bool allowEventLoopTasks)
         : m_mode(WTFMove(mode))
         , m_defaultMode(m_mode == WorkerRunLoop::defaultMode())
+        , m_allowEventLoopTasks(allowEventLoopTasks)
     {
     }
 
+    const String mode() const
+    {
+        return m_mode;
+    }
+
     bool isDefaultMode() const
     {
         return m_defaultMode;
@@ -78,12 +85,13 @@
 
     bool operator()(const WorkerDedicatedRunLoop::Task& task) const
     {
-        return m_defaultMode || m_mode == task.mode();
+        return m_defaultMode || m_mode == task.mode() || (m_allowEventLoopTasks && task.mode() == WorkerEventLoop::taskMode());
     }
 
 private:
     String m_mode;
     bool m_defaultMode;
+    bool m_allowEventLoopTasks;
 };
 
 WorkerDedicatedRunLoop::WorkerDedicatedRunLoop()
@@ -137,7 +145,7 @@
 void WorkerDedicatedRunLoop::run(WorkerOrWorkletGlobalScope* context)
 {
     RunLoopSetup setup(*this, RunLoopSetup::IsForDebugging::No);
-    ModePredicate modePredicate(defaultMode());
+    ModePredicate modePredicate(defaultMode(), false);
     MessageQueueWaitResult result;
     do {
         result = runInMode(context, modePredicate);
@@ -148,14 +156,14 @@
 MessageQueueWaitResult WorkerDedicatedRunLoop::runInDebuggerMode(WorkerOrWorkletGlobalScope& context)
 {
     RunLoopSetup setup(*this, RunLoopSetup::IsForDebugging::Yes);
-    return runInMode(&context, ModePredicate { debuggerMode() });
+    return runInMode(&context, ModePredicate { debuggerMode(), false });
 }
 
-bool WorkerDedicatedRunLoop::runInMode(WorkerOrWorkletGlobalScope* context, const String& mode)
+bool WorkerDedicatedRunLoop::runInMode(WorkerOrWorkletGlobalScope* context, const String& mode, bool allowEventLoopTasks)
 {
     ASSERT(mode != debuggerMode());
     RunLoopSetup setup(*this, RunLoopSetup::IsForDebugging::No);
-    ModePredicate modePredicate(String { mode });
+    ModePredicate modePredicate(String { mode }, allowEventLoopTasks);
     return runInMode(context, modePredicate) != MessageQueueWaitResult::MessageQueueTerminated;
 }
 
@@ -164,10 +172,11 @@
     ASSERT(context);
     ASSERT(context->workerOrWorkletThread()->thread() == &Thread::current());
 
-    JSC::JSRunLoopTimer::TimerNotificationCallback timerAddedTask = createSharedTask<JSC::JSRunLoopTimer::TimerNotificationType>([this] {
+    const String predicateMode = predicate.mode();
+    JSC::JSRunLoopTimer::TimerNotificationCallback timerAddedTask = createSharedTask<JSC::JSRunLoopTimer::TimerNotificationType>([this, predicateMode] {
         // We don't actually do anything here, we just want to loop around runInMode
         // to both recalculate our deadline and to potentially run the run loop.
-        this->postTask([](ScriptExecutionContext&) { });
+        this->postTaskForMode([predicateMode](ScriptExecutionContext&) { }, predicateMode);
     });
 
 #if USE(GLIB)
@@ -311,7 +320,7 @@
     });
 }
 
-bool WorkerMainRunLoop::runInMode(WorkerOrWorkletGlobalScope*, const String&)
+bool WorkerMainRunLoop::runInMode(WorkerOrWorkletGlobalScope*, const String&, bool)
 {
     RunLoop::main().cycle();
     return true;

Modified: trunk/Source/WebCore/workers/WorkerRunLoop.h (292798 => 292799)


--- trunk/Source/WebCore/workers/WorkerRunLoop.h	2022-04-13 04:25:34 UTC (rev 292798)
+++ trunk/Source/WebCore/workers/WorkerRunLoop.h	2022-04-13 04:27:16 UTC (rev 292799)
@@ -48,7 +48,7 @@
 
     virtual ~WorkerRunLoop() = default;
 
-    virtual bool runInMode(WorkerOrWorkletGlobalScope*, const String& mode) = 0;
+    virtual bool runInMode(WorkerOrWorkletGlobalScope*, const String& mode, bool allowEventLoopTasks = false) = 0;
     virtual void postTaskAndTerminate(ScriptExecutionContext::Task&&) = 0;
     virtual void postTaskForMode(ScriptExecutionContext::Task&&, const String& mode) = 0;
     virtual void terminate() = 0;
@@ -75,7 +75,7 @@
     void run(WorkerOrWorkletGlobalScope*);
 
     // Waits for a single task and returns.
-    bool runInMode(WorkerOrWorkletGlobalScope*, const String& mode) final;
+    bool runInMode(WorkerOrWorkletGlobalScope*, const String& mode, bool) final;
     MessageQueueWaitResult runInDebuggerMode(WorkerOrWorkletGlobalScope&);
 
     void terminate() final;
@@ -125,7 +125,7 @@
     void terminate() final { m_terminated = true; }
     bool terminated() const final { return m_terminated; }
 
-    bool runInMode(WorkerOrWorkletGlobalScope*, const String& mode);
+    bool runInMode(WorkerOrWorkletGlobalScope*, const String& mode, bool);
     void postTaskAndTerminate(ScriptExecutionContext::Task&&) final;
     void postTaskForMode(ScriptExecutionContext::Task&&, const String& mode) final;
     Type type() const final { return Type::WorkerMainRunLoop; }

Modified: trunk/Source/WebCore/workers/WorkerScriptLoader.cpp (292798 => 292799)


--- trunk/Source/WebCore/workers/WorkerScriptLoader.cpp	2022-04-13 04:25:34 UTC (rev 292798)
+++ trunk/Source/WebCore/workers/WorkerScriptLoader.cpp	2022-04-13 04:27:16 UTC (rev 292799)
@@ -234,6 +234,13 @@
     if (m_failed)
         return;
 
+#if ENABLE(WEBASSEMBLY)
+    if (MIMETypeRegistry::isSupportedWebAssemblyMIMEType(m_responseMIMEType)) {
+        m_script.append(buffer);
+        return;
+    }
+#endif
+
     if (!m_decoder)
         m_decoder = TextResourceDecoder::create("text/_javascript_"_s, "UTF-8");
 
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to