strophe.js
Version:
Strophe.js is an XMPP library for JavaScript
74 lines • 3.38 kB
TypeScript
/**
* This file implements an incremental XML stream parser for the XEP-0114
* external-component transport (see {@link Component} in `component.ts`).
*
* A raw TCP stream has no message framing: bytes arrive in arbitrary chunks and
* a single, never-closing `<stream:stream>` root has to be parsed incrementally
* into its top-level child stanzas. This is the SAX push parser that
* `websocket.ts` anticipated in its "[TODO : We may actually want to use a SAX
* Push parser]" note.
*
* The parser is deliberately Node-only: it relies on `node:string_decoder` to
* reassemble multi-byte UTF-8 characters split across TCP reads and on `saxes`
* (a small, well-tested SAX tokenizer that ships with jsdom) for tokenization.
* The actual DOM construction reuses Strophe's own {@link xmlGenerator}, so the
* `Element` objects handed downstream are the exact same type produced by the
* BOSH and WebSocket transports.
*/
import { Buffer } from 'node:buffer';
export interface StreamParserHandlers {
/** Called once the opening `<stream:stream …>` header is seen, with its
* attributes (most importantly `id`). The header never closes until the
* stream ends, so this fires as soon as its start tag is complete. */
onStreamStart: (attrs: Record<string, string>) => void;
/** Called with each complete top-level stanza as a DOM {@link Element}. */
onStanza: (stanza: Element) => void;
/** Called when the closing `</stream:stream>` tag is received. */
onStreamEnd: () => void;
/** Called on any XML parse error. The stream should be considered dead. */
onError: (error: Error) => void;
}
/**
* Incrementally parses an XMPP component stream.
*
* Feed it raw socket chunks via {@link ComponentParser#write}; it emits
* stream-start, per-stanza and stream-end events through the handlers passed to
* the constructor. Robust to a stanza (or a single multi-byte character) being
* split across arbitrary chunk boundaries.
*/
export default class ComponentParser {
private readonly _handlers;
private _decoder;
private _parser;
/** Stack of elements currently being built (the in-progress stanza subtree).
* Empty in between top-level stanzas. Excludes the stream root, which is
* never materialised as an element. */
private _stack;
/** Whether the opening `<stream:stream>` header has been seen. */
private _streamOpened;
/** Set after a fatal parse error so that further writes are ignored. */
private _errored;
constructor(handlers: StreamParserHandlers);
/**
* Discard all parser state and start afresh. Called when a (re)connection
* begins so a new stream is parsed from a clean slate.
*/
reset(): void;
/**
* Feed a chunk of raw stream data into the parser.
*
* Accepts a `Buffer` (as delivered by a `node:net` socket) or an already
* decoded string. Buffers are run through a {@link StringDecoder} so that a
* multi-byte UTF-8 character split across two chunks is reassembled instead
* of corrupted.
* @param chunk - The bytes (or string) received from the socket.
*/
write(chunk: Buffer | string): void;
private _fail;
private _onOpenTag;
private _onText;
private _onCloseTag;
private _createElement;
private _flattenAttributes;
}
//# sourceMappingURL=component-parser.d.ts.map