nosovk
## Reproduction on Partytown 0.14.3 A minimal same-origin iframe example fails in Partytown but succeeds with a native parent script. This is independent of Google, analytics configuration, a reverse proxy, or a framework. Serve these files on localhost (a service-worker-capable secure context), and serve the installed 0.14.3 `lib` directory at `/~partytown/`. Use a fresh browser profile for each variant to avoid existing registrations. ### parent.html ```html <!doctype html> <script>window.partytown = { debug: true };</script> <script src="/~partytown/partytown.js"></script> <script> addEventListener('message', event => console.log('child', event.data)); </script> <body> <script type="text/partytown"> const frame = document.createElement('iframe'); frame.src = '/child.html'; document.body.appendChild(frame); </script> </body> ``` For the native control, omit Partytown initialization and use an ordinary script instead of `type="text/partytown"`. ### child.html ```html <!doctype html><body><script> const report = data => parent.postMessage(data, '*'); navigator.serviceWorker.addEventListener('message', e => report(e.data)); const url = '/dummy-sw.js'; // Separate Trusted Types variant: replace the line above with: // const url = trustedTypes.createPolicy('dummy-worker', { // createScriptURL: value => value // }).createScriptURL('/dummy-sw.js'); try { navigator.serviceWorker.register(url, { scope: '/' }) .then(reg => report({ registered: reg.scope })) .catch(error => report({ registerError: error.message })); } catch (error) { report({ registerError: error.message }); } try { navigator.serviceWorker.ready.then(reg => { report({ ready: reg.scope, active: reg.active.scriptURL }); reg.active.postMessage('ping'); }); } catch (error) { report({ readyError: error.message }); } </script></body> ``` ### dummy-sw.js ```js addEventListener('install', () => skipWaiting()); addEventListener('activate', event => event.waitUntil(clients.claim())); addEventListener('message', event => { if (event.data === 'ping') event.source.postMessage('pong'); }); ``` ## Actual results | Variant | register | ready | ping/pong | | --- | --- | --- | --- | | Native iframe, string URL | succeeds | succeeds with active worker | succeeds | | Native iframe, TrustedScriptURL | succeeds | succeeds with active worker | succeeds | | Partytown iframe, string URL | reports success | throws `TypeError: navigator.serviceWorker.ready.then is not a function` | not reached | | Partytown iframe, TrustedScriptURL | requests `/undefined`, gets 404 | same `.ready.then` TypeError | not reached | The 404 is the consequence of the TrustedScriptURL argument becoming `/undefined`, not a deliberately broken network request. No `register`/`ready` shim, native script opt-out, or Trusted Types disabling was used. Both executing Partytown workers were identified as 0.14.3 using CDP `Debugger.getScriptSource`, rather than relying only on package metadata. The string registration and TrustedScriptURL cases ran in separate browser sessions. ## Expected behavior Service-worker registration and `ready` should retain their semantics in an iframe created by a Partytown script, including TrustedScriptURL input and messaging. This investigation started with GTM's service-worker iframe through a same-origin gateway. The initial Google/proxy capture had transport defects and is NOT evidence of a successful Google iframe response or analytics failure on 0.14.3. The isolated reproducer above establishes the service-worker API defects without that proxy. If these APIs cannot be supported inside a virtual iframe, could Partytown support a selective native iframe boundary while keeping the GTM parent script in the worker? A narrowly matched iframe opt-out would need to preserve URL, lifecycle and messaging identity. This is a possible solution, not a claim that a particular new API is necessary. Related: #635, #749, #753. The unreadable-response fallback does not address service-worker semantics for readable same-origin iframe documents.