mirror of
https://github.com/microsoft/vscode.git
synced 2026-07-11 14:04:49 -05:00
@@ -55,6 +55,7 @@ export class SSEParser {
|
||||
private lastEventIdBuffer?: string;
|
||||
private reconnectionTime?: number;
|
||||
private buffer: Uint8Array[] = [];
|
||||
private endedOnCR = false;
|
||||
private readonly onEventHandler: SSEEventHandler;
|
||||
private readonly decoder: TextDecoder;
|
||||
/**
|
||||
@@ -84,8 +85,18 @@ export class SSEParser {
|
||||
* @param chunk The chunk to parse as a Uint8Array of UTF-8 encoded data.
|
||||
*/
|
||||
public feed(chunk: Uint8Array): void {
|
||||
if (chunk.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
let offset = 0;
|
||||
|
||||
// If the data stream was bifurcated between a CR and LF, avoid processing the CR as an extra newline
|
||||
if (this.endedOnCR && chunk[0] === Chr.LF) {
|
||||
offset++;
|
||||
}
|
||||
this.endedOnCR = false;
|
||||
|
||||
// Process complete lines from the buffer
|
||||
while (offset < chunk.length) {
|
||||
const indexCR = chunk.indexOf(Chr.CR, offset);
|
||||
@@ -103,12 +114,14 @@ export class SSEParser {
|
||||
this.processLine(str);
|
||||
|
||||
this.buffer.length = 0;
|
||||
offset = index + (chunk[offset] === Chr.CR && chunk[offset + 1] === Chr.LF ? 2 : 1);
|
||||
offset = index + (chunk[index] === Chr.CR && chunk[index + 1] === Chr.LF ? 2 : 1);
|
||||
}
|
||||
|
||||
|
||||
if (offset < chunk.length) {
|
||||
this.buffer.push(chunk.subarray(offset));
|
||||
} else {
|
||||
this.endedOnCR = chunk[chunk.length - 1] === Chr.CR;
|
||||
}
|
||||
}
|
||||
/**
|
||||
|
||||
@@ -42,6 +42,31 @@ suite('SSEParser', () => {
|
||||
assert.strictEqual(receivedEvents[0].type, 'custom');
|
||||
assert.strictEqual(receivedEvents[0].data, 'hello world');
|
||||
});
|
||||
test('handles events with explicit event type (CRLF)', () => {
|
||||
parser.feed(toUint8Array('event: custom\r\ndata: hello world\r\n\r\n'));
|
||||
|
||||
assert.strictEqual(receivedEvents.length, 1);
|
||||
assert.strictEqual(receivedEvents[0].type, 'custom');
|
||||
assert.strictEqual(receivedEvents[0].data, 'hello world');
|
||||
});
|
||||
test('stream processing chunks', () => {
|
||||
for (const lf of ['\n', '\r\n', '\r']) {
|
||||
const message = toUint8Array(`event: custom${lf}data: hello world${lf}${lf}event: custom2${lf}data: hello world2${lf}${lf}`);
|
||||
for (let chunkSize = 1; chunkSize < 5; chunkSize++) {
|
||||
receivedEvents.length = 0;
|
||||
|
||||
for (let i = 0; i < message.length; i += chunkSize) {
|
||||
const chunk = message.slice(i, i + chunkSize);
|
||||
parser.feed(chunk);
|
||||
}
|
||||
|
||||
assert.deepStrictEqual(receivedEvents, [
|
||||
{ type: 'custom', data: 'hello world' },
|
||||
{ type: 'custom2', data: 'hello world2' }
|
||||
], `Failed for chunk size ${chunkSize} and line ending ${JSON.stringify(lf)}`);
|
||||
}
|
||||
}
|
||||
});
|
||||
test('handles events with ID', () => {
|
||||
parser.feed(toUint8Array('event: custom\ndata: hello\nid: 123\n\n'));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user