| Differences between
and this patch
- a/Source/WebCore/ChangeLog +80 lines
Lines 1-3 a/Source/WebCore/ChangeLog_sec1
1
2021-02-09  Yusuke Suzuki  <ysuzuki@apple.com>
2
3
        JS Modules in Workers
4
        https://bugs.webkit.org/show_bug.cgi?id=164860
5
6
        Reviewed by NOBODY (OOPS!).
7
8
        * bindings/js/CachedModuleScriptLoader.cpp:
9
        (WebCore::CachedModuleScriptLoader::load):
10
        * bindings/js/CachedModuleScriptLoader.h:
11
        * bindings/js/CachedScriptFetcher.cpp:
12
        (WebCore::CachedScriptFetcher::requestModuleScript const):
13
        (WebCore::CachedScriptFetcher::requestScriptWithCache const):
14
        * bindings/js/CachedScriptFetcher.h:
15
        * bindings/js/JSDOMGlobalObject.cpp:
16
        (WebCore::scriptModuleLoader):
17
        (WebCore::JSDOMGlobalObject::moduleLoaderResolve):
18
        (WebCore::JSDOMGlobalObject::moduleLoaderFetch):
19
        (WebCore::JSDOMGlobalObject::moduleLoaderEvaluate):
20
        (WebCore::JSDOMGlobalObject::moduleLoaderImportModule):
21
        (WebCore::JSDOMGlobalObject::moduleLoaderCreateImportMetaProperties):
22
        * bindings/js/JSDOMGlobalObject.h:
23
        * bindings/js/JSDOMWindowBase.cpp:
24
        (WebCore::JSDOMWindowBase::moduleLoaderResolve): Deleted.
25
        (WebCore::JSDOMWindowBase::moduleLoaderFetch): Deleted.
26
        (WebCore::JSDOMWindowBase::moduleLoaderEvaluate): Deleted.
27
        (WebCore::JSDOMWindowBase::moduleLoaderImportModule): Deleted.
28
        (WebCore::JSDOMWindowBase::moduleLoaderCreateImportMetaProperties): Deleted.
29
        * bindings/js/JSDOMWindowBase.h:
30
        * bindings/js/JSWorkerGlobalScopeBase.cpp:
31
        * bindings/js/JSWorkletGlobalScopeBase.cpp:
32
        * bindings/js/ScriptModuleLoader.cpp:
33
        (WebCore::ScriptModuleLoader::ScriptModuleLoader):
34
        (WebCore::resolveModuleSpecifier):
35
        (WebCore::ScriptModuleLoader::resolve):
36
        (WebCore::ScriptModuleLoader::fetch):
37
        (WebCore::ScriptModuleLoader::moduleURL):
38
        (WebCore::ScriptModuleLoader::responseURLFromRequestURL):
39
        (WebCore::ScriptModuleLoader::evaluate):
40
        (WebCore::ScriptModuleLoader::importModule):
41
        * bindings/js/ScriptModuleLoader.h:
42
        * dom/LoadableModuleScript.cpp:
43
        (WebCore::LoadableModuleScript::load): Deleted.
44
        * dom/LoadableModuleScript.h:
45
        * dom/ScriptElement.cpp:
46
        (WebCore::ScriptElement::requestModuleScript):
47
        * dom/ScriptElementCachedScriptFetcher.cpp:
48
        (WebCore::ScriptElementCachedScriptFetcher::requestModuleScript const):
49
        * dom/ScriptElementCachedScriptFetcher.h:
50
        * workers/Worker.cpp:
51
        (WebCore::Worker::Worker):
52
        (WebCore::Worker::create):
53
        (WebCore::Worker::notifyFinished):
54
        * workers/Worker.h:
55
        * workers/Worker.idl:
56
        * workers/WorkerGlobalScope.h:
57
        * workers/WorkerGlobalScopeProxy.h:
58
        * workers/WorkerMessagingProxy.cpp:
59
        (WebCore::WorkerMessagingProxy::startWorkerGlobalScope):
60
        * workers/WorkerMessagingProxy.h:
61
        * workers/WorkerOrWorkletGlobalScope.cpp:
62
        (WebCore::WorkerOrWorkletGlobalScope::WorkerOrWorkletGlobalScope):
63
        * workers/WorkerOrWorkletGlobalScope.h:
64
        (WebCore::WorkerOrWorkletGlobalScope::moduleLoader):
65
        * workers/WorkerOrWorkletScriptController.cpp:
66
        (WebCore::jsValueToModuleKey):
67
        (WebCore::WorkerOrWorkletScriptController::evaluateModule):
68
        (WebCore::driveRunLoop):
69
        (WebCore::WorkerOrWorkletScriptController::loadModuleSynchronously):
70
        (WebCore::WorkerOrWorkletScriptController::linkAndEvaluateModule):
71
        * workers/WorkerOrWorkletScriptController.h:
72
        * workers/WorkerRunLoop.cpp:
73
        (WebCore::WorkerRunLoop::postTaskAndTerminate):
74
        * workers/WorkerThread.cpp:
75
        (WebCore::WorkerParameters::isolatedCopy const):
76
        (WebCore::WorkerThread::evaluateScriptIfNecessary):
77
        * workers/WorkerThread.h:
78
        * workers/service/context/ServiceWorkerThread.cpp:
79
        (WebCore::ServiceWorkerThread::ServiceWorkerThread):
80
1
2021-02-07  Lauro Moura  <lmoura@igalia.com>
81
2021-02-07  Lauro Moura  <lmoura@igalia.com>
2
82
3
        REGRESSION(r272379) [WPE] imported/w3c/web-platform-tests/mathml/relations/css-styling/mathvariant tests are Image Failing
83
        REGRESSION(r272379) [WPE] imported/w3c/web-platform-tests/mathml/relations/css-styling/mathvariant tests are Image Failing
- a/Source/WebCore/bindings/js/CachedModuleScriptLoader.cpp -2 / +2 lines
Lines 61-71 CachedModuleScriptLoader::~CachedModuleScriptLoader() a/Source/WebCore/bindings/js/CachedModuleScriptLoader.cpp_sec1
61
    }
61
    }
62
}
62
}
63
63
64
bool CachedModuleScriptLoader::load(Document& document, const URL& sourceURL)
64
bool CachedModuleScriptLoader::load(ScriptExecutionContext& context, const URL& sourceURL)
65
{
65
{
66
    ASSERT(!m_cachedScript);
66
    ASSERT(!m_cachedScript);
67
    String integrity = m_parameters ? m_parameters->integrity() : String { };
67
    String integrity = m_parameters ? m_parameters->integrity() : String { };
68
    m_cachedScript = m_scriptFetcher->requestModuleScript(document, sourceURL, WTFMove(integrity));
68
    m_cachedScript = m_scriptFetcher->requestModuleScript(context, sourceURL, WTFMove(integrity));
69
    if (!m_cachedScript)
69
    if (!m_cachedScript)
70
        return false;
70
        return false;
71
    m_sourceURL = sourceURL;
71
    m_sourceURL = sourceURL;
- a/Source/WebCore/bindings/js/CachedModuleScriptLoader.h -2 / +2 lines
Lines 38-46 class CachedModuleScriptLoaderClient; a/Source/WebCore/bindings/js/CachedModuleScriptLoader.h_sec1
38
class CachedScript;
38
class CachedScript;
39
class CachedScriptFetcher;
39
class CachedScriptFetcher;
40
class DeferredPromise;
40
class DeferredPromise;
41
class Document;
42
class JSDOMGlobalObject;
41
class JSDOMGlobalObject;
43
class ModuleFetchParameters;
42
class ModuleFetchParameters;
43
class ScriptExecutionContext;
44
44
45
class CachedModuleScriptLoader final : public RefCounted<CachedModuleScriptLoader>, private CachedResourceClient {
45
class CachedModuleScriptLoader final : public RefCounted<CachedModuleScriptLoader>, private CachedResourceClient {
46
public:
46
public:
Lines 48-54 class CachedModuleScriptLoader final : public RefCounted<CachedModuleScriptLoade a/Source/WebCore/bindings/js/CachedModuleScriptLoader.h_sec2
48
48
49
    virtual ~CachedModuleScriptLoader();
49
    virtual ~CachedModuleScriptLoader();
50
50
51
    bool load(Document&, const URL& sourceURL);
51
    bool load(ScriptExecutionContext&, const URL& sourceURL);
52
52
53
    CachedScriptFetcher& scriptFetcher() { return m_scriptFetcher.get(); }
53
    CachedScriptFetcher& scriptFetcher() { return m_scriptFetcher.get(); }
54
    CachedScript* cachedScript() { return m_cachedScript.get(); }
54
    CachedScript* cachedScript() { return m_cachedScript.get(); }
- a/Source/WebCore/bindings/js/CachedScriptFetcher.cpp -19 / +27 lines
Lines 32-37 a/Source/WebCore/bindings/js/CachedScriptFetcher.cpp_sec1
32
#include "CrossOriginAccessControl.h"
32
#include "CrossOriginAccessControl.h"
33
#include "Document.h"
33
#include "Document.h"
34
#include "Settings.h"
34
#include "Settings.h"
35
#include "WorkerOrWorkletGlobalScope.h"
35
36
36
namespace WebCore {
37
namespace WebCore {
37
38
Lines 40-71 Ref<CachedScriptFetcher> CachedScriptFetcher::create(const String& charset) a/Source/WebCore/bindings/js/CachedScriptFetcher.cpp_sec2
40
    return adoptRef(*new CachedScriptFetcher(charset));
41
    return adoptRef(*new CachedScriptFetcher(charset));
41
}
42
}
42
43
43
CachedResourceHandle<CachedScript> CachedScriptFetcher::requestModuleScript(Document& document, const URL& sourceURL, String&& integrity) const
44
CachedResourceHandle<CachedScript> CachedScriptFetcher::requestModuleScript(ScriptExecutionContext& context, const URL& sourceURL, String&& integrity) const
44
{
45
{
45
    return requestScriptWithCache(document, sourceURL, String { }, WTFMove(integrity), { });
46
    return requestScriptWithCache(context, sourceURL, String { }, WTFMove(integrity), { });
46
}
47
}
47
48
48
CachedResourceHandle<CachedScript> CachedScriptFetcher::requestScriptWithCache(Document& document, const URL& sourceURL, const String& crossOriginMode, String&& integrity, Optional<ResourceLoadPriority> resourceLoadPriority) const
49
CachedResourceHandle<CachedScript> CachedScriptFetcher::requestScriptWithCache(ScriptExecutionContext& context, const URL& sourceURL, const String& crossOriginMode, String&& integrity, Optional<ResourceLoadPriority> resourceLoadPriority) const
49
{
50
{
50
    if (!document.settings().isScriptEnabled())
51
    // Without scripting, there is no way to start Workers.
51
        return nullptr;
52
    if (is<Document>(context)) {
53
        auto& document = downcast<Document>(context);
54
        if (!document.settings().isScriptEnabled())
55
            return nullptr;
52
56
53
    ASSERT(document.contentSecurityPolicy());
57
        ASSERT(document.contentSecurityPolicy());
54
    bool hasKnownNonce = document.contentSecurityPolicy()->allowScriptWithNonce(m_nonce, m_isInUserAgentShadowTree);
58
        bool hasKnownNonce = document.contentSecurityPolicy()->allowScriptWithNonce(m_nonce, m_isInUserAgentShadowTree);
55
    ResourceLoaderOptions options = CachedResourceLoader::defaultCachedResourceOptions();
59
        ResourceLoaderOptions options = CachedResourceLoader::defaultCachedResourceOptions();
56
    options.contentSecurityPolicyImposition = hasKnownNonce ? ContentSecurityPolicyImposition::SkipPolicyCheck : ContentSecurityPolicyImposition::DoPolicyCheck;
60
        options.contentSecurityPolicyImposition = hasKnownNonce ? ContentSecurityPolicyImposition::SkipPolicyCheck : ContentSecurityPolicyImposition::DoPolicyCheck;
57
    options.sameOriginDataURLFlag = SameOriginDataURLFlag::Set;
61
        options.sameOriginDataURLFlag = SameOriginDataURLFlag::Set;
58
    options.integrity = WTFMove(integrity);
62
        options.integrity = WTFMove(integrity);
59
    options.referrerPolicy = m_referrerPolicy;
63
        options.referrerPolicy = m_referrerPolicy;
60
64
61
    auto request = createPotentialAccessControlRequest(sourceURL, WTFMove(options), document, crossOriginMode);
65
        auto request = createPotentialAccessControlRequest(sourceURL, WTFMove(options), document, crossOriginMode);
62
    request.upgradeInsecureRequestIfNeeded(document);
66
        request.upgradeInsecureRequestIfNeeded(document);
63
    request.setCharset(m_charset);
67
        request.setCharset(m_charset);
64
    request.setPriority(WTFMove(resourceLoadPriority));
68
        request.setPriority(WTFMove(resourceLoadPriority));
65
    if (!m_initiatorName.isNull())
69
        if (!m_initiatorName.isNull())
66
        request.setInitiator(m_initiatorName);
70
            request.setInitiator(m_initiatorName);
67
71
68
    return document.cachedResourceLoader().requestScript(WTFMove(request)).value_or(nullptr);
72
        return document.cachedResourceLoader().requestScript(WTFMove(request)).value_or(nullptr);
73
    } else {
74
        dataLogLn("WORKER");
75
        return nullptr;
76
    }
69
}
77
}
70
78
71
}
79
}
- a/Source/WebCore/bindings/js/CachedScriptFetcher.h -3 / +3 lines
Lines 35-45 a/Source/WebCore/bindings/js/CachedScriptFetcher.h_sec1
35
namespace WebCore {
35
namespace WebCore {
36
36
37
class CachedScript;
37
class CachedScript;
38
class Document;
38
class ScriptExecutionContext;
39
39
40
class CachedScriptFetcher : public JSC::ScriptFetcher {
40
class CachedScriptFetcher : public JSC::ScriptFetcher {
41
public:
41
public:
42
    virtual CachedResourceHandle<CachedScript> requestModuleScript(Document&, const URL& sourceURL, String&& integrity) const;
42
    virtual CachedResourceHandle<CachedScript> requestModuleScript(ScriptExecutionContext&, const URL& sourceURL, String&& integrity) const;
43
43
44
    static Ref<CachedScriptFetcher> create(const String& charset);
44
    static Ref<CachedScriptFetcher> create(const String& charset);
45
45
Lines 58-64 class CachedScriptFetcher : public JSC::ScriptFetcher { a/Source/WebCore/bindings/js/CachedScriptFetcher.h_sec2
58
    {
58
    {
59
    }
59
    }
60
60
61
    CachedResourceHandle<CachedScript> requestScriptWithCache(Document&, const URL& sourceURL, const String& crossOriginMode, String&& integrity, Optional<ResourceLoadPriority>) const;
61
    CachedResourceHandle<CachedScript> requestScriptWithCache(ScriptExecutionContext&, const URL& sourceURL, const String& crossOriginMode, String&& integrity, Optional<ResourceLoadPriority>) const;
62
62
63
private:
63
private:
64
    String m_nonce;
64
    String m_nonce;
- a/Source/WebCore/bindings/js/JSDOMGlobalObject.cpp +73 lines
Lines 422-427 JSC::JSPromise* JSDOMGlobalObject::instantiateStreaming(JSC::JSGlobalObject* glo a/Source/WebCore/bindings/js/JSDOMGlobalObject.cpp_sec1
422
}
422
}
423
#endif
423
#endif
424
424
425
static ScriptModuleLoader* scriptModuleLoader(JSDOMGlobalObject* globalObject)
426
{
427
    VM& vm = globalObject->vm();
428
    if (globalObject->inherits<JSDOMWindowBase>(vm)) {
429
        if (auto document = jsCast<const JSDOMWindowBase*>(globalObject)->wrapped().document())
430
            return &document->moduleLoader();
431
        return nullptr;
432
    }
433
    if (globalObject->inherits<JSRemoteDOMWindowBase>(vm))
434
        return nullptr;
435
    if (globalObject->inherits<JSWorkerGlobalScopeBase>(vm))
436
        return &jsCast<const JSWorkerGlobalScopeBase*>(globalObject)->wrapped().moduleLoader();
437
    if (globalObject->inherits<JSWorkletGlobalScopeBase>(vm))
438
        return &jsCast<const JSWorkletGlobalScopeBase*>(globalObject)->wrapped().moduleLoader();
439
#if ENABLE(INDEXED_DATABASE)
440
    if (globalObject->inherits<JSIDBSerializationGlobalObject>(vm))
441
        return nullptr;
442
#endif
443
    dataLog("Unexpected global object: ", JSValue(globalObject), "\n");
444
    RELEASE_ASSERT_NOT_REACHED();
445
    return nullptr;
446
}
447
448
JSC::Identifier JSDOMGlobalObject::moduleLoaderResolve(JSC::JSGlobalObject* globalObject, JSC::JSModuleLoader* moduleLoader, JSC::JSValue moduleName, JSC::JSValue importerModuleKey, JSC::JSValue scriptFetcher)
449
{
450
    JSDOMGlobalObject* thisObject = JSC::jsCast<JSDOMGlobalObject*>(globalObject);
451
    if (auto* loader = scriptModuleLoader(thisObject))
452
        return loader->resolve(globalObject, moduleLoader, moduleName, importerModuleKey, scriptFetcher);
453
    return { };
454
}
455
456
JSC::JSInternalPromise* JSDOMGlobalObject::moduleLoaderFetch(JSC::JSGlobalObject* globalObject, JSC::JSModuleLoader* moduleLoader, JSC::JSValue moduleKey, JSC::JSValue parameters, JSC::JSValue scriptFetcher)
457
{
458
    VM& vm = globalObject->vm();
459
    auto scope = DECLARE_THROW_SCOPE(vm);
460
    JSDOMGlobalObject* thisObject = JSC::jsCast<JSDOMGlobalObject*>(globalObject);
461
    if (auto* loader = scriptModuleLoader(thisObject))
462
        RELEASE_AND_RETURN(scope, loader->fetch(globalObject, moduleLoader, moduleKey, parameters, scriptFetcher));
463
    JSC::JSInternalPromise* promise = JSC::JSInternalPromise::create(vm, globalObject->internalPromiseStructure());
464
    scope.release();
465
    promise->reject(globalObject, jsUndefined());
466
    return promise;
467
}
468
469
JSC::JSValue JSDOMGlobalObject::moduleLoaderEvaluate(JSC::JSGlobalObject* globalObject, JSC::JSModuleLoader* moduleLoader, JSC::JSValue moduleKey, JSC::JSValue moduleRecord, JSC::JSValue scriptFetcher)
470
{
471
    JSDOMGlobalObject* thisObject = JSC::jsCast<JSDOMGlobalObject*>(globalObject);
472
    if (auto* loader = scriptModuleLoader(thisObject))
473
        return loader->evaluate(globalObject, moduleLoader, moduleKey, moduleRecord, scriptFetcher);
474
    return JSC::jsUndefined();
475
}
476
477
JSC::JSInternalPromise* JSDOMGlobalObject::moduleLoaderImportModule(JSC::JSGlobalObject* globalObject, JSC::JSModuleLoader* moduleLoader, JSC::JSString* moduleName, JSC::JSValue parameters, const JSC::SourceOrigin& sourceOrigin)
478
{
479
    VM& vm = globalObject->vm();
480
    auto scope = DECLARE_THROW_SCOPE(vm);
481
    JSDOMGlobalObject* thisObject = JSC::jsCast<JSDOMGlobalObject*>(globalObject);
482
    if (auto* loader = scriptModuleLoader(thisObject))
483
        RELEASE_AND_RETURN(scope, loader->importModule(globalObject, moduleLoader, moduleName, parameters, sourceOrigin));
484
    JSC::JSInternalPromise* promise = JSC::JSInternalPromise::create(vm, globalObject->internalPromiseStructure());
485
    scope.release();
486
    promise->reject(globalObject, jsUndefined());
487
    return promise;
488
}
489
490
JSC::JSObject* JSDOMGlobalObject::moduleLoaderCreateImportMetaProperties(JSC::JSGlobalObject* globalObject, JSC::JSModuleLoader* moduleLoader, JSC::JSValue moduleKey, JSC::JSModuleRecord* moduleRecord, JSC::JSValue scriptFetcher)
491
{
492
    JSDOMGlobalObject* thisObject = JSC::jsCast<JSDOMGlobalObject*>(globalObject);
493
    if (auto* loader = scriptModuleLoader(thisObject))
494
        return loader->createImportMetaProperties(globalObject, moduleLoader, moduleKey, moduleRecord, scriptFetcher);
495
    return constructEmptyObject(globalObject->vm(), globalObject->nullPrototypeObjectStructure());
496
}
497
425
JSDOMGlobalObject& callerGlobalObject(JSGlobalObject& lexicalGlobalObject, CallFrame& callFrame)
498
JSDOMGlobalObject& callerGlobalObject(JSGlobalObject& lexicalGlobalObject, CallFrame& callFrame)
426
{
499
{
427
    class GetCallerGlobalObjectFunctor {
500
    class GetCallerGlobalObjectFunctor {
- a/Source/WebCore/bindings/js/JSDOMGlobalObject.h +6 lines
Lines 105-110 class WEBCORE_EXPORT JSDOMGlobalObject : public JSC::JSGlobalObject { a/Source/WebCore/bindings/js/JSDOMGlobalObject.h_sec1
105
    static JSC::JSPromise* instantiateStreaming(JSC::JSGlobalObject*, JSC::JSValue, JSC::JSObject*);
105
    static JSC::JSPromise* instantiateStreaming(JSC::JSGlobalObject*, JSC::JSValue, JSC::JSObject*);
106
#endif
106
#endif
107
107
108
    static JSC::Identifier moduleLoaderResolve(JSC::JSGlobalObject*, JSC::JSModuleLoader*, JSC::JSValue, JSC::JSValue, JSC::JSValue);
109
    static JSC::JSInternalPromise* moduleLoaderFetch(JSC::JSGlobalObject*, JSC::JSModuleLoader*, JSC::JSValue, JSC::JSValue, JSC::JSValue);
110
    static JSC::JSValue moduleLoaderEvaluate(JSC::JSGlobalObject*, JSC::JSModuleLoader*, JSC::JSValue, JSC::JSValue, JSC::JSValue);
111
    static JSC::JSInternalPromise* moduleLoaderImportModule(JSC::JSGlobalObject*, JSC::JSModuleLoader*, JSC::JSString*, JSC::JSValue, const JSC::SourceOrigin&);
112
    static JSC::JSObject* moduleLoaderCreateImportMetaProperties(JSC::JSGlobalObject*, JSC::JSModuleLoader*, JSC::JSValue, JSC::JSModuleRecord*, JSC::JSValue);
113
108
    JSDOMStructureMap m_structures;
114
    JSDOMStructureMap m_structures;
109
    JSDOMConstructorMap m_constructors;
115
    JSDOMConstructorMap m_constructors;
110
    DOMGuardedObjectSet m_guardedObjects;
116
    DOMGuardedObjectSet m_guardedObjects;
- a/Source/WebCore/bindings/js/JSDOMWindowBase.cpp -50 lines
Lines 339-392 void JSDOMWindowBase::fireFrameClearedWatchpointsForWindow(DOMWindow* window) a/Source/WebCore/bindings/js/JSDOMWindowBase.cpp_sec1
339
    }
339
    }
340
}
340
}
341
341
342
JSC::Identifier JSDOMWindowBase::moduleLoaderResolve(JSC::JSGlobalObject* globalObject, JSC::JSModuleLoader* moduleLoader, JSC::JSValue moduleName, JSC::JSValue importerModuleKey, JSC::JSValue scriptFetcher)
343
{
344
    JSDOMWindowBase* thisObject = JSC::jsCast<JSDOMWindowBase*>(globalObject);
345
    if (RefPtr<Document> document = thisObject->wrapped().document())
346
        return document->moduleLoader().resolve(globalObject, moduleLoader, moduleName, importerModuleKey, scriptFetcher);
347
    return { };
348
}
349
350
JSC::JSInternalPromise* JSDOMWindowBase::moduleLoaderFetch(JSC::JSGlobalObject* globalObject, JSC::JSModuleLoader* moduleLoader, JSC::JSValue moduleKey, JSC::JSValue parameters, JSC::JSValue scriptFetcher)
351
{
352
    VM& vm = globalObject->vm();
353
    auto scope = DECLARE_THROW_SCOPE(vm);
354
    JSDOMWindowBase* thisObject = JSC::jsCast<JSDOMWindowBase*>(globalObject);
355
    if (RefPtr<Document> document = thisObject->wrapped().document())
356
        RELEASE_AND_RETURN(scope, document->moduleLoader().fetch(globalObject, moduleLoader, moduleKey, parameters, scriptFetcher));
357
    JSC::JSInternalPromise* promise = JSC::JSInternalPromise::create(vm, globalObject->internalPromiseStructure());
358
    scope.release();
359
    promise->reject(globalObject, jsUndefined());
360
    return promise;
361
}
362
363
JSC::JSValue JSDOMWindowBase::moduleLoaderEvaluate(JSC::JSGlobalObject* globalObject, JSC::JSModuleLoader* moduleLoader, JSC::JSValue moduleKey, JSC::JSValue moduleRecord, JSC::JSValue scriptFetcher)
364
{
365
    JSDOMWindowBase* thisObject = JSC::jsCast<JSDOMWindowBase*>(globalObject);
366
    if (RefPtr<Document> document = thisObject->wrapped().document())
367
        return document->moduleLoader().evaluate(globalObject, moduleLoader, moduleKey, moduleRecord, scriptFetcher);
368
    return JSC::jsUndefined();
369
}
370
371
JSC::JSInternalPromise* JSDOMWindowBase::moduleLoaderImportModule(JSC::JSGlobalObject* globalObject, JSC::JSModuleLoader* moduleLoader, JSC::JSString* moduleName, JSC::JSValue parameters, const JSC::SourceOrigin& sourceOrigin)
372
{
373
    VM& vm = globalObject->vm();
374
    auto scope = DECLARE_THROW_SCOPE(vm);
375
    JSDOMWindowBase* thisObject = JSC::jsCast<JSDOMWindowBase*>(globalObject);
376
    if (RefPtr<Document> document = thisObject->wrapped().document())
377
        RELEASE_AND_RETURN(scope, document->moduleLoader().importModule(globalObject, moduleLoader, moduleName, parameters, sourceOrigin));
378
    JSC::JSInternalPromise* promise = JSC::JSInternalPromise::create(vm, globalObject->internalPromiseStructure());
379
    scope.release();
380
    promise->reject(globalObject, jsUndefined());
381
    return promise;
382
}
383
384
JSC::JSObject* JSDOMWindowBase::moduleLoaderCreateImportMetaProperties(JSC::JSGlobalObject* globalObject, JSC::JSModuleLoader* moduleLoader, JSC::JSValue moduleKey, JSC::JSModuleRecord* moduleRecord, JSC::JSValue scriptFetcher)
385
{
386
    JSDOMWindowBase* thisObject = JSC::jsCast<JSDOMWindowBase*>(globalObject);
387
    if (RefPtr<Document> document = thisObject->wrapped().document())
388
        return document->moduleLoader().createImportMetaProperties(globalObject, moduleLoader, moduleKey, moduleRecord, scriptFetcher);
389
    return constructEmptyObject(globalObject->vm(), globalObject->nullPrototypeObjectStructure());
390
}
391
392
} // namespace WebCore
342
} // namespace WebCore
- a/Source/WebCore/bindings/js/JSDOMWindowBase.h -6 lines
Lines 99-110 class WEBCORE_EXPORT JSDOMWindowBase : public JSDOMGlobalObject { a/Source/WebCore/bindings/js/JSDOMWindowBase.h_sec1
99
private:
99
private:
100
    using ResponseCallback = WTF::Function<void(const char*, size_t)>;
100
    using ResponseCallback = WTF::Function<void(const char*, size_t)>;
101
101
102
    static JSC::Identifier moduleLoaderResolve(JSC::JSGlobalObject*, JSC::JSModuleLoader*, JSC::JSValue, JSC::JSValue, JSC::JSValue);
103
    static JSC::JSInternalPromise* moduleLoaderFetch(JSC::JSGlobalObject*, JSC::JSModuleLoader*, JSC::JSValue, JSC::JSValue, JSC::JSValue);
104
    static JSC::JSValue moduleLoaderEvaluate(JSC::JSGlobalObject*, JSC::JSModuleLoader*, JSC::JSValue, JSC::JSValue, JSC::JSValue);
105
    static JSC::JSInternalPromise* moduleLoaderImportModule(JSC::JSGlobalObject*, JSC::JSModuleLoader*, JSC::JSString*, JSC::JSValue, const JSC::SourceOrigin&);
106
    static JSC::JSObject* moduleLoaderCreateImportMetaProperties(JSC::JSGlobalObject*, JSC::JSModuleLoader*, JSC::JSValue, JSC::JSModuleRecord*, JSC::JSValue);
107
108
    RefPtr<DOMWindow> m_wrapped;
102
    RefPtr<DOMWindow> m_wrapped;
109
    RefPtr<Event> m_currentEvent;
103
    RefPtr<Event> m_currentEvent;
110
};
104
};
- a/Source/WebCore/bindings/js/JSWorkerGlobalScopeBase.cpp -5 / +5 lines
Lines 59-69 const GlobalObjectMethodTable JSWorkerGlobalScopeBase::s_globalObjectMethodTable a/Source/WebCore/bindings/js/JSWorkerGlobalScopeBase.cpp_sec1
59
    &javaScriptRuntimeFlags,
59
    &javaScriptRuntimeFlags,
60
    &queueMicrotaskToEventLoop,
60
    &queueMicrotaskToEventLoop,
61
    &shouldInterruptScriptBeforeTimeout,
61
    &shouldInterruptScriptBeforeTimeout,
62
    nullptr, // moduleLoaderImportModule
62
    &moduleLoaderImportModule,
63
    nullptr, // moduleLoaderResolve
63
    &moduleLoaderResolve,
64
    nullptr, // moduleLoaderFetch
64
    &moduleLoaderFetch,
65
    nullptr, // moduleLoaderCreateImportMetaProperties
65
    &moduleLoaderCreateImportMetaProperties,
66
    nullptr, // moduleLoaderEvaluate
66
    &moduleLoaderEvaluate,
67
    &promiseRejectionTracker,
67
    &promiseRejectionTracker,
68
    &reportUncaughtExceptionAtEventLoop,
68
    &reportUncaughtExceptionAtEventLoop,
69
    &currentScriptExecutionOwner,
69
    &currentScriptExecutionOwner,
- a/Source/WebCore/bindings/js/JSWorkletGlobalScopeBase.cpp -5 / +5 lines
Lines 49-59 const GlobalObjectMethodTable JSWorkletGlobalScopeBase::s_globalObjectMethodTabl a/Source/WebCore/bindings/js/JSWorkletGlobalScopeBase.cpp_sec1
49
    &javaScriptRuntimeFlags,
49
    &javaScriptRuntimeFlags,
50
    nullptr, // queueMicrotaskToEventLoop
50
    nullptr, // queueMicrotaskToEventLoop
51
    &shouldInterruptScriptBeforeTimeout,
51
    &shouldInterruptScriptBeforeTimeout,
52
    nullptr, // moduleLoaderImportModule
52
    &moduleLoaderImportModule,
53
    nullptr, // moduleLoaderResolve
53
    &moduleLoaderResolve,
54
    nullptr, // moduleLoaderFetch
54
    &moduleLoaderFetch,
55
    nullptr, // moduleLoaderCreateImportMetaProperties
55
    &moduleLoaderCreateImportMetaProperties,
56
    nullptr, // moduleLoaderEvaluate
56
    &moduleLoaderEvaluate,
57
    &promiseRejectionTracker,
57
    &promiseRejectionTracker,
58
    &reportUncaughtExceptionAtEventLoop,
58
    &reportUncaughtExceptionAtEventLoop,
59
    &currentScriptExecutionOwner,
59
    &currentScriptExecutionOwner,
- a/Source/WebCore/bindings/js/ScriptModuleLoader.cpp -16 / +42 lines
Lines 29-35 a/Source/WebCore/bindings/js/ScriptModuleLoader.cpp_sec1
29
#include "CachedModuleScriptLoader.h"
29
#include "CachedModuleScriptLoader.h"
30
#include "CachedScript.h"
30
#include "CachedScript.h"
31
#include "CachedScriptFetcher.h"
31
#include "CachedScriptFetcher.h"
32
#include "Document.h"
33
#include "Frame.h"
32
#include "Frame.h"
34
#include "JSDOMBinding.h"
33
#include "JSDOMBinding.h"
35
#include "JSDOMPromiseDeferred.h"
34
#include "JSDOMPromiseDeferred.h"
Lines 52-59 a/Source/WebCore/bindings/js/ScriptModuleLoader.cpp_sec2
52
51
53
namespace WebCore {
52
namespace WebCore {
54
53
55
ScriptModuleLoader::ScriptModuleLoader(Document& document)
54
ScriptModuleLoader::ScriptModuleLoader(ScriptExecutionContext& context)
56
    : m_document(document)
55
    : m_context(context)
57
{
56
{
58
}
57
}
59
58
Lines 68-74 static bool isRootModule(JSC::JSValue importerModuleKey) a/Source/WebCore/bindings/js/ScriptModuleLoader.cpp_sec3
68
    return importerModuleKey.isSymbol() || importerModuleKey.isUndefined();
67
    return importerModuleKey.isSymbol() || importerModuleKey.isUndefined();
69
}
68
}
70
69
71
static Expected<URL, String> resolveModuleSpecifier(Document& document, const String& specifier, const URL& baseURL)
70
static Expected<URL, String> resolveModuleSpecifier(ScriptExecutionContext& context, const String& specifier, const URL& baseURL)
72
{
71
{
73
    // https://html.spec.whatwg.org/multipage/webappapis.html#resolve-a-module-specifier
72
    // https://html.spec.whatwg.org/multipage/webappapis.html#resolve-a-module-specifier
74
73
Lines 79-85 static Expected<URL, String> resolveModuleSpecifier(Document& document, const St a/Source/WebCore/bindings/js/ScriptModuleLoader.cpp_sec4
79
    if (!specifier.startsWith('/') && !specifier.startsWith("./") && !specifier.startsWith("../"))
78
    if (!specifier.startsWith('/') && !specifier.startsWith("./") && !specifier.startsWith("../"))
80
        return makeUnexpected(makeString("Module specifier, '"_s, specifier, "' does not start with \"/\", \"./\", or \"../\". Referenced from "_s, baseURL.string()));
79
        return makeUnexpected(makeString("Module specifier, '"_s, specifier, "' does not start with \"/\", \"./\", or \"../\". Referenced from "_s, baseURL.string()));
81
80
82
    auto result = document.completeURL(specifier, baseURL);
81
    URL result;
82
    if (is<Document>(context))
83
        result = downcast<Document>(context).completeURL(specifier, baseURL);
84
    else
85
        result = URL(baseURL, specifier);
86
83
    if (!result.isValid())
87
    if (!result.isValid())
84
        return makeUnexpected(makeString("Module name, '"_s, result.string(), "' does not resolve to a valid URL."_s));
88
        return makeUnexpected(makeString("Module name, '"_s, result.string(), "' does not resolve to a valid URL."_s));
85
    return result;
89
    return result;
Lines 107-113 JSC::Identifier ScriptModuleLoader::resolve(JSC::JSGlobalObject* jsGlobalObject, a/Source/WebCore/bindings/js/ScriptModuleLoader.cpp_sec5
107
    URL baseURL = responseURLFromRequestURL(*jsGlobalObject, importerModuleKey);
111
    URL baseURL = responseURLFromRequestURL(*jsGlobalObject, importerModuleKey);
108
    RETURN_IF_EXCEPTION(scope, { });
112
    RETURN_IF_EXCEPTION(scope, { });
109
113
110
    auto result = resolveModuleSpecifier(m_document, specifier, baseURL);
114
    auto result = resolveModuleSpecifier(m_context, specifier, baseURL);
111
    if (!result) {
115
    if (!result) {
112
        JSC::throwTypeError(jsGlobalObject, scope, result.error());
116
        JSC::throwTypeError(jsGlobalObject, scope, result.error());
113
        return { };
117
        return { };
Lines 163-169 JSC::JSInternalPromise* ScriptModuleLoader::fetch(JSC::JSGlobalObject* jsGlobalO a/Source/WebCore/bindings/js/ScriptModuleLoader.cpp_sec6
163
167
164
    auto loader = CachedModuleScriptLoader::create(*this, deferred.get(), *static_cast<CachedScriptFetcher*>(JSC::jsCast<JSC::JSScriptFetcher*>(scriptFetcher)->fetcher()), WTFMove(topLevelFetchParameters));
168
    auto loader = CachedModuleScriptLoader::create(*this, deferred.get(), *static_cast<CachedScriptFetcher*>(JSC::jsCast<JSC::JSScriptFetcher*>(scriptFetcher)->fetcher()), WTFMove(topLevelFetchParameters));
165
    m_loaders.add(loader.copyRef());
169
    m_loaders.add(loader.copyRef());
166
    if (!loader->load(m_document, completedURL)) {
170
    if (!loader->load(m_context, completedURL)) {
167
        loader->clearClient();
171
        loader->clearClient();
168
        m_loaders.remove(WTFMove(loader));
172
        m_loaders.remove(WTFMove(loader));
169
        rejectToPropagateNetworkError(deferred.get(), ModuleFetchFailureKind::WasErrored, "Importing a module script failed."_s);
173
        rejectToPropagateNetworkError(deferred.get(), ModuleFetchFailureKind::WasErrored, "Importing a module script failed."_s);
Lines 176-182 JSC::JSInternalPromise* ScriptModuleLoader::fetch(JSC::JSGlobalObject* jsGlobalO a/Source/WebCore/bindings/js/ScriptModuleLoader.cpp_sec7
176
URL ScriptModuleLoader::moduleURL(JSC::JSGlobalObject& jsGlobalObject, JSC::JSValue moduleKeyValue)
180
URL ScriptModuleLoader::moduleURL(JSC::JSGlobalObject& jsGlobalObject, JSC::JSValue moduleKeyValue)
177
{
181
{
178
    if (moduleKeyValue.isSymbol())
182
    if (moduleKeyValue.isSymbol())
179
        return m_document.url();
183
        return m_context.url();
180
184
181
    ASSERT(moduleKeyValue.isString());
185
    ASSERT(moduleKeyValue.isString());
182
    return URL(URL(), asString(moduleKeyValue)->value(&jsGlobalObject));
186
    return URL(URL(), asString(moduleKeyValue)->value(&jsGlobalObject));
Lines 187-194 URL ScriptModuleLoader::responseURLFromRequestURL(JSC::JSGlobalObject& jsGlobalO a/Source/WebCore/bindings/js/ScriptModuleLoader.cpp_sec8
187
    JSC::VM& vm = jsGlobalObject.vm();
191
    JSC::VM& vm = jsGlobalObject.vm();
188
    auto scope = DECLARE_THROW_SCOPE(vm);
192
    auto scope = DECLARE_THROW_SCOPE(vm);
189
193
190
    if (isRootModule(moduleKeyValue))
194
    if (isRootModule(moduleKeyValue)) {
191
        return m_document.baseURL();
195
        if (is<Document>(m_context))
196
            return downcast<Document>(m_context).baseURL();
197
        return m_context.url();
198
    }
192
199
193
    ASSERT(!isRootModule(moduleKeyValue));
200
    ASSERT(!isRootModule(moduleKeyValue));
194
    ASSERT(moduleKeyValue.isString());
201
    ASSERT(moduleKeyValue.isString());
Lines 219-226 JSC::JSValue ScriptModuleLoader::evaluate(JSC::JSGlobalObject* jsGlobalObject, J a/Source/WebCore/bindings/js/ScriptModuleLoader.cpp_sec9
219
    if (!sourceURL.isValid())
226
    if (!sourceURL.isValid())
220
        return JSC::throwTypeError(jsGlobalObject, scope, "Module key is an invalid URL."_s);
227
        return JSC::throwTypeError(jsGlobalObject, scope, "Module key is an invalid URL."_s);
221
228
222
    if (auto* frame = m_document.frame())
229
    if (is<Document>(m_context)) {
223
        return frame->script().evaluateModule(sourceURL, *moduleRecord);
230
        if (auto* frame = downcast<Document>(m_context).frame())
231
            return frame->script().evaluateModule(sourceURL, *moduleRecord);
232
    } else {
233
        ASSERT(is<WorkerOrWorkletGlobalScope>(m_context));
234
        if (auto* script = downcast<WorkerOrWorkletGlobalScope>(m_context).script())
235
            return script->evaluateModule(*moduleRecord);
236
    }
224
    return JSC::jsUndefined();
237
    return JSC::jsUndefined();
225
}
238
}
226
239
Lines 248-270 JSC::JSInternalPromise* ScriptModuleLoader::importModule(JSC::JSGlobalObject* js a/Source/WebCore/bindings/js/ScriptModuleLoader.cpp_sec10
248
    URL baseURL;
261
    URL baseURL;
249
    RefPtr<JSC::ScriptFetcher> scriptFetcher;
262
    RefPtr<JSC::ScriptFetcher> scriptFetcher;
250
    if (sourceOrigin.isNull()) {
263
    if (sourceOrigin.isNull()) {
251
        baseURL = m_document.baseURL();
264
        String charset;
252
        scriptFetcher = CachedScriptFetcher::create(m_document.charset());
265
        if (is<Document>(m_context)) {
266
            baseURL = downcast<Document>(m_context).baseURL();
267
            charset = downcast<Document>(m_context).charset();
268
        } else {
269
            baseURL = m_context.url();
270
            charset = "utf-8"_s;
271
        }
272
        scriptFetcher = CachedScriptFetcher::create(WTFMove(charset));
253
    } else {
273
    } else {
254
        baseURL = URL(URL(), sourceOrigin.string());
274
        baseURL = URL(URL(), sourceOrigin.string());
255
        if (!baseURL.isValid())
275
        if (!baseURL.isValid())
256
            return rejectPromise(globalObject, TypeError, "Importer module key is not a Symbol or a String."_s);
276
            return rejectPromise(globalObject, TypeError, "Importer module key is not a Symbol or a String."_s);
257
277
278
        String charset;
279
        if (is<Document>(m_context))
280
            charset = downcast<Document>(m_context).charset();
281
        else
282
            charset = "utf-8"_s;
283
258
        if (sourceOrigin.fetcher())
284
        if (sourceOrigin.fetcher())
259
            scriptFetcher = sourceOrigin.fetcher();
285
            scriptFetcher = sourceOrigin.fetcher();
260
        else
286
        else
261
            scriptFetcher = CachedScriptFetcher::create(m_document.charset());
287
            scriptFetcher = CachedScriptFetcher::create(WTFMove(charset));
262
    }
288
    }
263
    ASSERT(baseURL.isValid());
289
    ASSERT(baseURL.isValid());
264
    ASSERT(scriptFetcher);
290
    ASSERT(scriptFetcher);
265
291
266
    auto specifier = moduleName->value(jsGlobalObject);
292
    auto specifier = moduleName->value(jsGlobalObject);
267
    auto result = resolveModuleSpecifier(m_document, specifier, baseURL);
293
    auto result = resolveModuleSpecifier(m_context, specifier, baseURL);
268
    if (!result)
294
    if (!result)
269
        return rejectPromise(globalObject, TypeError, result.error());
295
        return rejectPromise(globalObject, TypeError, result.error());
270
296
- a/Source/WebCore/bindings/js/ScriptModuleLoader.h -4 / +4 lines
Lines 45-60 class SourceOrigin; a/Source/WebCore/bindings/js/ScriptModuleLoader.h_sec1
45
45
46
namespace WebCore {
46
namespace WebCore {
47
47
48
class Document;
49
class JSDOMGlobalObject;
48
class JSDOMGlobalObject;
49
class ScriptExecutionContext;
50
50
51
class ScriptModuleLoader final : private CachedModuleScriptLoaderClient {
51
class ScriptModuleLoader final : private CachedModuleScriptLoaderClient {
52
    WTF_MAKE_NONCOPYABLE(ScriptModuleLoader); WTF_MAKE_FAST_ALLOCATED;
52
    WTF_MAKE_NONCOPYABLE(ScriptModuleLoader); WTF_MAKE_FAST_ALLOCATED;
53
public:
53
public:
54
    explicit ScriptModuleLoader(Document&);
54
    explicit ScriptModuleLoader(ScriptExecutionContext&);
55
    ~ScriptModuleLoader();
55
    ~ScriptModuleLoader();
56
56
57
    Document& document() { return m_document; }
57
    ScriptExecutionContext& context() { return m_context; }
58
58
59
    JSC::Identifier resolve(JSC::JSGlobalObject*, JSC::JSModuleLoader*, JSC::JSValue moduleName, JSC::JSValue importerModuleKey, JSC::JSValue scriptFetcher);
59
    JSC::Identifier resolve(JSC::JSGlobalObject*, JSC::JSModuleLoader*, JSC::JSValue moduleName, JSC::JSValue importerModuleKey, JSC::JSValue scriptFetcher);
60
    JSC::JSInternalPromise* fetch(JSC::JSGlobalObject*, JSC::JSModuleLoader*, JSC::JSValue moduleKey, JSC::JSValue parameters, JSC::JSValue scriptFetcher);
60
    JSC::JSInternalPromise* fetch(JSC::JSGlobalObject*, JSC::JSModuleLoader*, JSC::JSValue moduleKey, JSC::JSValue parameters, JSC::JSValue scriptFetcher);
Lines 67-73 class ScriptModuleLoader final : private CachedModuleScriptLoaderClient { a/Source/WebCore/bindings/js/ScriptModuleLoader.h_sec2
67
    URL moduleURL(JSC::JSGlobalObject&, JSC::JSValue);
67
    URL moduleURL(JSC::JSGlobalObject&, JSC::JSValue);
68
    URL responseURLFromRequestURL(JSC::JSGlobalObject&, JSC::JSValue);
68
    URL responseURLFromRequestURL(JSC::JSGlobalObject&, JSC::JSValue);
69
69
70
    Document& m_document;
70
    ScriptExecutionContext& m_context;
71
    HashMap<String, URL> m_requestURLToResponseURLMap;
71
    HashMap<String, URL> m_requestURLToResponseURLMap;
72
    HashSet<Ref<CachedModuleScriptLoader>> m_loaders;
72
    HashSet<Ref<CachedModuleScriptLoader>> m_loaders;
73
};
73
};
- a/Source/WebCore/dom/LoadableModuleScript.cpp -12 lines
Lines 88-103 void LoadableModuleScript::execute(ScriptElement& scriptElement) a/Source/WebCore/dom/LoadableModuleScript.cpp_sec1
88
    scriptElement.executeModuleScript(*this);
88
    scriptElement.executeModuleScript(*this);
89
}
89
}
90
90
91
void LoadableModuleScript::load(Document& document, const URL& rootURL)
92
{
93
    if (auto* frame = document.frame())
94
        frame->script().loadModuleScript(*this, rootURL.string(), m_parameters.copyRef());
95
}
96
97
void LoadableModuleScript::load(Document& document, const ScriptSourceCode& sourceCode)
98
{
99
    if (auto* frame = document.frame())
100
        frame->script().loadModuleScript(*this, sourceCode);
101
}
102
103
}
91
}
- a/Source/WebCore/dom/LoadableModuleScript.h -3 / +2 lines
Lines 50-64 class LoadableModuleScript final : public LoadableScript { a/Source/WebCore/dom/LoadableModuleScript.h_sec1
50
50
51
    void setError(Error&&);
51
    void setError(Error&&);
52
52
53
    void load(Document&, const URL& rootURL);
54
    void load(Document&, const ScriptSourceCode&);
55
56
    void notifyLoadCompleted(UniquedStringImpl&);
53
    void notifyLoadCompleted(UniquedStringImpl&);
57
    void notifyLoadFailed(LoadableScript::Error&&);
54
    void notifyLoadFailed(LoadableScript::Error&&);
58
    void notifyLoadWasCanceled();
55
    void notifyLoadWasCanceled();
59
56
60
    UniquedStringImpl* moduleKey() const { return m_moduleKey.get(); }
57
    UniquedStringImpl* moduleKey() const { return m_moduleKey.get(); }
61
58
59
    ModuleFetchParameters& parameters() { return m_parameters.get(); }
60
62
private:
61
private:
63
    LoadableModuleScript(const String& nonce, const String& integrity, ReferrerPolicy, const String& crossOriginMode, const String& charset, const AtomString& initiatorName, bool isInUserAgentShadowTree);
62
    LoadableModuleScript(const String& nonce, const String& integrity, ReferrerPolicy, const String& crossOriginMode, const String& charset, const AtomString& initiatorName, bool isInUserAgentShadowTree);
64
63
- a/Source/WebCore/dom/ScriptElement.cpp -2 / +7 lines
Lines 42-47 a/Source/WebCore/dom/ScriptElement.cpp_sec1
42
#include "LoadableClassicScript.h"
42
#include "LoadableClassicScript.h"
43
#include "LoadableModuleScript.h"
43
#include "LoadableModuleScript.h"
44
#include "MIMETypeRegistry.h"
44
#include "MIMETypeRegistry.h"
45
#include "ModuleFetchParameters.h"
45
#include "PendingScript.h"
46
#include "PendingScript.h"
46
#include "RuntimeApplicationChecks.h"
47
#include "RuntimeApplicationChecks.h"
47
#include "SVGScriptElement.h"
48
#include "SVGScriptElement.h"
Lines 351-358 bool ScriptElement::requestModuleScript(const TextPosition& scriptStartPosition) a/Source/WebCore/dom/ScriptElement.cpp_sec2
351
            scriptCharset(),
352
            scriptCharset(),
352
            m_element.localName(),
353
            m_element.localName(),
353
            m_element.isInUserAgentShadowTree());
354
            m_element.isInUserAgentShadowTree());
354
        script->load(m_element.document(), moduleScriptRootURL);
355
        m_loadableScript = WTFMove(script);
355
        m_loadableScript = WTFMove(script);
356
        if (auto* frame = m_element.document().frame()) {
357
            auto& script = downcast<LoadableModuleScript>(*m_loadableScript.get());
358
            frame->script().loadModuleScript(script, moduleScriptRootURL.string(), makeRef(script.parameters()));
359
        }
356
        return true;
360
        return true;
357
    }
361
    }
358
362
Lines 367-374 bool ScriptElement::requestModuleScript(const TextPosition& scriptStartPosition) a/Source/WebCore/dom/ScriptElement.cpp_sec3
367
    if (!contentSecurityPolicy.allowInlineScript(m_element.document().url().string(), m_startLineNumber, sourceCode.source().toStringWithoutCopying(), hasKnownNonce))
371
    if (!contentSecurityPolicy.allowInlineScript(m_element.document().url().string(), m_startLineNumber, sourceCode.source().toStringWithoutCopying(), hasKnownNonce))
368
        return false;
372
        return false;
369
373
370
    script->load(m_element.document(), sourceCode);
371
    m_loadableScript = WTFMove(script);
374
    m_loadableScript = WTFMove(script);
375
    if (auto* frame = m_element.document().frame())
376
        frame->script().loadModuleScript(downcast<LoadableModuleScript>(*m_loadableScript.get()), sourceCode);
372
    return true;
377
    return true;
373
}
378
}
374
379
- a/Source/WebCore/dom/ScriptElementCachedScriptFetcher.cpp -2 / +2 lines
Lines 33-45 namespace WebCore { a/Source/WebCore/dom/ScriptElementCachedScriptFetcher.cpp_sec1
33
33
34
const ASCIILiteral ScriptElementCachedScriptFetcher::defaultCrossOriginModeForModule { "anonymous"_s };
34
const ASCIILiteral ScriptElementCachedScriptFetcher::defaultCrossOriginModeForModule { "anonymous"_s };
35
35
36
CachedResourceHandle<CachedScript> ScriptElementCachedScriptFetcher::requestModuleScript(Document& document, const URL& sourceURL, String&& integrity) const
36
CachedResourceHandle<CachedScript> ScriptElementCachedScriptFetcher::requestModuleScript(ScriptExecutionContext& context, const URL& sourceURL, String&& integrity) const
37
{
37
{
38
    // https://html.spec.whatwg.org/multipage/urls-and-fetching.html#cors-settings-attributes
38
    // https://html.spec.whatwg.org/multipage/urls-and-fetching.html#cors-settings-attributes
39
    // If the fetcher is not module script, credential mode is always "same-origin" ("anonymous").
39
    // If the fetcher is not module script, credential mode is always "same-origin" ("anonymous").
40
    // This code is for dynamic module import (`import` operator).
40
    // This code is for dynamic module import (`import` operator).
41
41
42
    return requestScriptWithCache(document, sourceURL, isClassicScript() ? defaultCrossOriginModeForModule : m_crossOriginMode, WTFMove(integrity), { });
42
    return requestScriptWithCache(context, sourceURL, isClassicScript() ? defaultCrossOriginModeForModule : m_crossOriginMode, WTFMove(integrity), { });
43
}
43
}
44
44
45
}
45
}
- a/Source/WebCore/dom/ScriptElementCachedScriptFetcher.h -1 / +1 lines
Lines 33-39 class ScriptElementCachedScriptFetcher : public CachedScriptFetcher { a/Source/WebCore/dom/ScriptElementCachedScriptFetcher.h_sec1
33
public:
33
public:
34
    static const ASCIILiteral defaultCrossOriginModeForModule;
34
    static const ASCIILiteral defaultCrossOriginModeForModule;
35
35
36
    virtual CachedResourceHandle<CachedScript> requestModuleScript(Document&, const URL& sourceURL, String&& integrity) const;
36
    virtual CachedResourceHandle<CachedScript> requestModuleScript(ScriptExecutionContext&, const URL& sourceURL, String&& integrity) const;
37
37
38
    virtual bool isClassicScript() const = 0;
38
    virtual bool isClassicScript() const = 0;
39
    virtual bool isModuleScript() const = 0;
39
    virtual bool isModuleScript() const = 0;
- a/Source/WebCore/workers/Worker.cpp -2 / +7 lines
Lines 70-75 inline Worker::Worker(ScriptExecutionContext& context, JSC::RuntimeFlags runtime a/Source/WebCore/workers/Worker.cpp_sec1
70
    , m_identifier("worker:" + Inspector::IdentifiersFactory::createIdentifier())
70
    , m_identifier("worker:" + Inspector::IdentifiersFactory::createIdentifier())
71
    , m_contextProxy(WorkerGlobalScopeProxy::create(*this))
71
    , m_contextProxy(WorkerGlobalScopeProxy::create(*this))
72
    , m_runtimeFlags(runtimeFlags)
72
    , m_runtimeFlags(runtimeFlags)
73
    , m_type(options.type)
74
    , m_credentials(options.credentials)
73
{
75
{
74
    static bool addedListener;
76
    static bool addedListener;
75
    if (!addedListener) {
77
    if (!addedListener) {
Lines 113-122 ExceptionOr<Ref<Worker>> Worker::create(ScriptExecutionContext& context, JSC::Ru a/Source/WebCore/workers/Worker.cpp_sec2
113
115
114
    FetchOptions fetchOptions;
116
    FetchOptions fetchOptions;
115
    fetchOptions.mode = FetchOptions::Mode::SameOrigin;
117
    fetchOptions.mode = FetchOptions::Mode::SameOrigin;
118
    if (worker->m_type == WorkerType::Module)
119
        fetchOptions.credentials = worker->m_credentials;
116
    fetchOptions.cache = FetchOptions::Cache::Default;
120
    fetchOptions.cache = FetchOptions::Cache::Default;
117
    fetchOptions.redirect = FetchOptions::Redirect::Follow;
121
    fetchOptions.redirect = FetchOptions::Redirect::Follow;
118
    fetchOptions.destination = FetchOptions::Destination::Worker;
122
    fetchOptions.destination = FetchOptions::Destination::Worker;
119
    worker->m_scriptLoader->loadAsynchronously(context, WTFMove(request), WTFMove(fetchOptions), contentSecurityPolicyEnforcement, ServiceWorkersMode::All, worker);
123
    worker->m_scriptLoader->loadAsynchronously(context, WTFMove(request), WTFMove(fetchOptions), contentSecurityPolicyEnforcement, ServiceWorkersMode::All, worker.get());
124
120
    return worker;
125
    return worker;
121
}
126
}
122
127
Lines 215-221 void Worker::notifyFinished() a/Source/WebCore/workers/Worker.cpp_sec3
215
    ReferrerPolicy referrerPolicy = ReferrerPolicy::EmptyString;
220
    ReferrerPolicy referrerPolicy = ReferrerPolicy::EmptyString;
216
    if (auto policy = parseReferrerPolicy(m_scriptLoader->referrerPolicy(), ReferrerPolicySource::HTTPHeader))
221
    if (auto policy = parseReferrerPolicy(m_scriptLoader->referrerPolicy(), ReferrerPolicySource::HTTPHeader))
217
        referrerPolicy = *policy;
222
        referrerPolicy = *policy;
218
    m_contextProxy.startWorkerGlobalScope(m_scriptLoader->url(), m_name, context->userAgent(m_scriptLoader->url()), isOnline, m_scriptLoader->script(), contentSecurityPolicyResponseHeaders, m_shouldBypassMainWorldContentSecurityPolicy, m_workerCreationTime, referrerPolicy, m_runtimeFlags);
223
    m_contextProxy.startWorkerGlobalScope(m_scriptLoader->url(), m_name, context->userAgent(m_scriptLoader->url()), isOnline, m_scriptLoader->script(), contentSecurityPolicyResponseHeaders, m_shouldBypassMainWorldContentSecurityPolicy, m_workerCreationTime, referrerPolicy, m_type, m_credentials, m_runtimeFlags);
219
    InspectorInstrumentation::scriptImported(*context, m_scriptLoader->identifier(), m_scriptLoader->script());
224
    InspectorInstrumentation::scriptImported(*context, m_scriptLoader->identifier(), m_scriptLoader->script());
220
}
225
}
221
226
- a/Source/WebCore/workers/Worker.h +8 lines
Lines 29-37 a/Source/WebCore/workers/Worker.h_sec1
29
#include "ActiveDOMObject.h"
29
#include "ActiveDOMObject.h"
30
#include "ContentSecurityPolicyResponseHeaders.h"
30
#include "ContentSecurityPolicyResponseHeaders.h"
31
#include "EventTarget.h"
31
#include "EventTarget.h"
32
#include "FetchRequestCredentials.h"
32
#include "MessagePort.h"
33
#include "MessagePort.h"
33
#include "PostMessageOptions.h"
34
#include "PostMessageOptions.h"
34
#include "WorkerScriptLoaderClient.h"
35
#include "WorkerScriptLoaderClient.h"
36
#include "WorkerType.h"
35
#include <JavaScriptCore/RuntimeFlags.h>
37
#include <JavaScriptCore/RuntimeFlags.h>
36
#include <wtf/MonotonicTime.h>
38
#include <wtf/MonotonicTime.h>
37
#include <wtf/Optional.h>
39
#include <wtf/Optional.h>
Lines 55-60 class Worker final : public AbstractWorker, public ActiveDOMObject, private Work a/Source/WebCore/workers/Worker.h_sec2
55
    WTF_MAKE_ISO_ALLOCATED(Worker);
57
    WTF_MAKE_ISO_ALLOCATED(Worker);
56
public:
58
public:
57
    struct Options {
59
    struct Options {
60
        WorkerType type;
61
        FetchRequestCredentials credentials;
58
        String name;
62
        String name;
59
    };
63
    };
60
    static ExceptionOr<Ref<Worker>> create(ScriptExecutionContext&, JSC::RuntimeFlags, const String& url, const Options&);
64
    static ExceptionOr<Ref<Worker>> create(ScriptExecutionContext&, JSC::RuntimeFlags, const String& url, const Options&);
Lines 79-84 class Worker final : public AbstractWorker, public ActiveDOMObject, private Work a/Source/WebCore/workers/Worker.h_sec3
79
    void postTaskToWorkerGlobalScope(Function<void(ScriptExecutionContext&)>&&);
83
    void postTaskToWorkerGlobalScope(Function<void(ScriptExecutionContext&)>&&);
80
#endif
84
#endif
81
85
86
    WorkerType type() const { return m_type; }
87
82
private:
88
private:
83
    explicit Worker(ScriptExecutionContext&, JSC::RuntimeFlags, const Options&);
89
    explicit Worker(ScriptExecutionContext&, JSC::RuntimeFlags, const Options&);
84
90
Lines 112-117 class Worker final : public AbstractWorker, public ActiveDOMObject, private Work a/Source/WebCore/workers/Worker.h_sec4
112
#if ENABLE(WEB_RTC)
118
#if ENABLE(WEB_RTC)
113
    HashSet<String> m_transformers;
119
    HashSet<String> m_transformers;
114
#endif
120
#endif
121
    WorkerType m_type { WorkerType::Classic };
122
    FetchRequestCredentials m_credentials { FetchRequestCredentials::SameOrigin };
115
};
123
};
116
124
117
} // namespace WebCore
125
} // namespace WebCore
- a/Source/WebCore/workers/Worker.idl +2 lines
Lines 38-43 a/Source/WebCore/workers/Worker.idl_sec1
38
};
38
};
39
39
40
dictionary WorkerOptions {
40
dictionary WorkerOptions {
41
    WorkerType type = "classic";
42
    FetchRequestCredentials credentials = "same-origin"; // credentials is only used if type is "module"
41
    DOMString name = "";
43
    DOMString name = "";
42
};
44
};
43
45
- a/Source/WebCore/workers/WorkerGlobalScope.h -2 lines
Lines 163-170 class WorkerGlobalScope : public Supplementable<WorkerGlobalScope>, public Base6 a/Source/WebCore/workers/WorkerGlobalScope.h_sec1
163
    mutable RefPtr<WorkerLocation> m_location;
163
    mutable RefPtr<WorkerLocation> m_location;
164
    mutable RefPtr<WorkerNavigator> m_navigator;
164
    mutable RefPtr<WorkerNavigator> m_navigator;
165
165
166
    std::unique_ptr<WorkerOrWorkletScriptController> m_script;
167
168
    bool m_isOnline;
166
    bool m_isOnline;
169
    bool m_shouldBypassMainWorldContentSecurityPolicy;
167
    bool m_shouldBypassMainWorldContentSecurityPolicy;
170
168
- a/Source/WebCore/workers/WorkerGlobalScopeProxy.h -1 / +1 lines
Lines 48-54 class WorkerGlobalScopeProxy { a/Source/WebCore/workers/WorkerGlobalScopeProxy.h_sec1
48
public:
48
public:
49
    static WorkerGlobalScopeProxy& create(Worker&);
49
    static WorkerGlobalScopeProxy& create(Worker&);
50
50
51
    virtual void startWorkerGlobalScope(const URL& scriptURL, const String& name, const String& userAgent, bool isOnline, const String& sourceCode, const ContentSecurityPolicyResponseHeaders&, bool shouldBypassMainWorldContentSecurityPolicy, MonotonicTime timeOrigin, ReferrerPolicy, JSC::RuntimeFlags) = 0;
51
    virtual void startWorkerGlobalScope(const URL& scriptURL, const String& name, const String& userAgent, bool isOnline, const String& sourceCode, const ContentSecurityPolicyResponseHeaders&, bool shouldBypassMainWorldContentSecurityPolicy, MonotonicTime timeOrigin, ReferrerPolicy, WorkerType workerType, FetchRequestCredentials credentials, JSC::RuntimeFlags) = 0;
52
    virtual void terminateWorkerGlobalScope() = 0;
52
    virtual void terminateWorkerGlobalScope() = 0;
53
    virtual void postMessageToWorkerGlobalScope(MessageWithMessagePorts&&) = 0;
53
    virtual void postMessageToWorkerGlobalScope(MessageWithMessagePorts&&) = 0;
54
    virtual void postTaskToWorkerGlobalScope(Function<void(ScriptExecutionContext&)>&&) = 0;
54
    virtual void postTaskToWorkerGlobalScope(Function<void(ScriptExecutionContext&)>&&) = 0;
- a/Source/WebCore/workers/WorkerMessagingProxy.cpp -2 / +2 lines
Lines 73-79 WorkerMessagingProxy::~WorkerMessagingProxy() a/Source/WebCore/workers/WorkerMessagingProxy.cpp_sec1
73
        || (is<WorkerGlobalScope>(*m_scriptExecutionContext) && downcast<WorkerGlobalScope>(*m_scriptExecutionContext).thread().thread() == &Thread::current()));
73
        || (is<WorkerGlobalScope>(*m_scriptExecutionContext) && downcast<WorkerGlobalScope>(*m_scriptExecutionContext).thread().thread() == &Thread::current()));
74
}
74
}
75
75
76
void WorkerMessagingProxy::startWorkerGlobalScope(const URL& scriptURL, const String& name, const String& userAgent, bool isOnline, const String& sourceCode, const ContentSecurityPolicyResponseHeaders& contentSecurityPolicyResponseHeaders, bool shouldBypassMainWorldContentSecurityPolicy, MonotonicTime timeOrigin, ReferrerPolicy referrerPolicy, JSC::RuntimeFlags runtimeFlags)
76
void WorkerMessagingProxy::startWorkerGlobalScope(const URL& scriptURL, const String& name, const String& userAgent, bool isOnline, const String& sourceCode, const ContentSecurityPolicyResponseHeaders& contentSecurityPolicyResponseHeaders, bool shouldBypassMainWorldContentSecurityPolicy, MonotonicTime timeOrigin, ReferrerPolicy referrerPolicy, WorkerType workerType, FetchRequestCredentials credentials, JSC::RuntimeFlags runtimeFlags)
77
{
77
{
78
    // FIXME: This need to be revisited when we support nested worker one day
78
    // FIXME: This need to be revisited when we support nested worker one day
79
    ASSERT(m_scriptExecutionContext);
79
    ASSERT(m_scriptExecutionContext);
Lines 89-95 void WorkerMessagingProxy::startWorkerGlobalScope(const URL& scriptURL, const St a/Source/WebCore/workers/WorkerMessagingProxy.cpp_sec2
89
89
90
    SocketProvider* socketProvider = document.socketProvider();
90
    SocketProvider* socketProvider = document.socketProvider();
91
91
92
    WorkerParameters params = { scriptURL, name, identifier, userAgent, isOnline, contentSecurityPolicyResponseHeaders, shouldBypassMainWorldContentSecurityPolicy, timeOrigin, referrerPolicy, document.settingsValues() };
92
    WorkerParameters params = { scriptURL, name, identifier, userAgent, isOnline, contentSecurityPolicyResponseHeaders, shouldBypassMainWorldContentSecurityPolicy, timeOrigin, referrerPolicy, workerType, credentials, document.settingsValues() };
93
    auto thread = DedicatedWorkerThread::create(params, sourceCode, *this, *this, *this, startMode, document.topOrigin(), proxy, socketProvider, runtimeFlags);
93
    auto thread = DedicatedWorkerThread::create(params, sourceCode, *this, *this, *this, startMode, document.topOrigin(), proxy, socketProvider, runtimeFlags);
94
94
95
    workerThreadCreated(thread.get());
95
    workerThreadCreated(thread.get());
- a/Source/WebCore/workers/WorkerMessagingProxy.h -1 / +1 lines
Lines 50-56 class WorkerMessagingProxy final : public ThreadSafeRefCounted<WorkerMessagingPr a/Source/WebCore/workers/WorkerMessagingProxy.h_sec1
50
private:
50
private:
51
    // Implementations of WorkerGlobalScopeProxy.
51
    // Implementations of WorkerGlobalScopeProxy.
52
    // (Only use these functions in the worker object thread.)
52
    // (Only use these functions in the worker object thread.)
53
    void startWorkerGlobalScope(const URL& scriptURL, const String& name, const String& userAgent, bool isOnline, const String& sourceCode, const ContentSecurityPolicyResponseHeaders&, bool shouldBypassMainWorldContentSecurityPolicy, MonotonicTime timeOrigin, ReferrerPolicy, JSC::RuntimeFlags) final;
53
    void startWorkerGlobalScope(const URL& scriptURL, const String& name, const String& userAgent, bool isOnline, const String& sourceCode, const ContentSecurityPolicyResponseHeaders&, bool shouldBypassMainWorldContentSecurityPolicy, MonotonicTime timeOrigin, ReferrerPolicy, WorkerType workerType, FetchRequestCredentials credentials, JSC::RuntimeFlags) final;
54
    void terminateWorkerGlobalScope() final;
54
    void terminateWorkerGlobalScope() final;
55
    void postMessageToWorkerGlobalScope(MessageWithMessagePorts&&) final;
55
    void postMessageToWorkerGlobalScope(MessageWithMessagePorts&&) final;
56
    void postTaskToWorkerGlobalScope(Function<void(ScriptExecutionContext&)>&&) final;
56
    void postTaskToWorkerGlobalScope(Function<void(ScriptExecutionContext&)>&&) final;
- a/Source/WebCore/workers/WorkerOrWorkletGlobalScope.cpp +2 lines
Lines 26-31 a/Source/WebCore/workers/WorkerOrWorkletGlobalScope.cpp_sec1
26
#include "config.h"
26
#include "config.h"
27
#include "WorkerOrWorkletGlobalScope.h"
27
#include "WorkerOrWorkletGlobalScope.h"
28
28
29
#include "ScriptModuleLoader.h"
29
#include "WorkerEventLoop.h"
30
#include "WorkerEventLoop.h"
30
#include "WorkerInspectorController.h"
31
#include "WorkerInspectorController.h"
31
#include "WorkerOrWorkletScriptController.h"
32
#include "WorkerOrWorkletScriptController.h"
Lines 39-44 WTF_MAKE_ISO_ALLOCATED_IMPL(WorkerOrWorkletGlobalScope); a/Source/WebCore/workers/WorkerOrWorkletGlobalScope.cpp_sec2
39
40
40
WorkerOrWorkletGlobalScope::WorkerOrWorkletGlobalScope(WorkerThreadType type, Ref<JSC::VM>&& vm, WorkerOrWorkletThread* thread)
41
WorkerOrWorkletGlobalScope::WorkerOrWorkletGlobalScope(WorkerThreadType type, Ref<JSC::VM>&& vm, WorkerOrWorkletThread* thread)
41
    : m_script(makeUnique<WorkerOrWorkletScriptController>(type, WTFMove(vm), this))
42
    : m_script(makeUnique<WorkerOrWorkletScriptController>(type, WTFMove(vm), this))
43
    , m_moduleLoader(makeUnique<ScriptModuleLoader>(*this))
42
    , m_thread(thread)
44
    , m_thread(thread)
43
    , m_inspectorController(makeUnique<WorkerInspectorController>(*this))
45
    , m_inspectorController(makeUnique<WorkerInspectorController>(*this))
44
{
46
{
- a/Source/WebCore/workers/WorkerOrWorkletGlobalScope.h +4 lines
Lines 32-37 a/Source/WebCore/workers/WorkerOrWorkletGlobalScope.h_sec1
32
namespace WebCore {
32
namespace WebCore {
33
33
34
class EventLoopTaskGroup;
34
class EventLoopTaskGroup;
35
class ScriptModuleLoader;
35
class WorkerEventLoop;
36
class WorkerEventLoop;
36
class WorkerInspectorController;
37
class WorkerInspectorController;
37
class WorkerOrWorkletScriptController;
38
class WorkerOrWorkletScriptController;
Lines 54-59 class WorkerOrWorkletGlobalScope : public ScriptExecutionContext, public RefCoun a/Source/WebCore/workers/WorkerOrWorkletGlobalScope.h_sec2
54
55
55
    unsigned long createUniqueIdentifier() { return m_uniqueIdentifier++; }
56
    unsigned long createUniqueIdentifier() { return m_uniqueIdentifier++; }
56
57
58
    ScriptModuleLoader& moduleLoader() { return *m_moduleLoader; }
59
57
    // ScriptExecutionContext.
60
    // ScriptExecutionContext.
58
    EventLoopTaskGroup& eventLoop() final;
61
    EventLoopTaskGroup& eventLoop() final;
59
    bool isContextThread() const final;
62
    bool isContextThread() const final;
Lines 88-93 class WorkerOrWorkletGlobalScope : public ScriptExecutionContext, public RefCoun a/Source/WebCore/workers/WorkerOrWorkletGlobalScope.h_sec3
88
    void derefEventTarget() final { deref(); }
91
    void derefEventTarget() final { deref(); }
89
92
90
    std::unique_ptr<WorkerOrWorkletScriptController> m_script;
93
    std::unique_ptr<WorkerOrWorkletScriptController> m_script;
94
    std::unique_ptr<ScriptModuleLoader> m_moduleLoader;
91
    WorkerOrWorkletThread* m_thread;
95
    WorkerOrWorkletThread* m_thread;
92
    RefPtr<WorkerEventLoop> m_eventLoop;
96
    RefPtr<WorkerEventLoop> m_eventLoop;
93
    std::unique_ptr<EventLoopTaskGroup> m_defaultTaskGroup;
97
    std::unique_ptr<EventLoopTaskGroup> m_defaultTaskGroup;
- a/Source/WebCore/workers/WorkerOrWorkletScriptController.cpp -1 / +158 lines
Lines 35-40 a/Source/WebCore/workers/WorkerOrWorkletScriptController.cpp_sec1
35
#include "JSExecState.h"
35
#include "JSExecState.h"
36
#include "JSPaintWorkletGlobalScope.h"
36
#include "JSPaintWorkletGlobalScope.h"
37
#include "JSServiceWorkerGlobalScope.h"
37
#include "JSServiceWorkerGlobalScope.h"
38
#include "LoadableModuleScript.h"
39
#include "ModuleFetchFailureKind.h"
40
#include "ModuleFetchParameters.h"
38
#include "ScriptSourceCode.h"
41
#include "ScriptSourceCode.h"
39
#include "WebCoreJSClientData.h"
42
#include "WebCoreJSClientData.h"
40
#include "WorkerConsoleClient.h"
43
#include "WorkerConsoleClient.h"
Lines 43-49 a/Source/WebCore/workers/WorkerOrWorkletScriptController.cpp_sec2
43
#include <JavaScriptCore/Exception.h>
46
#include <JavaScriptCore/Exception.h>
44
#include <JavaScriptCore/ExceptionHelpers.h>
47
#include <JavaScriptCore/ExceptionHelpers.h>
45
#include <JavaScriptCore/GCActivityCallback.h>
48
#include <JavaScriptCore/GCActivityCallback.h>
49
#include <JavaScriptCore/JSInternalPromise.h>
46
#include <JavaScriptCore/JSLock.h>
50
#include <JavaScriptCore/JSLock.h>
51
#include <JavaScriptCore/JSModuleRecord.h>
52
#include <JavaScriptCore/JSNativeStdFunction.h>
53
#include <JavaScriptCore/JSScriptFetchParameters.h>
54
#include <JavaScriptCore/JSScriptFetcher.h>
47
#include <JavaScriptCore/StrongInlines.h>
55
#include <JavaScriptCore/StrongInlines.h>
48
56
49
namespace WebCore {
57
namespace WebCore {
Lines 228-234 void WorkerOrWorkletScriptController::evaluate(const ScriptSourceCode& sourceCod a/Source/WebCore/workers/WorkerOrWorkletScriptController.cpp_sec3
228
    }
236
    }
229
}
237
}
230
238
231
template<typename JSGlobalScopePrototype, typename JSGlobalScope, typename GlobalScope>
239
static Identifier jsValueToModuleKey(JSGlobalObject* lexicalGlobalObject, JSValue value)
240
{
241
    if (value.isSymbol())
242
        return Identifier::fromUid(jsCast<Symbol*>(value)->privateName());
243
    ASSERT(value.isString());
244
    return asString(value)->toIdentifier(lexicalGlobalObject);
245
}
246
247
JSC::JSValue WorkerOrWorkletScriptController::evaluateModule(JSC::JSModuleRecord& moduleRecord)
248
{
249
    auto& globalObject = *m_globalScopeWrapper.get();
250
    VM& vm = globalObject.vm();
251
    JSLockHolder lock { vm };
252
    return moduleRecord.evaluate(&globalObject);
253
}
254
255
static void driveRunLoop(JSGlobalObject* globalObject)
256
{
257
    VM& vm = globalObject->vm();
258
    if (globalObject->inherits<JSWorkerGlobalScopeBase>(vm)) {
259
        jsCast<const JSWorkerGlobalScopeBase*>(globalObject)->wrapped().postTask([](ScriptExecutionContext&){});
260
        return;
261
    }
262
    if (globalObject->inherits<JSWorkletGlobalScopeBase>(vm)) {
263
        jsCast<const JSWorkletGlobalScopeBase*>(globalObject)->wrapped().postTask([](ScriptExecutionContext&){});
264
        return;
265
    }
266
}
267
268
MessageQueueWaitResult WorkerOrWorkletScriptController::loadModuleSynchronously(LoadableModuleScript& moduleScript, const ScriptSourceCode& sourceCode)
269
{
270
    if (isExecutionForbidden())
271
        return MessageQueueTerminated;
272
273
    initScriptIfNeeded();
274
275
    auto& globalObject = *m_globalScopeWrapper.get();
276
    VM& vm = globalObject.vm();
277
    JSLockHolder lock { vm };
278
279
    RefPtr<LoadableModuleScript> moduleScriptRef;
280
    {
281
        auto& promise = JSExecState::loadModule(globalObject, sourceCode.jsSourceCode(), JSC::JSScriptFetcher::create(vm, { &moduleScript }));
282
283
        moduleScriptRef = &moduleScript;
284
285
        auto& fulfillHandler = *JSNativeStdFunction::create(vm, &globalObject, 1, String(), [moduleScriptRef](JSGlobalObject* globalObject, CallFrame* callFrame) -> JSC::EncodedJSValue {
286
            driveRunLoop(globalObject);
287
            WTFReportBacktrace();
288
            VM& vm = globalObject->vm();
289
            auto scope = DECLARE_THROW_SCOPE(vm);
290
            Identifier moduleKey = jsValueToModuleKey(globalObject, callFrame->argument(0));
291
            RETURN_IF_EXCEPTION(scope, { });
292
            moduleScriptRef->notifyLoadCompleted(*moduleKey.impl());
293
            return JSValue::encode(jsUndefined());
294
        });
295
296
        auto& rejectHandler = *JSNativeStdFunction::create(vm, &globalObject, 1, String(), [moduleScriptRef](JSGlobalObject* globalObject, CallFrame* callFrame) {
297
            driveRunLoop(globalObject);
298
            WTFReportBacktrace();
299
            VM& vm = globalObject->vm();
300
            JSValue errorValue = callFrame->argument(0);
301
            if (errorValue.isObject()) {
302
                auto* object = JSC::asObject(errorValue);
303
                if (JSValue failureKindValue = object->getDirect(vm, static_cast<JSVMClientData&>(*vm.clientData).builtinNames().failureKindPrivateName())) {
304
                    // This is host propagated error in the module loader pipeline.
305
                    switch (static_cast<ModuleFetchFailureKind>(failureKindValue.asInt32())) {
306
                    case ModuleFetchFailureKind::WasErrored:
307
                        moduleScriptRef->notifyLoadFailed(LoadableScript::Error {
308
                            LoadableScript::ErrorType::CachedScript,
309
                            WTF::nullopt
310
                        });
311
                        break;
312
                    case ModuleFetchFailureKind::WasCanceled:
313
                        moduleScriptRef->notifyLoadWasCanceled();
314
                        break;
315
                    }
316
                    return JSValue::encode(jsUndefined());
317
                }
318
            }
319
320
            auto scope = DECLARE_CATCH_SCOPE(vm);
321
            moduleScriptRef->notifyLoadFailed(LoadableScript::Error {
322
                LoadableScript::ErrorType::CachedScript,
323
                LoadableScript::ConsoleMessage {
324
                    MessageSource::JS,
325
                    MessageLevel::Error,
326
                    retrieveErrorMessage(*globalObject, vm, errorValue, scope),
327
                }
328
            });
329
            return JSValue::encode(jsUndefined());
330
        });
331
332
        dataLogLn("STATUS ", static_cast<int>(promise.status(vm)));
333
        promise.then(&globalObject, &fulfillHandler, &rejectHandler);
334
    }
335
    m_globalScope->eventLoop().performMicrotaskCheckpoint();
336
337
    // Drive RunLoop until we get either of "Worker is terminated", "Loading is done", or "Loading is failed".
338
    WorkerRunLoop& runLoop = m_globalScope->workerOrWorkletThread()->runLoop();
339
    String mode = makeString("loadModuleSynchronously", runLoop.createUniqueId());
340
341
    dataLogLn("RUNLOOP ", static_cast<int>(moduleScriptRef->isLoaded()), " ", static_cast<int>(moduleScriptRef->wasCanceled()));
342
    MessageQueueWaitResult result = MessageQueueMessageReceived;
343
    while ((!moduleScriptRef->isLoaded() && !moduleScriptRef->wasCanceled()) && result != MessageQueueTerminated) {
344
        result = runLoop.runInMode(m_globalScope, mode);
345
    }
346
347
    // FIXME: Currently we are not offering cancelling.
348
    // if (!loader->done() && result == MessageQueueTerminated)
349
    //     loader->cancel();
350
351
    return result;
352
}
353
354
void WorkerOrWorkletScriptController::linkAndEvaluateModule(LoadableModuleScript& moduleScript, const ScriptSourceCode& sourceCode, String* returnedExceptionMessage)
355
{
356
    if (isExecutionForbidden())
357
        return;
358
359
    initScriptIfNeeded();
360
361
    auto& globalObject = *m_globalScopeWrapper.get();
362
    VM& vm = globalObject.vm();
363
    JSLockHolder lock { vm };
364
365
    NakedPtr<JSC::Exception> returnedException;
366
    JSExecState::linkAndEvaluateModule(globalObject, Identifier::fromUid(vm, moduleScript.moduleKey()), jsUndefined(), returnedException);
367
    if ((returnedException && isTerminatedExecutionException(vm, returnedException)) || isTerminatingExecution()) {
368
        forbidExecution();
369
        return;
370
    }
371
372
    if (returnedException) {
373
        if (m_globalScope->canIncludeErrorDetails(sourceCode.cachedScript(), sourceCode.url().string())) {
374
            // FIXME: It's not great that this can run arbitrary code to string-ify the value of the exception.
375
            // Do we need to do anything to handle that properly, if it, say, raises another exception?
376
            if (returnedExceptionMessage)
377
                *returnedExceptionMessage = returnedException->value().toWTFString(&globalObject);
378
        } else {
379
            // Overwrite the detailed error with a generic error.
380
            String genericErrorMessage { "Script error."_s };
381
            if (returnedExceptionMessage)
382
                *returnedExceptionMessage = genericErrorMessage;
383
            returnedException = JSC::Exception::create(vm, createError(&globalObject, genericErrorMessage));
384
        }
385
    }
386
}
387
388
    template<typename JSGlobalScopePrototype, typename JSGlobalScope, typename GlobalScope>
232
void WorkerOrWorkletScriptController::initScriptWithSubclass()
389
void WorkerOrWorkletScriptController::initScriptWithSubclass()
233
{
390
{
234
    ASSERT(!m_globalScopeWrapper);
391
    ASSERT(!m_globalScopeWrapper);
- a/Source/WebCore/workers/WorkerOrWorkletScriptController.h +7 lines
Lines 31-36 a/Source/WebCore/workers/WorkerOrWorkletScriptController.h_sec1
31
#include <JavaScriptCore/JSRunLoopTimer.h>
31
#include <JavaScriptCore/JSRunLoopTimer.h>
32
#include <wtf/Forward.h>
32
#include <wtf/Forward.h>
33
#include <wtf/Lock.h>
33
#include <wtf/Lock.h>
34
#include <wtf/MessageQueue.h>
34
#include <wtf/NakedPtr.h>
35
#include <wtf/NakedPtr.h>
35
36
36
namespace JSC {
37
namespace JSC {
Lines 44-49 class JSGlobalObject; a/Source/WebCore/workers/WorkerOrWorkletScriptController.h_sec2
44
namespace WebCore {
45
namespace WebCore {
45
46
46
class JSDOMGlobalObject;
47
class JSDOMGlobalObject;
48
class LoadableModuleScript;
47
class ScriptSourceCode;
49
class ScriptSourceCode;
48
class WorkerConsoleClient;
50
class WorkerConsoleClient;
49
class WorkerOrWorkletGlobalScope;
51
class WorkerOrWorkletGlobalScope;
Lines 94-99 class WorkerOrWorkletScriptController { a/Source/WebCore/workers/WorkerOrWorkletScriptController.h_sec3
94
    void evaluate(const ScriptSourceCode&, String* returnedExceptionMessage = nullptr);
96
    void evaluate(const ScriptSourceCode&, String* returnedExceptionMessage = nullptr);
95
    void evaluate(const ScriptSourceCode&, NakedPtr<JSC::Exception>& returnedException, String* returnedExceptionMessage = nullptr);
97
    void evaluate(const ScriptSourceCode&, NakedPtr<JSC::Exception>& returnedException, String* returnedExceptionMessage = nullptr);
96
98
99
    JSC::JSValue evaluateModule(JSC::JSModuleRecord&);
100
101
    void linkAndEvaluateModule(LoadableModuleScript&, const ScriptSourceCode& sourceCode, String* returnedExceptionMessage = nullptr);
102
    MessageQueueWaitResult loadModuleSynchronously(LoadableModuleScript&, const ScriptSourceCode&);
103
97
protected:
104
protected:
98
    WorkerOrWorkletGlobalScope* globalScope() const { return m_globalScope; }
105
    WorkerOrWorkletGlobalScope* globalScope() const { return m_globalScope; }
99
106
- a/Source/WebCore/workers/WorkerRunLoop.cpp +1 lines
Lines 251-256 void WorkerRunLoop::postTask(ScriptExecutionContext::Task&& task) a/Source/WebCore/workers/WorkerRunLoop.cpp_sec1
251
251
252
void WorkerRunLoop::postTaskAndTerminate(ScriptExecutionContext::Task&& task)
252
void WorkerRunLoop::postTaskAndTerminate(ScriptExecutionContext::Task&& task)
253
{
253
{
254
    WTFReportBacktrace();
254
    m_messageQueue.appendAndKill(makeUnique<Task>(WTFMove(task), defaultMode()));
255
    m_messageQueue.appendAndKill(makeUnique<Task>(WTFMove(task), defaultMode()));
255
}
256
}
256
257
- a/Source/WebCore/workers/WorkerThread.cpp -3 / +29 lines
Lines 28-33 a/Source/WebCore/workers/WorkerThread.cpp_sec1
28
#include "WorkerThread.h"
28
#include "WorkerThread.h"
29
29
30
#include "IDBConnectionProxy.h"
30
#include "IDBConnectionProxy.h"
31
#include "LoadableModuleScript.h"
31
#include "ScriptSourceCode.h"
32
#include "ScriptSourceCode.h"
32
#include "SecurityOrigin.h"
33
#include "SecurityOrigin.h"
33
#include "SocketProvider.h"
34
#include "SocketProvider.h"
Lines 55-60 WorkerParameters WorkerParameters::isolatedCopy() const a/Source/WebCore/workers/WorkerThread.cpp_sec2
55
        shouldBypassMainWorldContentSecurityPolicy,
56
        shouldBypassMainWorldContentSecurityPolicy,
56
        timeOrigin,
57
        timeOrigin,
57
        referrerPolicy,
58
        referrerPolicy,
59
        workerType,
60
        credentials,
58
        settingsValues.isolatedCopy()
61
        settingsValues.isolatedCopy()
59
    };
62
    };
60
}
63
}
Lines 123-131 bool WorkerThread::shouldWaitForWebInspectorOnStartup() const a/Source/WebCore/workers/WorkerThread.cpp_sec3
123
126
124
void WorkerThread::evaluateScriptIfNecessary(String& exceptionMessage)
127
void WorkerThread::evaluateScriptIfNecessary(String& exceptionMessage)
125
{
128
{
126
    globalScope()->script()->evaluate(ScriptSourceCode(m_startupData->sourceCode, URL(m_startupData->params.scriptURL)), &exceptionMessage);
129
    // We are currently holding only the initial script code. If the WorkerType is Module, we should fetch the entire graph before executing the rest of this.
127
130
    // We invoke module loader as if we are executing inline module script tag in Document.
128
    finishedEvaluatingScript();
131
132
    if (m_startupData->params.workerType == WorkerType::Classic) {
133
        globalScope()->script()->evaluate(ScriptSourceCode(m_startupData->sourceCode, URL(m_startupData->params.scriptURL)), &exceptionMessage);
134
        finishedEvaluatingScript();
135
    } else {
136
        // FIXME crossOrigin mode should be converted.
137
        // FIXME fix initiator name.
138
        // FIXME pass URL to module loader.
139
        dataLogLn("WORKER MODULE");
140
        ScriptSourceCode sourceCode(m_startupData->sourceCode, URL(m_startupData->params.scriptURL), { }, JSC::SourceProviderSourceType::Module);
141
        auto moduleScript = LoadableModuleScript::create(emptyString(), emptyString(), m_startupData->params.referrerPolicy, ScriptElementCachedScriptFetcher::defaultCrossOriginModeForModule, emptyString(), emptyAtom(), false);
142
        MessageQueueWaitResult result = globalScope()->script()->loadModuleSynchronously(moduleScript.get(), sourceCode);
143
        dataLogLn("WORKER MODULE FETCHED");
144
        if (result != MessageQueueTerminated) {
145
            if (!moduleScript->error() && !moduleScript->wasCanceled()) {
146
                // Evaluate.
147
                globalScope()->script()->linkAndEvaluateModule(moduleScript.get(), sourceCode, &exceptionMessage);
148
                dataLogLn("WORKER MODULE EVALUATED");
149
                finishedEvaluatingScript();
150
            } else {
151
                // FIXME Throw an error.
152
            }
153
        }
154
    }
129
155
130
    // Free the startup data to cause its member variable deref's happen on the worker's thread (since
156
    // Free the startup data to cause its member variable deref's happen on the worker's thread (since
131
    // all ref/derefs of these objects are happening on the thread at this point). Note that
157
    // all ref/derefs of these objects are happening on the thread at this point). Note that
- a/Source/WebCore/workers/WorkerThread.h +5 lines
Lines 26-32 a/Source/WebCore/workers/WorkerThread.h_sec1
26
#pragma once
26
#pragma once
27
27
28
#include "ContentSecurityPolicyResponseHeaders.h"
28
#include "ContentSecurityPolicyResponseHeaders.h"
29
#include "FetchRequestCredentials.h"
29
#include "WorkerOrWorkletThread.h"
30
#include "WorkerOrWorkletThread.h"
31
#include "WorkerRunLoop.h"
32
#include "WorkerType.h"
30
#include <JavaScriptCore/RuntimeFlags.h>
33
#include <JavaScriptCore/RuntimeFlags.h>
31
#include <memory>
34
#include <memory>
32
#include <wtf/URL.h>
35
#include <wtf/URL.h>
Lines 63-68 struct WorkerParameters { a/Source/WebCore/workers/WorkerThread.h_sec2
63
    bool shouldBypassMainWorldContentSecurityPolicy;
66
    bool shouldBypassMainWorldContentSecurityPolicy;
64
    MonotonicTime timeOrigin;
67
    MonotonicTime timeOrigin;
65
    ReferrerPolicy referrerPolicy;
68
    ReferrerPolicy referrerPolicy;
69
    WorkerType workerType;
70
    FetchRequestCredentials credentials;
66
    Settings::Values settingsValues;
71
    Settings::Values settingsValues;
67
72
68
    WorkerParameters isolatedCopy() const;
73
    WorkerParameters isolatedCopy() const;
- a/Source/WebCore/workers/service/context/ServiceWorkerThread.cpp -1 / +2 lines
Lines 73-80 class DummyServiceWorkerThreadProxy : public WorkerObjectProxy { a/Source/WebCore/workers/service/context/ServiceWorkerThread.cpp_sec1
73
// FIXME: Use a valid WorkerObjectProxy
73
// FIXME: Use a valid WorkerObjectProxy
74
// FIXME: Use valid runtime flags
74
// FIXME: Use valid runtime flags
75
75
76
// FIXME: Use a valid WorkerType and Credentails for module service workers.
76
ServiceWorkerThread::ServiceWorkerThread(const ServiceWorkerContextData& data, String&& userAgent, const Settings::Values& settingsValues, WorkerLoaderProxy& loaderProxy, WorkerDebuggerProxy& debuggerProxy, IDBClient::IDBConnectionProxy* idbConnectionProxy, SocketProvider* socketProvider)
77
ServiceWorkerThread::ServiceWorkerThread(const ServiceWorkerContextData& data, String&& userAgent, const Settings::Values& settingsValues, WorkerLoaderProxy& loaderProxy, WorkerDebuggerProxy& debuggerProxy, IDBClient::IDBConnectionProxy* idbConnectionProxy, SocketProvider* socketProvider)
77
    : WorkerThread({ data.scriptURL, emptyString(), "serviceworker:" + Inspector::IdentifiersFactory::createIdentifier(), WTFMove(userAgent), platformStrategies()->loaderStrategy()->isOnLine(), data.contentSecurityPolicy, false, MonotonicTime::now(), { }, settingsValues }, data.script, loaderProxy, debuggerProxy, DummyServiceWorkerThreadProxy::shared(), WorkerThreadStartMode::Normal, data.registration.key.topOrigin().securityOrigin().get(), idbConnectionProxy, socketProvider, JSC::RuntimeFlags::createAllEnabled())
78
    : 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())
78
    , m_data(data.isolatedCopy())
79
    , m_data(data.isolatedCopy())
79
    , m_workerObjectProxy(DummyServiceWorkerThreadProxy::shared())
80
    , m_workerObjectProxy(DummyServiceWorkerThreadProxy::shared())
80
    , m_heartBeatTimeout(SWContextManager::singleton().connection()->shouldUseShortTimeout() ? heartBeatTimeoutForTest : heartBeatTimeout)
81
    , m_heartBeatTimeout(SWContextManager::singleton().connection()->shouldUseShortTimeout() ? heartBeatTimeoutForTest : heartBeatTimeout)

Return to Bug 164860