format: prettify entire project

This commit is contained in:
Rim
2025-04-02 06:50:39 -04:00
parent 86f0782a98
commit 7ccc0be712
1711 changed files with 755867 additions and 235931 deletions

View File

@ -1,27 +1,27 @@
'use strict'
const { Transform } = require('node:stream')
const { isASCIINumber, isValidLastEventId } = require('./util')
'use strict';
const { Transform } = require('node:stream');
const { isASCIINumber, isValidLastEventId } = require('./util');
/**
* @type {number[]} BOM
*/
const BOM = [0xEF, 0xBB, 0xBF]
const BOM = [0xef, 0xbb, 0xbf];
/**
* @type {10} LF
*/
const LF = 0x0A
const LF = 0x0a;
/**
* @type {13} CR
*/
const CR = 0x0D
const CR = 0x0d;
/**
* @type {58} COLON
*/
const COLON = 0x3A
const COLON = 0x3a;
/**
* @type {32} SPACE
*/
const SPACE = 0x20
const SPACE = 0x20;
/**
* @typedef {object} EventSourceStreamEvent
@ -44,37 +44,37 @@ class EventSourceStream extends Transform {
/**
* @type {eventSourceSettings}
*/
state
state;
/**
* Leading byte-order-mark check.
* @type {boolean}
*/
checkBOM = true
checkBOM = true;
/**
* @type {boolean}
*/
crlfCheck = false
crlfCheck = false;
/**
* @type {boolean}
*/
eventEndCheck = false
eventEndCheck = false;
/**
* @type {Buffer|null}
*/
buffer = null
buffer = null;
pos = 0
pos = 0;
event = {
data: undefined,
event: undefined,
id: undefined,
retry: undefined
}
retry: undefined,
};
/**
* @param {object} options
@ -82,16 +82,16 @@ class EventSourceStream extends Transform {
* @param {eventSourceSettings} [options.eventSourceSettings]
* @param {(chunk: any, encoding?: BufferEncoding | undefined) => boolean} [options.push]
*/
constructor (options = {}) {
constructor(options = {}) {
// Enable object mode as EventSourceStream emits objects of shape
// EventSourceStreamEvent
options.readableObjectMode = true
options.readableObjectMode = true;
super(options)
super(options);
this.state = options.eventSourceSettings || {}
this.state = options.eventSourceSettings || {};
if (options.push) {
this.push = options.push
this.push = options.push;
}
}
@ -101,10 +101,10 @@ class EventSourceStream extends Transform {
* @param {Function} callback
* @returns {void}
*/
_transform (chunk, _encoding, callback) {
_transform(chunk, _encoding, callback) {
if (chunk.length === 0) {
callback()
return
callback();
return;
}
// Cache the chunk in the buffer, as the data might not be complete while
@ -113,9 +113,9 @@ class EventSourceStream extends Transform {
// incoming chunks
// see: https://github.com/nodejs/undici/issues/2630
if (this.buffer) {
this.buffer = Buffer.concat([this.buffer, chunk])
this.buffer = Buffer.concat([this.buffer, chunk]);
} else {
this.buffer = chunk
this.buffer = chunk;
}
// Strip leading byte-order-mark if we opened the stream and started
@ -126,33 +126,30 @@ class EventSourceStream extends Transform {
// Check if the first byte is the same as the first byte of the BOM
if (this.buffer[0] === BOM[0]) {
// If it is, we need to wait for more data
callback()
return
callback();
return;
}
// Set the checkBOM flag to false as we don't need to check for the
// BOM anymore
this.checkBOM = false
this.checkBOM = false;
// The buffer only contains one byte so we need to wait for more data
callback()
return
callback();
return;
case 2:
// Check if the first two bytes are the same as the first two bytes
// of the BOM
if (
this.buffer[0] === BOM[0] &&
this.buffer[1] === BOM[1]
) {
if (this.buffer[0] === BOM[0] && this.buffer[1] === BOM[1]) {
// If it is, we need to wait for more data, because the third byte
// is needed to determine if it is the BOM or not
callback()
return
callback();
return;
}
// Set the checkBOM flag to false as we don't need to check for the
// BOM anymore
this.checkBOM = false
break
this.checkBOM = false;
break;
case 3:
// Check if the first three bytes are the same as the first three
// bytes of the BOM
@ -162,18 +159,18 @@ class EventSourceStream extends Transform {
this.buffer[2] === BOM[2]
) {
// If it is, we can drop the buffered data, as it is only the BOM
this.buffer = Buffer.alloc(0)
this.buffer = Buffer.alloc(0);
// Set the checkBOM flag to false as we don't need to check for the
// BOM anymore
this.checkBOM = false
this.checkBOM = false;
// Await more data
callback()
return
callback();
return;
}
// If it is not the BOM, we can start processing the data
this.checkBOM = false
break
this.checkBOM = false;
break;
default:
// The buffer is longer than 3 bytes, so we can drop the BOM if it is
// present
@ -183,12 +180,12 @@ class EventSourceStream extends Transform {
this.buffer[2] === BOM[2]
) {
// Remove the BOM from the buffer
this.buffer = this.buffer.subarray(3)
this.buffer = this.buffer.subarray(3);
}
// Set the checkBOM flag to false as we don't need to check for the
this.checkBOM = false
break
this.checkBOM = false;
break;
}
}
@ -206,9 +203,9 @@ class EventSourceStream extends Transform {
// If the current character is a line feed, we can remove it
// from the buffer and reset the crlfCheck flag
if (this.buffer[this.pos] === LF) {
this.buffer = this.buffer.subarray(this.pos + 1)
this.pos = 0
this.crlfCheck = false
this.buffer = this.buffer.subarray(this.pos + 1);
this.pos = 0;
this.crlfCheck = false;
// It is possible that the line feed is not the end of the
// event. We need to check if the next character is an
@ -219,9 +216,9 @@ class EventSourceStream extends Transform {
// As we removed the line feed from the buffer and set the
// crlfCheck flag to false, we basically don't make any
// distinction between a line feed and a carriage return.
continue
continue;
}
this.crlfCheck = false
this.crlfCheck = false;
}
if (this.buffer[this.pos] === LF || this.buffer[this.pos] === CR) {
@ -230,22 +227,26 @@ class EventSourceStream extends Transform {
// next character is a line feed so we can remove it from the
// buffer
if (this.buffer[this.pos] === CR) {
this.crlfCheck = true
this.crlfCheck = true;
}
this.buffer = this.buffer.subarray(this.pos + 1)
this.pos = 0
this.buffer = this.buffer.subarray(this.pos + 1);
this.pos = 0;
if (
this.event.data !== undefined || this.event.event || this.event.id || this.event.retry) {
this.processEvent(this.event)
this.event.data !== undefined ||
this.event.event ||
this.event.id ||
this.event.retry
) {
this.processEvent(this.event);
}
this.clearEvent()
continue
this.clearEvent();
continue;
}
// If the current character is not an end-of-line, then the event
// is not finished and we have to reset the eventEndCheck flag
this.eventEndCheck = false
continue
this.eventEndCheck = false;
continue;
}
// If the current character is an end-of-line, we can process the
@ -255,51 +256,51 @@ class EventSourceStream extends Transform {
// set the crlfCheck flag to true, as we need to check if the
// next character is a line feed
if (this.buffer[this.pos] === CR) {
this.crlfCheck = true
this.crlfCheck = true;
}
// In any case, we can process the line as we reached an
// end-of-line character
this.parseLine(this.buffer.subarray(0, this.pos), this.event)
this.parseLine(this.buffer.subarray(0, this.pos), this.event);
// Remove the processed line from the buffer
this.buffer = this.buffer.subarray(this.pos + 1)
this.buffer = this.buffer.subarray(this.pos + 1);
// Reset the position as we removed the processed line from the buffer
this.pos = 0
this.pos = 0;
// A line was processed and this could be the end of the event. We need
// to check if the next line is empty to determine if the event is
// finished.
this.eventEndCheck = true
continue
this.eventEndCheck = true;
continue;
}
this.pos++
this.pos++;
}
callback()
callback();
}
/**
* @param {Buffer} line
* @param {EventSourceStreamEvent} event
*/
parseLine (line, event) {
parseLine(line, event) {
// If the line is empty (a blank line)
// Dispatch the event, as defined below.
// This will be handled in the _transform method
if (line.length === 0) {
return
return;
}
// If the line starts with a U+003A COLON character (:)
// Ignore the line.
const colonPosition = line.indexOf(COLON)
const colonPosition = line.indexOf(COLON);
if (colonPosition === 0) {
return
return;
}
let field = ''
let value = ''
let field = '';
let value = '';
// If the line contains a U+003A COLON character (:)
if (colonPosition !== -1) {
@ -308,27 +309,27 @@ class EventSourceStream extends Transform {
// TODO: Investigate if there is a more performant way to extract the
// field
// see: https://github.com/nodejs/undici/issues/2630
field = line.subarray(0, colonPosition).toString('utf8')
field = line.subarray(0, colonPosition).toString('utf8');
// Collect the characters on the line after the first U+003A COLON
// character (:), and let value be that string.
// If value starts with a U+0020 SPACE character, remove it from value.
let valueStart = colonPosition + 1
let valueStart = colonPosition + 1;
if (line[valueStart] === SPACE) {
++valueStart
++valueStart;
}
// TODO: Investigate if there is a more performant way to extract the
// value
// see: https://github.com/nodejs/undici/issues/2630
value = line.subarray(valueStart).toString('utf8')
value = line.subarray(valueStart).toString('utf8');
// Otherwise, the string is not empty but does not contain a U+003A COLON
// character (:)
} else {
// Process the field using the steps described below, using the whole
// line as the field name, and the empty string as the field value.
field = line.toString('utf8')
value = ''
field = line.toString('utf8');
value = '';
}
// Modify the event with the field name and value. The value is also
@ -336,39 +337,39 @@ class EventSourceStream extends Transform {
switch (field) {
case 'data':
if (event[field] === undefined) {
event[field] = value
event[field] = value;
} else {
event[field] += `\n${value}`
event[field] += `\n${value}`;
}
break
break;
case 'retry':
if (isASCIINumber(value)) {
event[field] = value
event[field] = value;
}
break
break;
case 'id':
if (isValidLastEventId(value)) {
event[field] = value
event[field] = value;
}
break
break;
case 'event':
if (value.length > 0) {
event[field] = value
event[field] = value;
}
break
break;
}
}
/**
* @param {EventSourceStreamEvent} event
*/
processEvent (event) {
processEvent(event) {
if (event.retry && isASCIINumber(event.retry)) {
this.state.reconnectionTime = parseInt(event.retry, 10)
this.state.reconnectionTime = parseInt(event.retry, 10);
}
if (event.id && isValidLastEventId(event.id)) {
this.state.lastEventId = event.id
this.state.lastEventId = event.id;
}
// only dispatch event, when data is provided
@ -378,22 +379,22 @@ class EventSourceStream extends Transform {
options: {
data: event.data,
lastEventId: this.state.lastEventId,
origin: this.state.origin
}
})
origin: this.state.origin,
},
});
}
}
clearEvent () {
clearEvent() {
this.event = {
data: undefined,
event: undefined,
id: undefined,
retry: undefined
}
retry: undefined,
};
}
}
module.exports = {
EventSourceStream
}
EventSourceStream,
};

View File

@ -1,18 +1,18 @@
'use strict'
'use strict';
const { pipeline } = require('node:stream')
const { fetching } = require('../fetch')
const { makeRequest } = require('../fetch/request')
const { webidl } = require('../fetch/webidl')
const { EventSourceStream } = require('./eventsource-stream')
const { parseMIMEType } = require('../fetch/data-url')
const { createFastMessageEvent } = require('../websocket/events')
const { isNetworkError } = require('../fetch/response')
const { delay } = require('./util')
const { kEnumerableProperty } = require('../../core/util')
const { environmentSettingsObject } = require('../fetch/util')
const { pipeline } = require('node:stream');
const { fetching } = require('../fetch');
const { makeRequest } = require('../fetch/request');
const { webidl } = require('../fetch/webidl');
const { EventSourceStream } = require('./eventsource-stream');
const { parseMIMEType } = require('../fetch/data-url');
const { createFastMessageEvent } = require('../websocket/events');
const { isNetworkError } = require('../fetch/response');
const { delay } = require('./util');
const { kEnumerableProperty } = require('../../core/util');
const { environmentSettingsObject } = require('../fetch/util');
let experimentalWarned = false
let experimentalWarned = false;
/**
* A reconnection time, in milliseconds. This must initially be an implementation-defined value,
@ -24,7 +24,7 @@ let experimentalWarned = false
*
* @type {3000}
*/
const defaultReconnectionTime = 3000
const defaultReconnectionTime = 3000;
/**
* The readyState attribute represents the state of the connection.
@ -39,32 +39,32 @@ const defaultReconnectionTime = 3000
* agent is reconnecting.
* @type {0}
*/
const CONNECTING = 0
const CONNECTING = 0;
/**
* The user agent has an open connection and is dispatching events as it
* receives them.
* @type {1}
*/
const OPEN = 1
const OPEN = 1;
/**
* The connection is not open, and the user agent is not trying to reconnect.
* @type {2}
*/
const CLOSED = 2
const CLOSED = 2;
/**
* Requests for the element will have their mode set to "cors" and their credentials mode set to "same-origin".
* @type {'anonymous'}
*/
const ANONYMOUS = 'anonymous'
const ANONYMOUS = 'anonymous';
/**
* Requests for the element will have their mode set to "cors" and their credentials mode set to "include".
* @type {'use-credentials'}
*/
const USE_CREDENTIALS = 'use-credentials'
const USE_CREDENTIALS = 'use-credentials';
/**
* The EventSource interface is used to receive server-sent events. It
@ -78,26 +78,26 @@ class EventSource extends EventTarget {
#events = {
open: null,
error: null,
message: null
}
message: null,
};
#url
#withCredentials = false
#url;
#withCredentials = false;
/**
* @type {ReadyState}
*/
#readyState = CONNECTING
#readyState = CONNECTING;
#request = null
#controller = null
#request = null;
#controller = null;
#dispatcher
#dispatcher;
/**
* @type {import('./eventsource-stream').eventSourceSettings}
*/
#state
#state;
/**
* Creates a new EventSource object.
@ -105,58 +105,65 @@ class EventSource extends EventTarget {
* @param {EventSourceInit} [eventSourceInitDict={}]
* @see https://html.spec.whatwg.org/multipage/server-sent-events.html#the-eventsource-interface
*/
constructor (url, eventSourceInitDict = {}) {
constructor(url, eventSourceInitDict = {}) {
// 1. Let ev be a new EventSource object.
super()
super();
webidl.util.markAsUncloneable(this)
webidl.util.markAsUncloneable(this);
const prefix = 'EventSource constructor'
webidl.argumentLengthCheck(arguments, 1, prefix)
const prefix = 'EventSource constructor';
webidl.argumentLengthCheck(arguments, 1, prefix);
if (!experimentalWarned) {
experimentalWarned = true
process.emitWarning('EventSource is experimental, expect them to change at any time.', {
code: 'UNDICI-ES'
})
experimentalWarned = true;
process.emitWarning(
'EventSource is experimental, expect them to change at any time.',
{
code: 'UNDICI-ES',
}
);
}
url = webidl.converters.USVString(url)
eventSourceInitDict = webidl.converters.EventSourceInitDict(eventSourceInitDict, prefix, 'eventSourceInitDict')
url = webidl.converters.USVString(url);
eventSourceInitDict = webidl.converters.EventSourceInitDict(
eventSourceInitDict,
prefix,
'eventSourceInitDict'
);
this.#dispatcher = eventSourceInitDict.dispatcher
this.#dispatcher = eventSourceInitDict.dispatcher;
this.#state = {
lastEventId: '',
reconnectionTime: defaultReconnectionTime
}
reconnectionTime: defaultReconnectionTime,
};
// 2. Let settings be ev's relevant settings object.
// https://html.spec.whatwg.org/multipage/webappapis.html#environment-settings-object
const settings = environmentSettingsObject
const settings = environmentSettingsObject;
let urlRecord
let urlRecord;
try {
// 3. Let urlRecord be the result of encoding-parsing a URL given url, relative to settings.
urlRecord = new URL(url, settings.settingsObject.baseUrl)
this.#state.origin = urlRecord.origin
urlRecord = new URL(url, settings.settingsObject.baseUrl);
this.#state.origin = urlRecord.origin;
} catch (e) {
// 4. If urlRecord is failure, then throw a "SyntaxError" DOMException.
throw new DOMException(e, 'SyntaxError')
throw new DOMException(e, 'SyntaxError');
}
// 5. Set ev's url to urlRecord.
this.#url = urlRecord.href
this.#url = urlRecord.href;
// 6. Let corsAttributeState be Anonymous.
let corsAttributeState = ANONYMOUS
let corsAttributeState = ANONYMOUS;
// 7. If the value of eventSourceInitDict's withCredentials member is true,
// then set corsAttributeState to Use Credentials and set ev's
// withCredentials attribute to true.
if (eventSourceInitDict.withCredentials === true) {
corsAttributeState = USE_CREDENTIALS
this.#withCredentials = true
corsAttributeState = USE_CREDENTIALS;
this.#withCredentials = true;
}
// 8. Let request be the result of creating a potential-CORS request given
@ -166,30 +173,30 @@ class EventSource extends EventTarget {
keepalive: true,
// @see https://html.spec.whatwg.org/multipage/urls-and-fetching.html#cors-settings-attributes
mode: 'cors',
credentials: corsAttributeState === 'anonymous'
? 'same-origin'
: 'omit',
referrer: 'no-referrer'
}
credentials: corsAttributeState === 'anonymous' ? 'same-origin' : 'omit',
referrer: 'no-referrer',
};
// 9. Set request's client to settings.
initRequest.client = environmentSettingsObject.settingsObject
initRequest.client = environmentSettingsObject.settingsObject;
// 10. User agents may set (`Accept`, `text/event-stream`) in request's header list.
initRequest.headersList = [['accept', { name: 'accept', value: 'text/event-stream' }]]
initRequest.headersList = [
['accept', { name: 'accept', value: 'text/event-stream' }],
];
// 11. Set request's cache mode to "no-store".
initRequest.cache = 'no-store'
initRequest.cache = 'no-store';
// 12. Set request's initiator type to "other".
initRequest.initiator = 'other'
initRequest.initiator = 'other';
initRequest.urlList = [new URL(this.#url)]
initRequest.urlList = [new URL(this.#url)];
// 13. Set ev's request to request.
this.#request = makeRequest(initRequest)
this.#request = makeRequest(initRequest);
this.#connect()
this.#connect();
}
/**
@ -198,8 +205,8 @@ class EventSource extends EventTarget {
* @returns {ReadyState}
* @readonly
*/
get readyState () {
return this.#readyState
get readyState() {
return this.#readyState;
}
/**
@ -207,40 +214,40 @@ class EventSource extends EventTarget {
* @readonly
* @returns {string}
*/
get url () {
return this.#url
get url() {
return this.#url;
}
/**
* Returns a boolean indicating whether the EventSource object was
* instantiated with CORS credentials set (true), or not (false, the default).
*/
get withCredentials () {
return this.#withCredentials
get withCredentials() {
return this.#withCredentials;
}
#connect () {
if (this.#readyState === CLOSED) return
#connect() {
if (this.#readyState === CLOSED) return;
this.#readyState = CONNECTING
this.#readyState = CONNECTING;
const fetchParams = {
request: this.#request,
dispatcher: this.#dispatcher
}
dispatcher: this.#dispatcher,
};
// 14. Let processEventSourceEndOfBody given response res be the following step: if res is not a network error, then reestablish the connection.
const processEventSourceEndOfBody = (response) => {
if (isNetworkError(response)) {
this.dispatchEvent(new Event('error'))
this.close()
this.dispatchEvent(new Event('error'));
this.close();
}
this.#reconnect()
}
this.#reconnect();
};
// 15. Fetch request, with processResponseEndOfBody set to processEventSourceEndOfBody...
fetchParams.processResponseEndOfBody = processEventSourceEndOfBody
fetchParams.processResponseEndOfBody = processEventSourceEndOfBody;
// and processResponse set to the following steps given response res:
fetchParams.processResponse = (response) => {
@ -254,30 +261,29 @@ class EventSource extends EventTarget {
// user agent has failed the connection, it does not attempt to
// reconnect.
if (response.aborted) {
this.close()
this.dispatchEvent(new Event('error'))
return
this.close();
this.dispatchEvent(new Event('error'));
return;
// 2. Otherwise, if res is a network error, then reestablish the
// connection, unless the user agent knows that to be futile, in
// which case the user agent may fail the connection.
} else {
this.#reconnect()
return
this.#reconnect();
return;
}
}
// 3. Otherwise, if res's status is not 200, or if res's `Content-Type`
// is not `text/event-stream`, then fail the connection.
const contentType = response.headersList.get('content-type', true)
const mimeType = contentType !== null ? parseMIMEType(contentType) : 'failure'
const contentTypeValid = mimeType !== 'failure' && mimeType.essence === 'text/event-stream'
if (
response.status !== 200 ||
contentTypeValid === false
) {
this.close()
this.dispatchEvent(new Event('error'))
return
const contentType = response.headersList.get('content-type', true);
const mimeType =
contentType !== null ? parseMIMEType(contentType) : 'failure';
const contentTypeValid =
mimeType !== 'failure' && mimeType.essence === 'text/event-stream';
if (response.status !== 200 || contentTypeValid === false) {
this.close();
this.dispatchEvent(new Event('error'));
return;
}
// 4. Otherwise, announce the connection and interpret res's body
@ -288,42 +294,35 @@ class EventSource extends EventTarget {
// value other than CLOSED, sets the readyState attribute to OPEN
// and fires an event named open at the EventSource object.
// @see https://html.spec.whatwg.org/multipage/server-sent-events.html#sse-processing-model
this.#readyState = OPEN
this.dispatchEvent(new Event('open'))
this.#readyState = OPEN;
this.dispatchEvent(new Event('open'));
// If redirected to a different origin, set the origin to the new origin.
this.#state.origin = response.urlList[response.urlList.length - 1].origin
this.#state.origin = response.urlList[response.urlList.length - 1].origin;
const eventSourceStream = new EventSourceStream({
eventSourceSettings: this.#state,
push: (event) => {
this.dispatchEvent(createFastMessageEvent(
event.type,
event.options
))
this.dispatchEvent(createFastMessageEvent(event.type, event.options));
},
});
pipeline(response.body.stream, eventSourceStream, (error) => {
if (error?.aborted === false) {
this.close();
this.dispatchEvent(new Event('error'));
}
})
});
};
pipeline(response.body.stream,
eventSourceStream,
(error) => {
if (
error?.aborted === false
) {
this.close()
this.dispatchEvent(new Event('error'))
}
})
}
this.#controller = fetching(fetchParams)
this.#controller = fetching(fetchParams);
}
/**
* @see https://html.spec.whatwg.org/multipage/server-sent-events.html#sse-processing-model
* @returns {Promise<void>}
*/
async #reconnect () {
async #reconnect() {
// When a user agent is to reestablish the connection, the user agent must
// run the following steps. These steps are run in parallel, not as part of
// a task. (The tasks that it queues, of course, are run like normal tasks
@ -332,22 +331,22 @@ class EventSource extends EventTarget {
// 1. Queue a task to run the following steps:
// 1. If the readyState attribute is set to CLOSED, abort the task.
if (this.#readyState === CLOSED) return
if (this.#readyState === CLOSED) return;
// 2. Set the readyState attribute to CONNECTING.
this.#readyState = CONNECTING
this.#readyState = CONNECTING;
// 3. Fire an event named error at the EventSource object.
this.dispatchEvent(new Event('error'))
this.dispatchEvent(new Event('error'));
// 2. Wait a delay equal to the reconnection time of the event source.
await delay(this.#state.reconnectionTime)
await delay(this.#state.reconnectionTime);
// 5. Queue a task to run the following steps:
// 1. If the EventSource object's readyState attribute is not set to
// CONNECTING, then return.
if (this.#readyState !== CONNECTING) return
if (this.#readyState !== CONNECTING) return;
// 2. Let request be the EventSource object's request.
// 3. If the EventSource object's last event ID string is not the empty
@ -357,74 +356,78 @@ class EventSource extends EventTarget {
// 2. Set (`Last-Event-ID`, lastEventIDValue) in request's header
// list.
if (this.#state.lastEventId.length) {
this.#request.headersList.set('last-event-id', this.#state.lastEventId, true)
this.#request.headersList.set(
'last-event-id',
this.#state.lastEventId,
true
);
}
// 4. Fetch request and process the response obtained in this fashion, if any, as described earlier in this section.
this.#connect()
this.#connect();
}
/**
* Closes the connection, if any, and sets the readyState attribute to
* CLOSED.
*/
close () {
webidl.brandCheck(this, EventSource)
close() {
webidl.brandCheck(this, EventSource);
if (this.#readyState === CLOSED) return
this.#readyState = CLOSED
this.#controller.abort()
this.#request = null
if (this.#readyState === CLOSED) return;
this.#readyState = CLOSED;
this.#controller.abort();
this.#request = null;
}
get onopen () {
return this.#events.open
get onopen() {
return this.#events.open;
}
set onopen (fn) {
set onopen(fn) {
if (this.#events.open) {
this.removeEventListener('open', this.#events.open)
this.removeEventListener('open', this.#events.open);
}
if (typeof fn === 'function') {
this.#events.open = fn
this.addEventListener('open', fn)
this.#events.open = fn;
this.addEventListener('open', fn);
} else {
this.#events.open = null
this.#events.open = null;
}
}
get onmessage () {
return this.#events.message
get onmessage() {
return this.#events.message;
}
set onmessage (fn) {
set onmessage(fn) {
if (this.#events.message) {
this.removeEventListener('message', this.#events.message)
this.removeEventListener('message', this.#events.message);
}
if (typeof fn === 'function') {
this.#events.message = fn
this.addEventListener('message', fn)
this.#events.message = fn;
this.addEventListener('message', fn);
} else {
this.#events.message = null
this.#events.message = null;
}
}
get onerror () {
return this.#events.error
get onerror() {
return this.#events.error;
}
set onerror (fn) {
set onerror(fn) {
if (this.#events.error) {
this.removeEventListener('error', this.#events.error)
this.removeEventListener('error', this.#events.error);
}
if (typeof fn === 'function') {
this.#events.error = fn
this.addEventListener('error', fn)
this.#events.error = fn;
this.addEventListener('error', fn);
} else {
this.#events.error = null
this.#events.error = null;
}
}
}
@ -435,26 +438,26 @@ const constantsPropertyDescriptors = {
configurable: false,
enumerable: true,
value: CONNECTING,
writable: false
writable: false,
},
OPEN: {
__proto__: null,
configurable: false,
enumerable: true,
value: OPEN,
writable: false
writable: false,
},
CLOSED: {
__proto__: null,
configurable: false,
enumerable: true,
value: CLOSED,
writable: false
}
}
writable: false,
},
};
Object.defineProperties(EventSource, constantsPropertyDescriptors)
Object.defineProperties(EventSource.prototype, constantsPropertyDescriptors)
Object.defineProperties(EventSource, constantsPropertyDescriptors);
Object.defineProperties(EventSource.prototype, constantsPropertyDescriptors);
Object.defineProperties(EventSource.prototype, {
close: kEnumerableProperty,
@ -463,22 +466,22 @@ Object.defineProperties(EventSource.prototype, {
onopen: kEnumerableProperty,
readyState: kEnumerableProperty,
url: kEnumerableProperty,
withCredentials: kEnumerableProperty
})
withCredentials: kEnumerableProperty,
});
webidl.converters.EventSourceInitDict = webidl.dictionaryConverter([
{
key: 'withCredentials',
converter: webidl.converters.boolean,
defaultValue: () => false
defaultValue: () => false,
},
{
key: 'dispatcher', // undici only
converter: webidl.converters.any
}
])
converter: webidl.converters.any,
},
]);
module.exports = {
EventSource,
defaultReconnectionTime
}
defaultReconnectionTime,
};

View File

@ -1,13 +1,13 @@
'use strict'
'use strict';
/**
* Checks if the given value is a valid LastEventId.
* @param {string} value
* @returns {boolean}
*/
function isValidLastEventId (value) {
function isValidLastEventId(value) {
// LastEventId should not contain U+0000 NULL
return value.indexOf('\u0000') === -1
return value.indexOf('\u0000') === -1;
}
/**
@ -15,23 +15,23 @@ function isValidLastEventId (value) {
* @param {string} value
* @returns {boolean}
*/
function isASCIINumber (value) {
if (value.length === 0) return false
function isASCIINumber(value) {
if (value.length === 0) return false;
for (let i = 0; i < value.length; i++) {
if (value.charCodeAt(i) < 0x30 || value.charCodeAt(i) > 0x39) return false
if (value.charCodeAt(i) < 0x30 || value.charCodeAt(i) > 0x39) return false;
}
return true
return true;
}
// https://github.com/nodejs/undici/issues/2664
function delay (ms) {
function delay(ms) {
return new Promise((resolve) => {
setTimeout(resolve, ms).unref()
})
setTimeout(resolve, ms).unref();
});
}
module.exports = {
isValidLastEventId,
isASCIINumber,
delay
}
delay,
};