source: webkit/trunk/Source/WebCore/workers/ScriptBuffer.cpp

Last change on this file was 292799, checked in by [email protected], 3 years ago

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):

File size: 2.9 KB
Line 
1/*
2 * Copyright (C) 2021 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 *
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
13 * distribution.
14 * * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31#include "config.h"
32#include "ScriptBuffer.h"
33
34#include <wtf/text/StringBuilder.h>
35
36namespace WebCore {
37
38ScriptBuffer::ScriptBuffer(const String& string)
39{
40 auto utf8 = string.utf8();
41 m_buffer.append(utf8.data(), utf8.length());
42}
43
44ScriptBuffer ScriptBuffer::empty()
45{
46 return ScriptBuffer { SharedBuffer::create() };
47}
48
49String ScriptBuffer::toString() const
50{
51 if (!m_buffer)
52 return String();
53
54 StringBuilder builder;
55 m_buffer.get()->forEachSegment([&](auto& segment) {
56 builder.append(String::fromUTF8(segment.data(), segment.size()));
57 });
58 return builder.toString();
59}
60
61bool ScriptBuffer::containsSingleFileMappedSegment() const
62{
63 return m_buffer && m_buffer.get()->hasOneSegment() && m_buffer.get()->begin()->segment->containsMappedFileData();
64}
65
66void ScriptBuffer::append(const String& string)
67{
68 auto utf8 = string.utf8();
69 m_buffer.append(utf8.data(), utf8.length());
70}
71
72void ScriptBuffer::append(const FragmentedSharedBuffer& buffer)
73{
74 m_buffer.append(buffer);
75}
76
77bool operator==(const ScriptBuffer& a, const ScriptBuffer& b)
78{
79 if (a.buffer() == b.buffer())
80 return true;
81 if (!a.buffer() || !b.buffer())
82 return false;
83 return *a.buffer() == *b.buffer();
84}
85
86bool operator!=(const ScriptBuffer& a, const ScriptBuffer& b)
87{
88 return !(a == b);
89}
90
91} // namespace WebCore
Note: See TracBrowser for help on using the repository browser.