W3C

HTML 5

A vocabulary and associated APIs for HTML and XHTML

← 8 Web WorkersTable of contents10 The HTML syntax →

9 Communication

9.1 Event definitions

Messages in server-sent events, Web sockets, cross-document messaging, and channel messaging use the message event.

The following interface is defined for this event:

interface MessageEvent : Event {
  readonly attribute any data;
  readonly attribute DOMString origin;
  readonly attribute DOMString lastEventId;
  readonly attribute WindowProxy source;
  readonly attribute MessagePortArray ports;
  void initMessageEvent(in DOMString typeArg, in boolean canBubbleArg, in boolean cancelableArg, in any dataArg, in DOMString originArg, in DOMString lastEventIdArg, in WindowProxy sourceArg, in MessagePortArray portsArg);
  void initMessageEventNS(in DOMString namespaceURI, in DOMString typeArg, in boolean canBubbleArg, in boolean cancelableArg, in any dataArg, in DOMString originArg, in DOMString lastEventIdArg, in WindowProxy sourceArg, in MessagePortArray portsArg);
};
event . data

Returns the data of the message.

event . origin

Returns the origin of the message, for server-sent events and cross-document messaging.

event . lastEventId

Returns the last event ID, for server-sent events.

event . source

Returns the WindowProxy of the source window, for cross-document messaging.

event . ports

Returns the MessagePortArray sent with the message, for cross-document messaging and channel messaging.

The initMessageEvent() and initMessageEventNS() methods must initialize the event in a manner analogous to the similarly-named methods in the DOM Events interfaces. [DOMEVENTS]

The data attribute represents the message being sent.

The origin attribute represents, in server-sent events and cross-document messaging, the origin of the document that sent the message (typically the scheme, hostname, and port of the document, but not its path or fragment identifier).

The lastEventId attribute represents, in server-sent events, the last event ID string of the event source.

The source attribute represents, in cross-document messaging, the WindowProxy of the browsing context of the Window object from which the message came.

The ports attribute represents, in cross-document messaging and channel messaging the MessagePortArray being sent, if any.

Unless otherwise specified, when the user agent creates and dispatches a message event in the algorithms described in the following sections, the lastEventId attribute must be the empty string, the origin attribute must be the empty string, the source attribute must be null, and the ports attribute must be null.

9.2 Server-sent events

9.3 Web sockets

9.4 Cross-document messaging

Web browsers, for security and privacy reasons, prevent documents in different domains from affecting each other; that is, cross-site scripting is disallowed.

While this is an important security feature, it prevents pages from different domains from communicating even when those pages are not hostile. This section introduces a messaging system that allows documents to communicate with each other regardless of their source domain, in a way designed to not enable cross-site scripting attacks.

The task source for the tasks in cross-document messaging is the posted message task source.

9.4.1 Introduction

This section is non-normative.

For example, if document A contains an iframe element that contains document B, and script in document A calls postMessage() on the Window object of document B, then a message event will be fired on that object, marked as originating from the Window of document A. The script in document A might look like:

var o = document.getElementsByTagName('iframe')[0];
o.contentWindow.postMessage('Hello world', 'http://b.example.org/');

To register an event handler for incoming events, the script would use addEventListener() (or similar mechanisms). For example, the script in document B might look like:

window.addEventListener('message', receiver, false);
function receiver(e) {
  if (e.origin == 'http://example.com') {
    if (e.data == 'Hello world') {
      e.source.postMessage('Hello', e.origin);
    } else {
      alert(e.data);
    }
  }
}

This script first checks the domain is the expected domain, and then looks at the message, which it either displays to the user, or responds to by sending a message back to the document which sent the message in the first place.

9.4.2 Security

9.4.2.1 Authors

Use of this API requires extra care to protect users from hostile entities abusing a site for their own purposes.

Authors should check the origin attribute to ensure that messages are only accepted from domains that they expect to receive messages from. Otherwise, bugs in the author's message handling code could be exploited by hostile sites.

Furthermore, even after checking the origin attribute, authors should also check that the data in question is of the expected format. Otherwise, if the source of the event has been attacked using a cross-site scripting flaw, further unchecked processing of information sent using the postMessage() method could result in the attack being propagated into the receiver.

Authors should not use the wildcard keyword ("*") in the targetOrigin argument in messages that contain any confidential information, as otherwise there is no way to guarantee that the message is only delivered to the recipient to which it was intended.

9.4.2.2 User agents

The integrity of this API is based on the inability for scripts of one origin to post arbitrary events (using dispatchEvent() or otherwise) to objects in other origins (those that are not the same).

Implementors are urged to take extra care in the implementation of this feature. It allows authors to transmit information from one domain to another domain, which is normally disallowed for security reasons. It also requires that UAs be careful to allow access to certain properties but not others.

9.4.3 Posting messages

window . postMessage(message, [ ports, ] targetOrigin)

Posts a message, optionally with an array of ports, to the given window.

If the origin of the target window doesn't match the given origin, the message is discarded, to avoid information leakage. To send the message to the target regardless of origin, set the target origin to "*".

Throws an INVALID_STATE_ERR if the ports array is not null and it contains either null entries or duplicate ports.

When a script invokes the postMessage(message, targetOrigin) method (with only two arguments) on a Window object, the user agent must follow these steps:

  1. If the value of the targetOrigin argument is not a single U+002A ASTERISK character ("*"), and resolving it relative to the first script's base URL either fails or results in a URL with a <host-specific> component that is neither empty nor a single U+002F SOLIDUS character (/), then throw a SYNTAX_ERR exception and abort the overall set of steps.

  2. Let message clone be the result of obtaining a structured clone of the message argument. If this throws an exception, then throw that exception and abort these steps.

  3. Return from the postMessage() method, but asynchronously continue running these steps.

  4. If the targetOrigin argument has a value other than a single literal U+002A ASTERISK character ("*"), and the Document of the Window object on which the method was invoked does not have the same origin as targetOrigin, then abort these steps silently.

  5. Create an event that uses the MessageEvent interface, with the event name message, which does not bubble, is not cancelable, and has no default action. The data attribute must be set to the value of message clone, the origin attribute must be set to the Unicode serialization of the origin of the script that invoked the method, and the source attribute must be set to the script's global object.

  6. Queue a task to dispatch the event created in the previous step at the Window object on which the method was invoked. The task source for this task is the posted message task source.

9.4.4 Posting messages with message ports

When a script invokes the postMessage(message, ports, targetOrigin) method (with three arguments) on a Window object, the user agent must follow these steps:

  1. If the value of the targetOrigin argument is not a single U+002A ASTERISK character ("*"), and resolving it relative to the first script's base URL either fails or results in a URL with a <host-specific> component that is neither empty nor a single U+002F SOLIDUS character (/), then throw a SYNTAX_ERR exception and abort the overall set of steps.

  2. Let message clone be the result of obtaining a structured clone of the message argument. If this throws an exception, then throw that exception and abort these steps.

  3. If the ports argument is null, then act as if the method had just been called with two arguments, message and targetOrigin.

  4. If any of the entries in ports are null, or if any MessagePort object is listed in ports more than once, then throw an INVALID_STATE_ERR exception.

  5. Let new ports be an empty array.

    For each port in ports in turn, obtain a new port by cloning the port with the Window object on which the method was invoked as the owner of the clone, and append the clone to the new ports array.

    If the original ports array was empty, then the new ports array will also be empty.

  6. Return from the postMessage() method, but asynchronously continue running these steps.

  7. If the targetOrigin argument has a value other than a single literal U+002A ASTERISK character ("*"), and the Document of the Window object on which the method was invoked does not have the same origin as targetOrigin, then abort these steps silently.

  8. Create an event that uses the MessageEvent interface, with the event name message, which does not bubble, is not cancelable, and has no default action. The data attribute must be set to the value of message clone, the origin attribute must be set to the Unicode serialization of the origin of the script that invoked the method, and the source attribute must be set to the script's global object.

  9. Let the ports attribute of the event be the new ports array.

  10. Queue a task to dispatch the event created in the previous step at the Window object on which the method was invoked. The task source for this task is the posted message task source.

These steps, with the exception of the second and third steps and the penultimate step, are identical to those in the previous section.

9.5 Channel messaging

9.5.1 Introduction

This section is non-normative.

An introduction to the channel and port APIs.

9.5.2 Message channels

[Constructor]
interface MessageChannel {
  readonly attribute MessagePort port1;
  readonly attribute MessagePort port2;
};
channel = new MessageChannel()

Returns a new MessageChannel object with two new MessagePort objects.

channel . port1

Returns the first MessagePort object.

channel . port2

Returns the second MessagePort object.

When the MessageChannel() constructor is called, it must run the following algorithm:

  1. Create a new MessagePort object owned by the script's global object, and let port1 be that object.

  2. Create a new MessagePort object owned by the script's global object, and let port2 be that object.

  3. Entangle the port1 and port2 objects.

  4. Instantiate a new MessageChannel object, and let channel be that object.

  5. Let the port1 attribute of the channel object be port1.

  6. Let the port2 attribute of the channel object be port2.

  7. Return channel.

This constructor must be visible when the script's global scope is either a Window object or an object implementing the WorkerUtils interface.

The port1 and port2 attributes must return the values they were assigned when the MessageChannel object was created.

9.5.3 Message ports

Each channel has two message ports. Data sent through one port is received by the other port, and vice versa.

typedef sequence<MessagePort> MessagePortArray;

interface MessagePort {
  void postMessage(in any message, optional in MessagePortArray ports);
  void start();
  void close();

  // event handler attributes
           attribute Function onmessage;
};
port . postMessage(message [, ports] )

Posts a message through the channel, optionally with the given ports.

Throws an INVALID_STATE_ERR if the ports array is not null and it contains either null entries, duplicate ports, or the source or target port.

port . start()

Begins dispatching messages received on the port.

port . close()

Disconnects the port, so that it is no longer active.

Objects implementing the MessagePort interface must also implement the EventTarget interface.

Each MessagePort object can be entangled with another (a symmetric relationship). Each MessagePort object also has a task source called the port message queue, initial empty. A port message queue can be enabled or disabled, and is initially disabled. Once enabled, a port can never be disabled again (though messages in the queue can get moved to another queue or removed altogether, which has much the same effect).

When the user agent is to create a new MessagePort object owned by a script's global object object owner, it must instantiate a new MessagePort object, and let its owner be owner.


When the user agent is to entangle two MessagePort objects, it must run the following steps:

  1. If one of the ports is already entangled, then disentangle it and the port that it was entangled with.

    If those two previously entangled ports were the two ports of a MessageChannel object, then that MessageChannel object no longer represents an actual channel: the two ports in that object are no longer entangled.

  2. Associate the two ports to be entangled, so that they form the two parts of a new channel. (There is no MessageChannel object that represents this channel.)


When the user agent is to clone a port original port, with the clone being owned by owner, it must run the following steps, which return a new MessagePort object. These steps must be run atomically.

  1. Create a new MessagePort object owned by owner, and let new port be that object.

  2. Move all the events in the port message queue of original port to the port message queue of new port, if any, leaving the new port's port message queue in its initial disabled state.

  3. If the original port is entangled with another port, then run these substeps:

    1. Let the remote port be the port with which the original port is entangled.

    2. Entangle the remote port and new port objects. The original port object will be disentangled by this process.

  4. Return new port. It is the clone.


The postMessage() method, when called on a port source port, must cause the user agent to run the following steps:

  1. Let target port be the port with which source port is entangled, if any.

  2. If the method was called with a second argument ports and that argument isn't null, then, if any of the entries in ports are null, or if any MessagePort object is listed in ports more than once, or if any of the entries in ports are either the source port or the target port (if any), then throw an INVALID_STATE_ERR exception.

  3. If there is no target port (i.e. if source port is not entangled), then abort these steps.

  4. Create an event that uses the MessageEvent interface, with the name message, which does not bubble, is not cancelable, and has no default action.

  5. Let message be the method's first argument.

  6. Let message clone be the result of obtaining a structured clone of message. If this throws an exception, then throw that exception and abort these steps.

  7. Let the data attribute of the event have the value of message clone.

  8. If the method was called with a second argument ports and that argument isn't null, then run the following substeps:

    1. Let new ports be an empty array.

      For each port in ports in turn, obtain a new port by cloning the port with the owner of the target port as the owner of the clone, and append the clone to the new ports array.

      If the original ports array was empty, then the new ports array will also be empty.

    2. Let the ports attribute of the event be the new ports array.

  9. Add the event to the port message queue of target port.


The start() method must enable its port's port message queue, if it is not already enabled.

When a port's port message queue is enabled, the event loop must use it as one of its task sources.

If the Document of the port's event handlers' global object is not fully active, then the messages are lost.


The close() method, when called on a port local port that is entangled with another port, must cause the user agents to disentangle the two ports. If the method is called on a port that is not entangled, then the method must do nothing.


The following are the event handler attributes (and their corresponding event handler event types) that must be supported, as DOM attributes, by all objects implementing the MessagePort interface:

event handler attribute Event handler event type
onmessage message

The first time a MessagePort object's onmessage DOM attribute is set, the port's port message queue must be enabled, as if the start() method had been called.

9.5.3.1 Ports and garbage collection

When a MessagePort object o is entangled, user agents must either act as if o's entangled MessagePort object has a strong reference to o, or as if o's owner has a strong reference to o.

Thus, a message port can be received, given an event listener, and then forgotten, and so long as that event listener could receive a message, the channel will be maintained.

Of course, if this was to occur on both sides of the channel, then both ports could be garbage collected, since they would not be reachable from live code, despite having a strong reference to each other.

Furthermore, a MessagePort object must not be garbage collected while there exists a message in a task queue that is to be dispatched on that MessagePort object, or while the MessagePort object's port message queue is open and there exists a message event in that queue.

Authors are strongly encouraged to explicitly close MessagePort objects to disentangle them, so that their resources can be recollected. Creating many MessagePort objects and discarding them without closing them can lead to high memory usage.