Signatur
Beschreibung
Die Eigenschaft source eines MessageEvent verweist auf das Objekt, das die Nachricht gesendet hat. Ihr Typ ist MessageEventSource, also je nach Kontext ein WindowProxy (bei window.postMessage() zwischen Fenstern, iframes und Pop-ups), ein MessagePort (bei Nachrichten, die in einem SharedWorker über connect ankommen) oder ein ServiceWorker (bei Nachrichten vom Service Worker an eine Seite über navigator.serviceWorker).
Am häufigsten braucht man source, um direkt zu antworten. Ein Fenster, das eine Nachricht bekommt, muss die Referenz auf das sendende Fenster nicht selbst kennen: event.source.postMessage(antwort, event.origin) reicht. So lassen sich Anfrage-Antwort-Protokolle zwischen Eltern-Seite und iframe oder Pop-up bauen.
Außerdem kann man mit source prüfen, welches Fenster die Nachricht geschickt hat, etwa mit event.source === iframe.contentWindow. Das ist sinnvoll, wenn mehrere iframes vom selben Ursprung eingebettet sind und sich über origin allein nicht unterscheiden lassen.
Bei Nachrichten über MessageChannel-Ports, von dedizierten Workern (worker.onmessage), über BroadcastChannel, WebSocket oder EventSource ist source in der Regel null.
Rückgabewert
null, wenn es keinen zuordenbaren Absender gibt (z. B. bei dedizierten Workern, BroadcastChannel, WebSocket oder EventSource).Beispiele
iframe antwortet der Eltern-Seite über event.source
// Im iframe (https://widget.example.com)
const ERLAUBTER_URSPRUNG = 'https://app.example.com';
window.addEventListener('message', (event) => {
// Zuerst immer den Ursprung prüfen
if (event.origin !== ERLAUBTER_URSPRUNG) return;
if (!event.source) return;
if (event.data?.type === 'ping') {
// Direkt an den Absender antworten, mit festem Zielursprung
event.source.postMessage({ type: 'pong', zeit: Date.now() }, event.origin);
}
});
Absender unter mehreren iframes erkennen
// In der Eltern-Seite
const chat = document.querySelector('#chat-frame');
const karte = document.querySelector('#map-frame');
window.addEventListener('message', (event) => {
if (event.origin !== 'https://widgets.example.com') return;
if (event.source === chat.contentWindow) {
console.log('Nachricht vom Chat:', event.data);
} else if (event.source === karte.contentWindow) {
console.log('Nachricht von der Karte:', event.data);
} else {
console.warn('Unbekannter Absender – ignoriert');
}
});
Service Worker antwortet dem Client
// sw.js – Nachricht von einer Seite empfangen
self.addEventListener('message', (event) => {
// event.source ist hier ein Client-Objekt (WindowClient)
if (event.data === 'version?') {
event.source.postMessage({ version: '2.3.1' });
}
});
// Seite (main.js)
navigator.serviceWorker.addEventListener('message', (event) => {
// event.source ist hier das ServiceWorker-Objekt
console.log(event.source instanceof ServiceWorker, event.data);
});
const registrierung = await navigator.serviceWorker.ready;
registrierung.active.postMessage('version?');
SharedWorker: Port aus dem connect-Ereignis
// shared-worker.js
const ports = new Set();
self.addEventListener('connect', (event) => {
// Beim connect-Ereignis ist ports[0] (und source) der neue MessagePort
const port = event.ports[0];
ports.add(port);
port.onmessage = (e) => {
// Nachricht an alle verbundenen Tabs weiterleiten
ports.forEach((p) => p.postMessage(e.data));
};
});
// Wichtig · Fallstricke
- Sicherheit:
sourceersetzt keine Prüfung des Ursprungs. Kontrolliere immer zuerstevent.origingegen eine feste Liste erlaubter Ursprünge, bevor duevent.dataverarbeitest oder übersourceantwortest. Sonst kann jede Seite, die eine Referenz auf dein Fenster hat (z. B. überwindow.open), Nachrichten einschleusen. - Beim Antworten mit
event.source.postMessage()als Zielursprungevent.originangeben, nicht'*'. So landen vertrauliche Daten nicht bei einem Fenster, das inzwischen zu einer anderen Seite navigiert wurde. - Rechne mit
null: Bei dedizierten Workern,MessageChannel-Ports,BroadcastChannel,WebSocketundEventSourceistsourceleer. Außerdem kann das sendende Fenster schon geschlossen sein. Dann bleibt die Referenz zwar bestehen,event.source.closedist abertrue. - Ein fremdes
WindowProxygibt wegen der Same-Origin-Policy nur wenige Eigenschaften frei, etwapostMessage,close,closed,location(nur schreibend) undframes. Aufdocumentkann man nicht zugreifen. - Im Service Worker ist
event.sourceeinClient/WindowClient, nicht derMessageEventSource-Typ im engeren Sinn. Dieses Ereignis ist technisch einExtendableMessageEvent. - Browser-Unterstützung: in allen modernen Browsern vorhanden (Baseline).