[WIP] feat: run scripts inside cross-origin iframe #318
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Still WIP but should not change much - any feedback is appreciated
(Sorry for such a long description)
This PR allows executing scripts inside an iframe which can be moved to a different origin. Based on discussion in issue #5.
Motivation
Executing 3rd party code on a different origin improves isolation even further because scripts can no longer access IndexedDB or fetch resources from the main document origin.
Enabling the feature
sandboxLib
property topartytown
config, e.g.sandboxLib: 'http://partytown-sandbox.my-site.com/~partytown/'
. This path can also lead to same-origin Partytown lib path, although it will not introduce any additional isolation because the workers will be created on same origin.This feature is currently opt-in because it introduces a completely new Main Thread-Web Worker and Main Thread-Service Worker communication mechanism. However, I think it might become default in the future. The startup might be just a bit slower, but performance difference should be unnoticeable.
How it works
Previously, Partytown used to load a sandbox script which later spawned a web worker and a service worker. The hierarchy looked like this.
Now, with
sandboxLib
defined, Partytown loads an iframe (from a possibly different origin) which spawns web worker and service worker under same domain as the iframe.Previously, web worker was spawned from main document, meaning you could attach a message listener to the worker and access the DOM directly from within the listener.
Now, the worker is spawned inside a different origin iframe, meaning
postMessage
must be used instead. In #5 the proposed solution was to have an extrapostMessage
call between main document to the iframe, but that would lead to an additional message hop and slightly worse performance (I tested this appraoch, it led to an overhead of 100 ms in PT Benchmark). In my PR I useMessageChannel
for all main doc-worker communication, and I only communicate with the iframe to passMessagePort
.So in other words, the new isolated iframe is only responsible for registering web worker/service worker and passing
MessagePort
to them.The new communication works like this:
MessagePort
to the iframe viapostMessage
(one MessagePort for WW and one for SW).MessagePort
, then an event listener is set for the port. From now on workers usemessagePort.postMessage
instead of the default worker scopepostMessage
.Known issues
same-site
,postMessage
messages withSharedArrayBuffer
never arrive (no errors in console).TypeError: Typed array for wait/notify must wrap a SharedArrayBuffer.
I would appreciate any ideas on these issues.
Questions for Partydown devs
TODO: