Start · Sprachen · JavaScript · Referenz · MessageEvent.source

MessageEvent.source

Eigenschaft

Schreibgeschützte Eigenschaft, die den Absender einer Nachricht liefert: ein <code>WindowProxy</code>, <code>MessagePort</code>, <code>ServiceWorker</code> oder <code>null</code>.

seit JavaScript Baseline: alle Browser Kategorie: webapi

Signatur

get MessageEvent.source

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

Typ
WindowProxy | MessagePort | ServiceWorker | null
Beschreibung
Das Objekt, das die Nachricht gesendet hat, oder 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');
  }
});
Nachricht vom Chat: { text: 'Hallo' }

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?');
true { version: '2.3.1' }

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: source ersetzt keine Prüfung des Ursprungs. Kontrolliere immer zuerst event.origin gegen eine feste Liste erlaubter Ursprünge, bevor du event.data verarbeitest oder über source antwortest. Sonst kann jede Seite, die eine Referenz auf dein Fenster hat (z. B. über window.open), Nachrichten einschleusen.
  • Beim Antworten mit event.source.postMessage() als Zielursprung event.origin angeben, 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, WebSocket und EventSource ist source leer. Außerdem kann das sendende Fenster schon geschlossen sein. Dann bleibt die Referenz zwar bestehen, event.source.closed ist aber true.
  • Ein fremdes WindowProxy gibt wegen der Same-Origin-Policy nur wenige Eigenschaften frei, etwa postMessage, close, closed, location (nur schreibend) und frames. Auf document kann man nicht zugreifen.
  • Im Service Worker ist event.source ein Client/WindowClient, nicht der MessageEventSource-Typ im engeren Sinn. Dieses Ereignis ist technisch ein ExtendableMessageEvent.
  • Browser-Unterstützung: in allen modernen Browsern vorhanden (Baseline).