t2ym/thin-hook

[bootstrap.js] Incorrect hook.parameters.baseURI in some edge cases

Closed this issue · 0 comments

t2ym commented

[bootstrap.js] Incorrect hook.parameters.baseURI in some edge cases

Reproducible Cases

  • Web workers that are not in the same directory as the entry page
  • [In potential future support] Dynamic top pages that are not in the same directory as the entry page

Fix

  • Add basePath configuration for bootstrap-js plugin
  • Hard-code basePath to bootstrap.js
  • Derive baseURI from basePath and the origin
diff --git a/demo-config/config.js b/demo-config/config.js
index 55f3ddee..74936287 100644
--- a/demo-config/config.js
+++ b/demo-config/config.js
@@ -569,6 +569,7 @@ class TargetConfig extends Injectable(Traceable(Configurable(GulpDefaultRegistry
     .assign('bootstrap-js')({
       [TargetConfig.needResolution]: true,
       type: 'bootstrap',
+      basePath: () => this.url.root + (this.url.root.endsWith('/') ? '' : '/'),
       emptyDocument: () => this.getPluginUrl('empty-document', 'bootstrap-js', true /* startsWithDot */),
       markParsed: () => this.getPluginUrl('mark-parsed-js', 'bootstrap-js'),
       //onloadWrapper: `event.target.addEventListener('srcdoc-load', () => { $onload$ })`,
diff --git a/plugins/bootstrap-js/bootstrap.js b/plugins/bootstrap-js/bootstrap.js
index 6e8f9f34..e09db061 100644
--- a/plugins/bootstrap-js/bootstrap.js
+++ b/plugins/bootstrap-js/bootstrap.js
@@ -3,22 +3,30 @@ if (hook.parameters[Symbol.for('bootstrap.js')]) {
 }
 else {
   hook.parameters[Symbol.for('bootstrap.js')] = true;
+/* @ifdef basePath */
+  const basePath = '/* @echo basePath */'; // hard-coded URL path of the entry page
+/* @endif */
   let baseURI;
   let noHookAuthorization = '';
   switch (self.constructor.name) {
   case 'Window':
+    let script = top.document.querySelector('script');
+    let src = script.src;
+    if (!src) {
+      location = 'about:blank'; // top SVG is not supported
+    }
     if (self === top) {
-      baseURI = location.href;
+/* @ifndef basePath */
+      baseURI = new URL('.', document.currentScript.src).href; // assuming the bootstrap.js script resides at the same directory as the entry page
+/* @endif */
+/* @ifdef basePath */
+      baseURI = new URL(basePath, document.currentScript.src).href; // same origin as bootstrap.js
+/* @endif */
     }
     else {
       baseURI = top.hook.parameters.baseURI;
     }
     hook.parameters.baseURI = baseURI;
-    let script = top.document.querySelector('script');
-    let src = script.src;
-    if (!src) {
-      location = 'about:blank'; // top SVG is not supported
-    }
     noHookAuthorization = new URL(src, baseURI).searchParams.get('no-hook-authorization');
     break;
   case 'ServiceWorkerGlobalScope':
@@ -29,17 +37,27 @@ else {
   case 'DedicatedWorkerGlobalScope':
   case 'SharedWorkerGlobalScope':
     // For Hook Workers; Insignificant in hooked web workers
+/* @ifndef basePath */
     baseURI = new URL(location.origin + 
         (new URL(location.href).searchParams.has('service-worker-initiator')
           ? new URL(location.href).searchParams.get('service-worker-initiator')
           : location.pathname
         )
       ).href;
+/* @endif */
+/* @ifdef basePath */
+    baseURI = new URL(basePath, location.origin).href; // Note: same origin as worker location; no support for CORS worker scripts
+/* @endif */
     hook.parameters.baseURI = baseURI;
     noHookAuthorization = new URL(location.href).searchParams.has('no-hook-authorization') ? new URL(location.href).searchParams.get('no-hook-authorization') : '';
     break;
   default:
+/* @ifndef basePath */
     baseURI = location.href;
+/* @endif */
+/* @ifdef basePath */
+    baseURI = new URL(basePath, location.origin).href; // same origin
+/* @endif */
     hook.parameters.baseURI = baseURI;
     break;
   }

Notes

  • No support for CORS web worker scripts
  • import.meta is a SyntaxError unless the worker is a module
    • introducing bootstrap-module.js is inappropriate