Decouple module loading initiator from ScriptElement
authorutatane.tea@gmail.com <utatane.tea@gmail.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 11 Jan 2017 12:12:37 +0000 (12:12 +0000)
committerutatane.tea@gmail.com <utatane.tea@gmail.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 11 Jan 2017 12:12:37 +0000 (12:12 +0000)
https://bugs.webkit.org/show_bug.cgi?id=166888

Reviewed by Saam Barati and Ryosuke Niwa.

Source/JavaScriptCore:

Add ScriptFetcher and JSScriptFetcher.

* CMakeLists.txt:
* JavaScriptCore.xcodeproj/project.pbxproj:
* builtins/ModuleLoaderPrototype.js:
(requestFetch):
(requestInstantiate):
(requestSatisfy):
(requestInstantiateAll):
(requestLink):
(moduleEvaluation):
(loadAndEvaluateModule):
(importModule):
* llint/LLIntData.cpp:
(JSC::LLInt::Data::performAssertions):
* llint/LowLevelInterpreter.asm:
* runtime/Completion.cpp:
(JSC::loadAndEvaluateModule):
(JSC::loadModule):
(JSC::linkAndEvaluateModule):
* runtime/Completion.h:
* runtime/JSModuleLoader.cpp:
(JSC::JSModuleLoader::loadAndEvaluateModule):
(JSC::JSModuleLoader::loadModule):
(JSC::JSModuleLoader::linkAndEvaluateModule):
(JSC::JSModuleLoader::resolve):
(JSC::JSModuleLoader::fetch):
(JSC::JSModuleLoader::instantiate):
(JSC::JSModuleLoader::evaluate):
* runtime/JSModuleLoader.h:
* runtime/JSScriptFetcher.cpp: Copied from Source/WebCore/dom/LoadableScript.cpp.
(JSC::JSScriptFetcher::destroy):
* runtime/JSScriptFetcher.h: Added.
(JSC::JSScriptFetcher::createStructure):
(JSC::JSScriptFetcher::create):
(JSC::JSScriptFetcher::fetcher):
(JSC::JSScriptFetcher::JSScriptFetcher):
* runtime/JSType.h:
* runtime/ScriptFetcher.h: Copied from Source/WebCore/dom/LoadableScript.cpp.
(JSC::ScriptFetcher::~ScriptFetcher):
* runtime/VM.cpp:
(JSC::VM::VM):
* runtime/VM.h:

Source/WebCore:

Previously, we use ScriptElement (JSElement for ScriptElement) as the module loading initiator.
This element is used to transfer the metadata like charset throughout the module pipeline.
As a result, our module loader in the browser side is tightly coupled with ScriptElement.
It is not good since it prevent us from using the module loader in the non-DOM environment like
Web Workers.

So we decouple the necessary informations from ScriptElement. We move these information to
LoadableScript. And we use JSScriptFetcher to transfer LoadableScript through the JS implemented
module loader pipeline. We select LoadableScript instead of LoadableModuleScript since this initiator
information will be leveraged even in classic scripts once we implement the dynamic import.

No behavior change.

* ForwardingHeaders/runtime/JSScriptFetcher.h: Copied from Source/WebCore/dom/LoadableScript.cpp.
* ForwardingHeaders/runtime/ScriptFetcher.h: Copied from Source/WebCore/dom/LoadableScript.cpp.
* bindings/js/CachedModuleScript.cpp:
(WebCore::CachedModuleScript::create):
(WebCore::CachedModuleScript::load):
(WebCore::CachedModuleScript::CachedModuleScript): Deleted.
* bindings/js/CachedModuleScript.h:
Now we can merge CachedModuleScript to LoadableScript. But we do not do this in this patch since
we focus on decoupling the initiator information from ScriptElement.

(WebCore::CachedModuleScript::nonce): Deleted.
(WebCore::CachedModuleScript::crossOriginMode): Deleted.
* bindings/js/CachedModuleScriptLoader.cpp:
(WebCore::CachedModuleScriptLoader::load):
* bindings/js/CachedModuleScriptLoader.h:
* bindings/js/JSDOMWindowBase.cpp:
(WebCore::JSDOMWindowBase::moduleLoaderResolve):
(WebCore::JSDOMWindowBase::moduleLoaderFetch):
(WebCore::JSDOMWindowBase::moduleLoaderEvaluate):
* bindings/js/JSMainThreadExecState.h:
(WebCore::JSMainThreadExecState::loadModule):
(WebCore::JSMainThreadExecState::linkAndEvaluateModule):
* bindings/js/ScriptController.cpp:
(WebCore::ScriptController::loadModuleScriptInWorld):
(WebCore::ScriptController::loadModuleScript):
(WebCore::ScriptController::linkAndEvaluateModuleScriptInWorld):
(WebCore::ScriptController::linkAndEvaluateModuleScript):
* bindings/js/ScriptController.h:
* bindings/js/ScriptModuleLoader.cpp:
(WebCore::ScriptModuleLoader::fetch):
* bindings/js/ScriptModuleLoader.h:
* dom/LoadableClassicScript.cpp:
(WebCore::LoadableClassicScript::create):
(WebCore::LoadableClassicScript::~LoadableClassicScript):
(WebCore::LoadableClassicScript::isLoaded):
(WebCore::LoadableClassicScript::error):
(WebCore::LoadableClassicScript::wasCanceled):
(WebCore::LoadableClassicScript::notifyFinished):
(WebCore::LoadableClassicScript::load):
* dom/LoadableClassicScript.h:
* dom/LoadableModuleScript.cpp:
(WebCore::LoadableModuleScript::create):
(WebCore::LoadableModuleScript::LoadableModuleScript):
(WebCore::LoadableModuleScript::load):
* dom/LoadableModuleScript.h:
* dom/LoadableScript.cpp:
(WebCore::LoadableScript::requestScriptWithCache):
* dom/LoadableScript.h:
(WebCore::LoadableScript::LoadableScript):
* dom/ScriptElement.cpp:
(WebCore::ScriptElement::requestClassicScript):
(WebCore::ScriptElement::requestModuleScript):
(WebCore::ScriptElement::executeModuleScript):
(WebCore::ScriptElement::requestScriptWithCacheForModuleScript): Deleted.
(WebCore::ScriptElement::requestScriptWithCache): Deleted.
* dom/ScriptElement.h:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@210585 268f45cc-cd09-0410-ab3c-d52691b4dbfc

37 files changed:
Source/JavaScriptCore/CMakeLists.txt
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
Source/JavaScriptCore/builtins/ModuleLoaderPrototype.js
Source/JavaScriptCore/llint/LLIntData.cpp
Source/JavaScriptCore/llint/LowLevelInterpreter.asm
Source/JavaScriptCore/runtime/Completion.cpp
Source/JavaScriptCore/runtime/Completion.h
Source/JavaScriptCore/runtime/JSModuleLoader.cpp
Source/JavaScriptCore/runtime/JSModuleLoader.h
Source/JavaScriptCore/runtime/JSScriptFetcher.cpp [new file with mode: 0644]
Source/JavaScriptCore/runtime/JSScriptFetcher.h [new file with mode: 0644]
Source/JavaScriptCore/runtime/JSType.h
Source/JavaScriptCore/runtime/ScriptFetcher.h [new file with mode: 0644]
Source/JavaScriptCore/runtime/VM.cpp
Source/JavaScriptCore/runtime/VM.h
Source/WebCore/ChangeLog
Source/WebCore/ForwardingHeaders/runtime/JSScriptFetcher.h [new file with mode: 0644]
Source/WebCore/ForwardingHeaders/runtime/ScriptFetcher.h [new file with mode: 0644]
Source/WebCore/bindings/js/CachedModuleScript.cpp
Source/WebCore/bindings/js/CachedModuleScript.h
Source/WebCore/bindings/js/CachedModuleScriptLoader.cpp
Source/WebCore/bindings/js/CachedModuleScriptLoader.h
Source/WebCore/bindings/js/JSDOMWindowBase.cpp
Source/WebCore/bindings/js/JSMainThreadExecState.h
Source/WebCore/bindings/js/ScriptController.cpp
Source/WebCore/bindings/js/ScriptController.h
Source/WebCore/bindings/js/ScriptModuleLoader.cpp
Source/WebCore/bindings/js/ScriptModuleLoader.h
Source/WebCore/dom/LoadableClassicScript.cpp
Source/WebCore/dom/LoadableClassicScript.h
Source/WebCore/dom/LoadableModuleScript.cpp
Source/WebCore/dom/LoadableModuleScript.h
Source/WebCore/dom/LoadableScript.cpp
Source/WebCore/dom/LoadableScript.h
Source/WebCore/dom/ScriptElement.cpp
Source/WebCore/dom/ScriptElement.h

index 005b8d9..b686500 100644 (file)
@@ -784,6 +784,7 @@ set(JavaScriptCore_SOURCES
     runtime/JSPropertyNameIterator.cpp
     runtime/JSProxy.cpp
     runtime/JSScope.cpp
+    runtime/JSScriptFetcher.cpp
     runtime/JSSegmentedVariableObject.cpp
     runtime/JSSet.cpp
     runtime/JSSetIterator.cpp
index c86821a..8ac2e9b 100644 (file)
@@ -1,3 +1,54 @@
+2017-01-11  Yusuke Suzuki  <utatane.tea@gmail.com>
+
+        Decouple module loading initiator from ScriptElement
+        https://bugs.webkit.org/show_bug.cgi?id=166888
+
+        Reviewed by Saam Barati and Ryosuke Niwa.
+
+        Add ScriptFetcher and JSScriptFetcher.
+
+        * CMakeLists.txt:
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * builtins/ModuleLoaderPrototype.js:
+        (requestFetch):
+        (requestInstantiate):
+        (requestSatisfy):
+        (requestInstantiateAll):
+        (requestLink):
+        (moduleEvaluation):
+        (loadAndEvaluateModule):
+        (importModule):
+        * llint/LLIntData.cpp:
+        (JSC::LLInt::Data::performAssertions):
+        * llint/LowLevelInterpreter.asm:
+        * runtime/Completion.cpp:
+        (JSC::loadAndEvaluateModule):
+        (JSC::loadModule):
+        (JSC::linkAndEvaluateModule):
+        * runtime/Completion.h:
+        * runtime/JSModuleLoader.cpp:
+        (JSC::JSModuleLoader::loadAndEvaluateModule):
+        (JSC::JSModuleLoader::loadModule):
+        (JSC::JSModuleLoader::linkAndEvaluateModule):
+        (JSC::JSModuleLoader::resolve):
+        (JSC::JSModuleLoader::fetch):
+        (JSC::JSModuleLoader::instantiate):
+        (JSC::JSModuleLoader::evaluate):
+        * runtime/JSModuleLoader.h:
+        * runtime/JSScriptFetcher.cpp: Copied from Source/WebCore/dom/LoadableScript.cpp.
+        (JSC::JSScriptFetcher::destroy):
+        * runtime/JSScriptFetcher.h: Added.
+        (JSC::JSScriptFetcher::createStructure):
+        (JSC::JSScriptFetcher::create):
+        (JSC::JSScriptFetcher::fetcher):
+        (JSC::JSScriptFetcher::JSScriptFetcher):
+        * runtime/JSType.h:
+        * runtime/ScriptFetcher.h: Copied from Source/WebCore/dom/LoadableScript.cpp.
+        (JSC::ScriptFetcher::~ScriptFetcher):
+        * runtime/VM.cpp:
+        (JSC::VM::VM):
+        * runtime/VM.h:
+
 2017-01-10  Yusuke Suzuki  <utatane.tea@gmail.com>
 
         Implement JSSourceCode to propagate SourceCode in module pipeline
index 76384fa..7cfeb99 100644 (file)
                FEFD6FC61D5E7992008F2F0B /* JSStringInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = FEFD6FC51D5E7970008F2F0B /* JSStringInlines.h */; settings = {ATTRIBUTES = (Private, ); }; };
                FA3AB211C8494524AB390267 /* JSSourceCode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F73926918DC64330AFCDF0D7 /* JSSourceCode.cpp */; };
                BDFCB2BBE90F41349E1B0BED /* JSSourceCode.h in Headers */ = {isa = PBXBuildFile; fileRef = 3032175DF1AD47D8998B34E1 /* JSSourceCode.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               14815F5F991C46BEB98D0016 /* JSScriptFetcher.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 11C197C2624848EDA84CED7F /* JSScriptFetcher.cpp */; };
+               9064337DD4B0402BAF34A592 /* JSScriptFetcher.h in Headers */ = {isa = PBXBuildFile; fileRef = 6BA93C9590484C5BAD9316EA /* JSScriptFetcher.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               CEAE7D7B889B477BA93ABA6C /* ScriptFetcher.h in Headers */ = {isa = PBXBuildFile; fileRef = 8852151A9C3842389B3215B7 /* ScriptFetcher.h */; settings = {ATTRIBUTES = (Private, ); }; };
 /* End PBXBuildFile section */
 
 /* Begin PBXContainerItemProxy section */
                FEFD6FC51D5E7970008F2F0B /* JSStringInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSStringInlines.h; sourceTree = "<group>"; };
                F73926918DC64330AFCDF0D7 /* JSSourceCode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JSSourceCode.cpp; path = JSSourceCode.cpp; sourceTree = "<group>"; };
                3032175DF1AD47D8998B34E1 /* JSSourceCode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JSSourceCode.h; path = JSSourceCode.h; sourceTree = "<group>"; };
+               11C197C2624848EDA84CED7F /* JSScriptFetcher.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JSScriptFetcher.cpp; path = JSScriptFetcher.cpp; sourceTree = "<group>"; };
+               6BA93C9590484C5BAD9316EA /* JSScriptFetcher.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JSScriptFetcher.h; path = JSScriptFetcher.h; sourceTree = "<group>"; };
+               8852151A9C3842389B3215B7 /* ScriptFetcher.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ScriptFetcher.h; path = ScriptFetcher.h; sourceTree = "<group>"; };
 /* End PBXFileReference section */
 
 /* Begin PBXFrameworksBuildPhase section */
                                425BA1337E4344E1B269A671 /* SourceOrigin.h */,
                                F73926918DC64330AFCDF0D7 /* JSSourceCode.cpp */,
                                3032175DF1AD47D8998B34E1 /* JSSourceCode.h */,
+                               11C197C2624848EDA84CED7F /* JSScriptFetcher.cpp */,
+                               6BA93C9590484C5BAD9316EA /* JSScriptFetcher.h */,
+                               8852151A9C3842389B3215B7 /* ScriptFetcher.h */,
                        );
                        path = runtime;
                        sourceTree = "<group>";
                                86704B4312DB8A8100A9FE7B /* YarrSyntaxChecker.h in Headers */,
                                2D342F36F7244096804ADB24 /* SourceOrigin.h in Headers */,
                                BDFCB2BBE90F41349E1B0BED /* JSSourceCode.h in Headers */,
+                               9064337DD4B0402BAF34A592 /* JSScriptFetcher.h in Headers */,
+                               CEAE7D7B889B477BA93ABA6C /* ScriptFetcher.h in Headers */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                                86704B8912DBA33700A9FE7B /* YarrPattern.cpp in Sources */,
                                86704B4212DB8A8100A9FE7B /* YarrSyntaxChecker.cpp in Sources */,
                                FA3AB211C8494524AB390267 /* JSSourceCode.cpp in Sources */,
+                               14815F5F991C46BEB98D0016 /* JSScriptFetcher.cpp in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
index d4a777f..68e00c1 100644 (file)
@@ -204,7 +204,7 @@ function instantiation(result, source, entry)
 
 // Loader.
 
-function requestFetch(key, initiator)
+function requestFetch(key, fetcher)
 {
     // https://whatwg.github.io/loader/#request-fetch
 
@@ -220,7 +220,7 @@ function requestFetch(key, initiator)
     //     Take the key and fetch the resource actually.
     //     For example, JavaScriptCore shell can provide the hook fetching the resource
     //     from the local file system.
-    var fetchPromise = this.fetch(key, initiator).then((source) => {
+    var fetchPromise = this.fetch(key, fetcher).then((source) => {
         @setStateToMax(entry, @ModuleInstantiate);
         return source;
     });
@@ -228,7 +228,7 @@ function requestFetch(key, initiator)
     return fetchPromise;
 }
 
-function requestInstantiate(key, initiator)
+function requestInstantiate(key, fetcher)
 {
     // https://whatwg.github.io/loader/#request-instantiate
 
@@ -238,7 +238,7 @@ function requestInstantiate(key, initiator)
     if (entry.instantiate)
         return entry.instantiate;
 
-    var instantiatePromise = this.requestFetch(key, initiator).then((source) => {
+    var instantiatePromise = this.requestFetch(key, fetcher).then((source) => {
         // Hook point.
         // 3. Loader.instantiate
         //     https://whatwg.github.io/loader/#browser-instantiate
@@ -246,7 +246,7 @@ function requestInstantiate(key, initiator)
         //     by parsing the module source code.
         //     It has the chance to provide the optional module instance that is different from
         //     the ordinary one.
-        return this.instantiate(key, source, initiator).then((optionalInstance) => {
+        return this.instantiate(key, source, fetcher).then((optionalInstance) => {
             this.commitInstantiated(entry, optionalInstance, source);
             return entry;
         });
@@ -255,7 +255,7 @@ function requestInstantiate(key, initiator)
     return instantiatePromise;
 }
 
-function requestSatisfy(key, initiator)
+function requestSatisfy(key, fetcher)
 {
     // https://whatwg.github.io/loader/#satisfy-instance
 
@@ -265,7 +265,7 @@ function requestSatisfy(key, initiator)
     if (entry.satisfy)
         return entry.satisfy;
 
-    var satisfyPromise = this.requestInstantiate(key, initiator).then((entry) => {
+    var satisfyPromise = this.requestInstantiate(key, fetcher).then((entry) => {
         var depLoads = [];
         for (var i = 0, length = entry.dependencies.length; i < length; ++i) {
             let pair = entry.dependencies[i];
@@ -275,7 +275,7 @@ function requestSatisfy(key, initiator)
             //     https://whatwg.github.io/loader/#browser-resolve
             //     Take the name and resolve it to the unique identifier for the resource location.
             //     For example, take the "jquery" and return the URL for the resource.
-            var promise = this.resolve(pair.key, key, initiator).then((depKey) => {
+            var promise = this.resolve(pair.key, key, fetcher).then((depKey) => {
                 var depEntry = this.ensureRegistered(depKey);
 
                 // Recursive resolving. The dependencies of this entry is being resolved or already resolved.
@@ -294,7 +294,7 @@ function requestSatisfy(key, initiator)
                     });
                 }
 
-                return this.requestSatisfy(depKey, initiator).then((entry) => {
+                return this.requestSatisfy(depKey, fetcher).then((entry) => {
                     pair.value = entry.module;
                     return entry;
                 });
@@ -312,16 +312,16 @@ function requestSatisfy(key, initiator)
     return satisfyPromise;
 }
 
-function requestInstantiateAll(key, initiator)
+function requestInstantiateAll(key, fetcher)
 {
     // https://whatwg.github.io/loader/#request-instantiate-all
 
     "use strict";
 
-    return this.requestSatisfy(key, initiator);
+    return this.requestSatisfy(key, fetcher);
 }
 
-function requestLink(key, initiator)
+function requestLink(key, fetcher)
 {
     // https://whatwg.github.io/loader/#request-link
 
@@ -334,26 +334,26 @@ function requestLink(key, initiator)
         return deferred.@promise;
     }
 
-    return this.requestInstantiateAll(key, initiator).then((entry) => {
-        this.link(entry, initiator);
+    return this.requestInstantiateAll(key, fetcher).then((entry) => {
+        this.link(entry, fetcher);
         return entry;
     });
 }
 
-function requestReady(key, initiator)
+function requestReady(key, fetcher)
 {
     // https://whatwg.github.io/loader/#request-ready
 
     "use strict";
 
-    return this.requestLink(key, initiator).then((entry) => {
-        this.moduleEvaluation(entry.module, initiator);
+    return this.requestLink(key, fetcher).then((entry) => {
+        this.moduleEvaluation(entry.module, fetcher);
     });
 }
 
 // Linking semantics.
 
-function link(entry, initiator)
+function link(entry, fetcher)
 {
     // https://whatwg.github.io/loader/#link
 
@@ -373,15 +373,15 @@ function link(entry, initiator)
     var dependencies = entry.dependencies;
     for (var i = 0, length = dependencies.length; i < length; ++i) {
         var pair = dependencies[i];
-        this.link(pair.value.registryEntry, initiator);
+        this.link(pair.value.registryEntry, fetcher);
     }
 
-    this.moduleDeclarationInstantiation(entry.module, initiator);
+    this.moduleDeclarationInstantiation(entry.module, fetcher);
 }
 
 // Module semantics.
 
-function moduleEvaluation(moduleRecord, initiator)
+function moduleEvaluation(moduleRecord, fetcher)
 {
     // http://www.ecma-international.org/ecma-262/6.0/#sec-moduleevaluation
 
@@ -398,9 +398,9 @@ function moduleEvaluation(moduleRecord, initiator)
     for (var i = 0, length = dependencies.length; i < length; ++i) {
         var pair = dependencies[i];
         var requiredModuleRecord = pair.value;
-        this.moduleEvaluation(requiredModuleRecord, initiator);
+        this.moduleEvaluation(requiredModuleRecord, fetcher);
     }
-    this.evaluate(entry.key, moduleRecord, initiator);
+    this.evaluate(entry.key, moduleRecord, fetcher);
 }
 
 // APIs to control the module loader.
@@ -431,7 +431,7 @@ function provide(key, stage, value)
     @throwTypeError("Requested module is already ready to be executed.");
 }
 
-function loadAndEvaluateModule(moduleName, referrer, initiator)
+function loadAndEvaluateModule(moduleName, referrer, fetcher)
 {
     "use strict";
 
@@ -439,12 +439,12 @@ function loadAndEvaluateModule(moduleName, referrer, initiator)
     // resolve: moduleName => Promise(moduleKey)
     // Take the name and resolve it to the unique identifier for the resource location.
     // For example, take the "jquery" and return the URL for the resource.
-    return this.resolve(moduleName, referrer, initiator).then((key) => {
-        return this.requestReady(key, initiator);
+    return this.resolve(moduleName, referrer, fetcher).then((key) => {
+        return this.requestReady(key, fetcher);
     });
 }
 
-function loadModule(moduleName, referrer, initiator)
+function loadModule(moduleName, referrer, fetcher)
 {
     "use strict";
 
@@ -452,14 +452,14 @@ function loadModule(moduleName, referrer, initiator)
     // resolve: moduleName => Promise(moduleKey)
     // Take the name and resolve it to the unique identifier for the resource location.
     // For example, take the "jquery" and return the URL for the resource.
-    return this.resolve(moduleName, referrer, initiator).then((key) => {
-        return this.requestInstantiateAll(key, initiator);
+    return this.resolve(moduleName, referrer, fetcher).then((key) => {
+        return this.requestInstantiateAll(key, fetcher);
     }).then((entry) => {
         return entry.key;
     });
 }
 
-function linkAndEvaluateModule(key, initiator)
+function linkAndEvaluateModule(key, fetcher)
 {
     "use strict";
 
@@ -467,11 +467,11 @@ function linkAndEvaluateModule(key, initiator)
     if (entry.state < @ModuleLink)
         @throwTypeError("Requested module is not instantiated yet.");
 
-    this.link(entry, initiator);
-    return this.moduleEvaluation(entry.module, initiator);
+    this.link(entry, fetcher);
+    return this.moduleEvaluation(entry.module, fetcher);
 }
 
-function importModule(moduleName, referrer, initiator)
+function importModule(moduleName, referrer, fetcher)
 {
     "use strict";
 
@@ -479,10 +479,10 @@ function importModule(moduleName, referrer, initiator)
     // resolve: moduleName => Promise(moduleKey)
     // Take the name and resolve it to the unique identifier for the resource location.
     // For example, take the "jquery" and return the URL for the resource.
-    return this.resolve(moduleName, referrer, initiator).then((key) => {
-        return this.requestInstantiateAll(key, initiator);
+    return this.resolve(moduleName, referrer, fetcher).then((key) => {
+        return this.requestInstantiateAll(key, fetcher);
     }).then((entry) => {
-        this.linkAndEvaluateModule(entry.key, initiator);
+        this.linkAndEvaluateModule(entry.key, fetcher);
         return this.getModuleNamespaceObject(entry.module);
     });
 }
index 6cb21cd..8b615a1 100644 (file)
@@ -156,21 +156,21 @@ void Data::performAssertions(VM& vm)
     
     STATIC_ASSERT(StringType == 6);
     STATIC_ASSERT(SymbolType == 7);
-    STATIC_ASSERT(ObjectType == 22);
-    STATIC_ASSERT(FinalObjectType == 23);
-    STATIC_ASSERT(JSFunctionType == 25);
-    STATIC_ASSERT(ArrayType == 33);
-    STATIC_ASSERT(DerivedArrayType == 34);
-    STATIC_ASSERT(ProxyObjectType == 52);
-    STATIC_ASSERT(Int8ArrayType == 35);
-    STATIC_ASSERT(Int16ArrayType == 36);
-    STATIC_ASSERT(Int32ArrayType == 37);
-    STATIC_ASSERT(Uint8ArrayType == 38);
-    STATIC_ASSERT(Uint8ClampedArrayType == 39);
-    STATIC_ASSERT(Uint16ArrayType == 40);
-    STATIC_ASSERT(Uint32ArrayType == 41);
-    STATIC_ASSERT(Float32ArrayType == 42);
-    STATIC_ASSERT(Float64ArrayType == 43);
+    STATIC_ASSERT(ObjectType == 23);
+    STATIC_ASSERT(FinalObjectType == 24);
+    STATIC_ASSERT(JSFunctionType == 26);
+    STATIC_ASSERT(ArrayType == 34);
+    STATIC_ASSERT(DerivedArrayType == 35);
+    STATIC_ASSERT(ProxyObjectType == 53);
+    STATIC_ASSERT(Int8ArrayType == 36);
+    STATIC_ASSERT(Int16ArrayType == 37);
+    STATIC_ASSERT(Int32ArrayType == 38);
+    STATIC_ASSERT(Uint8ArrayType == 39);
+    STATIC_ASSERT(Uint8ClampedArrayType == 40);
+    STATIC_ASSERT(Uint16ArrayType == 41);
+    STATIC_ASSERT(Uint32ArrayType == 42);
+    STATIC_ASSERT(Float32ArrayType == 43);
+    STATIC_ASSERT(Float64ArrayType == 44);
     STATIC_ASSERT(MasqueradesAsUndefined == 1);
     STATIC_ASSERT(ImplementsDefaultHasInstance == 2);
     STATIC_ASSERT(FirstConstantRegisterIndex == 0x40000000);
index 9b32826..ec24773 100644 (file)
@@ -345,24 +345,24 @@ const SlowPutArrayStorageShape = 0x0C
 # Type constants.
 const StringType = 6
 const SymbolType = 7
-const ObjectType = 22
-const FinalObjectType = 23
-const JSFunctionType = 25
-const ArrayType = 33
-const DerivedArrayType = 34
-const ProxyObjectType = 52
+const ObjectType = 23
+const FinalObjectType = 24
+const JSFunctionType = 26
+const ArrayType = 34
+const DerivedArrayType = 35
+const ProxyObjectType = 53
 
 # The typed array types need to be numbered in a particular order because of the manually written
 # switch statement in get_by_val and put_by_val.
-const Int8ArrayType = 35
-const Int16ArrayType = 36
-const Int32ArrayType = 37
-const Uint8ArrayType = 38
-const Uint8ClampedArrayType = 39
-const Uint16ArrayType = 40
-const Uint32ArrayType = 41
-const Float32ArrayType = 42
-const Float64ArrayType = 43
+const Int8ArrayType = 36
+const Int16ArrayType = 37
+const Int32ArrayType = 38
+const Uint8ArrayType = 39
+const Uint8ClampedArrayType = 40
+const Uint16ArrayType = 41
+const Uint32ArrayType = 42
+const Float32ArrayType = 43
+const Float64ArrayType = 44
 
 const FirstArrayType = Int8ArrayType
 const LastArrayType = Float64ArrayType
index b2f595c..e4768ee 100644 (file)
@@ -161,26 +161,26 @@ static JSInternalPromise* rejectPromise(ExecState* exec, JSGlobalObject* globalO
     return deferred->promise();
 }
 
-static JSInternalPromise* loadAndEvaluateModule(const JSLockHolder&, ExecState* exec, JSGlobalObject* globalObject, JSValue moduleName, JSValue referrer, JSValue initiator)
+static JSInternalPromise* loadAndEvaluateModule(const JSLockHolder&, ExecState* exec, JSGlobalObject* globalObject, JSValue moduleName, JSValue referrer, JSValue scriptFetcher)
 {
-    return globalObject->moduleLoader()->loadAndEvaluateModule(exec, moduleName, referrer, initiator);
+    return globalObject->moduleLoader()->loadAndEvaluateModule(exec, moduleName, referrer, scriptFetcher);
 }
 
-static JSInternalPromise* loadAndEvaluateModule(const JSLockHolder& lock, ExecState* exec, JSGlobalObject* globalObject, const Identifier& moduleName, JSValue initiator)
+static JSInternalPromise* loadAndEvaluateModule(const JSLockHolder& lock, ExecState* exec, JSGlobalObject* globalObject, const Identifier& moduleName, JSValue scriptFetcher)
 {
-    return loadAndEvaluateModule(lock, exec, globalObject, identifierToJSValue(exec->vm(), moduleName), jsUndefined(), initiator);
+    return loadAndEvaluateModule(lock, exec, globalObject, identifierToJSValue(exec->vm(), moduleName), jsUndefined(), scriptFetcher);
 }
 
-JSInternalPromise* loadAndEvaluateModule(ExecState* exec, const String& moduleName, JSValue initiator)
+JSInternalPromise* loadAndEvaluateModule(ExecState* exec, const String& moduleName, JSValue scriptFetcher)
 {
     JSLockHolder lock(exec);
     RELEASE_ASSERT(exec->vm().atomicStringTable() == wtfThreadData().atomicStringTable());
     RELEASE_ASSERT(!exec->vm().isCollectorBusyOnCurrentThread());
 
-    return loadAndEvaluateModule(lock, exec, exec->vmEntryGlobalObject(), Identifier::fromString(exec, moduleName), initiator);
+    return loadAndEvaluateModule(lock, exec, exec->vmEntryGlobalObject(), Identifier::fromString(exec, moduleName), scriptFetcher);
 }
 
-JSInternalPromise* loadAndEvaluateModule(ExecState* exec, const SourceCode& source, JSValue initiator)
+JSInternalPromise* loadAndEvaluateModule(ExecState* exec, const SourceCode& source, JSValue scriptFetcher)
 {
     VM& vm = exec->vm();
     JSLockHolder lock(vm);
@@ -196,29 +196,29 @@ JSInternalPromise* loadAndEvaluateModule(ExecState* exec, const SourceCode& sour
     globalObject->moduleLoader()->provide(exec, key, JSModuleLoader::Status::Fetch, source);
     RETURN_IF_EXCEPTION(scope, rejectPromise(exec, globalObject));
 
-    return loadAndEvaluateModule(lock, exec, globalObject, key, jsUndefined(), initiator);
+    return loadAndEvaluateModule(lock, exec, globalObject, key, jsUndefined(), scriptFetcher);
 }
 
-static JSInternalPromise* loadModule(const JSLockHolder&, ExecState* exec, JSGlobalObject* globalObject, JSValue moduleName, JSValue referrer, JSValue initiator)
+static JSInternalPromise* loadModule(const JSLockHolder&, ExecState* exec, JSGlobalObject* globalObject, JSValue moduleName, JSValue referrer, JSValue scriptFetcher)
 {
-    return globalObject->moduleLoader()->loadModule(exec, moduleName, referrer, initiator);
+    return globalObject->moduleLoader()->loadModule(exec, moduleName, referrer, scriptFetcher);
 }
 
-static JSInternalPromise* loadModule(const JSLockHolder& lock, ExecState* exec, JSGlobalObject* globalObject, const Identifier& moduleName, JSValue initiator)
+static JSInternalPromise* loadModule(const JSLockHolder& lock, ExecState* exec, JSGlobalObject* globalObject, const Identifier& moduleName, JSValue scriptFetcher)
 {
-    return loadModule(lock, exec, globalObject, identifierToJSValue(exec->vm(), moduleName), jsUndefined(), initiator);
+    return loadModule(lock, exec, globalObject, identifierToJSValue(exec->vm(), moduleName), jsUndefined(), scriptFetcher);
 }
 
-JSInternalPromise* loadModule(ExecState* exec, const String& moduleName, JSValue initiator)
+JSInternalPromise* loadModule(ExecState* exec, const String& moduleName, JSValue scriptFetcher)
 {
     JSLockHolder lock(exec);
     RELEASE_ASSERT(exec->vm().atomicStringTable() == wtfThreadData().atomicStringTable());
     RELEASE_ASSERT(!exec->vm().isCollectorBusyOnCurrentThread());
 
-    return loadModule(lock, exec, exec->vmEntryGlobalObject(), Identifier::fromString(exec, moduleName), initiator);
+    return loadModule(lock, exec, exec->vmEntryGlobalObject(), Identifier::fromString(exec, moduleName), scriptFetcher);
 }
 
-JSInternalPromise* loadModule(ExecState* exec, const SourceCode& source, JSValue initiator)
+JSInternalPromise* loadModule(ExecState* exec, const SourceCode& source, JSValue scriptFetcher)
 {
     VM& vm = exec->vm();
     JSLockHolder lock(vm);
@@ -235,17 +235,17 @@ JSInternalPromise* loadModule(ExecState* exec, const SourceCode& source, JSValue
     globalObject->moduleLoader()->provide(exec, key, JSModuleLoader::Status::Fetch, source);
     RETURN_IF_EXCEPTION(scope, rejectPromise(exec, globalObject));
 
-    return loadModule(lock, exec, globalObject, key, jsUndefined(), initiator);
+    return loadModule(lock, exec, globalObject, key, jsUndefined(), scriptFetcher);
 }
 
-JSValue linkAndEvaluateModule(ExecState* exec, const Identifier& moduleKey, JSValue initiator)
+JSValue linkAndEvaluateModule(ExecState* exec, const Identifier& moduleKey, JSValue scriptFetcher)
 {
     JSLockHolder lock(exec);
     RELEASE_ASSERT(exec->vm().atomicStringTable() == wtfThreadData().atomicStringTable());
     RELEASE_ASSERT(!exec->vm().isCollectorBusyOnCurrentThread());
 
     JSGlobalObject* globalObject = exec->vmEntryGlobalObject();
-    return globalObject->moduleLoader()->linkAndEvaluateModule(exec, identifierToJSValue(exec->vm(), moduleKey), initiator);
+    return globalObject->moduleLoader()->linkAndEvaluateModule(exec, identifierToJSValue(exec->vm(), moduleKey), scriptFetcher);
 }
 
 } // namespace JSC
index 198d7ec..822bc42 100644 (file)
@@ -57,14 +57,14 @@ inline JSValue profiledEvaluate(ExecState* exec, ProfilingReason reason, const S
 JS_EXPORT_PRIVATE JSValue evaluateWithScopeExtension(ExecState*, const SourceCode&, JSObject* scopeExtension, NakedPtr<Exception>& returnedException);
 
 // Load the module source and evaluate it.
-JS_EXPORT_PRIVATE JSInternalPromise* loadAndEvaluateModule(ExecState*, const String& moduleName, JSValue initiator = jsUndefined());
-JS_EXPORT_PRIVATE JSInternalPromise* loadAndEvaluateModule(ExecState*, const SourceCode&, JSValue initiator = jsUndefined());
+JS_EXPORT_PRIVATE JSInternalPromise* loadAndEvaluateModule(ExecState*, const String& moduleName, JSValue scriptFetcher = jsUndefined());
+JS_EXPORT_PRIVATE JSInternalPromise* loadAndEvaluateModule(ExecState*, const SourceCode&, JSValue scriptFetcher = jsUndefined());
 
 // Fetch the module source, and instantiate the module record.
-JS_EXPORT_PRIVATE JSInternalPromise* loadModule(ExecState*, const String& moduleName, JSValue initiator = jsUndefined());
-JS_EXPORT_PRIVATE JSInternalPromise* loadModule(ExecState*, const SourceCode&, JSValue initiator = jsUndefined());
+JS_EXPORT_PRIVATE JSInternalPromise* loadModule(ExecState*, const String& moduleName, JSValue scriptFetcher = jsUndefined());
+JS_EXPORT_PRIVATE JSInternalPromise* loadModule(ExecState*, const SourceCode&, JSValue scriptFetcher = jsUndefined());
 
 // Link and evaluate the already linked module. This function is called in a sync manner.
-JS_EXPORT_PRIVATE JSValue linkAndEvaluateModule(ExecState*, const Identifier& moduleKey, JSValue initiator = jsUndefined());
+JS_EXPORT_PRIVATE JSValue linkAndEvaluateModule(ExecState*, const Identifier& moduleKey, JSValue scriptFetcher = jsUndefined());
 
 } // namespace JSC
index c00fdc0..96f1822 100644 (file)
@@ -93,7 +93,7 @@ JSValue JSModuleLoader::provide(ExecState* exec, JSValue key, Status status, con
     return call(exec, function, callType, callData, this, arguments);
 }
 
-JSInternalPromise* JSModuleLoader::loadAndEvaluateModule(ExecState* exec, JSValue moduleName, JSValue referrer, JSValue initiator)
+JSInternalPromise* JSModuleLoader::loadAndEvaluateModule(ExecState* exec, JSValue moduleName, JSValue referrer, JSValue scriptFetcher)
 {
     JSObject* function = jsCast<JSObject*>(get(exec, exec->propertyNames().builtinNames().loadAndEvaluateModulePublicName()));
     CallData callData;
@@ -103,12 +103,12 @@ JSInternalPromise* JSModuleLoader::loadAndEvaluateModule(ExecState* exec, JSValu
     MarkedArgumentBuffer arguments;
     arguments.append(moduleName);
     arguments.append(referrer);
-    arguments.append(initiator);
+    arguments.append(scriptFetcher);
 
     return jsCast<JSInternalPromise*>(call(exec, function, callType, callData, this, arguments));
 }
 
-JSInternalPromise* JSModuleLoader::loadModule(ExecState* exec, JSValue moduleName, JSValue referrer, JSValue initiator)
+JSInternalPromise* JSModuleLoader::loadModule(ExecState* exec, JSValue moduleName, JSValue referrer, JSValue scriptFetcher)
 {
     JSObject* function = jsCast<JSObject*>(get(exec, exec->propertyNames().builtinNames().loadModulePublicName()));
     CallData callData;
@@ -118,12 +118,12 @@ JSInternalPromise* JSModuleLoader::loadModule(ExecState* exec, JSValue moduleNam
     MarkedArgumentBuffer arguments;
     arguments.append(moduleName);
     arguments.append(referrer);
-    arguments.append(initiator);
+    arguments.append(scriptFetcher);
 
     return jsCast<JSInternalPromise*>(call(exec, function, callType, callData, this, arguments));
 }
 
-JSValue JSModuleLoader::linkAndEvaluateModule(ExecState* exec, JSValue moduleKey, JSValue initiator)
+JSValue JSModuleLoader::linkAndEvaluateModule(ExecState* exec, JSValue moduleKey, JSValue scriptFetcher)
 {
     JSObject* function = jsCast<JSObject*>(get(exec, exec->propertyNames().builtinNames().linkAndEvaluateModulePublicName()));
     CallData callData;
@@ -132,7 +132,7 @@ JSValue JSModuleLoader::linkAndEvaluateModule(ExecState* exec, JSValue moduleKey
 
     MarkedArgumentBuffer arguments;
     arguments.append(moduleKey);
-    arguments.append(initiator);
+    arguments.append(scriptFetcher);
 
     return call(exec, function, callType, callData, this, arguments);
 }
@@ -161,20 +161,20 @@ JSInternalPromise* JSModuleLoader::importModule(ExecState* exec, JSString* modul
     return deferred->promise();
 }
 
-JSInternalPromise* JSModuleLoader::resolve(ExecState* exec, JSValue name, JSValue referrer, JSValue initiator)
+JSInternalPromise* JSModuleLoader::resolve(ExecState* exec, JSValue name, JSValue referrer, JSValue scriptFetcher)
 {
     if (Options::dumpModuleLoadingState())
         dataLog("Loader [resolve] ", printableModuleKey(exec, name), "\n");
 
     JSGlobalObject* globalObject = exec->lexicalGlobalObject();
     if (globalObject->globalObjectMethodTable()->moduleLoaderResolve)
-        return globalObject->globalObjectMethodTable()->moduleLoaderResolve(globalObject, exec, this, name, referrer, initiator);
+        return globalObject->globalObjectMethodTable()->moduleLoaderResolve(globalObject, exec, this, name, referrer, scriptFetcher);
     JSInternalPromiseDeferred* deferred = JSInternalPromiseDeferred::create(exec, globalObject);
     deferred->resolve(exec, name);
     return deferred->promise();
 }
 
-JSInternalPromise* JSModuleLoader::fetch(ExecState* exec, JSValue key, JSValue initiator)
+JSInternalPromise* JSModuleLoader::fetch(ExecState* exec, JSValue key, JSValue scriptFetcher)
 {
     if (Options::dumpModuleLoadingState())
         dataLog("Loader [fetch] ", printableModuleKey(exec, key), "\n");
@@ -183,7 +183,7 @@ JSInternalPromise* JSModuleLoader::fetch(ExecState* exec, JSValue key, JSValue i
     VM& vm = globalObject->vm();
     auto scope = DECLARE_CATCH_SCOPE(vm);
     if (globalObject->globalObjectMethodTable()->moduleLoaderFetch)
-        return globalObject->globalObjectMethodTable()->moduleLoaderFetch(globalObject, exec, this, key, initiator);
+        return globalObject->globalObjectMethodTable()->moduleLoaderFetch(globalObject, exec, this, key, scriptFetcher);
     JSInternalPromiseDeferred* deferred = JSInternalPromiseDeferred::create(exec, globalObject);
     String moduleKey = key.toWTFString(exec);
     if (UNLIKELY(scope.exception())) {
@@ -196,27 +196,27 @@ JSInternalPromise* JSModuleLoader::fetch(ExecState* exec, JSValue key, JSValue i
     return deferred->promise();
 }
 
-JSInternalPromise* JSModuleLoader::instantiate(ExecState* exec, JSValue key, JSValue source, JSValue initiator)
+JSInternalPromise* JSModuleLoader::instantiate(ExecState* exec, JSValue key, JSValue source, JSValue scriptFetcher)
 {
     if (Options::dumpModuleLoadingState())
         dataLog("Loader [instantiate] ", printableModuleKey(exec, key), "\n");
 
     JSGlobalObject* globalObject = exec->lexicalGlobalObject();
     if (globalObject->globalObjectMethodTable()->moduleLoaderInstantiate)
-        return globalObject->globalObjectMethodTable()->moduleLoaderInstantiate(globalObject, exec, this, key, source, initiator);
+        return globalObject->globalObjectMethodTable()->moduleLoaderInstantiate(globalObject, exec, this, key, source, scriptFetcher);
     JSInternalPromiseDeferred* deferred = JSInternalPromiseDeferred::create(exec, globalObject);
     deferred->resolve(exec, jsUndefined());
     return deferred->promise();
 }
 
-JSValue JSModuleLoader::evaluate(ExecState* exec, JSValue key, JSValue moduleRecordValue, JSValue initiator)
+JSValue JSModuleLoader::evaluate(ExecState* exec, JSValue key, JSValue moduleRecordValue, JSValue scriptFetcher)
 {
     if (Options::dumpModuleLoadingState())
         dataLog("Loader [evaluate] ", printableModuleKey(exec, key), "\n");
 
     JSGlobalObject* globalObject = exec->lexicalGlobalObject();
     if (globalObject->globalObjectMethodTable()->moduleLoaderEvaluate)
-        return globalObject->globalObjectMethodTable()->moduleLoaderEvaluate(globalObject, exec, this, key, moduleRecordValue, initiator);
+        return globalObject->globalObjectMethodTable()->moduleLoaderEvaluate(globalObject, exec, this, key, moduleRecordValue, scriptFetcher);
 
     JSModuleRecord* moduleRecord = jsDynamicCast<JSModuleRecord*>(moduleRecordValue);
     if (!moduleRecord)
index 62cc382..5db1eff 100644 (file)
@@ -64,18 +64,18 @@ public:
 
     // APIs to control the module loader.
     JSValue provide(ExecState*, JSValue key, Status, const SourceCode&);
-    JSInternalPromise* loadAndEvaluateModule(ExecState*, JSValue moduleName, JSValue referrer, JSValue initiator);
-    JSInternalPromise* loadModule(ExecState*, JSValue moduleName, JSValue referrer, JSValue initiator);
-    JSValue linkAndEvaluateModule(ExecState*, JSValue moduleKey, JSValue initiator);
+    JSInternalPromise* loadAndEvaluateModule(ExecState*, JSValue moduleName, JSValue referrer, JSValue scriptFetcher);
+    JSInternalPromise* loadModule(ExecState*, JSValue moduleName, JSValue referrer, JSValue scriptFetcher);
+    JSValue linkAndEvaluateModule(ExecState*, JSValue moduleKey, JSValue scriptFetcher);
 
     // Platform dependent hooked APIs.
     JSInternalPromise* importModule(ExecState*, JSString* moduleName, const SourceOrigin& referrer);
-    JSInternalPromise* resolve(ExecState*, JSValue name, JSValue referrer, JSValue initiator);
-    JSInternalPromise* fetch(ExecState*, JSValue key, JSValue initiator);
-    JSInternalPromise* instantiate(ExecState*, JSValue key, JSValue source, JSValue initiator);
+    JSInternalPromise* resolve(ExecState*, JSValue name, JSValue referrer, JSValue scriptFetcher);
+    JSInternalPromise* fetch(ExecState*, JSValue key, JSValue scriptFetcher);
+    JSInternalPromise* instantiate(ExecState*, JSValue key, JSValue source, JSValue scriptFetcher);
 
     // Additional platform dependent hooked APIs.
-    JSValue evaluate(ExecState*, JSValue key, JSValue moduleRecord, JSValue initiator);
+    JSValue evaluate(ExecState*, JSValue key, JSValue moduleRecord, JSValue scriptFetcher);
 
     // Utility functions.
     JSModuleNamespaceObject* getModuleNamespaceObject(ExecState*, JSValue moduleRecord);
diff --git a/Source/JavaScriptCore/runtime/JSScriptFetcher.cpp b/Source/JavaScriptCore/runtime/JSScriptFetcher.cpp
new file mode 100644 (file)
index 0000000..ca3c5ba
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2017 Yusuke Suzuki <utatane.tea@gmail.com>
+ *
+ * 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.
+ */
+
+#include "config.h"
+#include "JSScriptFetcher.h"
+
+#include "JSCInlines.h"
+
+namespace JSC {
+
+const ClassInfo JSScriptFetcher::s_info = { "JSScriptFetcher", nullptr, nullptr, CREATE_METHOD_TABLE(JSScriptFetcher) };
+
+void JSScriptFetcher::destroy(JSCell* cell)
+{
+    static_cast<JSScriptFetcher*>(cell)->~JSScriptFetcher();
+}
+
+} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/JSScriptFetcher.h b/Source/JavaScriptCore/runtime/JSScriptFetcher.h
new file mode 100644 (file)
index 0000000..0994db1
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2017 Yusuke Suzuki <utatane.tea@gmail.com>
+ *
+ * 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
+
+#include "JSGlobalObject.h"
+#include "JSObject.h"
+#include "ScriptFetcher.h"
+
+namespace JSC {
+
+class JSScriptFetcher : public JSCell {
+public:
+    using Base = JSCell;
+
+    static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
+    static const bool needsDestruction = true;
+
+    DECLARE_EXPORT_INFO;
+
+    static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
+    {
+        return Structure::create(vm, globalObject, prototype, TypeInfo(JSScriptFetcherType, StructureFlags), info());
+    }
+
+    static JSScriptFetcher* create(VM& vm, Structure* structure, RefPtr<ScriptFetcher>&& scriptFetcher)
+    {
+        auto* result = new (NotNull, allocateCell<JSScriptFetcher>(vm.heap)) JSScriptFetcher(vm, structure, WTFMove(scriptFetcher));
+        result->finishCreation(vm);
+        return result;
+    }
+
+    static JSScriptFetcher* create(VM& vm, RefPtr<ScriptFetcher>&& scriptFetcher)
+    {
+        return create(vm, vm.scriptFetcherStructure.get(), WTFMove(scriptFetcher));
+    }
+
+    ScriptFetcher* fetcher() const
+    {
+        return m_fetcher.get();
+    }
+
+    static void destroy(JSCell*);
+
+private:
+    JSScriptFetcher(VM& vm, Structure* structure, RefPtr<ScriptFetcher>&& scriptFetcher)
+        : Base(vm, structure)
+        , m_fetcher(WTFMove(scriptFetcher))
+    {
+    }
+
+    RefPtr<ScriptFetcher> m_fetcher;
+};
+
+} // namespace JSC
index ae184de..bef6c06 100644 (file)
@@ -51,6 +51,7 @@ enum JSType : uint8_t {
 
     JSFixedArrayType,
     JSSourceCodeType,
+    JSScriptFetcherType,
 
     // The ObjectType value must come before any JSType that is a subclass of JSObject.
     ObjectType,
diff --git a/Source/JavaScriptCore/runtime/ScriptFetcher.h b/Source/JavaScriptCore/runtime/ScriptFetcher.h
new file mode 100644 (file)
index 0000000..bd0ae29
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2017 Yusuke Suzuki <utatane.tea@gmail.com>
+ *
+ * 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
+
+#include <wtf/RefCounted.h>
+
+namespace JSC {
+
+class ScriptFetcher : public RefCounted<ScriptFetcher> {
+public:
+    virtual ~ScriptFetcher() { }
+};
+
+} // namespace JSC
index 38e99ad..2abc8a2 100644 (file)
@@ -71,6 +71,7 @@
 #include "JSMap.h"
 #include "JSPromiseDeferred.h"
 #include "JSPropertyNameEnumerator.h"
+#include "JSScriptFetcher.h"
 #include "JSSourceCode.h"
 #include "JSTemplateRegistryKey.h"
 #include "JSWebAssembly.h"
@@ -240,6 +241,7 @@ VM::VM(VMType vmType, HeapType heapType)
     symbolTableStructure.set(*this, SymbolTable::createStructure(*this, 0, jsNull()));
     fixedArrayStructure.set(*this, JSFixedArray::createStructure(*this, 0, jsNull()));
     sourceCodeStructure.set(*this, JSSourceCode::createStructure(*this, 0, jsNull()));
+    scriptFetcherStructure.set(*this, JSScriptFetcher::createStructure(*this, 0, jsNull()));
     structureChainStructure.set(*this, StructureChain::createStructure(*this, 0, jsNull()));
     sparseArrayValueMapStructure.set(*this, SparseArrayValueMap::createStructure(*this, 0, jsNull()));
     templateRegistryKeyStructure.set(*this, JSTemplateRegistryKey::createStructure(*this, 0, jsNull()));
index 3ebed73..2a82fe0 100644 (file)
@@ -327,6 +327,7 @@ public:
     Strong<Structure> symbolTableStructure;
     Strong<Structure> fixedArrayStructure;
     Strong<Structure> sourceCodeStructure;
+    Strong<Structure> scriptFetcherStructure;
     Strong<Structure> structureChainStructure;
     Strong<Structure> sparseArrayValueMapStructure;
     Strong<Structure> templateRegistryKeyStructure;
index f1509c0..2019a92 100644 (file)
@@ -1,3 +1,80 @@
+2017-01-11  Yusuke Suzuki  <utatane.tea@gmail.com>
+
+        Decouple module loading initiator from ScriptElement
+        https://bugs.webkit.org/show_bug.cgi?id=166888
+
+        Reviewed by Saam Barati and Ryosuke Niwa.
+
+        Previously, we use ScriptElement (JSElement for ScriptElement) as the module loading initiator.
+        This element is used to transfer the metadata like charset throughout the module pipeline.
+        As a result, our module loader in the browser side is tightly coupled with ScriptElement.
+        It is not good since it prevent us from using the module loader in the non-DOM environment like
+        Web Workers.
+
+        So we decouple the necessary informations from ScriptElement. We move these information to
+        LoadableScript. And we use JSScriptFetcher to transfer LoadableScript through the JS implemented
+        module loader pipeline. We select LoadableScript instead of LoadableModuleScript since this initiator
+        information will be leveraged even in classic scripts once we implement the dynamic import.
+
+        No behavior change.
+
+        * ForwardingHeaders/runtime/JSScriptFetcher.h: Copied from Source/WebCore/dom/LoadableScript.cpp.
+        * ForwardingHeaders/runtime/ScriptFetcher.h: Copied from Source/WebCore/dom/LoadableScript.cpp.
+        * bindings/js/CachedModuleScript.cpp:
+        (WebCore::CachedModuleScript::create):
+        (WebCore::CachedModuleScript::load):
+        (WebCore::CachedModuleScript::CachedModuleScript): Deleted.
+        * bindings/js/CachedModuleScript.h:
+        Now we can merge CachedModuleScript to LoadableScript. But we do not do this in this patch since
+        we focus on decoupling the initiator information from ScriptElement.
+
+        (WebCore::CachedModuleScript::nonce): Deleted.
+        (WebCore::CachedModuleScript::crossOriginMode): Deleted.
+        * bindings/js/CachedModuleScriptLoader.cpp:
+        (WebCore::CachedModuleScriptLoader::load):
+        * bindings/js/CachedModuleScriptLoader.h:
+        * bindings/js/JSDOMWindowBase.cpp:
+        (WebCore::JSDOMWindowBase::moduleLoaderResolve):
+        (WebCore::JSDOMWindowBase::moduleLoaderFetch):
+        (WebCore::JSDOMWindowBase::moduleLoaderEvaluate):
+        * bindings/js/JSMainThreadExecState.h:
+        (WebCore::JSMainThreadExecState::loadModule):
+        (WebCore::JSMainThreadExecState::linkAndEvaluateModule):
+        * bindings/js/ScriptController.cpp:
+        (WebCore::ScriptController::loadModuleScriptInWorld):
+        (WebCore::ScriptController::loadModuleScript):
+        (WebCore::ScriptController::linkAndEvaluateModuleScriptInWorld):
+        (WebCore::ScriptController::linkAndEvaluateModuleScript):
+        * bindings/js/ScriptController.h:
+        * bindings/js/ScriptModuleLoader.cpp:
+        (WebCore::ScriptModuleLoader::fetch):
+        * bindings/js/ScriptModuleLoader.h:
+        * dom/LoadableClassicScript.cpp:
+        (WebCore::LoadableClassicScript::create):
+        (WebCore::LoadableClassicScript::~LoadableClassicScript):
+        (WebCore::LoadableClassicScript::isLoaded):
+        (WebCore::LoadableClassicScript::error):
+        (WebCore::LoadableClassicScript::wasCanceled):
+        (WebCore::LoadableClassicScript::notifyFinished):
+        (WebCore::LoadableClassicScript::load):
+        * dom/LoadableClassicScript.h:
+        * dom/LoadableModuleScript.cpp:
+        (WebCore::LoadableModuleScript::create):
+        (WebCore::LoadableModuleScript::LoadableModuleScript):
+        (WebCore::LoadableModuleScript::load):
+        * dom/LoadableModuleScript.h:
+        * dom/LoadableScript.cpp:
+        (WebCore::LoadableScript::requestScriptWithCache):
+        * dom/LoadableScript.h:
+        (WebCore::LoadableScript::LoadableScript):
+        * dom/ScriptElement.cpp:
+        (WebCore::ScriptElement::requestClassicScript):
+        (WebCore::ScriptElement::requestModuleScript):
+        (WebCore::ScriptElement::executeModuleScript):
+        (WebCore::ScriptElement::requestScriptWithCacheForModuleScript): Deleted.
+        (WebCore::ScriptElement::requestScriptWithCache): Deleted.
+        * dom/ScriptElement.h:
+
 2017-01-11  Carlos Garcia Campos  <cgarcia@igalia.com>
 
         [GStreamer] Use smart pointers and modernize code in WebKitWebAudioSourceGStreamer
diff --git a/Source/WebCore/ForwardingHeaders/runtime/JSScriptFetcher.h b/Source/WebCore/ForwardingHeaders/runtime/JSScriptFetcher.h
new file mode 100644 (file)
index 0000000..b073afb
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2017 Yusuke Suzuki <utatane.tea@gmail.com>
+ *
+ * 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
+#include <JavaScriptCore/JSScriptFetcher.h>
diff --git a/Source/WebCore/ForwardingHeaders/runtime/ScriptFetcher.h b/Source/WebCore/ForwardingHeaders/runtime/ScriptFetcher.h
new file mode 100644 (file)
index 0000000..6658334
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2017 Yusuke Suzuki <utatane.tea@gmail.com>
+ *
+ * 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
+#include <JavaScriptCore/ScriptFetcher.h>
index 4bef2a8..0fec4b5 100644 (file)
 #include "CachedModuleScriptClient.h"
 #include "DOMWrapperWorld.h"
 #include "Document.h"
-#include "Element.h"
 #include "ExceptionCode.h"
 #include "Frame.h"
 #include "ScriptController.h"
-#include "ScriptElement.h"
 #include "ScriptModuleLoader.h"
 #include "ScriptRunner.h"
 #include "ScriptSourceCode.h"
 
 namespace WebCore {
 
-Ref<CachedModuleScript> CachedModuleScript::create(const String& nonce, const String& crossOriginMode)
+Ref<CachedModuleScript> CachedModuleScript::create()
 {
-    return adoptRef(*new CachedModuleScript(nonce, crossOriginMode));
+    return adoptRef(*new CachedModuleScript());
 }
 
-CachedModuleScript::CachedModuleScript(const String& nonce, const String& crossOriginMode)
-    : m_nonce(nonce)
-    , m_crossOriginMode(crossOriginMode)
+void CachedModuleScript::load(Document& document, const URL& rootURL, LoadableScript& loadableScript)
 {
+    if (auto* frame = document.frame())
+        frame->script().loadModuleScript(*this, rootURL.string(), loadableScript);
 }
 
-void CachedModuleScript::load(Element& initiator, const URL& rootURL)
+void CachedModuleScript::load(Document& document, const ScriptSourceCode& sourceCode, LoadableScript& loadableScript)
 {
-    if (auto* frame = initiator.document().frame())
-        frame->script().loadModuleScript(*this, rootURL.string(), initiator);
-}
-
-void CachedModuleScript::load(Element& initiator, const ScriptSourceCode& sourceCode)
-{
-    if (auto* frame = initiator.document().frame())
-        frame->script().loadModuleScript(*this, sourceCode, initiator);
+    if (auto* frame = document.frame())
+        frame->script().loadModuleScript(*this, sourceCode, loadableScript);
 }
 
 void CachedModuleScript::notifyLoadCompleted(UniquedStringImpl& moduleKey)
index 9eaa76b..562d93d 100644 (file)
 namespace WebCore {
 
 class CachedModuleScriptClient;
-class Element;
+class Document;
 class ScriptSourceCode;
 
 class CachedModuleScript : public RefCounted<CachedModuleScript> {
 public:
     UniquedStringImpl* moduleKey() { return m_moduleKey.get(); }
 
-    void evaluate(Element&);
-
     void notifyLoadCompleted(UniquedStringImpl& moduleKey);
     void notifyLoadFailed(LoadableScript::Error&&);
     void notifyLoadWasCanceled();
@@ -52,23 +50,16 @@ public:
     void addClient(CachedModuleScriptClient&);
     void removeClient(CachedModuleScriptClient&);
 
-    static Ref<CachedModuleScript> create(const String& nonce, const String& crossOriginMode);
-
-    void load(Element& initiator, const URL& rootURL);
-    void load(Element& initiator, const ScriptSourceCode&);
+    static Ref<CachedModuleScript> create();
 
-    const String& nonce() const { return m_nonce; }
-    const String& crossOriginMode() const { return m_crossOriginMode; }
+    void load(Document&, const URL& rootURL, LoadableScript&);
+    void load(Document&, const ScriptSourceCode&, LoadableScript&);
 
 private:
-    CachedModuleScript(const String& nonce, const String& crossOriginMode);
-
     void notifyClientFinished();
 
     RefPtr<UniquedStringImpl> m_moduleKey;
     HashCountedSet<CachedModuleScriptClient*> m_clients;
-    String m_nonce;
-    String m_crossOriginMode;
     std::optional<LoadableScript::Error> m_error;
     bool m_wasCanceled { false };
     bool m_isLoaded { false };
index c499cda..60bdd48 100644 (file)
 #include "config.h"
 #include "CachedModuleScriptLoader.h"
 
-#include "CachedResourceLoader.h"
 #include "CachedScript.h"
 #include "DOMWrapperWorld.h"
 #include "Frame.h"
 #include "JSDOMBinding.h"
+#include "LoadableScript.h"
 #include "ResourceLoaderOptions.h"
 #include "ScriptController.h"
-#include "ScriptElement.h"
 #include "ScriptModuleLoader.h"
 #include "ScriptSourceCode.h"
 
@@ -58,10 +57,10 @@ CachedModuleScriptLoader::~CachedModuleScriptLoader()
     }
 }
 
-bool CachedModuleScriptLoader::load(ScriptElement& scriptElement, const URL& sourceURL)
+bool CachedModuleScriptLoader::load(Document& document, LoadableScript& loadableScript, const URL& sourceURL)
 {
     ASSERT(!m_cachedScript);
-    m_cachedScript = scriptElement.requestScriptWithCacheForModuleScript(sourceURL);
+    m_cachedScript = loadableScript.requestScriptWithCache(document, sourceURL);
     if (!m_cachedScript)
         return false;
 
index 8b35fcb..32fde3b 100644 (file)
@@ -36,8 +36,9 @@ namespace WebCore {
 class CachedModuleScriptLoaderClient;
 class CachedScript;
 class DeferredPromise;
+class Document;
 class JSDOMGlobalObject;
-class ScriptElement;
+class LoadableScript;
 class URL;
 
 class CachedModuleScriptLoader final : public RefCounted<CachedModuleScriptLoader>, private CachedResourceClient {
@@ -46,7 +47,7 @@ public:
 
     virtual ~CachedModuleScriptLoader();
 
-    bool load(ScriptElement&, const URL& sourceURL);
+    bool load(Document&, LoadableScript&, const URL& sourceURL);
 
     CachedScript* cachedScript() { return m_cachedScript.get(); }
 
index 397e594..54b93eb 100644 (file)
@@ -305,29 +305,29 @@ void JSDOMWindowBase::fireFrameClearedWatchpointsForWindow(DOMWindow* window)
 }
 
 
-JSC::JSInternalPromise* JSDOMWindowBase::moduleLoaderResolve(JSC::JSGlobalObject* globalObject, JSC::ExecState* exec, JSC::JSModuleLoader* moduleLoader, JSC::JSValue moduleName, JSC::JSValue importerModuleKey, JSC::JSValue initiator)
+JSC::JSInternalPromise* JSDOMWindowBase::moduleLoaderResolve(JSC::JSGlobalObject* globalObject, JSC::ExecState* exec, JSC::JSModuleLoader* moduleLoader, JSC::JSValue moduleName, JSC::JSValue importerModuleKey, JSC::JSValue scriptFetcher)
 {
     JSDOMWindowBase* thisObject = JSC::jsCast<JSDOMWindowBase*>(globalObject);
     if (RefPtr<Document> document = thisObject->wrapped().document())
-        return document->moduleLoader()->resolve(globalObject, exec, moduleLoader, moduleName, importerModuleKey, initiator);
+        return document->moduleLoader()->resolve(globalObject, exec, moduleLoader, moduleName, importerModuleKey, scriptFetcher);
     JSC::JSInternalPromiseDeferred* deferred = JSC::JSInternalPromiseDeferred::create(exec, globalObject);
     return deferred->reject(exec, jsUndefined());
 }
 
-JSC::JSInternalPromise* JSDOMWindowBase::moduleLoaderFetch(JSC::JSGlobalObject* globalObject, JSC::ExecState* exec, JSC::JSModuleLoader* moduleLoader, JSC::JSValue moduleKey, JSC::JSValue initiator)
+JSC::JSInternalPromise* JSDOMWindowBase::moduleLoaderFetch(JSC::JSGlobalObject* globalObject, JSC::ExecState* exec, JSC::JSModuleLoader* moduleLoader, JSC::JSValue moduleKey, JSC::JSValue scriptFetcher)
 {
     JSDOMWindowBase* thisObject = JSC::jsCast<JSDOMWindowBase*>(globalObject);
     if (RefPtr<Document> document = thisObject->wrapped().document())
-        return document->moduleLoader()->fetch(globalObject, exec, moduleLoader, moduleKey, initiator);
+        return document->moduleLoader()->fetch(globalObject, exec, moduleLoader, moduleKey, scriptFetcher);
     JSC::JSInternalPromiseDeferred* deferred = JSC::JSInternalPromiseDeferred::create(exec, globalObject);
     return deferred->reject(exec, jsUndefined());
 }
 
-JSC::JSValue JSDOMWindowBase::moduleLoaderEvaluate(JSC::JSGlobalObject* globalObject, JSC::ExecState* exec, JSC::JSModuleLoader* moduleLoader, JSC::JSValue moduleKey, JSC::JSValue moduleRecord, JSC::JSValue initiator)
+JSC::JSValue JSDOMWindowBase::moduleLoaderEvaluate(JSC::JSGlobalObject* globalObject, JSC::ExecState* exec, JSC::JSModuleLoader* moduleLoader, JSC::JSValue moduleKey, JSC::JSValue moduleRecord, JSC::JSValue scriptFetcher)
 {
     JSDOMWindowBase* thisObject = JSC::jsCast<JSDOMWindowBase*>(globalObject);
     if (RefPtr<Document> document = thisObject->wrapped().document())
-        return document->moduleLoader()->evaluate(globalObject, exec, moduleLoader, moduleKey, moduleRecord, initiator);
+        return document->moduleLoader()->evaluate(globalObject, exec, moduleLoader, moduleKey, moduleRecord, scriptFetcher);
     return JSC::jsUndefined();
 }
 
index c2766f0..d244efe 100644 (file)
@@ -93,25 +93,25 @@ public:
         task.run(exec);
     }
 
-    static JSC::JSInternalPromise& loadModule(JSC::ExecState& state, const String& moduleName, JSC::JSValue initiator)
+    static JSC::JSInternalPromise& loadModule(JSC::ExecState& state, const String& moduleName, JSC::JSValue scriptFetcher)
     {
         JSMainThreadExecState currentState(&state);
-        return *JSC::loadModule(&state, moduleName, initiator);
+        return *JSC::loadModule(&state, moduleName, scriptFetcher);
     }
 
-    static JSC::JSInternalPromise& loadModule(JSC::ExecState& state, const JSC::SourceCode& sourceCode, JSC::JSValue initiator)
+    static JSC::JSInternalPromise& loadModule(JSC::ExecState& state, const JSC::SourceCode& sourceCode, JSC::JSValue scriptFetcher)
     {
         JSMainThreadExecState currentState(&state);
-        return *JSC::loadModule(&state, sourceCode, initiator);
+        return *JSC::loadModule(&state, sourceCode, scriptFetcher);
     }
 
-    static JSC::JSValue linkAndEvaluateModule(JSC::ExecState& state, const JSC::Identifier& moduleKey, JSC::JSValue initiator, NakedPtr<JSC::Exception>& returnedException)
+    static JSC::JSValue linkAndEvaluateModule(JSC::ExecState& state, const JSC::Identifier& moduleKey, JSC::JSValue scriptFetcher, NakedPtr<JSC::Exception>& returnedException)
     {
         JSC::VM& vm = state.vm();
         auto scope = DECLARE_CATCH_SCOPE(vm);
     
         JSMainThreadExecState currentState(&state);
-        auto returnValue = JSC::linkAndEvaluateModule(&state, moduleKey, initiator);
+        auto returnValue = JSC::linkAndEvaluateModule(&state, moduleKey, scriptFetcher);
         if (UNLIKELY(scope.exception())) {
             returnedException = scope.exception();
             scope.clearException();
index 37c9edf..3237635 100644 (file)
@@ -43,7 +43,6 @@
 #include "PageConsoleClient.h"
 #include "PageGroup.h"
 #include "PluginViewBase.h"
-#include "ScriptElement.h"
 #include "ScriptSourceCode.h"
 #include "ScriptableDocumentParser.h"
 #include "Settings.h"
@@ -60,6 +59,7 @@
 #include <runtime/JSLock.h>
 #include <runtime/JSModuleRecord.h>
 #include <runtime/JSNativeStdFunction.h>
+#include <runtime/JSScriptFetcher.h>
 #include <wtf/SetForScope.h>
 #include <wtf/Threading.h>
 #include <wtf/text/TextPosition.h>
@@ -186,39 +186,39 @@ JSValue ScriptController::evaluate(const ScriptSourceCode& sourceCode, Exception
     return evaluateInWorld(sourceCode, mainThreadNormalWorld(), exceptionDetails);
 }
 
-void ScriptController::loadModuleScriptInWorld(CachedModuleScript& moduleScript, const String& moduleName, DOMWrapperWorld& world, Element& element)
+void ScriptController::loadModuleScriptInWorld(CachedModuleScript& moduleScript, const String& moduleName, LoadableScript& loadableScript, DOMWrapperWorld& world)
 {
     JSLockHolder lock(world.vm());
 
     auto& shell = *windowShell(world);
     auto& state = *shell.window()->globalExec();
 
-    auto& promise = JSMainThreadExecState::loadModule(state, moduleName, toJS(&state, shell.window(), &element));
+    auto& promise = JSMainThreadExecState::loadModule(state, moduleName, JSC::JSScriptFetcher::create(state.vm(), { &loadableScript }));
     setupModuleScriptHandlers(moduleScript, promise, world);
 }
 
-void ScriptController::loadModuleScript(CachedModuleScript& moduleScript, const String& moduleName, Element& element)
+void ScriptController::loadModuleScript(CachedModuleScript& moduleScript, const String& moduleName, LoadableScript& loadableScript)
 {
-    loadModuleScriptInWorld(moduleScript, moduleName, mainThreadNormalWorld(), element);
+    loadModuleScriptInWorld(moduleScript, moduleName, loadableScript, mainThreadNormalWorld());
 }
 
-void ScriptController::loadModuleScriptInWorld(CachedModuleScript& moduleScript, const ScriptSourceCode& sourceCode, DOMWrapperWorld& world, Element& element)
+void ScriptController::loadModuleScriptInWorld(CachedModuleScript& moduleScript, const ScriptSourceCode& sourceCode, LoadableScript& loadableScript, DOMWrapperWorld& world)
 {
     JSLockHolder lock(world.vm());
 
     auto& shell = *windowShell(world);
     auto& state = *shell.window()->globalExec();
 
-    auto& promise = JSMainThreadExecState::loadModule(state, sourceCode.jsSourceCode(), toJS(&state, shell.window(), &element));
+    auto& promise = JSMainThreadExecState::loadModule(state, sourceCode.jsSourceCode(), JSC::JSScriptFetcher::create(state.vm(), { &loadableScript }));
     setupModuleScriptHandlers(moduleScript, promise, world);
 }
 
-void ScriptController::loadModuleScript(CachedModuleScript& moduleScript, const ScriptSourceCode& sourceCode, Element& element)
+void ScriptController::loadModuleScript(CachedModuleScript& moduleScript, const ScriptSourceCode& sourceCode, LoadableScript& loadableScript)
 {
-    loadModuleScriptInWorld(moduleScript, sourceCode, mainThreadNormalWorld(), element);
+    loadModuleScriptInWorld(moduleScript, sourceCode, loadableScript, mainThreadNormalWorld());
 }
 
-JSC::JSValue ScriptController::linkAndEvaluateModuleScriptInWorld(CachedModuleScript& moduleScript, DOMWrapperWorld& world, Element& element)
+JSC::JSValue ScriptController::linkAndEvaluateModuleScriptInWorld(CachedModuleScript& moduleScript, DOMWrapperWorld& world)
 {
     JSLockHolder lock(world.vm());
 
@@ -230,7 +230,7 @@ JSC::JSValue ScriptController::linkAndEvaluateModuleScriptInWorld(CachedModuleSc
     Ref<Frame> protector(m_frame);
 
     NakedPtr<JSC::Exception> evaluationException;
-    auto returnValue = JSMainThreadExecState::linkAndEvaluateModule(state, Identifier::fromUid(&state.vm(), moduleScript.moduleKey()), toJS(&state, shell.window(), &element), evaluationException);
+    auto returnValue = JSMainThreadExecState::linkAndEvaluateModule(state, Identifier::fromUid(&state.vm(), moduleScript.moduleKey()), jsUndefined(), evaluationException);
     if (evaluationException) {
         // FIXME: Give a chance to dump the stack trace if the "crossorigin" attribute allows.
         // https://bugs.webkit.org/show_bug.cgi?id=164539
@@ -240,9 +240,9 @@ JSC::JSValue ScriptController::linkAndEvaluateModuleScriptInWorld(CachedModuleSc
     return returnValue;
 }
 
-JSC::JSValue ScriptController::linkAndEvaluateModuleScript(CachedModuleScript& moduleScript, Element& element)
+JSC::JSValue ScriptController::linkAndEvaluateModuleScript(CachedModuleScript& moduleScript)
 {
-    return linkAndEvaluateModuleScriptInWorld(moduleScript, mainThreadNormalWorld(), element);
+    return linkAndEvaluateModuleScriptInWorld(moduleScript, mainThreadNormalWorld());
 }
 
 JSC::JSValue ScriptController::evaluateModule(const URL& sourceURL, JSModuleRecord& moduleRecord, DOMWrapperWorld& world)
index 5268f01..9e20c2c 100644 (file)
@@ -55,6 +55,7 @@ class CachedModuleScript;
 class Frame;
 class HTMLDocument;
 class HTMLPlugInElement;
+class LoadableScript;
 class SecurityOrigin;
 class ScriptSourceCode;
 class Widget;
@@ -113,13 +114,13 @@ public:
     JSC::JSValue evaluate(const ScriptSourceCode&, ExceptionDetails* = nullptr);
     JSC::JSValue evaluateInWorld(const ScriptSourceCode&, DOMWrapperWorld&, ExceptionDetails* = nullptr);
 
-    void loadModuleScriptInWorld(CachedModuleScript&, const String& moduleName, DOMWrapperWorld&, Element&);
-    void loadModuleScript(CachedModuleScript&, const String& moduleName, Element&);
-    void loadModuleScriptInWorld(CachedModuleScript&, const ScriptSourceCode&, DOMWrapperWorld&, Element&);
-    void loadModuleScript(CachedModuleScript&, const ScriptSourceCode&, Element&);
+    void loadModuleScriptInWorld(CachedModuleScript&, const String& moduleName, LoadableScript&, DOMWrapperWorld&);
+    void loadModuleScript(CachedModuleScript&, const String& moduleName, LoadableScript&);
+    void loadModuleScriptInWorld(CachedModuleScript&, const ScriptSourceCode&, LoadableScript&, DOMWrapperWorld&);
+    void loadModuleScript(CachedModuleScript&, const ScriptSourceCode&, LoadableScript&);
 
-    JSC::JSValue linkAndEvaluateModuleScriptInWorld(CachedModuleScript& , DOMWrapperWorld&, Element&);
-    JSC::JSValue linkAndEvaluateModuleScript(CachedModuleScript&, Element&);
+    JSC::JSValue linkAndEvaluateModuleScriptInWorld(CachedModuleScript& , DOMWrapperWorld&);
+    JSC::JSValue linkAndEvaluateModuleScript(CachedModuleScript&);
 
     JSC::JSValue evaluateModule(const URL&, JSC::JSModuleRecord&, DOMWrapperWorld&);
     JSC::JSValue evaluateModule(const URL&, JSC::JSModuleRecord&);
index b3f65b2..8dd24c3 100644 (file)
 #include "Document.h"
 #include "Frame.h"
 #include "JSDOMBinding.h"
-#include "JSElement.h"
 #include "LoadableModuleScript.h"
 #include "MIMETypeRegistry.h"
 #include "ScriptController.h"
-#include "ScriptElement.h"
 #include "ScriptSourceCode.h"
 #include <runtime/JSInternalPromise.h>
 #include <runtime/JSInternalPromiseDeferred.h>
 #include <runtime/JSModuleRecord.h>
+#include <runtime/JSScriptFetcher.h>
 #include <runtime/JSSourceCode.h>
 #include <runtime/JSString.h>
 #include <runtime/Symbol.h>
@@ -134,11 +133,9 @@ JSC::JSInternalPromise* ScriptModuleLoader::resolve(JSC::JSGlobalObject* jsGloba
     return jsPromise.promise();
 }
 
-JSC::JSInternalPromise* ScriptModuleLoader::fetch(JSC::JSGlobalObject* jsGlobalObject, JSC::ExecState* exec, JSC::JSModuleLoader*, JSC::JSValue moduleKeyValue, JSC::JSValue initiator)
+JSC::JSInternalPromise* ScriptModuleLoader::fetch(JSC::JSGlobalObject* jsGlobalObject, JSC::ExecState* exec, JSC::JSModuleLoader*, JSC::JSValue moduleKeyValue, JSC::JSValue scriptFetcher)
 {
-    // FIXME: What guarantees these are true? Why don't we need to check?
-    ASSERT(JSC::jsDynamicCast<JSElement*>(initiator));
-    ASSERT(isScriptElement(JSC::jsDynamicCast<JSElement*>(initiator)->wrapped()));
+    ASSERT(JSC::jsDynamicCast<JSC::JSScriptFetcher*>(scriptFetcher));
 
     auto& globalObject = *JSC::jsCast<JSDOMGlobalObject*>(jsGlobalObject);
     auto& jsPromise = *JSC::JSInternalPromiseDeferred::create(exec, &globalObject);
@@ -164,7 +161,7 @@ JSC::JSInternalPromise* ScriptModuleLoader::fetch(JSC::JSGlobalObject* jsGlobalO
     if (auto* frame = m_document.frame()) {
         auto loader = CachedModuleScriptLoader::create(*this, deferred.get());
         m_loaders.add(loader.copyRef());
-        if (!loader->load(downcastScriptElement(JSC::jsCast<JSElement*>(initiator)->wrapped()), completedURL)) {
+        if (!loader->load(m_document, *static_cast<LoadableScript*>(JSC::jsCast<JSC::JSScriptFetcher*>(scriptFetcher)->fetcher()), completedURL)) {
             loader->clearClient();
             m_loaders.remove(WTFMove(loader));
             deferred->reject(frame->script().moduleLoaderAlreadyReportedErrorSymbol());
index 6f7dc67..a0683ff 100644 (file)
@@ -54,9 +54,9 @@ public:
 
     Document& document() { return m_document; }
 
-    JSC::JSInternalPromise* resolve(JSC::JSGlobalObject*, JSC::ExecState*, JSC::JSModuleLoader*, JSC::JSValue moduleName, JSC::JSValue importerModuleKey, JSC::JSValue initiator);
-    JSC::JSInternalPromise* fetch(JSC::JSGlobalObject*, JSC::ExecState*, JSC::JSModuleLoader*, JSC::JSValue moduleKey, JSC::JSValue initiator);
-    JSC::JSValue evaluate(JSC::JSGlobalObject*, JSC::ExecState*, JSC::JSModuleLoader*, JSC::JSValue moduleKey, JSC::JSValue moduleRecord, JSC::JSValue initiator);
+    JSC::JSInternalPromise* resolve(JSC::JSGlobalObject*, JSC::ExecState*, JSC::JSModuleLoader*, JSC::JSValue moduleName, JSC::JSValue importerModuleKey, JSC::JSValue scriptFetcher);
+    JSC::JSInternalPromise* fetch(JSC::JSGlobalObject*, JSC::ExecState*, JSC::JSModuleLoader*, JSC::JSValue moduleKey, JSC::JSValue scriptFetcher);
+    JSC::JSValue evaluate(JSC::JSGlobalObject*, JSC::ExecState*, JSC::JSModuleLoader*, JSC::JSValue moduleKey, JSC::JSValue moduleRecord, JSC::JSValue scriptFetcher);
 
 private:
     void notifyFinished(CachedModuleScriptLoader&, RefPtr<DeferredPromise>) final;
index 90961b8..98cb06d 100644 (file)
 
 namespace WebCore {
 
-Ref<LoadableClassicScript> LoadableClassicScript::create(CachedResourceHandle<CachedScript>&& cachedScript)
+Ref<LoadableClassicScript> LoadableClassicScript::create(const String& nonce, const String& crossOriginMode, const String& charset, const AtomicString& initiatorName, bool isInUserAgentShadowTree)
 {
-    ASSERT(cachedScript);
-    auto script = adoptRef(*new LoadableClassicScript(WTFMove(cachedScript)));
-    cachedScript->addClient(script.get());
-    return script;
+    return adoptRef(*new LoadableClassicScript(nonce, crossOriginMode, charset, initiatorName, isInUserAgentShadowTree));
 }
 
 LoadableClassicScript::~LoadableClassicScript()
 {
-    m_cachedScript->removeClient(*this);
+    if (m_cachedScript)
+        m_cachedScript->removeClient(*this);
 }
 
 bool LoadableClassicScript::isLoaded() const
 {
+    ASSERT(m_cachedScript);
     return m_cachedScript->isLoaded();
 }
 
 std::optional<LoadableScript::Error> LoadableClassicScript::error() const
 {
+    ASSERT(m_cachedScript);
     if (m_error)
         return m_error;
 
@@ -64,11 +64,13 @@ std::optional<LoadableScript::Error> LoadableClassicScript::error() const
 
 bool LoadableClassicScript::wasCanceled() const
 {
+    ASSERT(m_cachedScript);
     return m_cachedScript->wasCanceled();
 }
 
 void LoadableClassicScript::notifyFinished(CachedResource& resource)
 {
+    ASSERT(m_cachedScript);
     if (resource.resourceError().isAccessControl()) {
         static NeverDestroyed<String> consoleMessage(ASCIILiteral("Cross-origin script load denied by Cross-Origin Resource Sharing policy."));
         m_error = Error {
@@ -105,4 +107,14 @@ void LoadableClassicScript::execute(ScriptElement& scriptElement)
     scriptElement.executeClassicScript(ScriptSourceCode(m_cachedScript.get(), JSC::SourceProviderSourceType::Program));
 }
 
+bool LoadableClassicScript::load(Document& document, const URL& sourceURL)
+{
+    ASSERT(!m_cachedScript);
+    m_cachedScript = requestScriptWithCache(document, sourceURL);
+    if (!m_cachedScript)
+        return false;
+    m_cachedScript->addClient(*this);
+    return true;
+}
+
 }
index ad41dc2..6a3a30c 100644 (file)
@@ -42,7 +42,7 @@ class LoadableClassicScript final : public LoadableScript, private CachedResourc
 public:
     virtual ~LoadableClassicScript();
 
-    static Ref<LoadableClassicScript> create(CachedResourceHandle<CachedScript>&&);
+    static Ref<LoadableClassicScript> create(const String& nonce, const String& crossOriginMode, const String& charset, const AtomicString& initiatorName, bool isInUserAgentShadowTree);
     bool isLoaded() const final;
     std::optional<Error> error() const final;
     bool wasCanceled() const final;
@@ -52,12 +52,17 @@ public:
 
     void execute(ScriptElement&) final;
 
+    bool load(Document&, const URL&);
+
 private:
-    LoadableClassicScript(CachedResourceHandle<CachedScript>&& cachedScript) : m_cachedScript(WTFMove(cachedScript)) { }
+    LoadableClassicScript(const String& nonce, const String& crossOriginMode, const String& charset, const AtomicString& initiatorName, bool isInUserAgentShadowTree)
+        : LoadableScript(nonce, crossOriginMode, charset, initiatorName, isInUserAgentShadowTree)
+    {
+    }
 
     void notifyFinished(CachedResource&) final;
 
-    CachedResourceHandle<CachedScript> m_cachedScript;
+    CachedResourceHandle<CachedScript> m_cachedScript { };
     std::optional<Error> m_error { std::nullopt };
 };
 
index 84287ee..0eb10b5 100644 (file)
 
 namespace WebCore {
 
-Ref<LoadableModuleScript> LoadableModuleScript::create(CachedModuleScript& moduleScript)
+Ref<LoadableModuleScript> LoadableModuleScript::create(const String& nonce, const String& crossOriginMode, const String& charset, const AtomicString& initiatorName, bool isInUserAgentShadowTree)
 {
-    auto script = adoptRef(*new LoadableModuleScript(moduleScript));
-    moduleScript.addClient(script.get());
-    return script;
+    return adoptRef(*new LoadableModuleScript(nonce, crossOriginMode, charset, initiatorName, isInUserAgentShadowTree, CachedModuleScript::create()));
 }
 
-LoadableModuleScript::LoadableModuleScript(CachedModuleScript& moduleScript)
-    : m_moduleScript(moduleScript)
+LoadableModuleScript::LoadableModuleScript(const String& nonce, const String& crossOriginMode, const String& charset, const AtomicString& initiatorName, bool isInUserAgentShadowTree, Ref<CachedModuleScript>&& moduleScript)
+    : LoadableScript(nonce, crossOriginMode, charset, initiatorName, isInUserAgentShadowTree)
+    , m_moduleScript(WTFMove(moduleScript))
 {
+    m_moduleScript->addClient(*this);
 }
 
 LoadableModuleScript::~LoadableModuleScript()
@@ -72,4 +72,14 @@ void LoadableModuleScript::execute(ScriptElement& scriptElement)
     scriptElement.executeModuleScript(m_moduleScript.get());
 }
 
+void LoadableModuleScript::load(Document& document, const URL& rootURL)
+{
+    m_moduleScript->load(document, rootURL, *this);
+}
+
+void LoadableModuleScript::load(Document& document, const ScriptSourceCode& sourceCode)
+{
+    m_moduleScript->load(document, sourceCode, *this);
+}
+
 }
index ddea9f8..83f5391 100644 (file)
@@ -36,7 +36,7 @@ class LoadableModuleScript final : public LoadableScript, private CachedModuleSc
 public:
     virtual ~LoadableModuleScript();
 
-    static Ref<LoadableModuleScript> create(CachedModuleScript&);
+    static Ref<LoadableModuleScript> create(const String& nonce, const String& crossOriginMode, const String& charset, const AtomicString& initiatorName, bool isInUserAgentShadowTree);
 
     bool isLoaded() const final;
     std::optional<Error> error() const final;
@@ -49,8 +49,11 @@ public:
 
     void setError(Error&&);
 
+    void load(Document&, const URL& rootURL);
+    void load(Document&, const ScriptSourceCode&);
+
 private:
-    LoadableModuleScript(CachedModuleScript&);
+    LoadableModuleScript(const String& nonce, const String& crossOriginMode, const String& charset, const AtomicString& initiatorName, bool isInUserAgentShadowTree, Ref<CachedModuleScript>&&);
 
     void notifyFinished(CachedModuleScript&) final;
 
index efdb6b8..a3f0d14 100644 (file)
 #include "config.h"
 #include "LoadableScript.h"
 
+#include "CachedResourceLoader.h"
+#include "CachedScript.h"
+#include "ContentSecurityPolicy.h"
+#include "Document.h"
 #include "LoadableScriptClient.h"
+#include "Settings.h"
 
 namespace WebCore {
 
@@ -55,4 +60,25 @@ void LoadableScript::notifyClientFinished()
         client->notifyFinished(*this);
 }
 
+CachedResourceHandle<CachedScript> LoadableScript::requestScriptWithCache(Document& document, const URL& sourceURL) const
+{
+    auto* settings = document.settings();
+    if (settings && !settings->isScriptEnabled())
+        return nullptr;
+
+    ASSERT(document.contentSecurityPolicy());
+    bool hasKnownNonce = document.contentSecurityPolicy()->allowScriptWithNonce(m_nonce, m_isInUserAgentShadowTree);
+    ResourceLoaderOptions options = CachedResourceLoader::defaultCachedResourceOptions();
+    options.contentSecurityPolicyImposition = hasKnownNonce ? ContentSecurityPolicyImposition::SkipPolicyCheck : ContentSecurityPolicyImposition::DoPolicyCheck;
+
+    CachedResourceRequest request(ResourceRequest(sourceURL), options);
+    request.setAsPotentiallyCrossOrigin(m_crossOriginMode, document);
+    request.upgradeInsecureRequestIfNeeded(document);
+
+    request.setCharset(m_charset);
+    request.setInitiator(m_initiatorName);
+
+    return document.cachedResourceLoader().requestScript(WTFMove(request));
+}
+
 }
index ba22fb1..72704da 100644 (file)
 
 #pragma once
 
+#include "CachedResourceHandle.h"
 #include <runtime/ConsoleTypes.h>
+#include <runtime/JSScriptFetcher.h>
 #include <wtf/HashCountedSet.h>
 #include <wtf/RefCounted.h>
 #include <wtf/text/WTFString.h>
 
 namespace WebCore {
 
+class CachedScript;
+class Document;
 class LoadableScriptClient;
 class ScriptElement;
+class URL;
 
-class LoadableScript : public RefCounted<LoadableScript> {
+class LoadableScript : public JSC::ScriptFetcher {
 public:
     enum class ErrorType {
         CachedScript,
@@ -68,10 +73,27 @@ public:
     virtual bool isClassicScript() const { return false; }
     virtual bool isModuleScript() const { return false; }
 
+    CachedResourceHandle<CachedScript> requestScriptWithCache(Document&, const URL& sourceURL) const;
+
 protected:
+    LoadableScript(const String& nonce, const String& crossOriginMode, const String& charset, const AtomicString& initiatorName, bool isInUserAgentShadowTree)
+        : m_nonce(nonce)
+        , m_crossOriginMode(crossOriginMode)
+        , m_charset(charset)
+        , m_initiatorName(initiatorName)
+        , m_isInUserAgentShadowTree(isInUserAgentShadowTree)
+    {
+    }
+
     void notifyClientFinished();
 
 private:
+    String m_nonce;
+    String m_crossOriginMode;
+    String m_charset;
+    AtomicString m_initiatorName;
+    bool m_isInUserAgentShadowTree { false };
+
     HashCountedSet<LoadableScriptClient*> m_clients;
 };
 
index f68637a..b433fbc 100644 (file)
@@ -292,11 +292,14 @@ bool ScriptElement::requestClassicScript(const String& sourceURL)
 
     ASSERT(!m_loadableScript);
     if (!stripLeadingAndTrailingHTMLSpaces(sourceURL).isEmpty()) {
-        String nonceAttribute = m_element.attributeWithoutSynchronization(HTMLNames::nonceAttr);
-        String crossOriginMode = m_element.attributeWithoutSynchronization(HTMLNames::crossoriginAttr);
-        auto request = requestScriptWithCache(m_element.document().completeURL(sourceURL), nonceAttribute, crossOriginMode);
-        if (request) {
-            m_loadableScript = LoadableClassicScript::create(WTFMove(request));
+        auto script = LoadableClassicScript::create(
+            m_element.attributeWithoutSynchronization(HTMLNames::nonceAttr),
+            m_element.attributeWithoutSynchronization(HTMLNames::crossoriginAttr),
+            scriptCharset(),
+            m_element.localName(),
+            m_element.isInUserAgentShadowTree());
+        if (script->load(m_element.document(), m_element.document().completeURL(sourceURL))) {
+            m_loadableScript = WTFMove(script);
             m_isExternalScript = true;
         }
     }
@@ -339,9 +342,9 @@ bool ScriptElement::requestModuleScript(const TextPosition& scriptStartPosition)
         }
 
         m_isExternalScript = true;
-        auto moduleScript = CachedModuleScript::create(nonce, crossOriginMode);
-        m_loadableScript = LoadableModuleScript::create(moduleScript.get());
-        moduleScript->load(m_element, moduleScriptRootURL);
+        auto script = LoadableModuleScript::create(nonce, crossOriginMode, scriptCharset(), m_element.localName(), m_element.isInUserAgentShadowTree());
+        script->load(m_element.document(), moduleScriptRootURL);
+        m_loadableScript = WTFMove(script);
         return true;
     }
 
@@ -354,42 +357,12 @@ bool ScriptElement::requestModuleScript(const TextPosition& scriptStartPosition)
     if (!contentSecurityPolicy.allowInlineScript(m_element.document().url(), m_startLineNumber, sourceCode.source().toStringWithoutCopying(), hasKnownNonce))
         return false;
 
-    auto moduleScript = CachedModuleScript::create(nonce, crossOriginMode);
-    m_loadableScript = LoadableModuleScript::create(moduleScript.get());
-    moduleScript->load(m_element, sourceCode);
+    auto script = LoadableModuleScript::create(nonce, crossOriginMode, scriptCharset(), m_element.localName(), m_element.isInUserAgentShadowTree());
+    script->load(m_element.document(), sourceCode);
+    m_loadableScript = WTFMove(script);
     return true;
 }
 
-CachedResourceHandle<CachedScript> ScriptElement::requestScriptWithCacheForModuleScript(const URL& sourceURL)
-{
-    ASSERT(m_loadableScript);
-    ASSERT(is<LoadableModuleScript>(*m_loadableScript));
-    auto& moduleScript = downcast<LoadableModuleScript>(*m_loadableScript);
-    return requestScriptWithCache(sourceURL, moduleScript.moduleScript().nonce(), moduleScript.moduleScript().crossOriginMode());
-}
-
-CachedResourceHandle<CachedScript> ScriptElement::requestScriptWithCache(const URL& sourceURL, const String& nonceAttribute, const String& crossOriginMode)
-{
-    Document& document = m_element.document();
-    auto* settings = document.settings();
-    if (settings && !settings->isScriptEnabled())
-        return nullptr;
-
-    ASSERT(document.contentSecurityPolicy());
-    bool hasKnownNonce = document.contentSecurityPolicy()->allowScriptWithNonce(nonceAttribute, m_element.isInUserAgentShadowTree());
-    ResourceLoaderOptions options = CachedResourceLoader::defaultCachedResourceOptions();
-    options.contentSecurityPolicyImposition = hasKnownNonce ? ContentSecurityPolicyImposition::SkipPolicyCheck : ContentSecurityPolicyImposition::DoPolicyCheck;
-
-    CachedResourceRequest request(ResourceRequest(sourceURL), options);
-    request.setAsPotentiallyCrossOrigin(crossOriginMode, document);
-    request.upgradeInsecureRequestIfNeeded(document);
-
-    request.setCharset(scriptCharset());
-    request.setInitiator(&element());
-
-    return document.cachedResourceLoader().requestScript(WTFMove(request));
-}
-
 void ScriptElement::executeClassicScript(const ScriptSourceCode& sourceCode)
 {
     ASSERT(m_alreadyStarted);
@@ -430,7 +403,7 @@ void ScriptElement::executeModuleScript(CachedModuleScript& moduleScript)
     IgnoreDestructiveWriteCountIncrementer ignoreDesctructiveWriteCountIncrementer(&document);
     CurrentScriptIncrementer currentScriptIncrementer(document, m_element);
 
-    frame->script().linkAndEvaluateModuleScript(moduleScript, element());
+    frame->script().linkAndEvaluateModuleScript(moduleScript);
 }
 
 void ScriptElement::executeScriptAndDispatchEvent(LoadableScript& loadableScript)
index 5f181df..03025f8 100644 (file)
@@ -66,8 +66,6 @@ public:
     bool willExecuteInOrder() const { return m_willExecuteInOrder; }
     LoadableScript* loadableScript() { return m_loadableScript.get(); }
 
-    CachedResourceHandle<CachedScript> requestScriptWithCacheForModuleScript(const URL&);
-
     // https://html.spec.whatwg.org/multipage/scripting.html#concept-script-type
     enum class ScriptType { Classic, Module };
     ScriptType scriptType() const { return m_isModuleScript ? ScriptType::Module : ScriptType::Classic; }