'Is it possible to add a property to an iframe window object before it loads such that the value is available to scripts in the frame?

I would like to add a property to an iframe's window before the page loads its content. I would like it set so that scripts loaded on the source have access to that property.

As an example, this is what I am attempting to do:

<!- index.html ->
<body>
  <script type="module">
    const iframe = document.createElement('iframe')
    iframe.src = 'about:blank'

    const onLoad1 = new Promise(res => iframe.onload = res)
    document.body.appendChild(iframe)
    await onLoad1

    iframe.contentWindow.foo = 'something'
    console.log(iframe.contentWindow.foo)

    const onLoad2 = new Promise(res => iframe.onload = res)
    iframe.src = 'frame.html' // same origin
    await onLoad2

    console.log(iframe.contentWindow.foo) // currently undefined
  </script>
</body>
<!- frame.html ->
<script>
  console.log(window.foo) // currently undefined
</script>

I realise the contentWindow is a new Window because re-assigning the src property triggers a new page load.

I was hopeful that travelling from about:blank to a same origin path would grant me special powers persist properties set on the window but that wasn't the case.

Currently (what I am trying to avoid), I am resorting to emitting a custom event and capturing that asynchronously within the frame. This is a cumbersome dance and not ideal for situations where values must be known synchronously.

<!- index.html ->
<body>
  <script type="module">
    const iframe = document.createElement('iframe')
    iframe.src = 'frame.html'

    const onLoad1 = new Promise(res => iframe.onload = res)
    document.body.appendChild(iframe)
    await onLoad1

    function sendValue() {
      iframe.contentWindow.dispatchEvent(
        new CustomEvent('custom:onload', { detail: 'foo' }))
    }

    iframe.contentWindow.addEventListener('custom:request:onload', sendValue)
    sendValue()
  </script>
</body>
<!- frame.html ->
<body>
  <script async type="module">
    const onfoo = new Promise(
      res => window.addEventListener('custom:request:onload', e => res(e.detail))
    
    window.dispatchEvent(new CustomEvent('custom:request:onload'))
  </script>
</body>


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source