diff --git a/source b/source index 9f6bfcc10b4..87002be6f20 100644 --- a/source +++ b/source @@ -2793,6 +2793,21 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute +
The following terms are defined in Streams: STREAMS
+ +ReadableStreamReadableStreamDefaultReaderTransformStreamlongobjectPromiseUint8ArrayUint8ClampedArrayunrestricted doubleunsigned longabout: URL, that is used as an
identifier for kinds of media tracks. ABOUT
+ This specification defines the URL about:event-stream as a reserved,
+ though unresolvable, about: URL, that is used as the URL of EventSource objects created via fromReadableStream(). ABOUT
This specification defines the URL about:srcdoc as a reserved, though
unresolvable, about: URL, that is used as the URL of constructor(USVString url, optional EventSourceInit eventSourceInitDict = {});
+ static EventSource fromReadableStream(ReadableStream stream);
+
readonly attribute USVString url;
readonly attribute boolean withCredentials;
+ readonly attribute DOMString lastEventId;
+ readonly attribute unsigned long long reconnectionTime;
// ready state
const unsigned short CONNECTING = 0;
@@ -128394,6 +128419,7 @@ interface EventSource : EventTarget {
attribute EventHandler onmessage;
attribute EventHandler onerror;
undefined close();
+ undefined reset();
};
dictionary EventSourceInit {
@@ -128417,10 +128443,15 @@ dictionary EventSourceInit {
A last event ID string. This must initially be the empty string.
A stream reader (a
+ ReadableStreamDefaultReader or null), initially null.
Apart from url these are not currently exposed on
- the EventSource object.
Apart from url, last event ID string, and reconnection time, these are not currently
+ exposed on the EventSource object.
include".
source = EventSource.fromReadableStream(stream)Creates a new EventSource that reads from the given
+ ReadableStream. The stream cannot be locked.
+ The EventSource will parse the stream as a text/event-stream
+ format event stream.
No network connection is managed and no reconnection is attempted when the + stream closes or errors.
+source.close()Aborts any instances of the fetch algorithm started for
this EventSource object, and sets the readyState attribute to CLOSED.
ReadableStream, the stream is also canceled.
+ source.reset()Discards any partially received event data in the parser's internal buffers. This is useful
+ when using fromReadableStream() with a
+ TransformStream to implement reconnection, as a broken connection may leave an
+ incomplete event in the buffer. Calling this between reconnections ensures the parser starts
+ from a clean state.
Has no effect on EventSource objects that were not created via fromReadableStream().
source.urlReturns the URL providing the event - stream.
about:event-stream" when the source was created from a
+ ReadableStream.
source.withCredentialsReturns true if the credentials mode
for connection requests to the URL providing the event
- stream is set to "include", and false otherwise.
include", and false otherwise. Always returns
+ false when the source was created from a ReadableStream.
source.readyStateReturns the state of this EventSource object's connection. It can have the
values described below.
source.lastEventIdReturns the last event ID string that was set by the server via the id field, or the empty string if none have been received.
source.reconnectionTimeReturns the reconnection time in milliseconds. This is initially an
+ implementation-defined value, and can be updated by the server via the retry field.
The static fromReadableStream(stream)
+ method, when invoked, must run these steps:
Let reader be ? AcquireReadableStreamDefaultReader(stream).
Let ev be a new EventSource object.
Set ev's url to the URL
+ record about:event-stream.
Set ev's stream reader + to reader.
Announce the connection.
In parallel, interpret + reader line by line.
+ +When the stream signals done or an error: fail the connection.
+Return ev.
The url
attribute's getter must return the serialization of
@@ -128568,6 +128675,20 @@ dictionary EventSourceInit {
false.
The lastEventId attribute's getter must return this
+ EventSource object's last event ID
+ string.
The reconnectionTime attribute's getter must
+ return this EventSource object's reconnection time.
The readyState attribute represents the state of the
connection. It can have the following values:
The close()
- method must abort any instances of the fetch algorithm started
- for this EventSource object, and must set the readyState attribute to CLOSED.
Abort any instances of the fetch algorithm started
+ for this EventSource object.
Let reader be this EventSource object's stream reader.
If reader is not null, then + ! ReadableStreamCancel(reader.[[stream]], undefined).
Set the readyState attribute to CLOSED.
The reset()
+ method must run the following steps:
If this EventSource object's stream reader is null, then return.
Act as if the end of the file has been reached for the purposes of interpreting the event stream.
Resume interpreting subsequent input from this
+ EventSource object's stream
+ reader.
The fromReadableStream() method
+ allows applications to handle networking and reconnection logic themselves, while still using
+ EventSource for event stream parsing. The following example uses a
+ TransformStream to allow multiple fetch() responses to be piped
+ through to a single EventSource:
const url = "https://example.com/events";
+const ts = new TransformStream();
+const source = EventSource.fromReadableStream(ts.readable);
+source.onmessage = (event) => {
+ console.log("Received:", event.data);
+};
+
+async function connect() {
+ const headers = { "Authorization": "Bearer token123" };
+ if (source.lastEventId) {
+ headers["Last-Event-ID"] = source.lastEventId;
+ }
+ try {
+ const response = await fetch(url, { headers });
+ await response.body.pipeTo(ts.writable, { preventClose: true });
+ } catch (e) {
+ // Discard any incomplete event left in the parser's buffer.
+ source.reset();
+ }
+
+ // The fetch stream has ended, but ts.writable is still open, so
+ // ts.readable does not signal done and the EventSource stays open.
+ // If close() was called, stop reconnecting:
+ if (source.readyState === EventSource.CLOSED) return;
+ // Wait and reconnect:
+ const delay = source.reconnectionTime;
+ setTimeout(connect, delay);
+}
+
+connect();
+
+ Using { preventClose: true } in the pipeTo() call prevents the TransformStream's writable
+ side from being closed when the fetch stream ends. This keeps the readable side — and therefore
+ the EventSource — alive between reconnections, preserving all registered event
+ listeners.
Legacy proxy servers are known to, in certain cases, drop HTTP connections after a short @@ -129149,17 +129345,40 @@ data: test
If a user agent is to forcibly close an
EventSource object (this happens when a Document object goes away
- permanently), the user agent must abort any instances of the fetch algorithm started for this EventSource object,
- and must set the readyState attribute to CLOSED.
Abort any instances of the fetch algorithm started
+ for this EventSource object.
Let reader be this EventSource object's stream reader.
If reader is not null, then + ! ReadableStreamCancel(reader.[[stream]], undefined).
Set the readyState attribute to CLOSED.
If an EventSource object is garbage collected while its connection is still open,
- the user agent must abort any instance of the fetch algorithm
- opened by this EventSource.
Abort any instance of the fetch algorithm opened by
+ this EventSource.
Let reader be this EventSource object's stream reader.
If reader is not null, then + ! ReadableStreamCancel(reader.[[stream]], undefined).