refactor: use specific error types in decoders and parser

This commit is contained in:
Johann Schopplich
2025-10-29 09:01:43 +01:00
parent ee5c158ddf
commit 1776ae1834
3 changed files with 14 additions and 14 deletions

View File

@@ -29,7 +29,7 @@ import {
export function decodeValueFromLines(cursor: LineCursor, options: ResolvedDecodeOptions): JsonValue { export function decodeValueFromLines(cursor: LineCursor, options: ResolvedDecodeOptions): JsonValue {
const first = cursor.peek() const first = cursor.peek()
if (!first) { if (!first) {
throw new Error('No content to decode') throw new ReferenceError('No content to decode')
} }
// Check for root array // Check for root array
@@ -230,7 +230,7 @@ function decodeListArray(
if (options.strict && !cursor.atEnd()) { if (options.strict && !cursor.atEnd()) {
const nextLine = cursor.peek() const nextLine = cursor.peek()
if (nextLine && nextLine.depth === itemDepth && nextLine.content.startsWith(LIST_ITEM_PREFIX)) { if (nextLine && nextLine.depth === itemDepth && nextLine.content.startsWith(LIST_ITEM_PREFIX)) {
throw new Error(`Expected ${header.length} list array items, but found more`) throw new RangeError(`Expected ${header.length} list array items, but found more`)
} }
} }
@@ -284,7 +284,7 @@ function decodeTabularArray(
if (!hasColon) { if (!hasColon) {
// No colon = data row (for single-field tables) // No colon = data row (for single-field tables)
throw new Error(`Expected ${header.length} tabular rows, but found more`) throw new RangeError(`Expected ${header.length} tabular rows, but found more`)
} }
else if (hasDelimiter) { else if (hasDelimiter) {
// Has both colon and delimiter - check which comes first // Has both colon and delimiter - check which comes first
@@ -292,7 +292,7 @@ function decodeTabularArray(
const delimiterPos = nextLine.content.indexOf(header.delimiter) const delimiterPos = nextLine.content.indexOf(header.delimiter)
if (delimiterPos < colonPos) { if (delimiterPos < colonPos) {
// Delimiter before colon = data row // Delimiter before colon = data row
throw new Error(`Expected ${header.length} tabular rows, but found more`) throw new RangeError(`Expected ${header.length} tabular rows, but found more`)
} }
// Colon before delimiter = key-value pair, OK // Colon before delimiter = key-value pair, OK
} }
@@ -315,7 +315,7 @@ function decodeListItem(
): JsonValue { ): JsonValue {
const line = cursor.next() const line = cursor.next()
if (!line) { if (!line) {
throw new Error('Expected list item') throw new ReferenceError('Expected list item')
} }
const afterHyphen = line.content.slice(LIST_ITEM_PREFIX.length) const afterHyphen = line.content.slice(LIST_ITEM_PREFIX.length)
@@ -382,7 +382,7 @@ function decodeFirstFieldOnHyphen(
function assertExpectedCount(actual: number, expected: number, what: string, options: ResolvedDecodeOptions): void { function assertExpectedCount(actual: number, expected: number, what: string, options: ResolvedDecodeOptions): void {
if (options.strict && actual !== expected) { if (options.strict && actual !== expected) {
throw new Error(`Expected ${expected} ${what}, but got ${actual}`) throw new RangeError(`Expected ${expected} ${what}, but got ${actual}`)
} }
} }

View File

@@ -36,7 +36,7 @@ export function decode(input: string, options?: DecodeOptions): JsonValue {
const lines = toParsedLines(input, resolved.indent) const lines = toParsedLines(input, resolved.indent)
if (lines.length === 0) { if (lines.length === 0) {
throw new Error('Cannot decode empty input') throw new TypeError('Cannot decode empty input: input must be a non-empty string')
} }
const cursor = new LineCursor(lines) const cursor = new LineCursor(lines)

View File

@@ -256,7 +256,7 @@ export function parseStringLiteral(token: string): string {
if (trimmed[i] === DOUBLE_QUOTE) { if (trimmed[i] === DOUBLE_QUOTE) {
// Found closing quote // Found closing quote
if (i !== trimmed.length - 1) { if (i !== trimmed.length - 1) {
throw new Error('Unexpected characters after closing quote') throw new SyntaxError('Unexpected characters after closing quote')
} }
const content = trimmed.slice(1, i) const content = trimmed.slice(1, i)
return unescapeString(content) return unescapeString(content)
@@ -265,7 +265,7 @@ export function parseStringLiteral(token: string): string {
} }
// If we get here, no closing quote was found // If we get here, no closing quote was found
throw new Error('Unterminated string: missing closing quote') throw new SyntaxError('Unterminated string: missing closing quote')
} }
return trimmed return trimmed
@@ -278,7 +278,7 @@ export function unescapeString(value: string): string {
while (i < value.length) { while (i < value.length) {
if (value[i] === BACKSLASH) { if (value[i] === BACKSLASH) {
if (i + 1 >= value.length) { if (i + 1 >= value.length) {
throw new Error('Invalid escape sequence: backslash at end of string') throw new SyntaxError('Invalid escape sequence: backslash at end of string')
} }
const next = value[i + 1] const next = value[i + 1]
@@ -308,7 +308,7 @@ export function unescapeString(value: string): string {
continue continue
} }
throw new Error(`Invalid escape sequence: \\${next}`) throw new SyntaxError(`Invalid escape sequence: \\${next}`)
} }
result += value[i] result += value[i]
@@ -326,7 +326,7 @@ export function parseUnquotedKey(content: string, start: number): { key: string,
// Validate that a colon was found // Validate that a colon was found
if (end >= content.length || content[end] !== COLON) { if (end >= content.length || content[end] !== COLON) {
throw new Error('Missing colon after key') throw new SyntaxError('Missing colon after key')
} }
const key = content.slice(start, end).trim() const key = content.slice(start, end).trim()
@@ -355,7 +355,7 @@ export function parseQuotedKey(content: string, start: number): { key: string, e
// Validate and skip colon after quoted key // Validate and skip colon after quoted key
if (end >= content.length || content[end] !== COLON) { if (end >= content.length || content[end] !== COLON) {
throw new Error('Missing colon after key') throw new SyntaxError('Missing colon after key')
} }
end++ end++
@@ -366,7 +366,7 @@ export function parseQuotedKey(content: string, start: number): { key: string, e
i++ i++
} }
throw new Error('Unterminated quoted key') throw new SyntaxError('Unterminated quoted key')
} }
export function parseKeyToken(content: string, start: number): { key: string, end: number } { export function parseKeyToken(content: string, start: number): { key: string, end: number } {