Skip to content

Commit 69fe7dc

Browse files
timreichenkt3k
andauthored
fix(toml): fix empty inline table bug (#6587)
Co-authored-by: Yoshiya Hinosawa <[email protected]>
1 parent b47cf1c commit 69fe7dc

File tree

2 files changed

+45
-6
lines changed

2 files changed

+45
-6
lines changed

toml/_parser.ts

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -207,9 +207,39 @@ function or<T>(parsers: ParserComponent<T>[]): ParserComponent<T> {
207207
};
208208
}
209209

210+
/** Join the parse results of the given parser into an array.
211+
*
212+
* If the parser fails at the first attempt, it will return an empty array.
213+
*/
210214
function join<T>(
211215
parser: ParserComponent<T>,
212216
separator: string,
217+
): ParserComponent<T[]> {
218+
const Separator = character(separator);
219+
return (scanner: Scanner): ParseResult<T[]> => {
220+
const out: T[] = [];
221+
const first = parser(scanner);
222+
if (!first.ok) return success(out);
223+
out.push(first.body);
224+
while (!scanner.eof()) {
225+
if (!Separator(scanner).ok) break;
226+
const result = parser(scanner);
227+
if (!result.ok) {
228+
throw new SyntaxError(`Invalid token after "${separator}"`);
229+
}
230+
out.push(result.body);
231+
}
232+
return success(out);
233+
};
234+
}
235+
236+
/** Join the parse results of the given parser into an array.
237+
*
238+
* This requires the parser to succeed at least once.
239+
*/
240+
function join1<T>(
241+
parser: ParserComponent<T>,
242+
separator: string,
213243
): ParserComponent<T[]> {
214244
const Separator = character(separator);
215245
return (scanner: Scanner): ParseResult<T[]> => {
@@ -522,7 +552,7 @@ export function symbols(scanner: Scanner): ParseResult<unknown> {
522552
return success(value);
523553
}
524554

525-
export const dottedKey = join(or([bareKey, basicString, literalString]), ".");
555+
export const dottedKey = join1(or([bareKey, basicString, literalString]), ".");
526556

527557
const BINARY_REGEXP = /0b[01]+(?:_[01]+)*\b/y;
528558
export function binary(scanner: Scanner): ParseResult<number | string> {
@@ -639,11 +669,7 @@ export function inlineTable(
639669
scanner.next(2);
640670
return success({});
641671
}
642-
const pairs = surround(
643-
"{",
644-
join(pair, ","),
645-
"}",
646-
)(scanner);
672+
const pairs = surround("{", join(pair, ","), "}")(scanner);
647673
if (!pairs.ok) return failure();
648674
let table = {};
649675
for (const pair of pairs.body) {

toml/parse_test.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1408,3 +1408,16 @@ Deno.test({
14081408
);
14091409
},
14101410
});
1411+
1412+
Deno.test({
1413+
name: "parse() handles empty inline table",
1414+
fn() {
1415+
const input = `[package.metadata.details]
1416+
readme = { }`;
1417+
const expected = {
1418+
package: { metadata: { details: { readme: {} } } },
1419+
};
1420+
const actual = parse(input);
1421+
assertEquals(actual, expected);
1422+
},
1423+
});

0 commit comments

Comments
 (0)