HTML Standard
9.3
Cross-document messaging
9.3.1
Introduction
9.3.2
Security
9.3.2.1
Authors
9.3.2.2
User agents
9.3.3
Posting messages
9.4
Channel messaging
9.4.1
Introduction
9.4.1.1
Examples
9.4.1.2
Ports as the basis of an object-capability model on the web
9.4.1.3
Ports as the basis of abstracting out service implementations
9.4.2
Message channels
9.4.3
The
MessageEventTarget
mixin
9.4.4
Message ports
9.4.5
Ports and garbage collection
9.5
Broadcasting to other browsing contexts
9.3
Cross-document messaging
Window/postMessage
Support in all current engines.
Firefox
3+
Safari
4+
Chrome
2+
Opera
9.5+
Edge
79+
Edge (Legacy)
12+
Internet Explorer
10+
Firefox Android
Safari iOS
Chrome Android
WebView Android
≤37+
Samsung Internet
Opera Android
10.1+
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
postMessage()
API can be used as a
tracking
vector
9.3.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
document
getElementsByTagName
'iframe'
)[
];
contentWindow
postMessage
'Hello world'
'https://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
if
origin
==
'https://example.com'
if
data
==
'Hello world'
source
postMessage
'Hello'
origin
);
else
alert
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.3.2
Security
9.3.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.
Authors who accept messages from any origin are encouraged to consider the risks of a
denial-of-service attack. An attacker could send a high volume of messages; if the receiving page
performs expensive computation or causes network traffic to be sent for each such message, the
attacker's message could be multiplied into a denial-of-service attack. Authors are encouraged to
employ rate limiting (only accepting a certain number of messages per minute) to make such attacks
impractical.
9.3.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
).
Implementers 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.
User agents are also encouraged to consider rate-limiting message traffic between different
origins
, to protect naïve sites from denial-of-service
attacks.
9.3.3
Posting messages
window
postMessage
message
[,
options
])
Window/postMessage
Support in all current engines.
Firefox
3+
Safari
4+
Chrome
2+
Opera
9.5+
Edge
79+
Edge (Legacy)
12+
Internet Explorer
10+
Firefox Android
Safari iOS
Chrome Android
WebView Android
37+
Samsung Internet
Opera Android
10.1+
Posts a message to the given window. Messages can be structured objects, e.g. nested objects
and arrays, can contain JavaScript values (strings, numbers,
Date
objects, etc.),
and can contain certain data objects such as
File
Blob
FileList
, and
ArrayBuffer
objects.
Objects listed in the
transfer
member
of
options
are transferred, not just cloned, meaning that they are no longer usable
on the sending side.
A target origin can be specified using the
targetOrigin
member of
options
. If not provided, it defaults to "
". This default
restricts the message to same-origin targets only.
If the origin of the target window doesn't match the given target 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 a
DataCloneError
DOMException
if
transfer
array contains duplicate objects or if
message
could not be
cloned.
window
postMessage
message
targetOrigin
[,
transfer
])
This is an alternate version of
postMessage()
where the target origin is specified
as a parameter. Calling
window.postMessage(message, target, transfer)
is
equivalent to
window.postMessage(message, {targetOrigin,
transfer})
When posting a message to a
Window
of a
browsing context
that has just been navigated to a new
Document
is likely to result in the message not
receiving its intended recipient: the scripts in the target
browsing context
have to
have had time to set up listeners for the messages. Thus, for instance, in situations where a
message is to be sent to the
Window
of newly created child
iframe
authors are advised to have the child
Document
post a message to their parent
announcing their readiness to receive messages, and for the parent to wait for this message before
beginning posting messages.
The
window post message steps
, given a
targetWindow
message
and
options
, are as follows:
Let
targetRealm
be
targetWindow
's
realm
Let
incumbentSettings
be the
incumbent settings object
Let
targetOrigin
be
options
["
targetOrigin
"].
If
targetOrigin
is a single U+002F SOLIDUS character (/), then set
targetOrigin
to
incumbentSettings
's
origin
Otherwise, if
targetOrigin
is not a single U+002A ASTERISK character (*),
then:
Let
parsedURL
be the result of running the
URL parser
on
targetOrigin
If
parsedURL
is failure, then throw a
SyntaxError
DOMException
Set
targetOrigin
to
parsedURL
's
origin
Let
transfer
be
options
["
transfer
"].
Let
serializeWithTransferResult
be
StructuredSerializeWithTransfer
message
transfer
). Rethrow
any exceptions.
Queue a global task
on the
posted message task source
given
targetWindow
to run the following steps:
If the
targetOrigin
argument is not a single literal U+002A ASTERISK character
(*) and
targetWindow
's
associated
Document
's
origin
is not
same origin
with
targetOrigin
, then return.
Let
origin
be
incumbentSettings
's
origin
Let
source
be the
WindowProxy
object corresponding to
incumbentSettings
's
global
object
(a
Window
object).
Let
deserializeRecord
be
StructuredDeserializeWithTransfer
serializeWithTransferResult
targetRealm
).
If this throws an exception, catch it,
fire an
event
named
messageerror
at
targetWindow
, using
MessageEvent
, with its
origin
initialized to
origin
and
the
source
attribute initialized to
source
, and then return.
Let
messageClone
be
deserializeRecord
.[[Deserialized]].
Let
newPorts
be a new
frozen array
consisting of all
MessagePort
objects in
deserializeRecord
.[[TransferredValues]], if any,
maintaining their relative order.
Fire an event
named
message
at
targetWindow
, using
MessageEvent
, with its
origin
initialized to
origin
, the
source
attribute initialized to
source
, the
data
attribute initialized to
messageClone
, and the
ports
attribute
initialized to
newPorts
The
Window
interface's
postMessage(
message
options
method steps are to run the
window post message
steps
given
this
message
, and
options
The
Window
interface's
postMessage(
message
targetOrigin
transfer
method steps are to run the
window post message
steps
given
this
message
, and «[ "
targetOrigin
" →
targetOrigin
, "
transfer
transfer
]».
9.4
Channel messaging
Channel_Messaging_API
Support in all current engines.
Firefox
41+
Safari
5+
Chrome
2+
Opera
10.6+
Edge
79+
Edge (Legacy)
12+
Internet Explorer
10+
Firefox Android
Safari iOS
Chrome Android
WebView Android
Samsung Internet
Opera Android
11+
Channel_Messaging_API/Using_channel_messaging
Support in all current engines.
Firefox
41+
Safari
5+
Chrome
2+
Opera
10.6+
Edge
79+
Edge (Legacy)
12+
Internet Explorer
10+
Firefox Android
Safari iOS
Chrome Android
WebView Android
Samsung Internet
Opera Android
11+
9.4.1
Introduction
This section is non-normative.
To enable independent pieces of code (e.g. running in different
browsing contexts
) to communicate directly, authors can use
channel
messaging
Communication channels in this mechanism are implemented as two-ways pipes, with a port at each
end. Messages sent in one port are delivered at the other port, and vice-versa. Messages are
delivered as DOM events, without interrupting or blocking running
tasks
To create a connection (two "entangled" ports), the
MessageChannel()
constructor is called:
var
channel
new
MessageChannel
();
One of the ports is kept as the local port, and the other port is sent to the remote code, e.g.
using
postMessage()
otherWindow
postMessage
'hello'
'https://example.com'
channel
port2
]);
To send messages, the
postMessage()
method on
the port is used:
channel
port1
postMessage
'hello'
);
To receive messages, one listens to
message
events:
channel
port1
onmessage
handleMessage
function
handleMessage
event
// message is in event.data
// ...
Data sent on a port can be structured data; for example here an array of strings is passed on a
MessagePort
port1
postMessage
([
'hello'
'world'
]);
9.4.1.1
Examples
This section is non-normative.
In this example, two JavaScript libraries are connected to each other using
MessagePort
s. This allows the libraries to later be hosted in different frames, or
in
Worker
objects, without any change to the APIs.
script
src
"contacts.js"
>
script
script
src
"compose-mail.js"
>
script
script
var
channel
new
MessageChannel
();
composer
addContactsProvider
channel
port1
);
contacts
registerConsumer
channel
port2
);
script
Here's what the "addContactsProvider()" function's implementation could look like:
function
addContactsProvider
port
port
onmessage
function
event
switch
event
data
messageType
case
'search-result'
handleSearchResult
event
data
results
);
break
case
'search-done'
handleSearchDone
();
break
case
'search-error'
handleSearchError
event
data
message
);
break
// ...
};
};
Alternatively, it could be implemented as follows:
function
addContactsProvider
port
port
addEventListener
'message'
function
event
if
event
data
messageType
==
'search-result'
handleSearchResult
event
data
results
);
});
port
addEventListener
'message'
function
event
if
event
data
messageType
==
'search-done'
handleSearchDone
();
});
port
addEventListener
'message'
function
event
if
event
data
messageType
==
'search-error'
handleSearchError
event
data
message
);
});
// ...
port
start
();
};
The key difference is that when using
addEventListener()
, the
start()
method must also be invoked. When using
onmessage
, the call to
start()
is implied.
The
start()
method, whether called explicitly or
implicitly (by setting
onmessage
),
starts the flow of messages: messages posted on message ports are initially paused, so that they
don't get dropped on the floor before the script has had a chance to set up its handlers.
9.4.1.2
Ports as the basis of an object-capability model on the web
This section is non-normative.
Ports can be viewed as a way to expose limited capabilities (in the object-capability model
sense) to other actors in the system. This can either be a weak capability system, where the ports
are merely used as a convenient model within a particular origin, or as a strong capability model,
where they are provided by one origin
provider
as the only mechanism by which
another origin
consumer
can effect change in or obtain information from
provider
For example, consider a situation in which a social web site embeds in one
iframe
the user's email contacts provider (an address book site, from a second origin), and in a second
iframe
a game (from a third origin). The outer social site and the game in the second
iframe
cannot access anything inside the first
iframe
; together they can
only:
Navigate
the
iframe
to a new
URL
, such as the same
URL
but with a different
fragment
causing the
Window
in the
iframe
to receive a
hashchange
event.
Resize the
iframe
, causing the
Window
in the
iframe
to receive a
resize
event.
Send a
message
event to the
Window
in the
iframe
using the
window.postMessage()
API.
The contacts provider can use these methods, most particularly the third one, to provide an API
that can be accessed by other origins to manipulate the user's address book. For example, it could
respond to a message "
add-contact Guillaume Tell
" by adding the given person and email address to the user's
address book.
To avoid any site on the web being able to manipulate the user's contacts, the contacts
provider might only allow certain trusted sites, such as the social site, to do this.
Now suppose the game wanted to add a contact to the user's address book, and that the social
site was willing to allow it to do so on its behalf, essentially "sharing" the trust that the
contacts provider had with the social site. There are several ways it could do this; most simply,
it could just proxy messages between the game site and the contacts site. However, this solution
has a number of difficulties: it requires the social site to either completely trust the game site
not to abuse the privilege, or it requires that the social site verify each request to make sure
it's not a request that it doesn't want to allow (such as adding multiple contacts, reading the
contacts, or deleting them); it also requires some additional complexity if there's ever the
possibility of multiple games simultaneously trying to interact with the contacts provider.
Using message channels and
MessagePort
objects, however, all of these problems can
go away. When the game tells the social site that it wants to add a contact, the social site can
ask the contacts provider not for it to add a contact, but for the
capability
to add a
single contact. The contacts provider then creates a pair of
MessagePort
objects, and
sends one of them back to the social site, who forwards it on to the game. The game and the
contacts provider then have a direct connection, and the contacts provider knows to only honor a
single "add contact" request, nothing else. In other words, the game has been granted the
capability to add a single contact.
9.4.1.3
Ports as the basis of abstracting out service implementations
This section is non-normative.
Continuing the example from the previous section, consider the contacts provider in particular.
While an initial implementation might have simply used
XMLHttpRequest
objects in the
service's
iframe
, an evolution of the service might instead want to use a
shared worker
with a single
WebSocket
connection.
If the initial design used
MessagePort
objects to grant capabilities, or even just
to allow multiple simultaneous independent sessions, the service implementation can switch from
the
XMLHttpRequest
s-in-each-
iframe
model to the
shared-
WebSocket
model without changing the API at all: the ports on the service
provider side can all be forwarded to the shared worker without it affecting the users of the API
in the slightest.
9.4.2
Message channels
MessageChannel
Support in all current engines.
Firefox
41+
Safari
5+
Chrome
2+
Opera
10.6+
Edge
79+
Edge (Legacy)
12+
Internet Explorer
10+
Firefox Android
Safari iOS
Chrome Android
WebView Android
Samsung Internet
Opera Android
11+
Exposed
=(
Window
Worker
)]
interface
MessageChannel
constructor
();
readonly
attribute
MessagePort
port1
readonly
attribute
MessagePort
port2
};
channel
= new
MessageChannel
()
MessageChannel/MessageChannel
Support in all current engines.
Firefox
41+
Safari
5+
Chrome
2+
Opera
10.6+
Edge
79+
Edge (Legacy)
12+
Internet Explorer
10+
Firefox Android
Safari iOS
Chrome Android
WebView Android
Samsung Internet
Opera Android
11+
Returns a new
MessageChannel
object with two new
MessagePort
objects.
channel
port1
MessageChannel/port1
Support in all current engines.
Firefox
41+
Safari
5+
Chrome
2+
Opera
10.6+
Edge
79+
Edge (Legacy)
12+
Internet Explorer
10+
Firefox Android
Safari iOS
Chrome Android
WebView Android
Samsung Internet
Opera Android
11+
Returns the first
MessagePort
object.
channel
port2
MessageChannel/port2
Support in all current engines.
Firefox
41+
Safari
5+
Chrome
2+
Opera
10.6+
Edge
79+
Edge (Legacy)
12+
Internet Explorer
10+
Firefox Android
Safari iOS
Chrome Android
WebView Android
Samsung Internet
Opera Android
11+
Returns the second
MessagePort
object.
MessageChannel
object has an associated
port 1
and an associated
port 2
, both
MessagePort
objects.
The
new MessageChannel()
constructor steps
are:
Set
this
's
port 1
to a
new
MessagePort
in
this
's
relevant
realm
Set
this
's
port 2
to a
new
MessagePort
in
this
's
relevant
realm
Entangle
this
's
port 1
and
this
's
port 2
The
port1
getter steps are to return
this
's
port 1
The
port2
getter steps are to return
this
's
port 2
9.4.3
The
MessageEventTarget
mixin
interface
mixin
MessageEventTarget
attribute
EventHandler
onmessage
attribute
EventHandler
onmessageerror
};
The following are the
event handlers
(and their corresponding
event handler event types
) that must be supported,
as
event handler IDL attributes
, by objects implementing the
MessageEventTarget
interface:
Event handler
Event handler event type
onmessage
MessagePort/message_event
Support in all current engines.
Firefox
41+
Safari
5+
Chrome
2+
Opera
10.6+
Edge
79+
Edge (Legacy)
12+
Internet Explorer
10+
Firefox Android
Safari iOS
Chrome Android
WebView Android
37+
Samsung Internet
Opera Android
11.5+
DedicatedWorkerGlobalScope/message_event
Support in all current engines.
Firefox
3.5+
Safari
4+
Chrome
4+
Opera
10.6+
Edge
79+
Edge (Legacy)
12+
Internet Explorer
10+
Firefox Android
Safari iOS
5+
Chrome Android
WebView Android
37+
Samsung Internet
Opera Android
11.5+
message
onmessageerror
MessagePort/messageerror_event
Support in all current engines.
Firefox
57+
Safari
16.4+
Chrome
60+
Opera
Edge
79+
Edge (Legacy)
18
Internet Explorer
No
Firefox Android
Safari iOS
Chrome Android
WebView Android
Samsung Internet
Opera Android
47+
DedicatedWorkerGlobalScope/messageerror_event
Support in all current engines.
Firefox
57+
Safari
16.4+
Chrome
60+
Opera
Edge
79+
Edge (Legacy)
18
Internet Explorer
No
Firefox Android
Safari iOS
Chrome Android
WebView Android
Samsung Internet
Opera Android
47+
messageerror
9.4.4
Message ports
MessagePort
Support in all current engines.
Firefox
41+
Safari
5+
Chrome
2+
Opera
10.6+
Edge
79+
Edge (Legacy)
12+
Internet Explorer
10+
Firefox Android
Safari iOS
Chrome Android
WebView Android
Samsung Internet
Opera Android
11+
Each channel has two message ports. Data sent through one port is received by the other port,
and vice versa.
Exposed
=(
Window
Worker
AudioWorklet
),
Transferable
interface
MessagePort
EventTarget
undefined
postMessage
any
message
sequence
object
transfer
);
undefined
postMessage
any
message
optional
StructuredSerializeOptions
options
= {});
undefined
start
();
undefined
close
();
// event handlers
attribute
EventHandler
onclose
};
MessagePort
includes
MessageEventTarget
dictionary
StructuredSerializeOptions
sequence
object
transfer
= [];
};
port
postMessage
message
[,
transfer
])
MessagePort/postMessage
Support in all current engines.
Firefox
41+
Safari
5+
Chrome
2+
Opera
10.6+
Edge
79+
Edge (Legacy)
12+
Internet Explorer
10+
Firefox Android
Safari iOS
Chrome Android
WebView Android
Samsung Internet
Opera Android
11+
port
postMessage
message
[, {
transfer
}])
Posts a message through the channel. Objects listed in
transfer
are transferred,
not just cloned, meaning that they are no longer usable on the sending side.
Throws a
DataCloneError
DOMException
if
transfer
contains duplicate objects or
port
, or if
message
could not be cloned.
port
start
()
MessagePort/start
Support in all current engines.
Firefox
41+
Safari
5+
Chrome
2+
Opera
10.6+
Edge
79+
Edge (Legacy)
12+
Internet Explorer
10+
Firefox Android
Safari iOS
Chrome Android
WebView Android
Samsung Internet
Opera Android
11+
Begins dispatching messages received on the port.
port
close
()
MessagePort/close
Support in all current engines.
Firefox
41+
Safari
5+
Chrome
2+
Opera
10.6+
Edge
79+
Edge (Legacy)
12+
Internet Explorer
10+
Firefox Android
Safari iOS
Chrome Android
WebView Android
Samsung Internet
Opera Android
11+
Disconnects the port, so that it is no longer active.
Each
MessagePort
object has a
message event target
(a
MessageEventTarget
), to which the
message
and
messageerror
events are dispatched. Unless otherwise
specified, it defaults to the
MessagePort
object itself.
Each
MessagePort
object can be entangled with another (a symmetric relationship).
Each
MessagePort
object also has a
task source
called the
port
message queue
, initially 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). A
MessagePort
also has a
has been shipped
flag, which must
initially be false.
When a port's
port message queue
is enabled, the
event loop
must use
it as one of its
task sources
. When a port's
relevant
global object
is a
Window
, all
tasks
queued
on its
port message queue
must be associated with
the port's
relevant global object
's
associated
Document
If the document is
fully active
, but the event listeners were all
created in the context of documents that are
not
fully active
, then the
messages will not be received unless and until the documents become
fully active
again.
Each
event loop
has a
task source
called the
unshipped port
message queue
. This is a virtual
task source
: it must act as if it contained
the
tasks
of each
port message queue
of each
MessagePort
whose
has been shipped
flag is false, whose
port
message queue
is enabled, and whose
relevant agent
's
event loop
is that
event loop
, in the order
in which they were added to their respective
task source
. When a
task
would be removed from the
unshipped port message
queue
, it must instead be removed from its
port message queue
When a
MessagePort
's
has been shipped
flag is false, its
port
message queue
must be ignored for the purposes of the
event loop
. (The
unshipped port message queue
is used instead.)
The
has been shipped
flag is set to true when a port, its twin, or
the object it was cloned from, is or has been transferred. When a
MessagePort
's
has been shipped
flag is true, its
port message queue
acts as a
first-class
task source
, unaffected to any
unshipped port message
queue
When the user agent is to
entangle
two
MessagePort
objects, it must run
the following steps:
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.
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.)
Two ports
and
that have gone through this step
are now said to be entangled; one is entangled to the other, and vice versa.
While this specification describes this process as instantaneous,
implementations are more likely to implement it via message passing. As with all algorithms, the
key is "merely" that the end result be indistinguishable, in a black-box sense, from the
specification.
The
disentangle
steps, given a
MessagePort
initiatorPort
which initiates disentangling, are as follows:
Let
otherPort
be the
MessagePort
which
initiatorPort
was entangled with.
Assert
otherPort
exists.
Disentangle
initiatorPort
and
otherPort
, so that they are no longer
entangled or associated with each other.
Fire an event
named
close
at
otherPort
The
close
event will be fired even if the port is not
explicitly closed. The cases where this event is dispatched are:
the
close()
method was called;
the
Document
was
destroyed
; or
the
MessagePort
was
garbage
collected
We only dispatch the event on
otherPort
because
initiatorPort
explicitly
triggered the close, its
Document
no longer exists, or it was already garbage
collected, as described above.
MessagePort
objects are
transferable
objects
. Their
transfer steps
, given
value
and
dataHolder
, are:
Set
value
's
has been shipped
flag to true.
Set
dataHolder
.[[PortMessageQueue]] to
value
's
port message
queue
If
value
is entangled with another port
remotePort
, then:
Set
remotePort
's
has been shipped
flag to true.
Set
dataHolder
.[[RemotePort]] to
remotePort
Otherwise, set
dataHolder
.[[RemotePort]] to null.
Their
transfer-receiving steps
, given
dataHolder
and
value
are:
Set
value
's
has been shipped
flag to true.
Move all the
tasks
that are to fire
message
events in
dataHolder
.[[PortMessageQueue]] to the
port message queue
of
value
, if any, leaving
value
's
port message queue
in its initial disabled state, and, if
value
's
relevant global object
is a
Window
, associating the moved
tasks
with
value
's
relevant global object
's
associated
Document
If
dataHolder
.[[RemotePort]] is not null, then
entangle
dataHolder
.[[RemotePort]] and
value
. (This will disentangle
dataHolder
.[[RemotePort]] from the original port that was transferred.)
The
message port post message steps
, given
sourcePort
targetPort
message
, and
options
are as follows:
Let
transfer
be
options
["
transfer
"].
If
transfer
contains
sourcePort
, then throw a
DataCloneError
DOMException
Let
doomed
be false.
If
targetPort
is not null and
transfer
contains
targetPort
, then set
doomed
to true and
optionally report to a developer console that the target port was posted to itself, causing the
communication channel to be lost.
Let
serializeWithTransferResult
be
StructuredSerializeWithTransfer
message
transfer
). Rethrow
any exceptions.
If
targetPort
is null, or if
doomed
is true, then return.
Add a
task
that runs the following steps to the
port
message queue
of
targetPort
Let
finalTargetPort
be the
MessagePort
in whose
port message
queue
the task now finds itself.
This can be different from
targetPort
, if
targetPort
itself was transferred and thus all its tasks moved along with it.
Let
messageEventTarget
be
finalTargetPort
's
message event
target
Let
targetRealm
be
finalTargetPort
's
relevant realm
Let
deserializeRecord
be
StructuredDeserializeWithTransfer
serializeWithTransferResult
targetRealm
).
If this throws an exception, catch it,
fire an
event
named
messageerror
at
messageEventTarget
, using
MessageEvent
, and then return.
Let
messageClone
be
deserializeRecord
.[[Deserialized]].
Let
newPorts
be a new
frozen array
consisting of all
MessagePort
objects in
deserializeRecord
.[[TransferredValues]], if any,
maintaining their relative order.
Fire an event
named
message
at
messageEventTarget
, using
MessageEvent
, with the
data
attribute
initialized to
messageClone
and the
ports
attribute initialized to
newPorts
The
postMessage(
message
options
method steps are:
Let
targetPort
be the port with which
this
is entangled, if any;
otherwise let it be null.
Run the
message port post message steps
providing
this
targetPort
message
and
options
The
postMessage(
message
transfer
method steps are:
Let
targetPort
be the port with which
this
is entangled, if any;
otherwise let it be null.
Let
options
be «[ "
transfer
" →
transfer
]».
Run the
message port post message steps
providing
this
targetPort
message
and
options
The
start()
method steps are to enable
this
's
port message queue
, if it is not
already enabled.
The
close()
method steps are:
Set
this
's
[[Detached]]
internal slot value to true.
If
this
is entangled,
disentangle
it.
The following are the
event handlers
(and their corresponding
event handler event types
) that must be supported,
as
event handler IDL attributes
, by all objects implementing the
MessagePort
interface:
Event handler
Event handler event type
onclose
close
The first time a
MessagePort
object's
onmessage
IDL attribute is set, the port's
port message queue
must be enabled, as if the
start()
method had been called.
9.4.5
Ports and garbage collection
When a
MessagePort
object
is garbage collected, if
is
entangled, then the user agent must
disentangle
When a
MessagePort
object
is entangled and
message
or
messageerror
event listener is registered, user agents must act as if
's entangled
MessagePort
object has a strong reference to
Furthermore, a
MessagePort
object must not be garbage collected while there
exists an event referenced by a
task
in a
task
queue
that is to be dispatched on that
MessagePort
object, or while the
MessagePort
object's
port message queue
is enabled and not empty.
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. However, if a message port has a pending message, it is not garbage collected.
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
transient memory usage since garbage collection is not necessarily performed promptly, especially
for
MessagePort
s where garbage collection can involve cross-process coordination.
9.5
Broadcasting to other browsing contexts
BroadcastChannel
Support in all current engines.
Firefox
38+
Safari
15.4+
Chrome
54+
Opera
Edge
79+
Edge (Legacy)
Internet Explorer
No
Firefox Android
Safari iOS
Chrome Android
WebView Android
Samsung Internet
Opera Android
Broadcast_Channel_API
Support in all current engines.
Firefox
38+
Safari
15.4+
Chrome
54+
Opera
Edge
79+
Edge (Legacy)
Internet Explorer
No
Firefox Android
Safari iOS
Chrome Android
WebView Android
Samsung Internet
Opera Android
Pages on a single
origin
opened by the same user in the same user agent but in
different unrelated
browsing contexts
sometimes need to
send notifications to each other, for example "hey, the user logged in over here, check your
credentials again".
For elaborate cases, e.g. to manage locking of shared state, to manage synchronization of
resources between a server and multiple local clients, to share a
WebSocket
connection with a remote host, and so forth,
shared workers
are
the most appropriate solution.
For simple cases, though, where a shared worker would be an unreasonable overhead, authors can
use the simple channel-based broadcast mechanism described in this section.
Exposed
=(
Window
Worker
)]
interface
BroadcastChannel
EventTarget
constructor
DOMString
name
);
readonly
attribute
DOMString
name
undefined
postMessage
any
message
);
undefined
close
();
attribute
EventHandler
onmessage
attribute
EventHandler
onmessageerror
};
broadcastChannel
= new
BroadcastChannel
name
BroadcastChannel/BroadcastChannel
Support in all current engines.
Firefox
38+
Safari
15.4+
Chrome
54+
Opera
Edge
79+
Edge (Legacy)
Internet Explorer
No
Firefox Android
Safari iOS
Chrome Android
WebView Android
Samsung Internet
Opera Android
Returns a new
BroadcastChannel
object via which messages for the given channel
name can be sent and received.
broadcastChannel
name
BroadcastChannel/name
Support in all current engines.
Firefox
38+
Safari
15.4+
Chrome
54+
Opera
Edge
79+
Edge (Legacy)
Internet Explorer
No
Firefox Android
Safari iOS
Chrome Android
WebView Android
Samsung Internet
Opera Android
Returns the channel name (as passed to the constructor).
broadcastChannel
postMessage
message
BroadcastChannel/postMessage
Support in all current engines.
Firefox
38+
Safari
15.4+
Chrome
54+
Opera
Edge
79+
Edge (Legacy)
Internet Explorer
No
Firefox Android
Safari iOS
Chrome Android
WebView Android
Samsung Internet
Opera Android
Sends the given message to other
BroadcastChannel
objects set up for this
channel. Messages can be structured objects, e.g. nested objects and arrays.
broadcastChannel
close
()
BroadcastChannel/close
Support in all current engines.
Firefox
38+
Safari
15.4+
Chrome
54+
Opera
Edge
79+
Edge (Legacy)
Internet Explorer
No
Firefox Android
Safari iOS
Chrome Android
WebView Android
Samsung Internet
Opera Android
Closes the
BroadcastChannel
object, opening it up to garbage
collection.
BroadcastChannel
object has a
channel name
and a
closed flag
The
new BroadcastChannel(
name
constructor steps are:
Set
this
's
channel name
to
name
Set
this
's
closed flag
to false.
The
name
getter steps are to return
this
's
channel name
BroadcastChannel
object is said to be
eligible for messaging
when
its
relevant global object
is either:
Window
object whose
associated
Document
is
fully active
, or
WorkerGlobalScope
object whose
closing
flag is false and is not
suspendable
The
postMessage(
message
method
steps are:
If
this
is not
eligible for messaging
, then return.
If
this
's
closed flag
is true, then throw an
InvalidStateError
DOMException
Let
serialized
be
StructuredSerialize
message
). Rethrow
any exceptions.
Let
sourceOrigin
be
this
's
relevant settings object
's
origin
Let
sourceStorageKey
be the result of running
obtain a storage key for
non-storage purposes
with
this
's
relevant settings
object
Let
destinations
be a list of
BroadcastChannel
objects that
match the following criteria:
They are
eligible for messaging
The result of running
obtain a storage key for non-storage purposes
with
their
relevant settings object
equals
sourceStorageKey
Their
channel name
is
this
's
channel
name
Remove
source
from
destinations
Sort
destinations
such that all
BroadcastChannel
objects whose
relevant agents
are the same are sorted in creation order,
oldest first. (This does not define a complete ordering. Within this constraint, user agents may
sort the list in any
implementation-defined
manner.)
For each
destination
in
destinations
queue a global task
on the
DOM manipulation task source
given
destination
's
relevant
global object
to perform the following steps:
If
destination
's
closed
flag
is true, then abort these steps.
Let
targetRealm
be
destination
's
relevant realm
Let
data
be
StructuredDeserialize
serialized
targetRealm
).
If this throws an exception, catch it,
fire an
event
named
messageerror
at
destination
, using
MessageEvent
, with its
origin
initialized to
sourceOrigin
, and
then abort these steps.
Fire an event
named
message
at
destination
, using
MessageEvent
, with the
data
attribute
initialized to
data
and its
origin
initialized to
sourceOrigin
While a
BroadcastChannel
object whose
closed flag
is false has an event listener
registered for
message
or
messageerror
events, there must be a strong reference from the
BroadcastChannel
object's
relevant global object
to the
BroadcastChannel
object itself.
The
close()
method steps are to set
this
's
closed flag
to true.
Authors are strongly encouraged to explicitly close
BroadcastChannel
objects when they are no longer needed, so that they can be garbage collected. Creating many
BroadcastChannel
objects and discarding them while leaving them with an event
listener and without closing them can lead to an apparent memory leak, since the objects will
continue to live for as long as they have an event listener (or until their page or worker is
closed).
The following are the
event handlers
(and their corresponding
event handler event types
) that must be supported,
as
event handler IDL attributes
, by all objects implementing the
BroadcastChannel
interface:
Event handler
Event handler event type
onmessage
BroadcastChannel/message_event
Support in all current engines.
Firefox
38+
Safari
15.4+
Chrome
54+
Opera
Edge
79+
Edge (Legacy)
Internet Explorer
No
Firefox Android
Safari iOS
Chrome Android
WebView Android
Samsung Internet
Opera Android
message
onmessageerror
BroadcastChannel/messageerror_event
Support in all current engines.
Firefox
57+
Safari
15.4+
Chrome
60+
Opera
Edge
79+
Edge (Legacy)
Internet Explorer
No
Firefox Android
Safari iOS
Chrome Android
WebView Android
Samsung Internet
Opera Android
47+
messageerror
Suppose a page wants to know when the user logs out, even when the user does so from another
tab at the same site:
var
authChannel
new
BroadcastChannel
'auth'
);
authChannel
onmessage
function
event
if
event
data
==
'logout'
showLogout
();
function
logoutRequested
()
// called when the user asks us to log them out
doLogout
();
showLogout
();
authChannel
postMessage
'logout'
);
function
doLogout
()
// actually log the user out (e.g. clearing cookies)
// ...
function
showLogout
()
// update the UI to indicate we're logged out
// ...