Implement dynamic-import for WebCore
authorutatane.tea@gmail.com <utatane.tea@gmail.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 27 Jan 2017 10:49:23 +0000 (10:49 +0000)
committerutatane.tea@gmail.com <utatane.tea@gmail.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 27 Jan 2017 10:49:23 +0000 (10:49 +0000)
https://bugs.webkit.org/show_bug.cgi?id=166926

Reviewed by Ryosuke Niwa.

Source/WebCore:

This patch introduces browser side dynamic-import implementation.
The dynamic-import is new ES feature which is now stage 3.
The JSC shell already implements it.

The dynamic-import allows us to kick module loading in a dynamic manner.
For example, you can write,

    await module = import(`${HOST}/hello.js`);

The dynamic `import` operator (this is not a function) returns a promise with
module namespace object if the module loading succeeds. Otherwise, it returns
a rejected promise.

And importantly, this feature allows us to kick module loading from classic script.
Previously, module loading can be only used from <script type="module"> tag. And
all the module loading is done statically.

* CMakeLists.txt:
* WebCore.xcodeproj/project.pbxproj:
* bindings/js/CachedModuleScriptLoader.cpp:
(WebCore::CachedModuleScriptLoader::load):
* bindings/js/CachedScriptFetcher.cpp:
(WebCore::CachedScriptFetcher::create):
(WebCore::CachedScriptFetcher::requestModuleScript):
requestModuleScript function is used only when loading a new module script.
So, LoadableClassicScript should use requestScriptWithCache to load itself.
We pass String() for cross origin mode for null cross origin attribute as
specified.

(WebCore::CachedScriptFetcher::requestScriptWithCache):
* bindings/js/CachedScriptFetcher.h:
(WebCore::CachedScriptFetcher::CachedScriptFetcher):
* bindings/js/JSDOMWindowBase.cpp:
(WebCore::JSDOMWindowBase::moduleLoaderImportModule):
* bindings/js/JSDOMWindowBase.h:
* bindings/js/JSLazyEventListener.cpp:
(WebCore::JSLazyEventListener::initializeJSFunction):
* bindings/js/ScriptController.cpp:
(WebCore::ScriptController::executeScript):
* bindings/js/ScriptModuleLoader.cpp:
(WebCore::resolveModuleSpecifier):
Extract the part of resolving module specifier to a static function to use
it in ScriptModuleLoader::resolve and ScriptModuleLoader::importModule.

(WebCore::ScriptModuleLoader::resolve):
(WebCore::rejectPromise):
(WebCore::ScriptModuleLoader::importModule):
New hook moduleLoaderImportModule is implemented. This hook is called when
`import` operator is used. This hook is responsible to
    1. resolve the module name to obtain module specifier. (like, resolve the
        relative URL to get absolute URL.)
    2. kick module loading with the resolved specifier.
When resolving the module name, the referrer information is needed.
For example, "./script.js" will be resolved to "http://example.com/script.js" if
the referrer module specifier is "http://example.com/".
If `import("./script.js")` is executed in the classic script
src="http://example.com/test.js", it starts loading "http://example.com/script.js".
So the information of the caller of `import` operator is necessary here.
This appropriate referrer is propagated by SourceOrigin.

* bindings/js/ScriptModuleLoader.h:
* dom/InlineClassicScript.h:
* dom/LoadableClassicScript.cpp:
(WebCore::LoadableClassicScript::load):
* dom/LoadableClassicScript.h:
* dom/LoadableModuleScript.h:
* dom/LoadableScript.h:
(WebCore::LoadableScript::LoadableScript):
(WebCore::LoadableScript::isClassicScript): Deleted.
(WebCore::LoadableScript::isModuleScript): Deleted.
* dom/ScriptElement.h:
* dom/ScriptElementCachedScriptFetcher.cpp: Copied from Source/WebCore/dom/InlineClassicScript.h.
(WebCore::ScriptElementCachedScriptFetcher::requestModuleScript):
This requestModuleScript will be used when the script tag (or modules imported from the script tag) uses `import` operator.
In classic scripts, `crossorigin` mode always becomes "omit" while module scripts
propagate the original `crossorigin` value.

* dom/ScriptElementCachedScriptFetcher.h: Copied from Source/WebCore/bindings/js/CachedScriptFetcher.h.
(WebCore::ScriptElementCachedScriptFetcher::crossOriginMode):
(WebCore::ScriptElementCachedScriptFetcher::ScriptElementCachedScriptFetcher):

LayoutTests:

* http/tests/misc/import-absolute-url-expected.txt: Added.
* http/tests/misc/import-absolute-url.html: Added.
* http/tests/security/contentSecurityPolicy/1.1/import-scriptnonce-expected.txt: Added.
* http/tests/security/contentSecurityPolicy/1.1/import-scriptnonce.html: Added.
* http/tests/security/contentSecurityPolicy/1.1/resources/import-scriptnonce-allowed1.js: Added.
* http/tests/security/contentSecurityPolicy/1.1/resources/import-scriptnonce-allowed2.js: Added.
* http/tests/security/contentSecurityPolicy/1.1/resources/import-scriptnonce-allowed3.js: Added.
* http/tests/security/contentSecurityPolicy/1.1/resources/import-scriptnonce-allowed4.js: Added.
* http/tests/security/contentSecurityPolicy/1.1/resources/import-scriptnonce-allowed5.js: Added.
* http/tests/security/contentSecurityPolicy/1.1/resources/import-scriptnonce-allowed6.js: Added.
* http/tests/security/contentSecurityPolicy/1.1/resources/import-scriptnonce-blocked1.js: Added.
* http/tests/security/contentSecurityPolicy/1.1/resources/import-scriptnonce-blocked2.js: Added.
* http/tests/security/contentSecurityPolicy/1.1/resources/import-scriptnonce-blocked3.js: Added.
* http/tests/security/contentSecurityPolicy/1.1/resources/import-scriptnonce-blocked4.js: Added.
* http/tests/security/contentSecurityPolicy/1.1/resources/import-scriptnonce-blocked5.js: Added.
* http/tests/security/contentSecurityPolicy/1.1/resources/import-scriptnonce-blocked6.js: Added.
* http/tests/security/import-module-crossorigin-loads-error-expected.txt: Added.
* http/tests/security/import-module-crossorigin-loads-error-src-expected.txt: Added.
* http/tests/security/import-module-crossorigin-loads-error-src.html: Added.
* http/tests/security/import-module-crossorigin-loads-error.html: Added.
* http/tests/security/import-module-crossorigin-loads-expected.txt: Added.
* http/tests/security/import-module-crossorigin-loads-src-expected.txt: Added.
* http/tests/security/import-module-crossorigin-loads-src.html: Added.
* http/tests/security/import-module-crossorigin-loads.html: Added.
* http/tests/security/import-script-crossorigin-loads-error-expected.txt: Added.
* http/tests/security/import-script-crossorigin-loads-error.html: Added.
* http/tests/security/import-script-crossorigin-loads-omit-expected.txt: Added.
* http/tests/security/import-script-crossorigin-loads-omit.html: Added.
* http/tests/security/resources/cors-deny.php: Added.
* http/tests/security/resources/import-module-crossorigin-loads-error-src.js: Added.
(import.string_appeared_here.then):
* http/tests/security/resources/import-module-crossorigin-loads-src.js: Added.
(import.string_appeared_here.then):
* js/dom/modules/import-execution-order-expected.txt: Added.
* js/dom/modules/import-execution-order.html: Copied from LayoutTests/js/dom/modules/module-execution-error-inside-dependent-module-should-be-propagated-to-onerror.html.
* js/dom/modules/import-from-handler-expected.txt: Added.
* js/dom/modules/import-from-handler.html: Copied from LayoutTests/js/dom/modules/module-src-simple.html.
* js/dom/modules/import-from-javascript-url-expected.txt: Added.
* js/dom/modules/import-from-javascript-url.html: Copied from LayoutTests/js/dom/modules/module-execution-error-inside-dependent-module-should-be-propagated-to-onerror.html.
* js/dom/modules/import-from-loaded-classic-expected.txt: Added.
* js/dom/modules/import-from-loaded-classic.html: Copied from LayoutTests/js/dom/modules/module-src-simple.html.
* js/dom/modules/import-from-loaded-module-expected.txt: Added.
* js/dom/modules/import-from-loaded-module.html: Copied from LayoutTests/js/dom/modules/module-src-simple.html.
* js/dom/modules/import-from-module-expected.txt: Added.
* js/dom/modules/import-from-module.html: Copied from LayoutTests/js/dom/modules/module-src-simple.html.
* js/dom/modules/import-incorrect-relative-specifier-expected.txt: Added.
* js/dom/modules/import-incorrect-relative-specifier.html: Copied from LayoutTests/js/dom/modules/module-src-simple.html.
* js/dom/modules/import-simple-expected.txt: Added.
* js/dom/modules/import-simple.html: Copied from LayoutTests/js/dom/modules/module-src-simple.html.
* js/dom/modules/module-document-write-src.html:
* js/dom/modules/module-execution-error-inside-dependent-module-should-be-propagated-to-onerror.html:
* js/dom/modules/module-execution-order-mixed-with-classic-scripts.html:
* js/dom/modules/module-execution-order-mixed.html:
* js/dom/modules/module-inline-dynamic.html:
* js/dom/modules/module-inline-simple.html:
* js/dom/modules/module-load-event-with-src.html:
* js/dom/modules/module-load-same-module-from-different-entry-point-dynamic.html:
* js/dom/modules/module-load-same-module-from-different-entry-point-in-src.html:
* js/dom/modules/module-load-same-module-from-different-entry-point.html:
* js/dom/modules/module-not-found-error-event-with-src-and-import.html:
* js/dom/modules/module-src-current-script.html:
* js/dom/modules/module-src-dynamic.html:
* js/dom/modules/module-src-simple.html:
* js/dom/modules/module-type-case-insensitive.html:
* js/dom/modules/module-will-fire-beforeload.html:
* js/dom/modules/nomodule-dynamic-classic-src.html:
* js/dom/modules/nomodule-has-no-effect-on-module-inline.html:
* js/dom/modules/nomodule-has-no-effect-on-module-src.html:
* js/dom/modules/nomodule-prevents-execution-classic-script-src.html:
* js/dom/modules/nomodule-reflect.html:
* js/dom/modules/resources/error-classic-script.js: Renamed from LayoutTests/js/dom/modules/script-tests/error-classic-script.js.
* js/dom/modules/resources/import-from-loaded-classic-finish.js: Added.
* js/dom/modules/resources/import-from-loaded-classic.js: Added.
* js/dom/modules/resources/import-from-loaded-module-finish.js: Added.
* js/dom/modules/resources/import-from-loaded-module.js: Added.
* js/dom/modules/resources/module-document-write-src.js: Renamed from LayoutTests/js/dom/modules/script-tests/module-document-write-src.js.
* js/dom/modules/resources/module-execution-error-inside-dependent-module-should-be-propagated-to-onerror-throw.js: Renamed from LayoutTests/js/dom/modules/script-tests/module-execution-error-inside-dependent-module-should-be-propagated-to-onerror-throw.js.
* js/dom/modules/resources/module-execution-error-inside-dependent-module-should-be-propagated-to-onerror.js: Renamed from LayoutTests/js/dom/modules/script-tests/module-execution-error-inside-dependent-module-should-be-propagated-to-onerror.js.
* js/dom/modules/resources/module-execution-order-mixed-2.js: Renamed from LayoutTests/js/dom/modules/script-tests/module-execution-order-mixed-2.js.
* js/dom/modules/resources/module-execution-order-mixed-cappuccino.js: Renamed from LayoutTests/js/dom/modules/script-tests/module-execution-order-mixed-cappuccino.js.
* js/dom/modules/resources/module-execution-order-mixed-cocoa.js: Renamed from LayoutTests/js/dom/modules/script-tests/module-execution-order-mixed-cocoa.js.
* js/dom/modules/resources/module-execution-order-mixed-matcha.js: Renamed from LayoutTests/js/dom/modules/script-tests/module-execution-order-mixed-matcha.js.
* js/dom/modules/resources/module-execution-order-mixed-with-classic-scripts-2.js: Renamed from LayoutTests/js/dom/modules/script-tests/module-execution-order-mixed-with-classic-scripts-2.js.
* js/dom/modules/resources/module-execution-order-mixed-with-classic-scripts-cappuccino.js: Renamed from LayoutTests/js/dom/modules/script-tests/module-execution-order-mixed-with-classic-scripts-cappuccino.js.
* js/dom/modules/resources/module-execution-order-mixed-with-classic-scripts-cocoa.js: Renamed from LayoutTests/js/dom/modules/script-tests/module-execution-order-mixed-with-classic-scripts-cocoa.js.
* js/dom/modules/resources/module-execution-order-mixed-with-classic-scripts-matcha.js: Renamed from LayoutTests/js/dom/modules/script-tests/module-execution-order-mixed-with-classic-scripts-matcha.js.
* js/dom/modules/resources/module-execution-order-mixed-with-classic-scripts.js: Renamed from LayoutTests/js/dom/modules/script-tests/module-execution-order-mixed-with-classic-scripts.js.
* js/dom/modules/resources/module-execution-order-mixed.js: Renamed from LayoutTests/js/dom/modules/script-tests/module-execution-order-mixed.js.
* js/dom/modules/resources/module-inline-dynamic.js: Renamed from LayoutTests/js/dom/modules/script-tests/module-inline-dynamic.js.
* js/dom/modules/resources/module-inline-simple.js: Renamed from LayoutTests/js/dom/modules/script-tests/module-inline-simple.js.
* js/dom/modules/resources/module-load-event-with-src.js: Renamed from LayoutTests/js/dom/modules/script-tests/module-load-event-with-src.js.
* js/dom/modules/resources/module-load-same-module-from-different-entry-point.js: Renamed from LayoutTests/js/dom/modules/script-tests/module-load-same-module-from-different-entry-point.js.
* js/dom/modules/resources/module-not-found-error-event-with-src-and-import.js: Renamed from LayoutTests/js/dom/modules/script-tests/module-not-found-error-event-with-src-and-import.js.
* js/dom/modules/resources/module-src-current-script.js: Renamed from LayoutTests/js/dom/modules/script-tests/module-src-current-script.js.
* js/dom/modules/resources/module-src-dynamic-cocoa.js: Renamed from LayoutTests/js/dom/modules/script-tests/module-src-dynamic-cocoa.js.
* js/dom/modules/resources/module-src-dynamic.js: Renamed from LayoutTests/js/dom/modules/script-tests/module-src-dynamic.js.
* js/dom/modules/resources/module-src-simple-cocoa.js: Renamed from LayoutTests/js/dom/modules/script-tests/module-src-simple-cocoa.js.
* js/dom/modules/resources/module-src-simple.js: Renamed from LayoutTests/js/dom/modules/script-tests/module-src-simple.js.
* js/dom/modules/resources/module-will-fire-beforeload.js: Renamed from LayoutTests/js/dom/modules/script-tests/module-will-fire-beforeload.js.

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

120 files changed:
LayoutTests/ChangeLog
LayoutTests/http/tests/misc/import-absolute-url-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/misc/import-absolute-url.html [new file with mode: 0644]
LayoutTests/http/tests/security/contentSecurityPolicy/1.1/import-scriptnonce-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/security/contentSecurityPolicy/1.1/import-scriptnonce.html [new file with mode: 0644]
LayoutTests/http/tests/security/contentSecurityPolicy/1.1/resources/import-scriptnonce-allowed1.js [new file with mode: 0644]
LayoutTests/http/tests/security/contentSecurityPolicy/1.1/resources/import-scriptnonce-allowed2.js [new file with mode: 0644]
LayoutTests/http/tests/security/contentSecurityPolicy/1.1/resources/import-scriptnonce-allowed3.js [new file with mode: 0644]
LayoutTests/http/tests/security/contentSecurityPolicy/1.1/resources/import-scriptnonce-allowed4.js [new file with mode: 0644]
LayoutTests/http/tests/security/contentSecurityPolicy/1.1/resources/import-scriptnonce-allowed5.js [new file with mode: 0644]
LayoutTests/http/tests/security/contentSecurityPolicy/1.1/resources/import-scriptnonce-allowed6.js [new file with mode: 0644]
LayoutTests/http/tests/security/contentSecurityPolicy/1.1/resources/import-scriptnonce-blocked1.js [new file with mode: 0644]
LayoutTests/http/tests/security/contentSecurityPolicy/1.1/resources/import-scriptnonce-blocked2.js [new file with mode: 0644]
LayoutTests/http/tests/security/contentSecurityPolicy/1.1/resources/import-scriptnonce-blocked3.js [new file with mode: 0644]
LayoutTests/http/tests/security/contentSecurityPolicy/1.1/resources/import-scriptnonce-blocked4.js [new file with mode: 0644]
LayoutTests/http/tests/security/contentSecurityPolicy/1.1/resources/import-scriptnonce-blocked5.js [new file with mode: 0644]
LayoutTests/http/tests/security/contentSecurityPolicy/1.1/resources/import-scriptnonce-blocked6.js [new file with mode: 0644]
LayoutTests/http/tests/security/import-module-crossorigin-loads-error-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/security/import-module-crossorigin-loads-error-src-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/security/import-module-crossorigin-loads-error-src.html [new file with mode: 0644]
LayoutTests/http/tests/security/import-module-crossorigin-loads-error.html [new file with mode: 0644]
LayoutTests/http/tests/security/import-module-crossorigin-loads-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/security/import-module-crossorigin-loads-src-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/security/import-module-crossorigin-loads-src.html [new file with mode: 0644]
LayoutTests/http/tests/security/import-module-crossorigin-loads.html [new file with mode: 0644]
LayoutTests/http/tests/security/import-script-crossorigin-loads-error-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/security/import-script-crossorigin-loads-error.html [new file with mode: 0644]
LayoutTests/http/tests/security/import-script-crossorigin-loads-omit-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/security/import-script-crossorigin-loads-omit.html [new file with mode: 0644]
LayoutTests/http/tests/security/resources/cors-deny.php [new file with mode: 0755]
LayoutTests/http/tests/security/resources/import-module-crossorigin-loads-error-src.js [new file with mode: 0644]
LayoutTests/http/tests/security/resources/import-module-crossorigin-loads-src.js [new file with mode: 0644]
LayoutTests/js/dom/modules/import-execution-order-expected.txt [new file with mode: 0644]
LayoutTests/js/dom/modules/import-execution-order.html [new file with mode: 0644]
LayoutTests/js/dom/modules/import-from-handler-expected.txt [new file with mode: 0644]
LayoutTests/js/dom/modules/import-from-handler.html [new file with mode: 0644]
LayoutTests/js/dom/modules/import-from-javascript-url-expected.txt [new file with mode: 0644]
LayoutTests/js/dom/modules/import-from-javascript-url.html [new file with mode: 0644]
LayoutTests/js/dom/modules/import-from-loaded-classic-expected.txt [new file with mode: 0644]
LayoutTests/js/dom/modules/import-from-loaded-classic.html [new file with mode: 0644]
LayoutTests/js/dom/modules/import-from-loaded-module-expected.txt [new file with mode: 0644]
LayoutTests/js/dom/modules/import-from-loaded-module.html [new file with mode: 0644]
LayoutTests/js/dom/modules/import-from-module-expected.txt [new file with mode: 0644]
LayoutTests/js/dom/modules/import-from-module.html [new file with mode: 0644]
LayoutTests/js/dom/modules/import-incorrect-relative-specifier-expected.txt [new file with mode: 0644]
LayoutTests/js/dom/modules/import-incorrect-relative-specifier.html [new file with mode: 0644]
LayoutTests/js/dom/modules/import-simple-expected.txt [new file with mode: 0644]
LayoutTests/js/dom/modules/import-simple.html [new file with mode: 0644]
LayoutTests/js/dom/modules/module-document-write-src.html
LayoutTests/js/dom/modules/module-execution-error-inside-dependent-module-should-be-propagated-to-onerror.html
LayoutTests/js/dom/modules/module-execution-order-mixed-with-classic-scripts.html
LayoutTests/js/dom/modules/module-execution-order-mixed.html
LayoutTests/js/dom/modules/module-inline-dynamic.html
LayoutTests/js/dom/modules/module-inline-simple.html
LayoutTests/js/dom/modules/module-load-event-with-src.html
LayoutTests/js/dom/modules/module-load-same-module-from-different-entry-point-dynamic.html
LayoutTests/js/dom/modules/module-load-same-module-from-different-entry-point-in-src.html
LayoutTests/js/dom/modules/module-load-same-module-from-different-entry-point.html
LayoutTests/js/dom/modules/module-not-found-error-event-with-src-and-import.html
LayoutTests/js/dom/modules/module-src-current-script.html
LayoutTests/js/dom/modules/module-src-dynamic.html
LayoutTests/js/dom/modules/module-src-simple.html
LayoutTests/js/dom/modules/module-type-case-insensitive.html
LayoutTests/js/dom/modules/module-will-fire-beforeload.html
LayoutTests/js/dom/modules/nomodule-dynamic-classic-src.html
LayoutTests/js/dom/modules/nomodule-has-no-effect-on-module-inline.html
LayoutTests/js/dom/modules/nomodule-has-no-effect-on-module-src.html
LayoutTests/js/dom/modules/nomodule-prevents-execution-classic-script-src.html
LayoutTests/js/dom/modules/nomodule-reflect.html
LayoutTests/js/dom/modules/resources/error-classic-script.js [new file with mode: 0644]
LayoutTests/js/dom/modules/resources/import-from-loaded-classic-finish.js [new file with mode: 0644]
LayoutTests/js/dom/modules/resources/import-from-loaded-classic.js [new file with mode: 0644]
LayoutTests/js/dom/modules/resources/import-from-loaded-module-finish.js [new file with mode: 0644]
LayoutTests/js/dom/modules/resources/import-from-loaded-module.js [new file with mode: 0644]
LayoutTests/js/dom/modules/resources/import-src-simple.js [new file with mode: 0644]
LayoutTests/js/dom/modules/resources/module-document-write-src.js [new file with mode: 0644]
LayoutTests/js/dom/modules/resources/module-execution-error-inside-dependent-module-should-be-propagated-to-onerror-throw.js [new file with mode: 0644]
LayoutTests/js/dom/modules/resources/module-execution-error-inside-dependent-module-should-be-propagated-to-onerror.js [new file with mode: 0644]
LayoutTests/js/dom/modules/resources/module-execution-order-mixed-2.js [new file with mode: 0644]
LayoutTests/js/dom/modules/resources/module-execution-order-mixed-cappuccino.js [new file with mode: 0644]
LayoutTests/js/dom/modules/resources/module-execution-order-mixed-cocoa.js [new file with mode: 0644]
LayoutTests/js/dom/modules/resources/module-execution-order-mixed-matcha.js [new file with mode: 0644]
LayoutTests/js/dom/modules/resources/module-execution-order-mixed-with-classic-scripts-2.js [new file with mode: 0644]
LayoutTests/js/dom/modules/resources/module-execution-order-mixed-with-classic-scripts-cappuccino.js [new file with mode: 0644]
LayoutTests/js/dom/modules/resources/module-execution-order-mixed-with-classic-scripts-cocoa.js [new file with mode: 0644]
LayoutTests/js/dom/modules/resources/module-execution-order-mixed-with-classic-scripts-matcha.js [new file with mode: 0644]
LayoutTests/js/dom/modules/resources/module-execution-order-mixed-with-classic-scripts.js [new file with mode: 0644]
LayoutTests/js/dom/modules/resources/module-execution-order-mixed.js [new file with mode: 0644]
LayoutTests/js/dom/modules/resources/module-inline-dynamic.js [new file with mode: 0644]
LayoutTests/js/dom/modules/resources/module-inline-simple.js [new file with mode: 0644]
LayoutTests/js/dom/modules/resources/module-load-event-with-src.js [new file with mode: 0644]
LayoutTests/js/dom/modules/resources/module-load-same-module-from-different-entry-point.js [new file with mode: 0644]
LayoutTests/js/dom/modules/resources/module-not-found-error-event-with-src-and-import.js [new file with mode: 0644]
LayoutTests/js/dom/modules/resources/module-src-current-script.js [new file with mode: 0644]
LayoutTests/js/dom/modules/resources/module-src-dynamic-cocoa.js [new file with mode: 0644]
LayoutTests/js/dom/modules/resources/module-src-dynamic.js [new file with mode: 0644]
LayoutTests/js/dom/modules/resources/module-src-simple-cocoa.js [new file with mode: 0644]
LayoutTests/js/dom/modules/resources/module-src-simple.js [new file with mode: 0644]
LayoutTests/js/dom/modules/resources/module-will-fire-beforeload.js [new file with mode: 0644]
LayoutTests/js/dom/modules/script-tests/error-classic-script.js
Source/WebCore/CMakeLists.txt
Source/WebCore/ChangeLog
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/bindings/js/CachedModuleScriptLoader.cpp
Source/WebCore/bindings/js/CachedScriptFetcher.cpp
Source/WebCore/bindings/js/CachedScriptFetcher.h
Source/WebCore/bindings/js/JSDOMWindowBase.cpp
Source/WebCore/bindings/js/JSDOMWindowBase.h
Source/WebCore/bindings/js/JSLazyEventListener.cpp
Source/WebCore/bindings/js/ScriptController.cpp
Source/WebCore/bindings/js/ScriptModuleLoader.cpp
Source/WebCore/bindings/js/ScriptModuleLoader.h
Source/WebCore/dom/InlineClassicScript.h
Source/WebCore/dom/LoadableClassicScript.cpp
Source/WebCore/dom/LoadableClassicScript.h
Source/WebCore/dom/LoadableModuleScript.h
Source/WebCore/dom/LoadableScript.h
Source/WebCore/dom/ScriptElement.h
Source/WebCore/dom/ScriptElementCachedScriptFetcher.cpp [new file with mode: 0644]
Source/WebCore/dom/ScriptElementCachedScriptFetcher.h [new file with mode: 0644]

index 1ce45a3..1e1df0b 100644 (file)
@@ -1,3 +1,110 @@
+2017-01-27  Yusuke Suzuki  <utatane.tea@gmail.com>
+
+        Implement dynamic-import for WebCore
+        https://bugs.webkit.org/show_bug.cgi?id=166926
+
+        Reviewed by Ryosuke Niwa.
+
+        * http/tests/misc/import-absolute-url-expected.txt: Added.
+        * http/tests/misc/import-absolute-url.html: Added.
+        * http/tests/security/contentSecurityPolicy/1.1/import-scriptnonce-expected.txt: Added.
+        * http/tests/security/contentSecurityPolicy/1.1/import-scriptnonce.html: Added.
+        * http/tests/security/contentSecurityPolicy/1.1/resources/import-scriptnonce-allowed1.js: Added.
+        * http/tests/security/contentSecurityPolicy/1.1/resources/import-scriptnonce-allowed2.js: Added.
+        * http/tests/security/contentSecurityPolicy/1.1/resources/import-scriptnonce-allowed3.js: Added.
+        * http/tests/security/contentSecurityPolicy/1.1/resources/import-scriptnonce-allowed4.js: Added.
+        * http/tests/security/contentSecurityPolicy/1.1/resources/import-scriptnonce-allowed5.js: Added.
+        * http/tests/security/contentSecurityPolicy/1.1/resources/import-scriptnonce-allowed6.js: Added.
+        * http/tests/security/contentSecurityPolicy/1.1/resources/import-scriptnonce-blocked1.js: Added.
+        * http/tests/security/contentSecurityPolicy/1.1/resources/import-scriptnonce-blocked2.js: Added.
+        * http/tests/security/contentSecurityPolicy/1.1/resources/import-scriptnonce-blocked3.js: Added.
+        * http/tests/security/contentSecurityPolicy/1.1/resources/import-scriptnonce-blocked4.js: Added.
+        * http/tests/security/contentSecurityPolicy/1.1/resources/import-scriptnonce-blocked5.js: Added.
+        * http/tests/security/contentSecurityPolicy/1.1/resources/import-scriptnonce-blocked6.js: Added.
+        * http/tests/security/import-module-crossorigin-loads-error-expected.txt: Added.
+        * http/tests/security/import-module-crossorigin-loads-error-src-expected.txt: Added.
+        * http/tests/security/import-module-crossorigin-loads-error-src.html: Added.
+        * http/tests/security/import-module-crossorigin-loads-error.html: Added.
+        * http/tests/security/import-module-crossorigin-loads-expected.txt: Added.
+        * http/tests/security/import-module-crossorigin-loads-src-expected.txt: Added.
+        * http/tests/security/import-module-crossorigin-loads-src.html: Added.
+        * http/tests/security/import-module-crossorigin-loads.html: Added.
+        * http/tests/security/import-script-crossorigin-loads-error-expected.txt: Added.
+        * http/tests/security/import-script-crossorigin-loads-error.html: Added.
+        * http/tests/security/import-script-crossorigin-loads-omit-expected.txt: Added.
+        * http/tests/security/import-script-crossorigin-loads-omit.html: Added.
+        * http/tests/security/resources/cors-deny.php: Added.
+        * http/tests/security/resources/import-module-crossorigin-loads-error-src.js: Added.
+        (import.string_appeared_here.then):
+        * http/tests/security/resources/import-module-crossorigin-loads-src.js: Added.
+        (import.string_appeared_here.then):
+        * js/dom/modules/import-execution-order-expected.txt: Added.
+        * js/dom/modules/import-execution-order.html: Copied from LayoutTests/js/dom/modules/module-execution-error-inside-dependent-module-should-be-propagated-to-onerror.html.
+        * js/dom/modules/import-from-handler-expected.txt: Added.
+        * js/dom/modules/import-from-handler.html: Copied from LayoutTests/js/dom/modules/module-src-simple.html.
+        * js/dom/modules/import-from-javascript-url-expected.txt: Added.
+        * js/dom/modules/import-from-javascript-url.html: Copied from LayoutTests/js/dom/modules/module-execution-error-inside-dependent-module-should-be-propagated-to-onerror.html.
+        * js/dom/modules/import-from-loaded-classic-expected.txt: Added.
+        * js/dom/modules/import-from-loaded-classic.html: Copied from LayoutTests/js/dom/modules/module-src-simple.html.
+        * js/dom/modules/import-from-loaded-module-expected.txt: Added.
+        * js/dom/modules/import-from-loaded-module.html: Copied from LayoutTests/js/dom/modules/module-src-simple.html.
+        * js/dom/modules/import-from-module-expected.txt: Added.
+        * js/dom/modules/import-from-module.html: Copied from LayoutTests/js/dom/modules/module-src-simple.html.
+        * js/dom/modules/import-incorrect-relative-specifier-expected.txt: Added.
+        * js/dom/modules/import-incorrect-relative-specifier.html: Copied from LayoutTests/js/dom/modules/module-src-simple.html.
+        * js/dom/modules/import-simple-expected.txt: Added.
+        * js/dom/modules/import-simple.html: Copied from LayoutTests/js/dom/modules/module-src-simple.html.
+        * js/dom/modules/module-document-write-src.html:
+        * js/dom/modules/module-execution-error-inside-dependent-module-should-be-propagated-to-onerror.html:
+        * js/dom/modules/module-execution-order-mixed-with-classic-scripts.html:
+        * js/dom/modules/module-execution-order-mixed.html:
+        * js/dom/modules/module-inline-dynamic.html:
+        * js/dom/modules/module-inline-simple.html:
+        * js/dom/modules/module-load-event-with-src.html:
+        * js/dom/modules/module-load-same-module-from-different-entry-point-dynamic.html:
+        * js/dom/modules/module-load-same-module-from-different-entry-point-in-src.html:
+        * js/dom/modules/module-load-same-module-from-different-entry-point.html:
+        * js/dom/modules/module-not-found-error-event-with-src-and-import.html:
+        * js/dom/modules/module-src-current-script.html:
+        * js/dom/modules/module-src-dynamic.html:
+        * js/dom/modules/module-src-simple.html:
+        * js/dom/modules/module-type-case-insensitive.html:
+        * js/dom/modules/module-will-fire-beforeload.html:
+        * js/dom/modules/nomodule-dynamic-classic-src.html:
+        * js/dom/modules/nomodule-has-no-effect-on-module-inline.html:
+        * js/dom/modules/nomodule-has-no-effect-on-module-src.html:
+        * js/dom/modules/nomodule-prevents-execution-classic-script-src.html:
+        * js/dom/modules/nomodule-reflect.html:
+        * js/dom/modules/resources/error-classic-script.js: Renamed from LayoutTests/js/dom/modules/script-tests/error-classic-script.js.
+        * js/dom/modules/resources/import-from-loaded-classic-finish.js: Added.
+        * js/dom/modules/resources/import-from-loaded-classic.js: Added.
+        * js/dom/modules/resources/import-from-loaded-module-finish.js: Added.
+        * js/dom/modules/resources/import-from-loaded-module.js: Added.
+        * js/dom/modules/resources/module-document-write-src.js: Renamed from LayoutTests/js/dom/modules/script-tests/module-document-write-src.js.
+        * js/dom/modules/resources/module-execution-error-inside-dependent-module-should-be-propagated-to-onerror-throw.js: Renamed from LayoutTests/js/dom/modules/script-tests/module-execution-error-inside-dependent-module-should-be-propagated-to-onerror-throw.js.
+        * js/dom/modules/resources/module-execution-error-inside-dependent-module-should-be-propagated-to-onerror.js: Renamed from LayoutTests/js/dom/modules/script-tests/module-execution-error-inside-dependent-module-should-be-propagated-to-onerror.js.
+        * js/dom/modules/resources/module-execution-order-mixed-2.js: Renamed from LayoutTests/js/dom/modules/script-tests/module-execution-order-mixed-2.js.
+        * js/dom/modules/resources/module-execution-order-mixed-cappuccino.js: Renamed from LayoutTests/js/dom/modules/script-tests/module-execution-order-mixed-cappuccino.js.
+        * js/dom/modules/resources/module-execution-order-mixed-cocoa.js: Renamed from LayoutTests/js/dom/modules/script-tests/module-execution-order-mixed-cocoa.js.
+        * js/dom/modules/resources/module-execution-order-mixed-matcha.js: Renamed from LayoutTests/js/dom/modules/script-tests/module-execution-order-mixed-matcha.js.
+        * js/dom/modules/resources/module-execution-order-mixed-with-classic-scripts-2.js: Renamed from LayoutTests/js/dom/modules/script-tests/module-execution-order-mixed-with-classic-scripts-2.js.
+        * js/dom/modules/resources/module-execution-order-mixed-with-classic-scripts-cappuccino.js: Renamed from LayoutTests/js/dom/modules/script-tests/module-execution-order-mixed-with-classic-scripts-cappuccino.js.
+        * js/dom/modules/resources/module-execution-order-mixed-with-classic-scripts-cocoa.js: Renamed from LayoutTests/js/dom/modules/script-tests/module-execution-order-mixed-with-classic-scripts-cocoa.js.
+        * js/dom/modules/resources/module-execution-order-mixed-with-classic-scripts-matcha.js: Renamed from LayoutTests/js/dom/modules/script-tests/module-execution-order-mixed-with-classic-scripts-matcha.js.
+        * js/dom/modules/resources/module-execution-order-mixed-with-classic-scripts.js: Renamed from LayoutTests/js/dom/modules/script-tests/module-execution-order-mixed-with-classic-scripts.js.
+        * js/dom/modules/resources/module-execution-order-mixed.js: Renamed from LayoutTests/js/dom/modules/script-tests/module-execution-order-mixed.js.
+        * js/dom/modules/resources/module-inline-dynamic.js: Renamed from LayoutTests/js/dom/modules/script-tests/module-inline-dynamic.js.
+        * js/dom/modules/resources/module-inline-simple.js: Renamed from LayoutTests/js/dom/modules/script-tests/module-inline-simple.js.
+        * js/dom/modules/resources/module-load-event-with-src.js: Renamed from LayoutTests/js/dom/modules/script-tests/module-load-event-with-src.js.
+        * js/dom/modules/resources/module-load-same-module-from-different-entry-point.js: Renamed from LayoutTests/js/dom/modules/script-tests/module-load-same-module-from-different-entry-point.js.
+        * js/dom/modules/resources/module-not-found-error-event-with-src-and-import.js: Renamed from LayoutTests/js/dom/modules/script-tests/module-not-found-error-event-with-src-and-import.js.
+        * js/dom/modules/resources/module-src-current-script.js: Renamed from LayoutTests/js/dom/modules/script-tests/module-src-current-script.js.
+        * js/dom/modules/resources/module-src-dynamic-cocoa.js: Renamed from LayoutTests/js/dom/modules/script-tests/module-src-dynamic-cocoa.js.
+        * js/dom/modules/resources/module-src-dynamic.js: Renamed from LayoutTests/js/dom/modules/script-tests/module-src-dynamic.js.
+        * js/dom/modules/resources/module-src-simple-cocoa.js: Renamed from LayoutTests/js/dom/modules/script-tests/module-src-simple-cocoa.js.
+        * js/dom/modules/resources/module-src-simple.js: Renamed from LayoutTests/js/dom/modules/script-tests/module-src-simple.js.
+        * js/dom/modules/resources/module-will-fire-beforeload.js: Renamed from LayoutTests/js/dom/modules/script-tests/module-will-fire-beforeload.js.
+
 2017-01-26  Chris Dumez  <cdumez@apple.com>
 
         Crash when navigating back to a page in PacheCache when one of its frames has been removed
diff --git a/LayoutTests/http/tests/misc/import-absolute-url-expected.txt b/LayoutTests/http/tests/misc/import-absolute-url-expected.txt
new file mode 100644 (file)
index 0000000..ce5106e
--- /dev/null
@@ -0,0 +1,7 @@
+Test modules with absolute URLs.
+http://127.0.0.1:8000/misc/resources/module-absolute-url2.js
+http://127.0.0.1:8000/misc/resources/module-absolute-url.js
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/http/tests/misc/import-absolute-url.html b/LayoutTests/http/tests/misc/import-absolute-url.html
new file mode 100644 (file)
index 0000000..5662e0f
--- /dev/null
@@ -0,0 +1,18 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<meta charset="UTF-8">
+<script src="../../js-test-resources/js-test-pre.js"></script>
+</head>
+<body>
+Test modules with absolute URLs.<hr>
+<div id="console"></div>
+<script>
+var jsTestIsAsync = true;
+</script>
+<script>
+import("http://127.0.0.1:8000/misc/resources/module-absolute-url.js").then(finishJSTest);
+</script>
+<script src="../../js-test-resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/http/tests/security/contentSecurityPolicy/1.1/import-scriptnonce-expected.txt b/LayoutTests/http/tests/security/contentSecurityPolicy/1.1/import-scriptnonce-expected.txt
new file mode 100644 (file)
index 0000000..18aada4
--- /dev/null
@@ -0,0 +1,10 @@
+CONSOLE MESSAGE: line 61: Refused to execute a script because its hash, its nonce, or 'unsafe-inline' does not appear in the script-src directive of the Content Security Policy.
+CONSOLE MESSAGE: line 67: Refused to execute a script because its hash, its nonce, or 'unsafe-inline' does not appear in the script-src directive of the Content Security Policy.
+CONSOLE MESSAGE: line 73: Refused to execute a script because its hash, its nonce, or 'unsafe-inline' does not appear in the script-src directive of the Content Security Policy.
+CONSOLE MESSAGE: line 79: Refused to execute a script because its hash, its nonce, or 'unsafe-inline' does not appear in the script-src directive of the Content Security Policy.
+CONSOLE MESSAGE: line 85: Refused to execute a script because its hash, its nonce, or 'unsafe-inline' does not appear in the script-src directive of the Content Security Policy.
+CONSOLE MESSAGE: line 91: Refused to execute a script because its hash, its nonce, or 'unsafe-inline' does not appear in the script-src directive of the Content Security Policy.
+ALERT: 1,2,3,4,5,6
+This tests the effect of a script-nonce value.
+
+PASS
diff --git a/LayoutTests/http/tests/security/contentSecurityPolicy/1.1/import-scriptnonce.html b/LayoutTests/http/tests/security/contentSecurityPolicy/1.1/import-scriptnonce.html
new file mode 100644 (file)
index 0000000..a3c22f6
--- /dev/null
@@ -0,0 +1,99 @@
+<!DOCTYPE html>
+<html>
+    <head>
+        <meta http-equiv="Content-Security-Policy" content="script-src 'nonce-noncynonce' 'nonce-noncy+/=nonce'">
+    </head>
+    <body>
+        <script nonce="noncynonce">
+        if (window.testRunner) {
+            testRunner.dumpAsText();
+            testRunner.waitUntilDone();
+        }
+
+        var modules = new Set([
+            'allow1',
+            'allow2',
+            'allow3',
+        ]);
+
+        var array = [];
+        var count = 0;
+        function ok(num)
+        {
+            // load should be done for module tags before calling the result of import.
+            if (modules.has(`allow${num}`))
+                error(num);
+            array.push(num);
+            if (array.length === 6) {
+                alert(array.sort().toString());
+                done("PASS");
+            }
+        }
+
+        document.body.addEventListener('load', function (ev) {
+            let id = ev.target.id;
+            if (modules.has(id))
+                modules.delete(id);
+            else if (id)
+                error(id);
+        }, /* capture */ true);
+
+        document.body.addEventListener('error', function (ev) {
+            error(ev.target.id);
+        }, /* capture */ true);
+
+
+        function error(num)
+        {
+            alert(`FAIL (${num})`);
+        }
+
+        function done(msg) {
+            document.querySelector("pre").innerHTML = msg;
+            if (window.testRunner)
+                testRunner.notifyDone();
+        }
+        </script>
+
+        <script type="module" nonce="noncynonce" id="allow1">
+            import("./resources/import-scriptnonce-allowed1.js");
+        </script>
+        <script type="module" nonce="noncynonce noncynonce" id="block1">
+            import("./resources/import-scriptnonce-blocked1.js");
+        </script>
+        <script type="module" nonce="noncynonce" id="allow2">
+            import("./resources/import-scriptnonce-allowed2.js");
+        </script>
+        <script type="module" id="block2">
+            import("./resources/import-scriptnonce-blocked2.js");
+        </script>
+        <script type="module" nonce="noncy+/=nonce" id="allow3">
+            import("./resources/import-scriptnonce-allowed3.js");
+        </script>
+        <script type="module" nonce="noncynonceno?" id="block3">
+            import("./resources/import-scriptnonce-blocked3.js");
+        </script>
+        <script nonce="noncynonce" id="allow4">
+            import("./resources/import-scriptnonce-allowed4.js");
+        </script>
+        <script nonce="noncynonce noncynonce" id="block4">
+            import("./resources/import-scriptnonce-blocked4.js");
+        </script>
+        <script nonce="noncynonce" id="allow5">
+            import("./resources/import-scriptnonce-allowed5.js");
+        </script>
+        <script id="block5">
+            import("./resources/import-scriptnonce-blocked5.js");
+        </script>
+        <script nonce="noncy+/=nonce" id="allow6">
+            import("./resources/import-scriptnonce-allowed6.js");
+        </script>
+        <script nonce="noncynonceno?" id="block6">
+            import("./resources/import-scriptnonce-blocked6.js");
+        </script>
+        <p>
+            This tests the effect of a script-nonce value.
+        </p>
+        <pre></pre>
+    </body>
+</html>
diff --git a/LayoutTests/http/tests/security/contentSecurityPolicy/1.1/resources/import-scriptnonce-allowed1.js b/LayoutTests/http/tests/security/contentSecurityPolicy/1.1/resources/import-scriptnonce-allowed1.js
new file mode 100644 (file)
index 0000000..75ad903
--- /dev/null
@@ -0,0 +1 @@
+ok(1);
diff --git a/LayoutTests/http/tests/security/contentSecurityPolicy/1.1/resources/import-scriptnonce-allowed2.js b/LayoutTests/http/tests/security/contentSecurityPolicy/1.1/resources/import-scriptnonce-allowed2.js
new file mode 100644 (file)
index 0000000..b7458f4
--- /dev/null
@@ -0,0 +1 @@
+ok(2);
diff --git a/LayoutTests/http/tests/security/contentSecurityPolicy/1.1/resources/import-scriptnonce-allowed3.js b/LayoutTests/http/tests/security/contentSecurityPolicy/1.1/resources/import-scriptnonce-allowed3.js
new file mode 100644 (file)
index 0000000..3cfb321
--- /dev/null
@@ -0,0 +1 @@
+ok(3);
diff --git a/LayoutTests/http/tests/security/contentSecurityPolicy/1.1/resources/import-scriptnonce-allowed4.js b/LayoutTests/http/tests/security/contentSecurityPolicy/1.1/resources/import-scriptnonce-allowed4.js
new file mode 100644 (file)
index 0000000..dd7340e
--- /dev/null
@@ -0,0 +1 @@
+ok(4);
diff --git a/LayoutTests/http/tests/security/contentSecurityPolicy/1.1/resources/import-scriptnonce-allowed5.js b/LayoutTests/http/tests/security/contentSecurityPolicy/1.1/resources/import-scriptnonce-allowed5.js
new file mode 100644 (file)
index 0000000..82109ea
--- /dev/null
@@ -0,0 +1 @@
+ok(5);
diff --git a/LayoutTests/http/tests/security/contentSecurityPolicy/1.1/resources/import-scriptnonce-allowed6.js b/LayoutTests/http/tests/security/contentSecurityPolicy/1.1/resources/import-scriptnonce-allowed6.js
new file mode 100644 (file)
index 0000000..a90e919
--- /dev/null
@@ -0,0 +1 @@
+ok(6);
diff --git a/LayoutTests/http/tests/security/contentSecurityPolicy/1.1/resources/import-scriptnonce-blocked1.js b/LayoutTests/http/tests/security/contentSecurityPolicy/1.1/resources/import-scriptnonce-blocked1.js
new file mode 100644 (file)
index 0000000..1b9f470
--- /dev/null
@@ -0,0 +1 @@
+error(1);
diff --git a/LayoutTests/http/tests/security/contentSecurityPolicy/1.1/resources/import-scriptnonce-blocked2.js b/LayoutTests/http/tests/security/contentSecurityPolicy/1.1/resources/import-scriptnonce-blocked2.js
new file mode 100644 (file)
index 0000000..0bec6b0
--- /dev/null
@@ -0,0 +1 @@
+error(2);
diff --git a/LayoutTests/http/tests/security/contentSecurityPolicy/1.1/resources/import-scriptnonce-blocked3.js b/LayoutTests/http/tests/security/contentSecurityPolicy/1.1/resources/import-scriptnonce-blocked3.js
new file mode 100644 (file)
index 0000000..d4e675f
--- /dev/null
@@ -0,0 +1 @@
+error(3);
diff --git a/LayoutTests/http/tests/security/contentSecurityPolicy/1.1/resources/import-scriptnonce-blocked4.js b/LayoutTests/http/tests/security/contentSecurityPolicy/1.1/resources/import-scriptnonce-blocked4.js
new file mode 100644 (file)
index 0000000..3850996
--- /dev/null
@@ -0,0 +1 @@
+error(4);
diff --git a/LayoutTests/http/tests/security/contentSecurityPolicy/1.1/resources/import-scriptnonce-blocked5.js b/LayoutTests/http/tests/security/contentSecurityPolicy/1.1/resources/import-scriptnonce-blocked5.js
new file mode 100644 (file)
index 0000000..96eca6e
--- /dev/null
@@ -0,0 +1 @@
+error(5);
diff --git a/LayoutTests/http/tests/security/contentSecurityPolicy/1.1/resources/import-scriptnonce-blocked6.js b/LayoutTests/http/tests/security/contentSecurityPolicy/1.1/resources/import-scriptnonce-blocked6.js
new file mode 100644 (file)
index 0000000..44e4096
--- /dev/null
@@ -0,0 +1 @@
+error(6);
diff --git a/LayoutTests/http/tests/security/import-module-crossorigin-loads-error-expected.txt b/LayoutTests/http/tests/security/import-module-crossorigin-loads-error-expected.txt
new file mode 100644 (file)
index 0000000..824a3e4
--- /dev/null
@@ -0,0 +1,4 @@
+CONSOLE MESSAGE: Origin http://127.0.0.1:8000 is not allowed by Access-Control-Allow-Origin.
+This test passes if the module script does not load.
+
+PASS
diff --git a/LayoutTests/http/tests/security/import-module-crossorigin-loads-error-src-expected.txt b/LayoutTests/http/tests/security/import-module-crossorigin-loads-error-src-expected.txt
new file mode 100644 (file)
index 0000000..824a3e4
--- /dev/null
@@ -0,0 +1,4 @@
+CONSOLE MESSAGE: Origin http://127.0.0.1:8000 is not allowed by Access-Control-Allow-Origin.
+This test passes if the module script does not load.
+
+PASS
diff --git a/LayoutTests/http/tests/security/import-module-crossorigin-loads-error-src.html b/LayoutTests/http/tests/security/import-module-crossorigin-loads-error-src.html
new file mode 100644 (file)
index 0000000..49342b7
--- /dev/null
@@ -0,0 +1,16 @@
+<body>
+<p>This test passes if the module script does not load.</p>
+<pre></pre>
+<script>
+if (window.testRunner) {
+    testRunner.dumpAsText();
+    testRunner.waitUntilDone();
+}
+
+function done(msg) {
+    document.querySelector("pre").innerHTML = msg;
+    if (window.testRunner)
+        testRunner.notifyDone();
+}
+</script>
+<script type="module" src="./resources/import-module-crossorigin-loads-error-src.js"></script>
diff --git a/LayoutTests/http/tests/security/import-module-crossorigin-loads-error.html b/LayoutTests/http/tests/security/import-module-crossorigin-loads-error.html
new file mode 100644 (file)
index 0000000..1b0d7e0
--- /dev/null
@@ -0,0 +1,20 @@
+<body>
+<p>This test passes if the module script does not load.</p>
+<pre></pre>
+<script>
+if (window.testRunner) {
+    testRunner.dumpAsText();
+    testRunner.waitUntilDone();
+}
+
+function done(msg) {
+    document.querySelector("pre").innerHTML = msg;
+    if (window.testRunner)
+        testRunner.notifyDone();
+}
+</script>
+<script type="module">
+import("http://localhost:8000/security/resources/cors-deny.php?credentials=true").then(
+    function() { done("FAIL");},
+    function() { done("PASS"); });
+</script>
diff --git a/LayoutTests/http/tests/security/import-module-crossorigin-loads-expected.txt b/LayoutTests/http/tests/security/import-module-crossorigin-loads-expected.txt
new file mode 100644 (file)
index 0000000..7a6fcd1
--- /dev/null
@@ -0,0 +1,4 @@
+ALERT: script ran.
+This test passes if the module script loads.
+
+PASS
diff --git a/LayoutTests/http/tests/security/import-module-crossorigin-loads-src-expected.txt b/LayoutTests/http/tests/security/import-module-crossorigin-loads-src-expected.txt
new file mode 100644 (file)
index 0000000..7a6fcd1
--- /dev/null
@@ -0,0 +1,4 @@
+ALERT: script ran.
+This test passes if the module script loads.
+
+PASS
diff --git a/LayoutTests/http/tests/security/import-module-crossorigin-loads-src.html b/LayoutTests/http/tests/security/import-module-crossorigin-loads-src.html
new file mode 100644 (file)
index 0000000..41de3c0
--- /dev/null
@@ -0,0 +1,16 @@
+<body>
+<p>This test passes if the module script loads.</p>
+<pre></pre>
+<script>
+if (window.testRunner) {
+    testRunner.dumpAsText();
+    testRunner.waitUntilDone();
+}
+
+function done(msg) {
+    document.querySelector("pre").innerHTML = msg;
+    if (window.testRunner)
+        testRunner.notifyDone();
+}
+</script>
+<script type="module" src="./resources/import-module-crossorigin-loads-src.js"></script>
diff --git a/LayoutTests/http/tests/security/import-module-crossorigin-loads.html b/LayoutTests/http/tests/security/import-module-crossorigin-loads.html
new file mode 100644 (file)
index 0000000..ed4c2c2
--- /dev/null
@@ -0,0 +1,22 @@
+<body>
+<p>This test passes if the module script loads.</p>
+<pre></pre>
+<script>
+if (window.testRunner) {
+    testRunner.dumpAsText();
+    testRunner.waitUntilDone();
+}
+
+function done(msg) {
+    document.querySelector("pre").innerHTML = msg;
+    if (window.testRunner)
+        testRunner.notifyDone();
+}
+</script>
+<script type="module">
+// Executed with "omit".
+// https://github.com/tc39/proposal-dynamic-import/blob/master/HTML%20Integration.md
+import("http://localhost:8000/security/resources/cors-script.php?credentials=false").then(
+    function() { done("PASS");},
+    function() { done("FAIL"); });
+</script>
diff --git a/LayoutTests/http/tests/security/import-script-crossorigin-loads-error-expected.txt b/LayoutTests/http/tests/security/import-script-crossorigin-loads-error-expected.txt
new file mode 100644 (file)
index 0000000..824a3e4
--- /dev/null
@@ -0,0 +1,4 @@
+CONSOLE MESSAGE: Origin http://127.0.0.1:8000 is not allowed by Access-Control-Allow-Origin.
+This test passes if the module script does not load.
+
+PASS
diff --git a/LayoutTests/http/tests/security/import-script-crossorigin-loads-error.html b/LayoutTests/http/tests/security/import-script-crossorigin-loads-error.html
new file mode 100644 (file)
index 0000000..ef941cd
--- /dev/null
@@ -0,0 +1,21 @@
+<body>
+<p>This test passes if the module script does not load.</p>
+<pre></pre>
+<script crossorigin="use-credentials">
+if (window.testRunner) {
+    testRunner.dumpAsText();
+    testRunner.waitUntilDone();
+}
+
+function done(msg) {
+    document.querySelector("pre").innerHTML = msg;
+    if (window.testRunner)
+        testRunner.notifyDone();
+}
+
+// Executed with "omit".
+// https://github.com/tc39/proposal-dynamic-import/blob/master/HTML%20Integration.md
+import("http://localhost:8000/security/resources/cors-deny.php?credentials=true").then(
+    function() { done("FAIL");},
+    function() { done("PASS"); });
+</script>
diff --git a/LayoutTests/http/tests/security/import-script-crossorigin-loads-omit-expected.txt b/LayoutTests/http/tests/security/import-script-crossorigin-loads-omit-expected.txt
new file mode 100644 (file)
index 0000000..7a6fcd1
--- /dev/null
@@ -0,0 +1,4 @@
+ALERT: script ran.
+This test passes if the module script loads.
+
+PASS
diff --git a/LayoutTests/http/tests/security/import-script-crossorigin-loads-omit.html b/LayoutTests/http/tests/security/import-script-crossorigin-loads-omit.html
new file mode 100644 (file)
index 0000000..7f6ee39
--- /dev/null
@@ -0,0 +1,21 @@
+<body>
+<p>This test passes if the module script loads.</p>
+<pre></pre>
+<script crossorigin="use-credentials">
+if (window.testRunner) {
+    testRunner.dumpAsText();
+    testRunner.waitUntilDone();
+}
+
+function done(msg) {
+    document.querySelector("pre").innerHTML = msg;
+    if (window.testRunner)
+        testRunner.notifyDone();
+}
+
+// Executed with "omit".
+// https://github.com/tc39/proposal-dynamic-import/blob/master/HTML%20Integration.md
+import("http://localhost:8000/security/resources/cors-script.php?credentials=false").then(
+    function() { done("PASS");},
+    function() { done("FAIL"); });
+</script>
diff --git a/LayoutTests/http/tests/security/resources/cors-deny.php b/LayoutTests/http/tests/security/resources/cors-deny.php
new file mode 100755 (executable)
index 0000000..1e5f8e9
--- /dev/null
@@ -0,0 +1,16 @@
+<?php
+header("Access-Control-Allow-Origin: http://example.org/");
+header("Content-Type: application/javascript");
+
+if (isset($_GET["credentials"])) {
+    if (strtolower($_GET["credentials"]) == "true")
+        header("Access-Control-Allow-Credentials: true");
+    else
+        header("Access-Control-Allow-Credentials: false");
+}
+
+if (strtolower($_GET["fail"]) == "true")
+    echo "throw({toString: function(){ return 'SomeError' }});";
+else
+    echo "alert('script ran.');";
+?>
diff --git a/LayoutTests/http/tests/security/resources/import-module-crossorigin-loads-error-src.js b/LayoutTests/http/tests/security/resources/import-module-crossorigin-loads-error-src.js
new file mode 100644 (file)
index 0000000..369d020
--- /dev/null
@@ -0,0 +1,3 @@
+import("http://localhost:8000/security/resources/cors-deny.php?credentials=true").then(
+    function() { done("FAIL");},
+    function() { done("PASS"); });
diff --git a/LayoutTests/http/tests/security/resources/import-module-crossorigin-loads-src.js b/LayoutTests/http/tests/security/resources/import-module-crossorigin-loads-src.js
new file mode 100644 (file)
index 0000000..6876f91
--- /dev/null
@@ -0,0 +1,6 @@
+// Executed with "omit".
+// https://github.com/tc39/proposal-dynamic-import/blob/master/HTML%20Integration.md
+import("http://localhost:8000/security/resources/cors-script.php?credentials=false").then(
+    function() { done("PASS");},
+    function() { done("FAIL"); });
+
diff --git a/LayoutTests/js/dom/modules/import-execution-order-expected.txt b/LayoutTests/js/dom/modules/import-execution-order-expected.txt
new file mode 100644 (file)
index 0000000..7fd1db8
--- /dev/null
@@ -0,0 +1,17 @@
+Test import execution order.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+Module is not executed yet.
+PASS count++ is 0
+PASS count++ is 1
+PASS count++ is 2
+PASS count++ is 3
+PASS count++ is 4
+PASS count++ is 5
+PASS count++ is 6
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/js/dom/modules/import-execution-order.html b/LayoutTests/js/dom/modules/import-execution-order.html
new file mode 100644 (file)
index 0000000..61acf0e
--- /dev/null
@@ -0,0 +1,26 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<script src="../../../resources/js-test-pre.js"></script>
+</head>
+<body>
+<script>
+description('Test import execution order.');
+window.count = 0;
+
+// Module will be executed asynchronously.
+window.jsTestIsAsync = true;
+debug('Module is not executed yet.');
+</script>
+<script src="../../../resources/js-test-post.js"></script>
+<script>
+(async function () {
+    await import(`./resources/module-execution-order-mixed.js`);
+    shouldBe("count++", "4");
+    await import(`./resources/module-execution-order-mixed-2.js`);
+    shouldBe("count++", "6");
+    finishJSTest();
+}());
+</script>
+</body>
+</html>
diff --git a/LayoutTests/js/dom/modules/import-from-handler-expected.txt b/LayoutTests/js/dom/modules/import-from-handler-expected.txt
new file mode 100644 (file)
index 0000000..a37b7b8
--- /dev/null
@@ -0,0 +1,14 @@
+Test import from handler.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+Module is not executed yet.
+Module execution is confined in the module environment.
+PASS typeof cocoa is "undefined"
+PASS typeof exportedCocoa is "object"
+PASS exportedCocoa.taste() is "nice"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+MODULE
diff --git a/LayoutTests/js/dom/modules/import-from-handler.html b/LayoutTests/js/dom/modules/import-from-handler.html
new file mode 100644 (file)
index 0000000..94da83a
--- /dev/null
@@ -0,0 +1,23 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<script src="../../../resources/js-test-pre.js"></script>
+</head>
+<body>
+<script>
+description('Test import from handler.');
+
+// Module will be executed asynchronously.
+window.jsTestIsAsync = true;
+</script>
+<script>
+</script>
+<script src="../../../resources/js-test-post.js"></script>
+<a id="target" onclick="(import(`./resources/module-src-simple.js`)).then(() => finishJSTest())">MODULE</a>
+<script type="module">
+debug('Module is not executed yet.');
+let anchor = document.getElementById('target');
+anchor.dispatchEvent(new MouseEvent('click'));
+</script>
+</body>
+</html>
diff --git a/LayoutTests/js/dom/modules/import-from-javascript-url-expected.txt b/LayoutTests/js/dom/modules/import-from-javascript-url-expected.txt
new file mode 100644 (file)
index 0000000..924b881
--- /dev/null
@@ -0,0 +1,14 @@
+Test import from javascript URL.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+Module is not executed yet.
+Module execution is confined in the module environment.
+PASS typeof cocoa is "undefined"
+PASS typeof exportedCocoa is "object"
+PASS exportedCocoa.taste() is "nice"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+MODULE
diff --git a/LayoutTests/js/dom/modules/import-from-javascript-url.html b/LayoutTests/js/dom/modules/import-from-javascript-url.html
new file mode 100644 (file)
index 0000000..fd77229
--- /dev/null
@@ -0,0 +1,23 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<script src="../../../resources/js-test-pre.js"></script>
+</head>
+<body>
+<script>
+description('Test import from javascript URL.');
+
+// Module will be executed asynchronously.
+window.jsTestIsAsync = true;
+</script>
+<script>
+</script>
+<script src="../../../resources/js-test-post.js"></script>
+<a id="target" href="javascript:void((import(`./resources/module-src-simple.js`)).then(() => finishJSTest()))">MODULE</a>
+<script type="module">
+debug('Module is not executed yet.');
+let anchor = document.getElementById('target');
+anchor.dispatchEvent(new MouseEvent('click'));
+</script>
+</body>
+</html>
diff --git a/LayoutTests/js/dom/modules/import-from-loaded-classic-expected.txt b/LayoutTests/js/dom/modules/import-from-loaded-classic-expected.txt
new file mode 100644 (file)
index 0000000..b56896d
--- /dev/null
@@ -0,0 +1,12 @@
+Test import from loaded classic.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+import from loaded classic
+import from loaded classic finish
+PASS window.imported is true
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/js/dom/modules/import-from-loaded-classic.html b/LayoutTests/js/dom/modules/import-from-loaded-classic.html
new file mode 100644 (file)
index 0000000..41699d8
--- /dev/null
@@ -0,0 +1,24 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<script src="../../../resources/js-test-pre.js"></script>
+</head>
+<body>
+<script>
+description('Test import from loaded classic.');
+
+// Module will be executed asynchronously.
+window.jsTestIsAsync = true;
+
+function loaded()
+{
+    shouldBeTrue(`window.imported`);
+    finishJSTest();
+}
+</script>
+<script>
+</script>
+<script src="../../../resources/js-test-post.js"></script>
+<script src="./resources/import-from-loaded-classic.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/js/dom/modules/import-from-loaded-module-expected.txt b/LayoutTests/js/dom/modules/import-from-loaded-module-expected.txt
new file mode 100644 (file)
index 0000000..e148b5e
--- /dev/null
@@ -0,0 +1,12 @@
+Test import from loaded module.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+import from loaded module
+import from loaded module finish
+PASS window.imported is true
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/js/dom/modules/import-from-loaded-module.html b/LayoutTests/js/dom/modules/import-from-loaded-module.html
new file mode 100644 (file)
index 0000000..0a9c941
--- /dev/null
@@ -0,0 +1,25 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<script src="../../../resources/js-test-pre.js"></script>
+</head>
+<body>
+<script>
+description('Test import from loaded module.');
+
+// Module will be executed asynchronously.
+window.jsTestIsAsync = true;
+
+function loaded()
+{
+    shouldBeTrue(`window.imported`);
+    finishJSTest();
+}
+
+</script>
+<script>
+</script>
+<script src="../../../resources/js-test-post.js"></script>
+<script type="module" src="./resources/import-from-loaded-module.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/js/dom/modules/import-from-module-expected.txt b/LayoutTests/js/dom/modules/import-from-module-expected.txt
new file mode 100644 (file)
index 0000000..0bb67c9
--- /dev/null
@@ -0,0 +1,16 @@
+Test import from module script.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+Module is not executed yet.
+Module execution is confined in the module environment.
+PASS typeof cocoa is "undefined"
+PASS typeof exportedCocoa is "object"
+PASS exportedCocoa.taste() is "nice"
+PASS window.imported is true
+PASS window.passedCocoa is window.exportedCocoa
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/js/dom/modules/import-from-module.html b/LayoutTests/js/dom/modules/import-from-module.html
new file mode 100644 (file)
index 0000000..9767d45
--- /dev/null
@@ -0,0 +1,34 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<script src="../../../resources/js-test-pre.js"></script>
+</head>
+<body>
+<script>
+description('Test import from module script.');
+
+// Module will be executed asynchronously.
+window.jsTestIsAsync = true;
+window.passedCocoa = null;
+
+function loaded(cocoa)
+{
+    window.passedCocoa = cocoa;
+    shouldBeTrue(`window.imported`);
+    shouldBe(`window.passedCocoa`, `window.exportedCocoa`);
+    finishJSTest();
+}
+
+</script>
+<script>
+</script>
+<script src="../../../resources/js-test-post.js"></script>
+<script type="module">
+(async function() {
+    debug('Module is not executed yet.');
+    let ns = await import(`./resources/import-src-simple.js`);
+    loaded(ns.ok);
+}());
+</script>
+</body>
+</html>
diff --git a/LayoutTests/js/dom/modules/import-incorrect-relative-specifier-expected.txt b/LayoutTests/js/dom/modules/import-incorrect-relative-specifier-expected.txt
new file mode 100644 (file)
index 0000000..270a78d
--- /dev/null
@@ -0,0 +1,12 @@
+Test import rejects the incorrect relative specifiers.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS import("incorrect") rejected promise  with TypeError: Module specifier does not start with "/", "./", or "../"..
+PASS import("$hello") rejected promise  with TypeError: Module specifier does not start with "/", "./", or "../"..
+PASS import(".../test") rejected promise  with TypeError: Module specifier does not start with "/", "./", or "../"..
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/js/dom/modules/import-incorrect-relative-specifier.html b/LayoutTests/js/dom/modules/import-incorrect-relative-specifier.html
new file mode 100644 (file)
index 0000000..f6c8a6e
--- /dev/null
@@ -0,0 +1,22 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<script src="../../../resources/js-test-pre.js"></script>
+</head>
+<body>
+<script>
+description('Test import rejects the incorrect relative specifiers.');
+// Module will be executed asynchronously.
+window.jsTestIsAsync = true;
+</script>
+<script src="../../../resources/js-test-post.js"></script>
+<script>
+(async function () {
+    await shouldReject(`import("incorrect")`);
+    await shouldReject(`import("$hello")`);
+    await shouldReject(`import(".../test")`);
+    finishJSTest();
+}());
+</script>
+</body>
+</html>
diff --git a/LayoutTests/js/dom/modules/import-simple-expected.txt b/LayoutTests/js/dom/modules/import-simple-expected.txt
new file mode 100644 (file)
index 0000000..b563d2e
--- /dev/null
@@ -0,0 +1,14 @@
+Test import simple.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+Module is not executed yet.
+Module execution is confined in the module environment.
+PASS typeof cocoa is "undefined"
+PASS typeof exportedCocoa is "object"
+PASS exportedCocoa.taste() is "nice"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/js/dom/modules/import-simple.html b/LayoutTests/js/dom/modules/import-simple.html
new file mode 100644 (file)
index 0000000..81588c6
--- /dev/null
@@ -0,0 +1,24 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<script src="../../../resources/js-test-pre.js"></script>
+</head>
+<body>
+<script>
+description('Test import simple.');
+
+// Module will be executed asynchronously.
+window.jsTestIsAsync = true;
+</script>
+<script>
+</script>
+<script src="../../../resources/js-test-post.js"></script>
+<script>
+(async function() {
+    debug('Module is not executed yet.');
+    await import(`./resources/module-src-simple.js`);
+    finishJSTest();
+}());
+</script>
+</body>
+</html>
index 1afeacd..7aaee95 100644 (file)
@@ -14,6 +14,6 @@ window.jsTestIsAsync = true;
 debug('Module is not executed yet.');
 </script>
 <script src="../../../resources/js-test-post.js"></script>
-<script type="module" src="script-tests/module-document-write-src.js"></script>
+<script type="module" src="resources/module-document-write-src.js"></script>
 </body>
 </html>
index 817224b..b07c58f 100644 (file)
@@ -15,7 +15,7 @@ window.onerror = function () {
 </script>
 <script src="../../../resources/js-test-post.js"></script>
 <script type="module">
-import "./script-tests/module-execution-error-inside-dependent-module-should-be-propagated-to-onerror.js"
+import "./resources/module-execution-error-inside-dependent-module-should-be-propagated-to-onerror.js"
 testFailed("executed");
 </script>
 </body>
index 463fa33..67b6fbc 100644 (file)
@@ -20,7 +20,7 @@ shouldBe("count++", "0");
 <script>
 shouldBe("count++", "1");
 </script>
-<script type="module" src="script-tests/module-execution-order-mixed-with-classic-scripts.js"></script>
+<script type="module" src="resources/module-execution-order-mixed-with-classic-scripts.js"></script>
 <script>
 shouldBe("count++", "2");
 </script>
@@ -30,7 +30,7 @@ shouldBe("count++", "10");
 <script>
 shouldBe("count++", "3");
 </script>
-<script type="module" src="script-tests/module-execution-order-mixed-with-classic-scripts-2.js"></script>
+<script type="module" src="resources/module-execution-order-mixed-with-classic-scripts-2.js"></script>
 <script>
 shouldBe("count++", "4");
 </script>
index f480890..84fc902 100644 (file)
@@ -14,11 +14,11 @@ window.jsTestIsAsync = true;
 debug('Module is not executed yet.');
 </script>
 <script src="../../../resources/js-test-post.js"></script>
-<script type="module" src="script-tests/module-execution-order-mixed.js"></script>
+<script type="module" src="resources/module-execution-order-mixed.js"></script>
 <script type="module">
 shouldBe("count++", "4");
 </script>
-<script type="module" src="script-tests/module-execution-order-mixed-2.js"></script>
+<script type="module" src="resources/module-execution-order-mixed-2.js"></script>
 <script type="module">
 shouldBe("count++", "6");
 finishJSTest();
index 0148ae2..0b51b02 100644 (file)
@@ -16,7 +16,7 @@ debug('Module is not executed yet.');
 (function () {
     var element = document.createElement("script");
     element.textContent = `
-        import Cocoa from "./script-tests/module-inline-dynamic.js";
+        import Cocoa from "./resources/module-inline-dynamic.js";
         var cocoa = new Cocoa();
 
         debug("Module execution is confined in the module environment.");
index 4af4d88..d0e7585 100644 (file)
@@ -15,7 +15,7 @@ debug('Module is not executed yet.');
 </script>
 <script src="../../../resources/js-test-post.js"></script>
 <script type="module">
-import Cocoa from "./script-tests/module-inline-simple.js";
+import Cocoa from "./resources/module-inline-simple.js";
 var cocoa = new Cocoa();
 
 debug("Module execution is confined in the module environment.");
index 10b542a..384b54c 100644 (file)
@@ -16,6 +16,6 @@ function onLoad()
 }
 </script>
 <script src="../../../resources/js-test-post.js"></script>
-<script type="module" onload="onLoad()" src="script-tests/module-load-event-with-src.js"></script>
+<script type="module" onload="onLoad()" src="resources/module-load-event-with-src.js"></script>
 </body>
 </html>
index 1e706fd..af9b410 100644 (file)
@@ -20,12 +20,12 @@ function onLoad()
 </script>
 <script src="../../../resources/js-test-post.js"></script>
 <script type="module">
-import "./script-tests/module-load-same-module-from-different-entry-point.js"
+import "./resources/module-load-same-module-from-different-entry-point.js"
 debug('Executing the module.');
 shouldBe(`window.moduleExecutedCount`, `1`);
 var element = document.createElement("script");
 element.type = "module";
-element.innerText = `import "./script-tests/module-load-same-module-from-different-entry-point.js"`;
+element.innerText = `import "./resources/module-load-same-module-from-different-entry-point.js"`;
 element.onload = onLoad;
 document.body.appendChild(element);
 </script>
index bee9c10..cd102b1 100644 (file)
@@ -22,8 +22,8 @@ function finish() {
 
 </script>
 <script src="../../../resources/js-test-post.js"></script>
-<script type="module" src="./script-tests/module-load-same-module-from-different-entry-point.js" onload="onLoad()"></script>
-<script type="module" src="./script-tests/module-load-same-module-from-different-entry-point.js" onload="onLoad()"></script>
+<script type="module" src="./resources/module-load-same-module-from-different-entry-point.js" onload="onLoad()"></script>
+<script type="module" src="./resources/module-load-same-module-from-different-entry-point.js" onload="onLoad()"></script>
 <script type="module">
 finish();
 </script>
index b63e043..e05493d 100644 (file)
@@ -24,12 +24,12 @@ function onLoad() {
 </script>
 <script src="../../../resources/js-test-post.js"></script>
 <script type="module" onload="onLoad()">
-import "./script-tests/module-load-same-module-from-different-entry-point.js"
+import "./resources/module-load-same-module-from-different-entry-point.js"
 debug('Executing the module.');
 window.firstModuleIsExecuted = true;
 </script>
 <script type="module" onload="onLoad()">
-import "./script-tests/module-load-same-module-from-different-entry-point.js"
+import "./resources/module-load-same-module-from-different-entry-point.js"
 debug('Executing the module.');
 window.secondModuleIsExecuted = true;
 </script>
index 9d62c34..fc6b751 100644 (file)
@@ -16,7 +16,7 @@ function onError()
 }
 </script>
 <script src="../../../resources/js-test-post.js"></script>
-<script type="module" src="script-tests/module-not-found-error-event-with-src-and-import.js" onerror="onError()"></script>
+<script type="module" src="resources/module-not-found-error-event-with-src-and-import.js" onerror="onError()"></script>
 <script type="module">
 shouldNotBe(`error`, `null`);
 shouldBe(`error.type`, `"error"`);
index 57cf2f5..a4bafda 100644 (file)
@@ -14,6 +14,6 @@ window.jsTestIsAsync = true;
 debug('Module is not executed yet.');
 </script>
 <script src="../../../resources/js-test-post.js"></script>
-<script type="module" src="./script-tests/module-src-current-script.js"></script>
+<script type="module" src="./resources/module-src-current-script.js"></script>
 </body>
 </html>
index c966cfb..e1788f2 100644 (file)
@@ -16,7 +16,7 @@ debug('Module is not executed yet.');
 (function () {
     var element = document.createElement('script');
     element.type = 'module';
-    element.src = './script-tests/module-src-dynamic.js';
+    element.src = './resources/module-src-dynamic.js';
     document.body.appendChild(element);
 }());
 </script>
index 22af533..7a780f3 100644 (file)
@@ -14,6 +14,6 @@ window.jsTestIsAsync = true;
 debug('Module is not executed yet.');
 </script>
 <script src="../../../resources/js-test-post.js"></script>
-<script type="module" src="./script-tests/module-src-simple.js"></script>
+<script type="module" src="./resources/module-src-simple.js"></script>
 </body>
 </html>
index 72dd290..197265f 100644 (file)
@@ -26,12 +26,12 @@ debug('Module is not executed yet.');
 <script src="../../../resources/js-test-post.js"></script>
 
 <script type="MoDuLe">
-import Cocoa from "./script-tests/module-inline-simple.js";
+import Cocoa from "./resources/module-inline-simple.js";
 window.resolve1();
 </script>
 
 <script type="MODULE">
-import Cocoa from "./script-tests/module-inline-simple.js";
+import Cocoa from "./resources/module-inline-simple.js";
 window.resolve2();
 </script>
 
index 855ca92..c324e81 100644 (file)
@@ -11,6 +11,6 @@ window.jsTestIsAsync = true;
 debug('Module is not executed yet.');
 </script>
 <script src="../../../resources/js-test-post.js"></script>
-<script type="module" onbeforeload="finishJSTest()" src="script-tests/module-will-fire-beforeload.js"></script>
+<script type="module" onbeforeload="finishJSTest()" src="resources/module-will-fire-beforeload.js"></script>
 </body>
 </html>
index 5c73b38..85d368d 100644 (file)
@@ -16,7 +16,7 @@ window.jsTestIsAsync = true;
 (function () {
     var element = document.createElement('script');
     element.noModule = true;
-    element.src = './script-tests/error-classic-script.js';
+    element.src = './resources/error-classic-script.js';
     document.body.appendChild(element);
     setTimeout(function () {
         shouldBeFalse(`executed`);
index 0f3c671..5b45206 100644 (file)
@@ -15,7 +15,7 @@ debug('Module is not executed yet.');
 </script>
 <script src="../../../resources/js-test-post.js"></script>
 <script nomodule type="module">
-import Cocoa from "./script-tests/module-inline-simple.js";
+import Cocoa from "./resources/module-inline-simple.js";
 var cocoa = new Cocoa();
 
 debug("Module execution is confined in the module environment.");
index 26ba2b3..e184d63 100644 (file)
@@ -14,6 +14,6 @@ window.jsTestIsAsync = true;
 debug('Module is not executed yet.');
 </script>
 <script src="../../../resources/js-test-post.js"></script>
-<script nomodule type="module" src="./script-tests/module-src-simple.js"></script>
+<script nomodule type="module" src="./resources/module-src-simple.js"></script>
 </body>
 </html>
index cae3349..a5e67ad 100644 (file)
@@ -8,7 +8,7 @@
 description('Test nomodule prevents execution of classic script.');
 window.executed = false;
 </script>
-<script nomodule src="./script-tests/module-src-simple.js"></script>
+<script nomodule src="./resources/module-src-simple.js"></script>
 <script>
 shouldBeFalse(`executed`);
 </script>
index 868ac9e..a5f15e1 100644 (file)
@@ -13,7 +13,7 @@ window.executed2 = false;
 window.jsTestIsAsync = true;
 </script>
 <script src="../../../resources/js-test-post.js"></script>
-<script id="target" src="./script-tests/error-classic-script.js" nomodule></script>
+<script id="target" src="./resources/error-classic-script.js" nomodule></script>
 <script id="target2">
 window.executed2 = true;
 </script>
diff --git a/LayoutTests/js/dom/modules/resources/error-classic-script.js b/LayoutTests/js/dom/modules/resources/error-classic-script.js
new file mode 100644 (file)
index 0000000..3d70688
--- /dev/null
@@ -0,0 +1,3 @@
+window.executed = true;
+testFailed("error");
+
diff --git a/LayoutTests/js/dom/modules/resources/import-from-loaded-classic-finish.js b/LayoutTests/js/dom/modules/resources/import-from-loaded-classic-finish.js
new file mode 100644 (file)
index 0000000..6a7ca9d
--- /dev/null
@@ -0,0 +1,2 @@
+debug("import from loaded classic finish");
+window.imported = true;
diff --git a/LayoutTests/js/dom/modules/resources/import-from-loaded-classic.js b/LayoutTests/js/dom/modules/resources/import-from-loaded-classic.js
new file mode 100644 (file)
index 0000000..7d8ac3f
--- /dev/null
@@ -0,0 +1,2 @@
+debug("import from loaded classic");
+import("./import-from-loaded-classic-finish.js").then(loaded);
diff --git a/LayoutTests/js/dom/modules/resources/import-from-loaded-module-finish.js b/LayoutTests/js/dom/modules/resources/import-from-loaded-module-finish.js
new file mode 100644 (file)
index 0000000..3604402
--- /dev/null
@@ -0,0 +1,2 @@
+debug("import from loaded module finish");
+window.imported = true;
diff --git a/LayoutTests/js/dom/modules/resources/import-from-loaded-module.js b/LayoutTests/js/dom/modules/resources/import-from-loaded-module.js
new file mode 100644 (file)
index 0000000..b4874e7
--- /dev/null
@@ -0,0 +1,2 @@
+debug("import from loaded module");
+import("./import-from-loaded-module-finish.js").then(loaded);
diff --git a/LayoutTests/js/dom/modules/resources/import-src-simple.js b/LayoutTests/js/dom/modules/resources/import-src-simple.js
new file mode 100644 (file)
index 0000000..f9c47a8
--- /dev/null
@@ -0,0 +1,11 @@
+import Cocoa from "./module-src-simple-cocoa.js";
+var cocoa = new Cocoa();
+
+debug("Module execution is confined in the module environment.");
+shouldBeEqualToString("typeof cocoa", "undefined");
+
+window.exportedCocoa = cocoa;
+shouldBeEqualToString("typeof exportedCocoa", "object");
+shouldBeEqualToString("exportedCocoa.taste()", "nice");
+export let ok = cocoa;
+window.imported = true;
diff --git a/LayoutTests/js/dom/modules/resources/module-document-write-src.js b/LayoutTests/js/dom/modules/resources/module-document-write-src.js
new file mode 100644 (file)
index 0000000..cdc21ea
--- /dev/null
@@ -0,0 +1,2 @@
+document.write("TEST FAILED");
+finishJSTest();
diff --git a/LayoutTests/js/dom/modules/resources/module-execution-error-inside-dependent-module-should-be-propagated-to-onerror-throw.js b/LayoutTests/js/dom/modules/resources/module-execution-error-inside-dependent-module-should-be-propagated-to-onerror-throw.js
new file mode 100644 (file)
index 0000000..c6c15af
--- /dev/null
@@ -0,0 +1,2 @@
+debug("Executing the dependent module");
+throw new Error("out");
diff --git a/LayoutTests/js/dom/modules/resources/module-execution-error-inside-dependent-module-should-be-propagated-to-onerror.js b/LayoutTests/js/dom/modules/resources/module-execution-error-inside-dependent-module-should-be-propagated-to-onerror.js
new file mode 100644 (file)
index 0000000..bff4d95
--- /dev/null
@@ -0,0 +1,2 @@
+import "./module-execution-error-inside-dependent-module-should-be-propagated-to-onerror-throw.js"
+testFailed("executed");
diff --git a/LayoutTests/js/dom/modules/resources/module-execution-order-mixed-2.js b/LayoutTests/js/dom/modules/resources/module-execution-order-mixed-2.js
new file mode 100644 (file)
index 0000000..e33b9d3
--- /dev/null
@@ -0,0 +1 @@
+shouldBe("count++", "5");
diff --git a/LayoutTests/js/dom/modules/resources/module-execution-order-mixed-cappuccino.js b/LayoutTests/js/dom/modules/resources/module-execution-order-mixed-cappuccino.js
new file mode 100644 (file)
index 0000000..d481afd
--- /dev/null
@@ -0,0 +1,3 @@
+import "./module-execution-order-mixed-matcha.js"
+
+shouldBe("count++", "2");
diff --git a/LayoutTests/js/dom/modules/resources/module-execution-order-mixed-cocoa.js b/LayoutTests/js/dom/modules/resources/module-execution-order-mixed-cocoa.js
new file mode 100644 (file)
index 0000000..081f67e
--- /dev/null
@@ -0,0 +1,3 @@
+import "./module-execution-order-mixed-matcha.js";
+
+shouldBe("count++", "1");
diff --git a/LayoutTests/js/dom/modules/resources/module-execution-order-mixed-matcha.js b/LayoutTests/js/dom/modules/resources/module-execution-order-mixed-matcha.js
new file mode 100644 (file)
index 0000000..c2e15d7
--- /dev/null
@@ -0,0 +1 @@
+shouldBe("count++", "0");
diff --git a/LayoutTests/js/dom/modules/resources/module-execution-order-mixed-with-classic-scripts-2.js b/LayoutTests/js/dom/modules/resources/module-execution-order-mixed-with-classic-scripts-2.js
new file mode 100644 (file)
index 0000000..5770a05
--- /dev/null
@@ -0,0 +1 @@
+shouldBe("count++", "11");
diff --git a/LayoutTests/js/dom/modules/resources/module-execution-order-mixed-with-classic-scripts-cappuccino.js b/LayoutTests/js/dom/modules/resources/module-execution-order-mixed-with-classic-scripts-cappuccino.js
new file mode 100644 (file)
index 0000000..7b580de
--- /dev/null
@@ -0,0 +1,3 @@
+import "./module-execution-order-mixed-with-classic-scripts-matcha.js"
+
+shouldBe("count++", "8");
diff --git a/LayoutTests/js/dom/modules/resources/module-execution-order-mixed-with-classic-scripts-cocoa.js b/LayoutTests/js/dom/modules/resources/module-execution-order-mixed-with-classic-scripts-cocoa.js
new file mode 100644 (file)
index 0000000..c2ec003
--- /dev/null
@@ -0,0 +1,3 @@
+import "./module-execution-order-mixed-with-classic-scripts-matcha.js";
+
+shouldBe("count++", "7");
diff --git a/LayoutTests/js/dom/modules/resources/module-execution-order-mixed-with-classic-scripts-matcha.js b/LayoutTests/js/dom/modules/resources/module-execution-order-mixed-with-classic-scripts-matcha.js
new file mode 100644 (file)
index 0000000..937bbd2
--- /dev/null
@@ -0,0 +1 @@
+shouldBe("count++", "6");
diff --git a/LayoutTests/js/dom/modules/resources/module-execution-order-mixed-with-classic-scripts.js b/LayoutTests/js/dom/modules/resources/module-execution-order-mixed-with-classic-scripts.js
new file mode 100644 (file)
index 0000000..9640e1a
--- /dev/null
@@ -0,0 +1,4 @@
+import "./module-execution-order-mixed-with-classic-scripts-cocoa.js"
+import "./module-execution-order-mixed-with-classic-scripts-cappuccino.js"
+
+shouldBe("count++", "9");
diff --git a/LayoutTests/js/dom/modules/resources/module-execution-order-mixed.js b/LayoutTests/js/dom/modules/resources/module-execution-order-mixed.js
new file mode 100644 (file)
index 0000000..44386fb
--- /dev/null
@@ -0,0 +1,4 @@
+import "./module-execution-order-mixed-cocoa.js"
+import "./module-execution-order-mixed-cappuccino.js"
+
+shouldBe("count++", "3");
diff --git a/LayoutTests/js/dom/modules/resources/module-inline-dynamic.js b/LayoutTests/js/dom/modules/resources/module-inline-dynamic.js
new file mode 100644 (file)
index 0000000..24360a7
--- /dev/null
@@ -0,0 +1,5 @@
+export default class Cocoa {
+    taste() {
+        return "awesome";
+    }
+};
diff --git a/LayoutTests/js/dom/modules/resources/module-inline-simple.js b/LayoutTests/js/dom/modules/resources/module-inline-simple.js
new file mode 100644 (file)
index 0000000..24360a7
--- /dev/null
@@ -0,0 +1,5 @@
+export default class Cocoa {
+    taste() {
+        return "awesome";
+    }
+};
diff --git a/LayoutTests/js/dom/modules/resources/module-load-event-with-src.js b/LayoutTests/js/dom/modules/resources/module-load-event-with-src.js
new file mode 100644 (file)
index 0000000..ab77db6
--- /dev/null
@@ -0,0 +1,2 @@
+debug('Executing a module with src attribute.');
+window.moduleExecuted = true;
diff --git a/LayoutTests/js/dom/modules/resources/module-load-same-module-from-different-entry-point.js b/LayoutTests/js/dom/modules/resources/module-load-same-module-from-different-entry-point.js
new file mode 100644 (file)
index 0000000..dd6abf6
--- /dev/null
@@ -0,0 +1,2 @@
+debug('Executing module-load-same-module-from-different-entry-point.js.');
+window.moduleExecutedCount++;
diff --git a/LayoutTests/js/dom/modules/resources/module-not-found-error-event-with-src-and-import.js b/LayoutTests/js/dom/modules/resources/module-not-found-error-event-with-src-and-import.js
new file mode 100644 (file)
index 0000000..f98d7b4
--- /dev/null
@@ -0,0 +1 @@
+import "./not-found.js"
diff --git a/LayoutTests/js/dom/modules/resources/module-src-current-script.js b/LayoutTests/js/dom/modules/resources/module-src-current-script.js
new file mode 100644 (file)
index 0000000..ac3073f
--- /dev/null
@@ -0,0 +1,3 @@
+debug("Module execution is confined in the module environment.");
+shouldBe("document.currentScript", "null");
+finishJSTest();
diff --git a/LayoutTests/js/dom/modules/resources/module-src-dynamic-cocoa.js b/LayoutTests/js/dom/modules/resources/module-src-dynamic-cocoa.js
new file mode 100644 (file)
index 0000000..479592d
--- /dev/null
@@ -0,0 +1,7 @@
+class Cocoa {
+    taste() {
+        return "nice";
+    }
+}
+
+export default Cocoa;
diff --git a/LayoutTests/js/dom/modules/resources/module-src-dynamic.js b/LayoutTests/js/dom/modules/resources/module-src-dynamic.js
new file mode 100644 (file)
index 0000000..b51a7be
--- /dev/null
@@ -0,0 +1,10 @@
+import Cocoa from "./module-src-dynamic-cocoa.js";
+var cocoa = new Cocoa();
+
+debug("Module execution is confined in the module environment.");
+shouldBeEqualToString("typeof cocoa", "undefined");
+
+window.exportedCocoa = cocoa;
+shouldBeEqualToString("typeof exportedCocoa", "object");
+shouldBeEqualToString("exportedCocoa.taste()", "nice");
+finishJSTest();
diff --git a/LayoutTests/js/dom/modules/resources/module-src-simple-cocoa.js b/LayoutTests/js/dom/modules/resources/module-src-simple-cocoa.js
new file mode 100644 (file)
index 0000000..479592d
--- /dev/null
@@ -0,0 +1,7 @@
+class Cocoa {
+    taste() {
+        return "nice";
+    }
+}
+
+export default Cocoa;
diff --git a/LayoutTests/js/dom/modules/resources/module-src-simple.js b/LayoutTests/js/dom/modules/resources/module-src-simple.js
new file mode 100644 (file)
index 0000000..4d9c774
--- /dev/null
@@ -0,0 +1,10 @@
+import Cocoa from "./module-src-simple-cocoa.js";
+var cocoa = new Cocoa();
+
+debug("Module execution is confined in the module environment.");
+shouldBeEqualToString("typeof cocoa", "undefined");
+
+window.exportedCocoa = cocoa;
+shouldBeEqualToString("typeof exportedCocoa", "object");
+shouldBeEqualToString("exportedCocoa.taste()", "nice");
+finishJSTest();
diff --git a/LayoutTests/js/dom/modules/resources/module-will-fire-beforeload.js b/LayoutTests/js/dom/modules/resources/module-will-fire-beforeload.js
new file mode 100644 (file)
index 0000000..f0a3938
--- /dev/null
@@ -0,0 +1 @@
+testFailed("executed");
index 94c7c5f..3e1d504 100644 (file)
@@ -1475,6 +1475,7 @@ set(WebCore_SOURCES
     dom/Range.cpp
     dom/ScopedEventQueue.cpp
     dom/ScriptElement.cpp
+    dom/ScriptElementCachedScriptFetcher.cpp
     dom/ScriptExecutionContext.cpp
     dom/ScriptRunner.cpp
     dom/ScriptableDocumentParser.cpp
index d0cd35b..6afdcd8 100644 (file)
@@ -1,3 +1,91 @@
+2017-01-27  Yusuke Suzuki  <utatane.tea@gmail.com>
+
+        Implement dynamic-import for WebCore
+        https://bugs.webkit.org/show_bug.cgi?id=166926
+
+        Reviewed by Ryosuke Niwa.
+
+        This patch introduces browser side dynamic-import implementation.
+        The dynamic-import is new ES feature which is now stage 3.
+        The JSC shell already implements it.
+
+        The dynamic-import allows us to kick module loading in a dynamic manner.
+        For example, you can write,
+
+            await module = import(`${HOST}/hello.js`);
+
+        The dynamic `import` operator (this is not a function) returns a promise with
+        module namespace object if the module loading succeeds. Otherwise, it returns
+        a rejected promise.
+
+        And importantly, this feature allows us to kick module loading from classic script.
+        Previously, module loading can be only used from <script type="module"> tag. And
+        all the module loading is done statically.
+
+        * CMakeLists.txt:
+        * WebCore.xcodeproj/project.pbxproj:
+        * bindings/js/CachedModuleScriptLoader.cpp:
+        (WebCore::CachedModuleScriptLoader::load):
+        * bindings/js/CachedScriptFetcher.cpp:
+        (WebCore::CachedScriptFetcher::create):
+        (WebCore::CachedScriptFetcher::requestModuleScript):
+        requestModuleScript function is used only when loading a new module script.
+        So, LoadableClassicScript should use requestScriptWithCache to load itself.
+        We pass String() for cross origin mode for null cross origin attribute as
+        specified.
+
+        (WebCore::CachedScriptFetcher::requestScriptWithCache):
+        * bindings/js/CachedScriptFetcher.h:
+        (WebCore::CachedScriptFetcher::CachedScriptFetcher):
+        * bindings/js/JSDOMWindowBase.cpp:
+        (WebCore::JSDOMWindowBase::moduleLoaderImportModule):
+        * bindings/js/JSDOMWindowBase.h:
+        * bindings/js/JSLazyEventListener.cpp:
+        (WebCore::JSLazyEventListener::initializeJSFunction):
+        * bindings/js/ScriptController.cpp:
+        (WebCore::ScriptController::executeScript):
+        * bindings/js/ScriptModuleLoader.cpp:
+        (WebCore::resolveModuleSpecifier):
+        Extract the part of resolving module specifier to a static function to use
+        it in ScriptModuleLoader::resolve and ScriptModuleLoader::importModule.
+
+        (WebCore::ScriptModuleLoader::resolve):
+        (WebCore::rejectPromise):
+        (WebCore::ScriptModuleLoader::importModule):
+        New hook moduleLoaderImportModule is implemented. This hook is called when
+        `import` operator is used. This hook is responsible to
+            1. resolve the module name to obtain module specifier. (like, resolve the
+                relative URL to get absolute URL.)
+            2. kick module loading with the resolved specifier.
+        When resolving the module name, the referrer information is needed.
+        For example, "./script.js" will be resolved to "http://example.com/script.js" if
+        the referrer module specifier is "http://example.com/".
+        If `import("./script.js")` is executed in the classic script
+        src="http://example.com/test.js", it starts loading "http://example.com/script.js".
+        So the information of the caller of `import` operator is necessary here.
+        This appropriate referrer is propagated by SourceOrigin.
+
+        * bindings/js/ScriptModuleLoader.h:
+        * dom/InlineClassicScript.h:
+        * dom/LoadableClassicScript.cpp:
+        (WebCore::LoadableClassicScript::load):
+        * dom/LoadableClassicScript.h:
+        * dom/LoadableModuleScript.h:
+        * dom/LoadableScript.h:
+        (WebCore::LoadableScript::LoadableScript):
+        (WebCore::LoadableScript::isClassicScript): Deleted.
+        (WebCore::LoadableScript::isModuleScript): Deleted.
+        * dom/ScriptElement.h:
+        * dom/ScriptElementCachedScriptFetcher.cpp: Copied from Source/WebCore/dom/InlineClassicScript.h.
+        (WebCore::ScriptElementCachedScriptFetcher::requestModuleScript):
+        This requestModuleScript will be used when the script tag (or modules imported from the script tag) uses `import` operator.
+        In classic scripts, `crossorigin` mode always becomes "omit" while module scripts
+        propagate the original `crossorigin` value.
+
+        * dom/ScriptElementCachedScriptFetcher.h: Copied from Source/WebCore/bindings/js/CachedScriptFetcher.h.
+        (WebCore::ScriptElementCachedScriptFetcher::crossOriginMode):
+        (WebCore::ScriptElementCachedScriptFetcher::ScriptElementCachedScriptFetcher):
+
 2017-01-26  Chris Dumez  <cdumez@apple.com>
 
         Revert r210474 it is no longer needed
index ca32596..e36e10e 100644 (file)
                E3B2F0F01D7F4CB500B0C9D1 /* LoadableClassicScript.h in Headers */ = {isa = PBXBuildFile; fileRef = E3B2F0E41D7F35EC00B0C9D1 /* LoadableClassicScript.h */; settings = {ATTRIBUTES = (Private, ); }; };
                E3B7C0631DC34160001FB0B8 /* JSDocumentDOMJIT.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E3B7C0621DC3415A001FB0B8 /* JSDocumentDOMJIT.cpp */; };
                E3C99A091DC3D41C00794AD3 /* DOMJITCheckDOM.h in Headers */ = {isa = PBXBuildFile; fileRef = E3C99A081DC3D41700794AD3 /* DOMJITCheckDOM.h */; };
+               E3E4E2A71E3B17100023BB8A /* ScriptElementCachedScriptFetcher.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E3E4E2A51E3B16FC0023BB8A /* ScriptElementCachedScriptFetcher.cpp */; };
+               E3E4E2A81E3B17100023BB8A /* ScriptElementCachedScriptFetcher.h in Headers */ = {isa = PBXBuildFile; fileRef = E3E4E2A61E3B16FC0023BB8A /* ScriptElementCachedScriptFetcher.h */; settings = {ATTRIBUTES = (Private, ); }; };
                E3FA38641D71812D00AA5950 /* PendingScriptClient.h in Headers */ = {isa = PBXBuildFile; fileRef = E3FA38611D716E7600AA5950 /* PendingScriptClient.h */; };
                E401C27517CE53EC00C41A35 /* ElementIteratorAssertions.h in Headers */ = {isa = PBXBuildFile; fileRef = E401C27417CE53EC00C41A35 /* ElementIteratorAssertions.h */; settings = {ATTRIBUTES = (Private, ); }; };
                E401E0A41C3C0B8300F34D10 /* StyleChange.h in Headers */ = {isa = PBXBuildFile; fileRef = E401E0A31C3C0B8300F34D10 /* StyleChange.h */; settings = {ATTRIBUTES = (Private, ); }; };
                E3B7C0621DC3415A001FB0B8 /* JSDocumentDOMJIT.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSDocumentDOMJIT.cpp; sourceTree = "<group>"; };
                E3C99A081DC3D41700794AD3 /* DOMJITCheckDOM.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOMJITCheckDOM.h; sourceTree = "<group>"; };
                E3D049931DADC04500718F3C /* NodeConstants.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NodeConstants.h; sourceTree = "<group>"; };
+               E3E4E2A51E3B16FC0023BB8A /* ScriptElementCachedScriptFetcher.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ScriptElementCachedScriptFetcher.cpp; sourceTree = "<group>"; };
+               E3E4E2A61E3B16FC0023BB8A /* ScriptElementCachedScriptFetcher.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScriptElementCachedScriptFetcher.h; sourceTree = "<group>"; };
                E3FA38611D716E7600AA5950 /* PendingScriptClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PendingScriptClient.h; sourceTree = "<group>"; };
                E401C27417CE53EC00C41A35 /* ElementIteratorAssertions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ElementIteratorAssertions.h; sourceTree = "<group>"; };
                E401E0A31C3C0B8300F34D10 /* StyleChange.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StyleChange.h; sourceTree = "<group>"; };
                                4998AED013FB224D0090B1AA /* ScriptedAnimationController.h */,
                                08A484750E5272C500C3FE76 /* ScriptElement.cpp */,
                                08A484760E5272C500C3FE76 /* ScriptElement.h */,
+                               E3E4E2A51E3B16FC0023BB8A /* ScriptElementCachedScriptFetcher.cpp */,
+                               E3E4E2A61E3B16FC0023BB8A /* ScriptElementCachedScriptFetcher.h */,
                                E11C9DAF0EB3699500E409DB /* ScriptExecutionContext.cpp */,
                                E11C9D9A0EB3681200E409DB /* ScriptExecutionContext.h */,
                                8A413ADF1207BBA50082016E /* ScriptRunner.cpp */,
                                26EA89A71B4F2B75008C5FD2 /* HashableActionList.h in Headers */,
                                8482B7461198C35400BFB005 /* HashChangeEvent.h in Headers */,
                                A8748BE012CBF2DC001FBA41 /* HashTools.h in Headers */,
+                               E3E4E2A81E3B17100023BB8A /* ScriptElementCachedScriptFetcher.h in Headers */,
                                F55B3DC01251F12D003EF269 /* HiddenInputType.h in Headers */,
                                515BE19C1D54F6C100DD7C68 /* HIDGamepad.h in Headers */,
                                515BE19E1D54F6C100DD7C68 /* HIDGamepadProvider.h in Headers */,
                                29A8124A0FBB9CA900510293 /* WebAccessibilityObjectWrapperBase.mm in Sources */,
                                AAA728F816D1D8BC00D3BBC6 /* WebAccessibilityObjectWrapperIOS.mm in Sources */,
                                AA478A8016CD70C3007D1BB4 /* WebAccessibilityObjectWrapperMac.mm in Sources */,
+                               E3E4E2A71E3B17100023BB8A /* ScriptElementCachedScriptFetcher.cpp in Sources */,
                                2D3EF4491917915C00034184 /* WebActionDisablingCALayerDelegate.mm in Sources */,
                                120DE3ED1C86CA3E00B6D4DD /* WebAnimation.cpp in Sources */,
                                07D637411BB0B11300256CE9 /* WebAudioSourceProviderAVFObjC.mm in Sources */,
index 44e9fe7..f15a464 100644 (file)
@@ -61,7 +61,7 @@ CachedModuleScriptLoader::~CachedModuleScriptLoader()
 bool CachedModuleScriptLoader::load(Document& document, const URL& sourceURL)
 {
     ASSERT(!m_cachedScript);
-    m_cachedScript = m_scriptFetcher->requestScriptWithCache(document, sourceURL);
+    m_cachedScript = m_scriptFetcher->requestModuleScript(document, sourceURL);
     if (!m_cachedScript)
         return false;
 
index 668e3cb..c69e9d1 100644 (file)
 
 namespace WebCore {
 
-CachedResourceHandle<CachedScript> CachedScriptFetcher::requestScriptWithCache(Document& document, const URL& sourceURL) const
+Ref<CachedScriptFetcher> CachedScriptFetcher::create(const String& charset)
+{
+    return adoptRef(*new CachedScriptFetcher(charset));
+}
+
+CachedResourceHandle<CachedScript> CachedScriptFetcher::requestModuleScript(Document& document, const URL& sourceURL) const
+{
+    return requestScriptWithCache(document, sourceURL, String());
+}
+
+CachedResourceHandle<CachedScript> CachedScriptFetcher::requestScriptWithCache(Document& document, const URL& sourceURL, const String& crossOriginMode) const
 {
     auto* settings = document.settings();
     if (settings && !settings->isScriptEnabled())
@@ -46,11 +56,12 @@ CachedResourceHandle<CachedScript> CachedScriptFetcher::requestScriptWithCache(D
     options.contentSecurityPolicyImposition = hasKnownNonce ? ContentSecurityPolicyImposition::SkipPolicyCheck : ContentSecurityPolicyImposition::DoPolicyCheck;
 
     CachedResourceRequest request(ResourceRequest(sourceURL), options);
-    request.setAsPotentiallyCrossOrigin(m_crossOriginMode, document);
+    request.setAsPotentiallyCrossOrigin(crossOriginMode, document);
     request.upgradeInsecureRequestIfNeeded(document);
 
     request.setCharset(m_charset);
-    request.setInitiator(m_initiatorName);
+    if (!m_initiatorName.isNull())
+        request.setInitiator(m_initiatorName);
 
     return document.cachedResourceLoader().requestScript(WTFMove(request));
 }
index 3f8d889..a1a82ce 100644 (file)
@@ -37,21 +37,28 @@ class URL;
 
 class CachedScriptFetcher : public JSC::ScriptFetcher {
 public:
-    CachedResourceHandle<CachedScript> requestScriptWithCache(Document&, const URL& sourceURL) const;
+    virtual CachedResourceHandle<CachedScript> requestModuleScript(Document&, const URL& sourceURL) const;
+
+    static Ref<CachedScriptFetcher> create(const String& charset);
 
 protected:
-    CachedScriptFetcher(const String& nonce, const String& crossOriginMode, const String& charset, const AtomicString& initiatorName, bool isInUserAgentShadowTree)
+    CachedScriptFetcher(const String& nonce, const String& charset, const AtomicString& initiatorName, bool isInUserAgentShadowTree)
         : m_nonce(nonce)
-        , m_crossOriginMode(crossOriginMode)
         , m_charset(charset)
         , m_initiatorName(initiatorName)
         , m_isInUserAgentShadowTree(isInUserAgentShadowTree)
     {
     }
 
+    CachedScriptFetcher(const String& charset)
+        : m_charset(charset)
+    {
+    }
+
+    CachedResourceHandle<CachedScript> requestScriptWithCache(Document&, const URL& sourceURL, const String& crossOriginMode) const;
+
 private:
     String m_nonce;
-    String m_crossOriginMode;
     String m_charset;
     AtomicString m_initiatorName;
     bool m_isInUserAgentShadowTree { false };
index fb598ed..80f5f23 100644 (file)
@@ -64,7 +64,7 @@ const GlobalObjectMethodTable JSDOMWindowBase::s_globalObjectMethodTable = {
     &javaScriptRuntimeFlags,
     &queueTaskToEventLoop,
     &shouldInterruptScriptBeforeTimeout,
-    nullptr,
+    &moduleLoaderImportModule,
     &moduleLoaderResolve,
     &moduleLoaderFetch,
     nullptr,
@@ -332,4 +332,13 @@ JSC::JSValue JSDOMWindowBase::moduleLoaderEvaluate(JSC::JSGlobalObject* globalOb
     return JSC::jsUndefined();
 }
 
+JSC::JSInternalPromise* JSDOMWindowBase::moduleLoaderImportModule(JSC::JSGlobalObject* globalObject, JSC::ExecState* exec, JSC::JSModuleLoader* moduleLoader, JSC::JSString* moduleName, const JSC::SourceOrigin& sourceOrigin)
+{
+    JSDOMWindowBase* thisObject = JSC::jsCast<JSDOMWindowBase*>(globalObject);
+    if (RefPtr<Document> document = thisObject->wrapped().document())
+        return document->moduleLoader()->importModule(globalObject, exec, moduleLoader, moduleName, sourceOrigin);
+    JSC::JSInternalPromiseDeferred* deferred = JSC::JSInternalPromiseDeferred::create(exec, globalObject);
+    return deferred->reject(exec, jsUndefined());
+}
+
 } // namespace WebCore
index f8814a5..9073837 100644 (file)
@@ -79,6 +79,7 @@ namespace WebCore {
         static JSC::JSInternalPromise* moduleLoaderResolve(JSC::JSGlobalObject*, JSC::ExecState*, JSC::JSModuleLoader*, JSC::JSValue, JSC::JSValue, JSC::JSValue);
         static JSC::JSInternalPromise* moduleLoaderFetch(JSC::JSGlobalObject*, JSC::ExecState*, JSC::JSModuleLoader*, JSC::JSValue, JSC::JSValue);
         static JSC::JSValue moduleLoaderEvaluate(JSC::JSGlobalObject*, JSC::ExecState*, JSC::JSModuleLoader*, JSC::JSValue, JSC::JSValue, JSC::JSValue);
+        static JSC::JSInternalPromise* moduleLoaderImportModule(JSC::JSGlobalObject*, JSC::ExecState*, JSC::JSModuleLoader*, JSC::JSString*, const JSC::SourceOrigin&);
 
         RefPtr<DOMWindow> m_wrapped;
         JSDOMWindowShell* m_shell;
index 39d2228..d270b26 100644 (file)
@@ -20,6 +20,7 @@
 #include "config.h"
 #include "JSLazyEventListener.h"
 
+#include "CachedScriptFetcher.h"
 #include "ContentSecurityPolicy.h"
 #include "Frame.h"
 #include "JSNode.h"
@@ -112,7 +113,7 @@ JSObject* JSLazyEventListener::initializeJSFunction(ScriptExecutionContext* exec
 
     JSObject* jsFunction = constructFunctionSkippingEvalEnabledCheck(
         exec, exec->lexicalGlobalObject(), args, Identifier::fromString(exec, m_functionName),
-        SourceOrigin { m_sourceURL }, m_sourceURL, m_sourcePosition, overrideLineNumber);
+        SourceOrigin { m_sourceURL, CachedScriptFetcher::create(document.charset()) }, m_sourceURL, m_sourcePosition, overrideLineNumber);
 
     if (UNLIKELY(scope.exception())) {
         reportCurrentException(exec);
index 01c5b3e..b991194 100644 (file)
@@ -675,7 +675,7 @@ bool ScriptController::canExecuteScripts(ReasonForCallingCanExecuteScripts reaso
 JSValue ScriptController::executeScript(const String& script, bool forceUserGesture, ExceptionDetails* exceptionDetails)
 {
     UserGestureIndicator gestureIndicator(forceUserGesture ? std::optional<ProcessingUserGestureState>(ProcessingUserGesture) : std::nullopt);
-    return executeScript(ScriptSourceCode(script, m_frame.document()->url()), exceptionDetails);
+    return executeScript(ScriptSourceCode(script, m_frame.document()->url(), TextPosition(), JSC::SourceProviderSourceType::Program, CachedScriptFetcher::create(m_frame.document()->charset())), exceptionDetails);
 }
 
 JSValue ScriptController::executeScript(const ScriptSourceCode& sourceCode, ExceptionDetails* exceptionDetails)
index 710510a..89acaff 100644 (file)
@@ -28,6 +28,7 @@
 
 #include "CachedModuleScriptLoader.h"
 #include "CachedScript.h"
+#include "CachedScriptFetcher.h"
 #include "Document.h"
 #include "Frame.h"
 #include "JSDOMBinding.h"
@@ -35,6 +36,7 @@
 #include "MIMETypeRegistry.h"
 #include "ScriptController.h"
 #include "ScriptSourceCode.h"
+#include <runtime/Completion.h>
 #include <runtime/JSInternalPromise.h>
 #include <runtime/JSInternalPromiseDeferred.h>
 #include <runtime/JSModuleRecord.h>
@@ -61,6 +63,23 @@ static bool isRootModule(JSC::JSValue importerModuleKey)
     return importerModuleKey.isSymbol() || importerModuleKey.isUndefined();
 }
 
+static Expected<URL, ASCIILiteral> resolveModuleSpecifier(Document& document, const String& specifier, const URL& baseURL)
+{
+    // https://html.spec.whatwg.org/multipage/webappapis.html#resolve-a-module-specifier
+
+    URL absoluteURL(URL(), specifier);
+    if (absoluteURL.isValid())
+        return absoluteURL;
+
+    if (!specifier.startsWith('/') && !specifier.startsWith("./") && !specifier.startsWith("../"))
+        return makeUnexpected(ASCIILiteral("Module specifier does not start with \"/\", \"./\", or \"../\"."));
+
+    auto result = document.completeURL(specifier, baseURL);
+    if (!result.isValid())
+        return makeUnexpected(ASCIILiteral("Module name does not resolve to a valid URL."));
+    return result;
+}
+
 JSC::JSInternalPromise* ScriptModuleLoader::resolve(JSC::JSGlobalObject* jsGlobalObject, JSC::ExecState* exec, JSC::JSModuleLoader*, JSC::JSValue moduleNameValue, JSC::JSValue importerModuleKey, JSC::JSValue)
 {
     auto& globalObject = *JSC::jsCast<JSDOMGlobalObject*>(jsGlobalObject);
@@ -75,60 +94,32 @@ JSC::JSInternalPromise* ScriptModuleLoader::resolve(JSC::JSGlobalObject* jsGloba
         return jsPromise.promise();
     }
 
-    // https://html.spec.whatwg.org/multipage/webappapis.html#resolve-a-module-specifier
-
     if (!moduleNameValue.isString()) {
-        promise->reject(TypeError, ASCIILiteral("Module specifier is not Symbol or String."));
+        promise->reject(TypeError, ASCIILiteral("Importer module key is not a Symbol or a String."));
         return jsPromise.promise();
     }
 
     String specifier = asString(moduleNameValue)->value(exec);
-
-    // 1. Apply the URL parser to specifier. If the result is not failure, return the result.
-    URL absoluteURL(URL(), specifier);
-    if (absoluteURL.isValid()) {
-        promise->resolve<IDLDOMString>(absoluteURL.string());
-        return jsPromise.promise();
-    }
-
-    // 2. If specifier does not start with the character U+002F SOLIDUS (/), the two-character sequence U+002E FULL STOP, U+002F SOLIDUS (./),
-    //    or the three-character sequence U+002E FULL STOP, U+002E FULL STOP, U+002F SOLIDUS (../), return failure and abort these steps.
-    if (!specifier.startsWith('/') && !specifier.startsWith("./") && !specifier.startsWith("../")) {
-        promise->reject(TypeError, ASCIILiteral("Module specifier does not start with \"/\", \"./\", or \"../\"."));
-        return jsPromise.promise();
-    }
-
-    // 3. Return the result of applying the URL parser to specifier with script's base URL as the base URL.
-
-    URL completedURL;
-
+    URL baseURL;
     if (isRootModule(importerModuleKey))
-        completedURL = m_document.completeURL(specifier);
-    else if (importerModuleKey.isString()) {
+        baseURL = m_document.baseURL();
+    else {
+        ASSERT(importerModuleKey.isString());
         URL importerModuleRequestURL(URL(), asString(importerModuleKey)->value(exec));
-        if (!importerModuleRequestURL.isValid()) {
-            promise->reject(TypeError, ASCIILiteral("Importer module key is an invalid URL."));
-            return jsPromise.promise();
-        }
+        ASSERT_WITH_MESSAGE(importerModuleRequestURL.isValid(), "Invalid module referrer never starts importing dependent modules.");
 
-        URL importerModuleResponseURL = m_requestURLToResponseURLMap.get(importerModuleRequestURL);
-        if (!importerModuleResponseURL.isValid()) {
-            promise->reject(TypeError, ASCIILiteral("Importer module has an invalid response URL."));
-            return jsPromise.promise();
-        }
-
-        completedURL = m_document.completeURL(specifier, importerModuleResponseURL);
-    } else {
-        promise->reject(TypeError, ASCIILiteral("Importer module key is not Symbol or String."));
-        return jsPromise.promise();
+        auto iterator = m_requestURLToResponseURLMap.find(importerModuleRequestURL);
+        ASSERT_WITH_MESSAGE(iterator != m_requestURLToResponseURLMap.end(), "Module referrer must register itself to the map before starting importing dependent modules.");
+        baseURL = iterator->value;
     }
 
-    if (!completedURL.isValid()) {
-        promise->reject(TypeError, ASCIILiteral("Module name constructs an invalid URL."));
+    auto result = resolveModuleSpecifier(m_document, specifier, baseURL);
+    if (!result) {
+        promise->reject(TypeError, result.error());
         return jsPromise.promise();
     }
 
-    promise->resolve<IDLDOMString>(completedURL.string());
+    promise->resolve<IDLDOMString>(result->string());
     return jsPromise.promise();
 }
 
@@ -199,6 +190,38 @@ JSC::JSValue ScriptModuleLoader::evaluate(JSC::JSGlobalObject*, JSC::ExecState*
     return JSC::jsUndefined();
 }
 
+static JSC::JSInternalPromise* rejectPromise(JSC::ExecState& state, JSDOMGlobalObject& globalObject, ExceptionCode ec, ASCIILiteral message)
+{
+    auto& jsPromise = *JSC::JSInternalPromiseDeferred::create(&state, &globalObject);
+    auto deferred = DeferredPromise::create(globalObject, jsPromise);
+    deferred->reject(ec, WTFMove(message));
+    return jsPromise.promise();
+}
+
+JSC::JSInternalPromise* ScriptModuleLoader::importModule(JSC::JSGlobalObject* jsGlobalObject, JSC::ExecState* exec, JSC::JSModuleLoader*, JSC::JSString* moduleName, const JSC::SourceOrigin& sourceOrigin)
+{
+    auto& state = *exec;
+    JSC::VM& vm = exec->vm();
+    auto& globalObject = *JSC::jsCast<JSDOMGlobalObject*>(jsGlobalObject);
+
+    // FIXME: setTimeout and setInterval with "string()" should propagate SourceOrigin.
+    // https://webkit.org/b/167097
+    ASSERT_WITH_MESSAGE(!sourceOrigin.isNull(), "If SourceOrigin is null, this function is not invoked.");
+    if (!sourceOrigin.fetcher())
+        return rejectPromise(state, globalObject, TypeError, ASCIILiteral("Could not use import operator in this context."));
+
+    URL baseURL(URL(), sourceOrigin.string());
+    if (!baseURL.isValid())
+        return rejectPromise(state, globalObject, TypeError, ASCIILiteral("Importer module key is not Symbol or String."));
+
+    auto specifier = moduleName->value(exec);
+    auto result = resolveModuleSpecifier(m_document, specifier, baseURL);
+    if (!result)
+        return rejectPromise(state, globalObject, TypeError, result.error());
+
+    return JSC::importModule(exec, JSC::Identifier::fromString(&vm, result->string()), JSC::JSScriptFetcher::create(vm, sourceOrigin.fetcher() ));
+}
+
 void ScriptModuleLoader::notifyFinished(CachedModuleScriptLoader& loader, RefPtr<DeferredPromise> promise)
 {
     // https://html.spec.whatwg.org/multipage/webappapis.html#fetch-a-single-module-script
index a0683ff..6e7a61b 100644 (file)
@@ -38,6 +38,7 @@ class ExecState;
 class JSGlobalObject;
 class JSInternalPromise;
 class JSModuleLoader;
+class SourceOrigin;
 
 }
 
@@ -57,6 +58,7 @@ public:
     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);
+    JSC::JSInternalPromise* importModule(JSC::JSGlobalObject*, JSC::ExecState*, JSC::JSModuleLoader*, JSC::JSString*, const JSC::SourceOrigin&);
 
 private:
     void notifyFinished(CachedModuleScriptLoader&, RefPtr<DeferredPromise>) final;
index 0e26535..9fa9f31 100644 (file)
 
 #pragma once
 
-#include "CachedScriptFetcher.h"
+#include "ScriptElementCachedScriptFetcher.h"
 
 namespace WebCore {
 
 class ScriptElement;
 
-class InlineClassicScript final : public CachedScriptFetcher {
+class InlineClassicScript final : public ScriptElementCachedScriptFetcher {
 public:
     static Ref<InlineClassicScript> create(ScriptElement&);
 
+    bool isClassicScript() const final { return true; }
+    bool isModuleScript() const final { return false; }
+
 private:
     InlineClassicScript(const String& nonce, const String& crossOriginMode, const String& charset, const AtomicString& initiatorName, bool isInUserAgentShadowTree)
-        : CachedScriptFetcher(nonce, crossOriginMode, charset, initiatorName, isInUserAgentShadowTree)
+        : ScriptElementCachedScriptFetcher(nonce, crossOriginMode, charset, initiatorName, isInUserAgentShadowTree)
     {
     }
 };
index 6119ab1..771d42d 100644 (file)
@@ -110,7 +110,7 @@ void LoadableClassicScript::execute(ScriptElement& scriptElement)
 bool LoadableClassicScript::load(Document& document, const URL& sourceURL)
 {
     ASSERT(!m_cachedScript);
-    m_cachedScript = requestScriptWithCache(document, sourceURL);
+    m_cachedScript = requestScriptWithCache(document, sourceURL, crossOriginMode());
     if (!m_cachedScript)
         return false;
     m_cachedScript->addClient(*this);
index dda02c6..dfac664 100644 (file)
@@ -47,7 +47,9 @@ public:
     bool wasCanceled() const final;
 
     CachedScript& cachedScript() { return *m_cachedScript; }
+
     bool isClassicScript() const final { return true; }
+    bool isModuleScript() const final { return false; }
 
     void execute(ScriptElement&) final;
 
index 83f5391..bd11c06 100644 (file)
@@ -43,6 +43,8 @@ public:
     bool wasCanceled() const final;
 
     CachedModuleScript& moduleScript() { return m_moduleScript.get(); }
+
+    bool isClassicScript() const final { return false; }
     bool isModuleScript() const final { return true; }
 
     void execute(ScriptElement&) final;
index ca84e81..5b53c4f 100644 (file)
@@ -25,7 +25,7 @@
 
 #pragma once
 
-#include "CachedScriptFetcher.h"
+#include "ScriptElementCachedScriptFetcher.h"
 #include <runtime/ConsoleTypes.h>
 #include <wtf/HashCountedSet.h>
 #include <wtf/RefCounted.h>
@@ -36,7 +36,7 @@ namespace WebCore {
 class LoadableScriptClient;
 class ScriptElement;
 
-class LoadableScript : public CachedScriptFetcher {
+class LoadableScript : public ScriptElementCachedScriptFetcher {
 public:
     enum class ErrorType {
         CachedScript,
@@ -66,12 +66,9 @@ public:
     void addClient(LoadableScriptClient&);
     void removeClient(LoadableScriptClient&);
 
-    virtual bool isClassicScript() const { return false; }
-    virtual bool isModuleScript() const { return false; }
-
 protected:
     LoadableScript(const String& nonce, const String& crossOriginMode, const String& charset, const AtomicString& initiatorName, bool isInUserAgentShadowTree)
-        : CachedScriptFetcher(nonce, crossOriginMode, charset, initiatorName, isInUserAgentShadowTree)
+        : ScriptElementCachedScriptFetcher(nonce, crossOriginMode, charset, initiatorName, isInUserAgentShadowTree)
     {
     }
 
index 0034667..b82118c 100644 (file)
@@ -95,8 +95,6 @@ private:
     bool ignoresLoadRequest() const;
     bool isScriptForEventSupported() const;
 
-    CachedResourceHandle<CachedScript> requestScriptWithCache(const URL&, const String& nonceAttribute, const String& crossoriginAttribute);
-
     bool requestClassicScript(const String& sourceURL);
     bool requestModuleScript(const TextPosition& scriptStartPosition);
 
diff --git a/Source/WebCore/dom/ScriptElementCachedScriptFetcher.cpp b/Source/WebCore/dom/ScriptElementCachedScriptFetcher.cpp
new file mode 100644 (file)
index 0000000..bd49f90
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * 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 "ScriptElementCachedScriptFetcher.h"
+
+#include "Element.h"
+#include "ScriptElement.h"
+
+namespace WebCore {
+
+CachedResourceHandle<CachedScript> ScriptElementCachedScriptFetcher::requestModuleScript(Document& document, const URL& sourceURL) const
+{
+    // https://github.com/tc39/proposal-dynamic-import/blob/master/HTML Integration.md
+    // If the fetcher is not module script, credential mode is always "omit".
+
+    return requestScriptWithCache(document, sourceURL, isClassicScript() ? ASCIILiteral("omit") : m_crossOriginMode);
+}
+
+}
diff --git a/Source/WebCore/dom/ScriptElementCachedScriptFetcher.h b/Source/WebCore/dom/ScriptElementCachedScriptFetcher.h
new file mode 100644 (file)
index 0000000..410cd30
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * 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. AND ITS CONTRIBUTORS ``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 ITS 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 "CachedScriptFetcher.h"
+
+namespace WebCore {
+
+class ScriptElementCachedScriptFetcher : public CachedScriptFetcher {
+public:
+    virtual CachedResourceHandle<CachedScript> requestModuleScript(Document&, const URL& sourceURL) const;
+
+    virtual bool isClassicScript() const = 0;
+    virtual bool isModuleScript() const = 0;
+
+    const String& crossOriginMode() const { return m_crossOriginMode; }
+
+protected:
+    ScriptElementCachedScriptFetcher(const String& nonce, const String& crossOriginMode, const String& charset, const AtomicString& initiatorName, bool isInUserAgentShadowTree)
+        : CachedScriptFetcher(nonce, charset, initiatorName, isInUserAgentShadowTree)
+        , m_crossOriginMode(crossOriginMode)
+    {
+    }
+
+private:
+    String m_crossOriginMode;
+};
+
+} // namespace WebCore