Lesson 0007 · ~10 minutes
One skill:
close
the
MessagePort
when you are done. Do not treat
event.data as server truth.
You can say this: “I call port.close() when I am
done. After that, a send does not arrive. I still check the
shape of event.data. A widget can lie.”
You still hold
port1. That is not the same as transfer.
Transfer moved port2. You keep
port1.
port.close() disconnects the pair.
(MDN)
The other end gets a
close event.
(HTML Standard)
After close, a send on that port does not arrive. The method may return. It may throw. Either way, the child must not get the data.
Close ports you create. The HTML Standard asks you to do this so the pair can be collected. (HTML §9.4.5)
port1.close();
useEffect(() => {
const channel = new MessageChannel();
channel.port1.onmessage = onPrivate;
iframeRef.current.contentWindow.postMessage(
{ type: "port" },
"https://widget.example",
[channel.port2],
);
return () => {
channel.port1.close();
};
}, []);
Close on unmount. Do not keep a dead port.
After you check
event.origin, you still check the shape of
event.data.
(HTML §9.3.2.1)
A compromised widget can send { role: "admin" }.
The origin can be the widget you expect. The data can still be a lie.
A port does not fix that. Who holds the port can still lie.
Your page decides. Your server decides. The clone does not.
window.addEventListener("message", (event) => {
if (event.origin !== "https://widget.example") return;
const data = event.data;
if (!data || data.type !== "filter") return;
if (typeof data.q !== "string") return;
setQuery(data.q);
});
The child below sends ready, then holds a port.
true.port: line must say held.
close event.
Do the five steps first. Then answer these questions.
You call port.close(). Then you call port.postMessage here.
The parent closed port1. The child still holds port2.
You transferred port2. You later call port1.close().
event.data is { role: "admin" } from the widget.
Why do you call port.close() when done?
close disconnects the pair
you still hold.
close.event.origin. Then check the shape of
event.data. Do not treat it as the server.
HTML §9.3.2.1 — Authors
(origin, then data format, never * with secrets).
Then
HTML §9.4.5
(close ports).