From 19e786f4f3c9a63c6427aae8a261d5be5616c111 Mon Sep 17 00:00:00 2001 From: Jake Archibald Date: Fri, 19 Feb 2021 12:06:10 +0000 Subject: [PATCH 1/9] No dynamic import in service worker --- .../import-module-scripts.https.html | 29 ------------------- .../no-dynamic-import-in-module.any.js | 4 +++ .../service-worker/no-dynamic-import.any.js | 3 ++ .../resources/basic-module-2.js | 1 + .../service-worker/resources/basic-module.js | 1 + .../resources/no-dynamic-import.js | 22 ++++++++++++++ tools/manifest/sourcefile.py | 1 + tools/serve/serve.py | 26 +++++++++++++++++ 8 files changed, 58 insertions(+), 29 deletions(-) delete mode 100644 service-workers/service-worker/import-module-scripts.https.html create mode 100644 service-workers/service-worker/no-dynamic-import-in-module.any.js create mode 100644 service-workers/service-worker/no-dynamic-import.any.js create mode 100644 service-workers/service-worker/resources/basic-module-2.js create mode 100644 service-workers/service-worker/resources/basic-module.js create mode 100644 service-workers/service-worker/resources/no-dynamic-import.js diff --git a/service-workers/service-worker/import-module-scripts.https.html b/service-workers/service-worker/import-module-scripts.https.html deleted file mode 100644 index 7bca8de64f5bc9..00000000000000 --- a/service-workers/service-worker/import-module-scripts.https.html +++ /dev/null @@ -1,29 +0,0 @@ - - -Tests for module import: ServiceWorker - - - - - - - diff --git a/service-workers/service-worker/no-dynamic-import-in-module.any.js b/service-workers/service-worker/no-dynamic-import-in-module.any.js new file mode 100644 index 00000000000000..47eac7d109f947 --- /dev/null +++ b/service-workers/service-worker/no-dynamic-import-in-module.any.js @@ -0,0 +1,4 @@ +// META: global=serviceworker-module + +import './basic-module-2.js'; +import './resources/no-dynamic-import.js'; diff --git a/service-workers/service-worker/no-dynamic-import.any.js b/service-workers/service-worker/no-dynamic-import.any.js new file mode 100644 index 00000000000000..25b370b7094bf8 --- /dev/null +++ b/service-workers/service-worker/no-dynamic-import.any.js @@ -0,0 +1,3 @@ +// META: global=serviceworker + +importScripts('resources/no-dynamic-import.js'); diff --git a/service-workers/service-worker/resources/basic-module-2.js b/service-workers/service-worker/resources/basic-module-2.js new file mode 100644 index 00000000000000..189b1c87fee75c --- /dev/null +++ b/service-workers/service-worker/resources/basic-module-2.js @@ -0,0 +1 @@ +export default 'hello again!'; diff --git a/service-workers/service-worker/resources/basic-module.js b/service-workers/service-worker/resources/basic-module.js new file mode 100644 index 00000000000000..789a89bc630847 --- /dev/null +++ b/service-workers/service-worker/resources/basic-module.js @@ -0,0 +1 @@ +export default 'hello!'; diff --git a/service-workers/service-worker/resources/no-dynamic-import.js b/service-workers/service-worker/resources/no-dynamic-import.js new file mode 100644 index 00000000000000..1cc1894cb2a4ac --- /dev/null +++ b/service-workers/service-worker/resources/no-dynamic-import.js @@ -0,0 +1,22 @@ +/** @type {[name: string, url: string][]} */ +const importUrlTests = [ + ["Module URL", "./resources/basic-module.js"], + // In no-dynamic-import-in-module.any.js, this module is also statically imported + ["Another module URL", "./resources/basic-module-2.js"], + [ + "Module data: URL", + "data:text/javascript;charset=utf-8," + + encodeURIComponent(`export default 'hello!';`), + ], +]; + +for (const [name, url] of importUrlTests) { + promise_test(async () => { + try { + await import(url); + assert_unreached("Import must not fulfill"); + } catch (err) { + assert_equals(err.constructor, TypeError, "TypeError thrown"); + } + }, name); +} diff --git a/tools/manifest/sourcefile.py b/tools/manifest/sourcefile.py index 5b99f90e458a29..3119aea20904c9 100644 --- a/tools/manifest/sourcefile.py +++ b/tools/manifest/sourcefile.py @@ -84,6 +84,7 @@ def read_script_metadata(f, regexp): _any_variants = { "window": {"suffix": ".any.html"}, "serviceworker": {"force_https": True}, + "serviceworker-module": {"force_https": True}, "sharedworker": {}, "dedicatedworker": {"suffix": ".any.worker.html"}, "worker": {"longhand": {"dedicatedworker", "sharedworker", "serviceworker"}}, diff --git a/tools/serve/serve.py b/tools/serve/serve.py index 644a8a93f704f0..0a59605e68bad4 100644 --- a/tools/serve/serve.py +++ b/tools/serve/serve.py @@ -296,6 +296,31 @@ class ServiceWorkersHandler(HtmlWrapperHandler): """ +class ServiceWorkersModuleHandler(HtmlWrapperHandler): + global_type = "serviceworker-module" + path_replace = [(".any.serviceworker-module.html", + ".any.js", ".any.worker.js")] + wrapper = """ + +%(meta)s + + +
+ +""" + + class AnyWorkerHandler(WrapperHandler): headers = [('Content-Type', 'text/javascript')] path_replace = [(".any.worker.js", ".any.js")] @@ -372,6 +397,7 @@ def add_mount_point(self, url_base, path): ("GET", "*.any.html", AnyHtmlHandler), ("GET", "*.any.sharedworker.html", SharedWorkersHandler), ("GET", "*.any.serviceworker.html", ServiceWorkersHandler), + ("GET", "*.any.serviceworker-module.html", ServiceWorkersModuleHandler), ("GET", "*.any.worker.js", AnyWorkerHandler), ("GET", "*.asis", handlers.AsIsHandler), ("GET", "/.well-known/origin-policy", handlers.PythonScriptHandler), From ca9d457e46740967f3099b2c6e8fb4ee3fd07dd7 Mon Sep 17 00:00:00 2001 From: Jake Archibald Date: Fri, 19 Feb 2021 12:27:47 +0000 Subject: [PATCH 2/9] Use import rather than importScripts --- tools/manifest/sourcefile.py | 1 + tools/serve/serve.py | 30 +++++++++++++++++++++++++++++- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/tools/manifest/sourcefile.py b/tools/manifest/sourcefile.py index 3119aea20904c9..c617a5b7b14b50 100644 --- a/tools/manifest/sourcefile.py +++ b/tools/manifest/sourcefile.py @@ -88,6 +88,7 @@ def read_script_metadata(f, regexp): "sharedworker": {}, "dedicatedworker": {"suffix": ".any.worker.html"}, "worker": {"longhand": {"dedicatedworker", "sharedworker", "serviceworker"}}, + "worker-module": {}, "jsshell": {"suffix": ".any.js"}, } # type: Dict[Text, Dict[Text, Any]] diff --git a/tools/serve/serve.py b/tools/serve/serve.py index 0a59605e68bad4..3597d73211e946 100644 --- a/tools/serve/serve.py +++ b/tools/serve/serve.py @@ -299,7 +299,7 @@ class ServiceWorkersHandler(HtmlWrapperHandler): class ServiceWorkersModuleHandler(HtmlWrapperHandler): global_type = "serviceworker-module" path_replace = [(".any.serviceworker-module.html", - ".any.js", ".any.worker.js")] + ".any.js", ".any.worker-module.js")] wrapper = """ %(meta)s @@ -348,6 +348,33 @@ def _script_replacement(self, key, value): return None +class AnyWorkerModuleHandler(WrapperHandler): + headers = [('Content-Type', 'text/javascript')] + path_replace = [(".any.worker-module.js", ".any.js")] + wrapper = """%(meta)s +self.GLOBAL = { + isWindow: function() { return false; }, + isWorker: function() { return true; }, +}; +import "/resources/testharness.js"; +%(script)s +import "%(path)s"; +done(); +""" + + def _meta_replacement(self, key, value): + return None + + def _script_replacement(self, key, value): + if key == "script": + attribute = value.replace("\\", "\\\\").replace('"', '\\"') + return 'import "%s";' % attribute + if key == "title": + value = value.replace("\\", "\\\\").replace('"', '\\"') + return 'self.META_TITLE = "%s";' % value + return None + + rewrites = [("GET", "/resources/WebIDLParser.js", "/resources/webidl2/lib/webidl2.js")] @@ -399,6 +426,7 @@ def add_mount_point(self, url_base, path): ("GET", "*.any.serviceworker.html", ServiceWorkersHandler), ("GET", "*.any.serviceworker-module.html", ServiceWorkersModuleHandler), ("GET", "*.any.worker.js", AnyWorkerHandler), + ("GET", "*.any.worker-module.js", AnyWorkerModuleHandler), ("GET", "*.asis", handlers.AsIsHandler), ("GET", "/.well-known/origin-policy", handlers.PythonScriptHandler), ("*", "*.py", handlers.PythonScriptHandler), From c6ae206ea26ba96bc5ddca834e8c5340bb6072e8 Mon Sep 17 00:00:00 2001 From: Jake Archibald Date: Fri, 19 Feb 2021 12:39:26 +0000 Subject: [PATCH 3/9] Better code reuse --- tools/serve/serve.py | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/tools/serve/serve.py b/tools/serve/serve.py index 3597d73211e946..a6691a8b12caa9 100644 --- a/tools/serve/serve.py +++ b/tools/serve/serve.py @@ -338,18 +338,20 @@ class AnyWorkerHandler(WrapperHandler): def _meta_replacement(self, key, value): return None + def _create_script_import(self, attribute): + return 'importScripts("%s")' % attribute + def _script_replacement(self, key, value): if key == "script": attribute = value.replace("\\", "\\\\").replace('"', '\\"') - return 'importScripts("%s")' % attribute + return self._create_script_import(attribute) if key == "title": value = value.replace("\\", "\\\\").replace('"', '\\"') return 'self.META_TITLE = "%s";' % value return None -class AnyWorkerModuleHandler(WrapperHandler): - headers = [('Content-Type', 'text/javascript')] +class AnyWorkerModuleHandler(AnyWorkerHandler): path_replace = [(".any.worker-module.js", ".any.js")] wrapper = """%(meta)s self.GLOBAL = { @@ -362,17 +364,8 @@ class AnyWorkerModuleHandler(WrapperHandler): done(); """ - def _meta_replacement(self, key, value): - return None - - def _script_replacement(self, key, value): - if key == "script": - attribute = value.replace("\\", "\\\\").replace('"', '\\"') - return 'import "%s";' % attribute - if key == "title": - value = value.replace("\\", "\\\\").replace('"', '\\"') - return 'self.META_TITLE = "%s";' % value - return None + def _create_script_import(self, attribute): + return 'import "%s";' % attribute rewrites = [("GET", "/resources/WebIDLParser.js", "/resources/webidl2/lib/webidl2.js")] From 2af527f4c0e0f1472eecf72b524337c5efbb2f3f Mon Sep 17 00:00:00 2001 From: Jake Archibald Date: Fri, 19 Feb 2021 14:20:08 +0000 Subject: [PATCH 4/9] Fixes following feedback --- .../no-dynamic-import-in-module.any.js | 3 +++ .../resources/no-dynamic-import.js | 17 +++++++---------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/service-workers/service-worker/no-dynamic-import-in-module.any.js b/service-workers/service-worker/no-dynamic-import-in-module.any.js index 47eac7d109f947..84b17629ccddc9 100644 --- a/service-workers/service-worker/no-dynamic-import-in-module.any.js +++ b/service-workers/service-worker/no-dynamic-import-in-module.any.js @@ -1,4 +1,7 @@ // META: global=serviceworker-module +// This is imported to ensure import('./basic-module-2.js') fails even if +// it has been previously statically imported. import './basic-module-2.js'; + import './resources/no-dynamic-import.js'; diff --git a/service-workers/service-worker/resources/no-dynamic-import.js b/service-workers/service-worker/resources/no-dynamic-import.js index 1cc1894cb2a4ac..8e42097e19f6c7 100644 --- a/service-workers/service-worker/resources/no-dynamic-import.js +++ b/service-workers/service-worker/resources/no-dynamic-import.js @@ -1,8 +1,8 @@ /** @type {[name: string, url: string][]} */ const importUrlTests = [ - ["Module URL", "./resources/basic-module.js"], + ["Module URL", "./basic-module.js"], // In no-dynamic-import-in-module.any.js, this module is also statically imported - ["Another module URL", "./resources/basic-module-2.js"], + ["Another module URL", "./basic-module-2.js"], [ "Module data: URL", "data:text/javascript;charset=utf-8," + @@ -11,12 +11,9 @@ const importUrlTests = [ ]; for (const [name, url] of importUrlTests) { - promise_test(async () => { - try { - await import(url); - assert_unreached("Import must not fulfill"); - } catch (err) { - assert_equals(err.constructor, TypeError, "TypeError thrown"); - } - }, name); + promise_test( + async (t) => + promise_rejects_js(t, TypeError, import(url), "Import must reject"), + name + ); } From 96aa038377cc9d0b0462589e64e8bbf3cca3907a Mon Sep 17 00:00:00 2001 From: Jake Archibald Date: Fri, 19 Feb 2021 14:33:00 +0000 Subject: [PATCH 5/9] Redundant async --- service-workers/service-worker/resources/no-dynamic-import.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/service-workers/service-worker/resources/no-dynamic-import.js b/service-workers/service-worker/resources/no-dynamic-import.js index 8e42097e19f6c7..ecedd6c5d75c7d 100644 --- a/service-workers/service-worker/resources/no-dynamic-import.js +++ b/service-workers/service-worker/resources/no-dynamic-import.js @@ -12,8 +12,7 @@ const importUrlTests = [ for (const [name, url] of importUrlTests) { promise_test( - async (t) => - promise_rejects_js(t, TypeError, import(url), "Import must reject"), + (t) => promise_rejects_js(t, TypeError, import(url), "Import must reject"), name ); } From 568429f4fedf42c0b98abad50e4eb6d6d6cb938f Mon Sep 17 00:00:00 2001 From: Jake Archibald Date: Mon, 22 Feb 2021 09:33:49 +0000 Subject: [PATCH 6/9] Adding support for dedicated worker modules and shared worker modules --- tools/manifest/sourcefile.py | 2 ++ tools/serve/serve.py | 37 ++++++++++++++++++++++++++++++++++-- 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/tools/manifest/sourcefile.py b/tools/manifest/sourcefile.py index c617a5b7b14b50..34e679eb8b73b7 100644 --- a/tools/manifest/sourcefile.py +++ b/tools/manifest/sourcefile.py @@ -86,7 +86,9 @@ def read_script_metadata(f, regexp): "serviceworker": {"force_https": True}, "serviceworker-module": {"force_https": True}, "sharedworker": {}, + "sharedworker-module": {}, "dedicatedworker": {"suffix": ".any.worker.html"}, + "dedicatedworker-module": {"suffix": ".any.worker-module.html"}, "worker": {"longhand": {"dedicatedworker", "sharedworker", "serviceworker"}}, "worker-module": {}, "jsshell": {"suffix": ".any.js"}, diff --git a/tools/serve/serve.py b/tools/serve/serve.py index a6691a8b12caa9..9b237951f6d9d1 100644 --- a/tools/serve/serve.py +++ b/tools/serve/serve.py @@ -227,6 +227,22 @@ class WorkersHandler(HtmlWrapperHandler): """ +class WorkerModulesHandler(HtmlWrapperHandler): + global_type = "dedicatedworker-module" + path_replace = [(".any.worker-module.html", ".any.js", ".any.worker-module.js"), + (".worker.html", ".worker.js")] + wrapper = """ + +%(meta)s + + +
+ +""" + + class WindowHandler(HtmlWrapperHandler): path_replace = [(".window.html", ".window.js")] wrapper = """ @@ -275,6 +291,21 @@ class SharedWorkersHandler(HtmlWrapperHandler): """ +class SharedWorkerModulesHandler(HtmlWrapperHandler): + global_type = "sharedworker-module" + path_replace = [(".any.sharedworker-module.html", ".any.js", ".any.worker-module.js")] + wrapper = """ + +%(meta)s + + +
+ +""" + + class ServiceWorkersHandler(HtmlWrapperHandler): global_type = "serviceworker" path_replace = [(".any.serviceworker.html", ".any.js", ".any.worker.js")] @@ -296,7 +327,7 @@ class ServiceWorkersHandler(HtmlWrapperHandler): """ -class ServiceWorkersModuleHandler(HtmlWrapperHandler): +class ServiceWorkerModulesHandler(HtmlWrapperHandler): global_type = "serviceworker-module" path_replace = [(".any.serviceworker-module.html", ".any.js", ".any.worker-module.js")] @@ -413,11 +444,13 @@ def add_mount_point(self, url_base, path): routes = [ ("GET", "*.worker.html", WorkersHandler), + ("GET", "*.worker-module.html", WorkerModulesHandler), ("GET", "*.window.html", WindowHandler), ("GET", "*.any.html", AnyHtmlHandler), ("GET", "*.any.sharedworker.html", SharedWorkersHandler), + ("GET", "*.any.sharedworker-module.html", SharedWorkerModulesHandler), ("GET", "*.any.serviceworker.html", ServiceWorkersHandler), - ("GET", "*.any.serviceworker-module.html", ServiceWorkersModuleHandler), + ("GET", "*.any.serviceworker-module.html", ServiceWorkerModulesHandler), ("GET", "*.any.worker.js", AnyWorkerHandler), ("GET", "*.any.worker-module.js", AnyWorkerModuleHandler), ("GET", "*.asis", handlers.AsIsHandler), From 1e08d95e05e27d3eea8f143200c5ae82f988c34c Mon Sep 17 00:00:00 2001 From: Jake Archibald Date: Tue, 23 Feb 2021 11:34:15 +0000 Subject: [PATCH 7/9] Adding BaseWorkerHandler and docs --- docs/writing-tests/testharness.md | 13 +++++++++++- tools/serve/serve.py | 35 +++++++++++++++++-------------- 2 files changed, 31 insertions(+), 17 deletions(-) diff --git a/docs/writing-tests/testharness.md b/docs/writing-tests/testharness.md index 7cf7f73a868e0a..49060bdd8e6cd7 100644 --- a/docs/writing-tests/testharness.md +++ b/docs/writing-tests/testharness.md @@ -140,6 +140,8 @@ It is possible to customize the set of scopes with a metadata comment, such as // ==> would only run in the window and service worker scope // META: global=dedicatedworker // ==> would run in the default dedicated worker scope +// META: global=dedicatedworker-module +// ==> would run in the dedicated worker scope as a module // META: global=worker // ==> would run in the dedicated, shared, and service worker scopes ``` @@ -149,8 +151,13 @@ are: * `window` (default): to be run at x.any.html * `dedicatedworker` (default): to be run at x.any.worker.html -* `serviceworker`: to be run at x.any.serviceworker.html (`.https` is implied) +* `dedicatedworker-module` to be run at x.any.worker-module.html +* `serviceworker`: to be run at x.any.serviceworker.html (`.https` is + implied) +* `serviceworker-module`: to be run at x.any.serviceworker-module.html + (`.https` is implied) * `sharedworker`: to be run at x.any.sharedworker.html +* `sharedworker-module`: to be run at x.any.sharedworker-module.html * `jsshell`: to be run in a JavaScript shell, without access to the DOM (currently only supported in SpiderMonkey, and skipped in wptrunner) * `worker`: shorthand for the dedicated, shared, and service worker scopes @@ -183,6 +190,10 @@ Use `// META: script=link/to/resource.js` at the beginning of the resource. For can be used to include both the global and a local `utils.js` in a test. +In window environments, the script will be included using a classic `