alesgenova / post-me

📩 Use web Workers and other Windows through a simple Promise API

Home Page:https://www.npmjs.com/package/post-me

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Starting child too long after parent handshake causes handshake message to be missed

cmawhorter opened this issue · comments

Describe the bug
Initiating parent handshake before child causes bot handshakes to wait indefinitely.

To Reproduce

  const parentOrigin = 'https://parent.example.com';
  const childOrigin = 'https://child.example.com';
  const [parentWindow, childWindow] = makeWindows(parentOrigin, childOrigin);
  let parentConnection: Promise<Connection>,
    childConnection: Promise<Connection>;
  // kick off parent handshake
  parentConnection = ParentHandshake(
    {},
    childWindow,
    childWindow.origin,
    parentWindow
  );
  // force a delay so problem always happens
  await (new Promise(resolve => setTimeout(resolve, 100));
  childConnection = ChildHandshake({}, parentWindow.origin, childWindow);
  // never succeeds because both connections miss their message
  await Promise.all([parentConnection, childConnection]);

Expected behavior
Both parent and child should continuously retry their handshake message until it succeeds or there is a hard error.

Yep, I can see how we could end up in a deadlock in this example.

Do you think something like this could also happen in the real world?
For example, in the little demo app, I only start the parent side of the handshake after the iframe onload callback (https://github.com/alesgenova/post-me/blob/main/demo/parent.js#L53), so that I can assume (or at least I hope) that the child is already listening for the handshake.

Is my assumption that it's enough to just put the handshake code in the onload callback wrong?

But even so, it may be good to do at least a few retries, to save the users from themselves :)

Do you think something like this could also happen in the real world?

Yes I do. This is the rule and not exception when working with iframes because iframe events don't fire cross origin so it's not possible to do onload.

Additionally -- no assumptions can be made about the child. Maybe the child handshake starts when a user clicks a button, for example, and not onload.

Because of that, the parent handshake would have to retry continuously until a connection is made (or probably a configurable timeout is hit).

Great, thanks for the explanation, then I will be merging your commit, and maybe build a little further on top of it