UNPKG

newline-async-iterator

Version:

Line-by-line async iterator for the browser and node

1 lines 12.3 kB
{"version":3,"file":"newline-async-iterator.cjs","sources":["../../src/compat.ts","../../src/decodeUTF8.ts","../../src/index.ts"],"sourcesContent":["// Feature detection - no global modifications per polyfill-removal plans\n\n/**\n * Convert a Uint8Array to a number array\n * Compatible with Node 0.8+ (no Array.from)\n */\nexport function uint8ArrayToArray(uint8Array: Uint8Array): number[] {\n if (typeof Array.from === 'function') return Array.from(uint8Array);\n\n // Fallback for old environments without Array.from\n const arr: number[] = [];\n for (let i = 0; i < uint8Array.length; i++) {\n arr.push(uint8Array[i]);\n }\n return arr;\n}\n","import { uint8ArrayToArray } from './compat.ts';\n\n/**\n * Get the expected length of a UTF-8 sequence from its first byte\n */\nfunction getUTF8SequenceLength(byte: number): number {\n if (byte < 0x80) return 1; // 0xxxxxxx - ASCII\n if (byte < 0xc0) return 0; // 10xxxxxx - continuation byte (invalid as start)\n if (byte < 0xe0) return 2; // 110xxxxx\n if (byte < 0xf0) return 3; // 1110xxxx\n if (byte < 0xf8) return 4; // 11110xxx\n return 0; // Invalid UTF-8 start byte\n}\n\n/**\n * Decode a single UTF-8 code point from bytes\n */\nfunction decodeCodePoint(bytes: number[], start: number, length: number): string {\n let codePoint: number;\n\n switch (length) {\n case 1:\n codePoint = bytes[start];\n break;\n case 2:\n codePoint = ((bytes[start] & 0x1f) << 6) | (bytes[start + 1] & 0x3f);\n break;\n case 3:\n codePoint = ((bytes[start] & 0x0f) << 12) | ((bytes[start + 1] & 0x3f) << 6) | (bytes[start + 2] & 0x3f);\n break;\n case 4:\n codePoint = ((bytes[start] & 0x07) << 18) | ((bytes[start + 1] & 0x3f) << 12) | ((bytes[start + 2] & 0x3f) << 6) | (bytes[start + 3] & 0x3f);\n break;\n default:\n return '\\ufffd'; // Replacement character for invalid sequences\n }\n\n // Handle code points outside BMP (need surrogate pairs in JavaScript)\n if (codePoint > 0xffff) {\n // Convert to surrogate pair\n codePoint -= 0x10000;\n return String.fromCharCode(0xd800 + (codePoint >> 10), 0xdc00 + (codePoint & 0x3ff));\n }\n\n return String.fromCharCode(codePoint);\n}\n\n/**\n * Create a fallback UTF-8 streaming decoder with its own state\n */\nfunction createFallbackDecoder(): (uint8Array: Uint8Array) => string {\n let pendingBytes: number[] = [];\n\n return function decode(uint8Array: Uint8Array): string {\n // Combine pending bytes with new input\n const inputBytes = uint8ArrayToArray(uint8Array);\n const bytes = pendingBytes.length > 0 ? pendingBytes.concat(inputBytes) : inputBytes;\n pendingBytes = [];\n\n let result = '';\n let i = 0;\n\n while (i < bytes.length) {\n const byte = bytes[i];\n const sequenceLength = getUTF8SequenceLength(byte);\n\n if (sequenceLength === 0) {\n // Invalid start byte or continuation byte - emit replacement character\n result += '\\ufffd';\n i++;\n continue;\n }\n\n if (i + sequenceLength > bytes.length) {\n // Incomplete sequence - save for next chunk\n pendingBytes = bytes.slice(i);\n break;\n }\n\n result += decodeCodePoint(bytes, i, sequenceLength);\n i += sequenceLength;\n }\n\n return result;\n };\n}\n\n/**\n * Create a TextDecoder-based streaming decoder\n */\nfunction createTextDecoderDecoder(): (uint8Array: Uint8Array) => string {\n const decoder = new TextDecoder('utf8');\n return function decode(uint8Array: Uint8Array): string {\n return decoder.decode(uint8Array, { stream: true });\n };\n}\n\n/**\n * Create a new UTF-8 streaming decoder instance.\n * Each decoder maintains its own state for handling multi-byte\n * characters that span chunk boundaries.\n */\nexport default function createUTF8Decoder(): (uint8Array: Uint8Array) => string {\n if (typeof TextDecoder !== 'undefined') {\n return createTextDecoderDecoder();\n }\n return createFallbackDecoder();\n}\n","import createUTF8Decoder from './decodeUTF8.ts';\n\nconst REGEX_NEW_LINE = /\\r?\\n|\\r/g;\n\nconst root = typeof window === 'undefined' ? global : window;\n// biome-ignore lint/suspicious/noShadowRestrictedNames: Legacy\nconst Symbol: SymbolConstructor = typeof root.Symbol === 'undefined' ? ({ asyncIterator: undefined } as unknown as SymbolConstructor) : root.Symbol;\n\n/**\n * Create a newline iterator recognizing CR, LF, and CRLF using the Symbol.asyncIterator interface\n *\n * @param source The async iterable of Uint8Array chunks to iterate through\n *\n * ```typescript\n * import newlineIterator from \"newline-async-iterator\";\n *\n * const iterator = newlineIterator(readableStream);\n * const results = [];\n * for await (const line of iterator) results.push(line);\n * console.log(results); // [\"some\", \"string\", \"combination\"];\n * ```\n */\n\nexport default function newlineIterator(source: AsyncIterable<Uint8Array> | AsyncIterator<Uint8Array>): AsyncIterableIterator<string> {\n const decodeUTF8 = createUTF8Decoder();\n const lines = [];\n let last = '';\n let done = false;\n\n const sourceIterator = Symbol.asyncIterator ? source[Symbol.asyncIterator]() : source;\n\n function generateNext(): Promise<IteratorResult<string, boolean>> {\n return new Promise((resolve, reject) => {\n sourceIterator.next().then((next) => {\n if (next.done) done = true;\n else last += decodeUTF8(next.value);\n\n const end = last.length > 0 ? last[last.length - 1] : '';\n if (done || (end !== '\\r' && end !== '\\n')) {\n const moreLines = last.split(REGEX_NEW_LINE);\n last = moreLines.pop();\n moreLines.forEach((line) => {\n lines.unshift(line);\n });\n if (done && last.length > 0) {\n lines.unshift(last);\n last = '';\n }\n }\n\n if (lines.length > 0) {\n const value = lines.pop();\n if (done && lines.length === 0 && value.length === 0) return resolve({ value: null, done: true });\n return resolve({ value, done: false });\n }\n if (done) return resolve({ value: null, done: true });\n generateNext().then(resolve).catch(reject); // get more\n });\n });\n }\n\n const iterator = {\n next(): Promise<IteratorResult<string, boolean>> {\n return generateNext();\n },\n [Symbol.asyncIterator](): AsyncIterator<string> {\n return this;\n },\n };\n\n return iterator as AsyncIterableIterator<string>;\n}\n"],"names":["uint8ArrayToArray","uint8Array","Array","from","arr","i","length","push","getUTF8SequenceLength","byte","decodeCodePoint","bytes","start","codePoint","String","fromCharCode","createFallbackDecoder","pendingBytes","decode","inputBytes","concat","result","sequenceLength","slice","createTextDecoderDecoder","decoder","TextDecoder","stream","createUTF8Decoder","REGEX_NEW_LINE","root","window","global","Symbol","asyncIterator","undefined","newlineIterator","source","decodeUTF8","lines","last","done","sourceIterator","generateNext","Promise","resolve","reject","next","then","value","end","moreLines","split","pop","forEach","line","unshift","catch","iterator"],"mappings":"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"}