Aaronius / penpal

A promise-based library for securely communicating with iframes via postMessage.
MIT License
381 stars 56 forks source link

error "Cannot read properties of null (reading 'postMessage')" #85

Closed KutnerUri closed 2 years ago

KutnerUri commented 2 years ago

version: 5.3.0 I am getting getting this error:

handleSynMessageFactory.js:16 Uncaught TypeError: Cannot read properties of null (reading 'postMessage')
    at handleSynMessageFactory.js:16:1
    at handleMessage (connectToChild.js:35:1)

It seems to come form this line of code:

// at parent/handleSynMessageFactory:
event.source.postMessage(synAckMessage, originForSending);

Usually the source is a window, so I'm guessing this is happening because the parent window is getting a message from an iframe that already closed (similar to the connectionDestroyed error during handshake).

Maybe add a null guard there?

Aaronius commented 2 years ago

Interesting! Thanks for reporting. Do you have a reproducible example I can look at?

Aaronius commented 2 years ago

Does this happen only after the connection has been made for some time? Do you know if the iframe has been removed or have you called destroy() on the connection object?

KutnerUri commented 2 years ago

yes, I'm calling connection.destroy(), like so:

useEffect(() => {
  const connection = connectToChild<ChildMethods>({
    iframe,
    methods: {
      pub: this.emitEvent,
    },
  });

  connection.promise
    .then(childConnection => (this.childApi = childConnection))
    .catch(err => {
      // eslint-disable-next-line no-console
      console.error("[Pubsub.ui]", "failed connecting to child iframe:", err);
    });

  const destroy = () => {
    connection && connection.destroy();
  };

  return () => destroy();
}, [ref?.current]);

I also upgraded to the latest version, "penpal": "6.2.1". It is difficult to reproduce, it's happening when switching between iframes a lot. Screen Shot 2022-03-01 at 12 43 05

You can see it here: https://bit.dev/teambit/base-ui

Aaronius commented 2 years ago

This is helpful. Thanks. I clicked between nav elements about a hundred times and didn't get it but I'll keep trying. Regardless, I'll probably add a null check. I'm just trying make sure there isn't a larger problem I should be aware of.

Aaronius commented 2 years ago

Fixed in v6.6.2. Thanks for reporting and for the details!

KutnerUri commented 2 years ago

6.2.2* :)

Aaronius commented 2 years ago

Lol…yes, thank you.

Aaronius commented 2 years ago

Hey @KutnerUri, I noticed you're doing some connectToParent retries here: https://github.com/teambit/bit/blob/385cdf34ef360e38319ada68ebe524d616fad541/scopes/harmony/pubsub/pubsub.preview.runtime.ts#L50-L65

I'd like to hear more about why that was necessary for you. I'm wondering if this may be useful to other users of Penpal and should be built into Penpal itself.

KutnerUri commented 2 years ago

I don't remember 100%, but I think it had some race condition because of server-side rendering.

When the site is pre-generated on the server, it loads the entire html, including iframes, so the browser loads/executes both the parent and child iframe at the same time. The main site takes a while to execute/rehydrate until it finally reaches the react hook that starts listening The child iframe is much simpler, and it sometimes manages to reach .connectToParent early enough, it didn't get a response and just time out.