From 5f44198345cb9fb941096671548202bcc110d67a Mon Sep 17 00:00:00 2001 From: Philip Chimento Date: Tue, 26 Nov 2024 12:57:29 -0800 Subject: [PATCH] Pass document path to WrapperHandler._script_replacement This is necessary so that imports inside a ShadowRealm will work regardless of the outer realm's base URL. Pass the document path into all of the virtual methods that result in generating dynamic imports in the served script. --- tools/serve/serve.py | 60 +++++++++++++++++++++++++++++++------------- 1 file changed, 43 insertions(+), 17 deletions(-) diff --git a/tools/serve/serve.py b/tools/serve/serve.py index 9d1283ff3e8a80..a852544ba572a0 100644 --- a/tools/serve/serve.py +++ b/tools/serve/serve.py @@ -8,6 +8,7 @@ import multiprocessing import os import platform +import posixpath import subprocess import sys import threading @@ -183,7 +184,8 @@ def _get_script(self, request): :param request: The Request being processed. """ for key, value in self._get_metadata(request): - replacement = self._script_replacement(key, value) + path = self._get_path(request.url_parts.path, True) + replacement = self._script_replacement(key, value, path) if replacement: yield replacement @@ -207,6 +209,13 @@ def _meta_replacement(self, key, value): # a specific metadata key: value pair. pass + @abc.abstractmethod + def _script_replacement(self, key, value, path): + # Get the string to insert into the script part of the wrapper + # document, given a specific metadata key: value pair and the path of + # the document. + pass + @abc.abstractmethod def check_exposure(self, request): # Raise an exception if this handler shouldn't be exposed after all. @@ -238,7 +247,7 @@ def _meta_replacement(self, key, value): return '%s' % value return None - def _script_replacement(self, key, value): + def _script_replacement(self, key, value, path): if key == "script": attribute = value.replace("&", "&").replace('"', """) return '' % attribute @@ -456,9 +465,14 @@ class ShadowRealmInWindowHandler(HtmlWrapperHandler): """ - def _script_replacement(self, key, value): + def _script_replacement(self, key, value, path): if key == "script": - return 'await import("%s");' % value + # ShadowRealm does not share the outer realm's base URI + module_specifier = ( + value + if posixpath.isabs(value) + else posixpath.join(posixpath.dirname(path), value)) + return 'await import("%s");' % module_specifier return None @@ -508,9 +522,14 @@ class ShadowRealmInShadowRealmHandler(HtmlWrapperHandler): """ - def _script_replacement(self, key, value): + def _script_replacement(self, key, value, path): if key == "script": - return 'await import("%s");' % value + # ShadowRealm does not share the outer realm's base URI + module_specifier = ( + value + if posixpath.isabs(value) + else posixpath.join(posixpath.dirname(path), value)) + return 'await import("%s");' % module_specifier return None @@ -569,15 +588,15 @@ def _meta_replacement(self, key, value): return None @abc.abstractmethod - def _create_script_import(self, attribute): - # Take attribute (a string URL to a JS script) and return JS source to import the script - # into the worker. + def _create_script_import(self, attribute, path): + # Take attribute (a string URL to a JS script) and path (the document's + # path) and return JS source to import the script into the worker. pass - def _script_replacement(self, key, value): + def _script_replacement(self, key, value, path): if key == "script": attribute = value.replace("\\", "\\\\").replace('"', '\\"') - return self._create_script_import(attribute) + return self._create_script_import(attribute, path) if key == "title": value = value.replace("\\", "\\\\").replace('"', '\\"') return 'self.META_TITLE = "%s";' % value @@ -598,7 +617,7 @@ class ClassicWorkerHandler(BaseWorkerHandler): done(); """ - def _create_script_import(self, attribute): + def _create_script_import(self, attribute, path): return 'importScripts("%s")' % attribute @@ -616,7 +635,7 @@ class ModuleWorkerHandler(BaseWorkerHandler): done(); """ - def _create_script_import(self, attribute): + def _create_script_import(self, attribute, path): return 'import "%s";' % attribute @@ -645,8 +664,13 @@ class ShadowRealmWorkerWrapperHandler(BaseWorkerHandler): })(); """ - def _create_script_import(self, attribute): - return 'await import("%s");' % attribute + def _create_script_import(self, attribute, path): + # ShadowRealm does not share the outer realm's base URI + module_specifier = ( + attribute + if posixpath.isabs(attribute) + else posixpath.join(posixpath.dirname(path), attribute)) + return 'await import("%s");' % module_specifier class ShadowRealmServiceWorkerWrapperHandler(BaseWorkerHandler): @@ -677,7 +701,8 @@ class ShadowRealmServiceWorkerWrapperHandler(BaseWorkerHandler): })(); """ - def _create_script_import(self, attribute): + def _create_script_import(self, attribute, path): + # fakeDynamicImport uses the outer realm's base URI return 'await fakeDynamicImport("%s");' % attribute @@ -708,7 +733,8 @@ class ShadowRealmAudioWorkletWrapperHandler(BaseWorkerHandler): } """ - def _create_script_import(self, attribute): + def _create_script_import(self, attribute, path): + # fakeDynamicImport uses the outer realm's base URI return 'await fakeDynamicImport("%s");' % attribute