Skip to content

Commit 255b799

Browse files
authored
BREAKING(jsonc): remove allowTrailingComma option (denoland#5119)
1 parent 9411d09 commit 255b799

File tree

6 files changed

+18
-62
lines changed

6 files changed

+18
-62
lines changed

jsonc/mod.ts

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,7 @@
1414
* import { assertEquals } from "@std/assert/assert-equals";
1515
*
1616
* assertEquals(parse('{"foo": "bar", } // comment'), { foo: "bar" });
17-
*
1817
* assertEquals(parse('{"foo": "bar", } /* comment *\/'), { foo: "bar" });
19-
*
20-
* assertEquals(
21-
* parse('{"foo": "bar" } // comment', { allowTrailingComma: false }),
22-
* { foo: "bar" }
23-
* );
2418
* ```
2519
*
2620
* @module

jsonc/parse.ts

Lines changed: 7 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,6 @@
44
import type { JsonValue } from "@std/json/types";
55
export type { JsonValue } from "@std/json/types";
66

7-
/** Options for {@linkcode parse}. */
8-
export interface ParseOptions {
9-
/** Allow trailing commas at the end of arrays and objects.
10-
*
11-
* @default {true}
12-
*/
13-
allowTrailingComma?: boolean;
14-
}
15-
167
/**
178
* Converts a JSON with Comments (JSONC) string into an object.
189
*
@@ -24,23 +15,18 @@ export interface ParseOptions {
2415
* assertEquals(parse('{"foo": "bar"}'), { foo: "bar" });
2516
* assertEquals(parse('{"foo": "bar", }'), { foo: "bar" });
2617
* assertEquals(parse('{"foo": "bar", } /* comment *\/'), { foo: "bar" });
27-
* assertEquals(parse('{"foo": "bar" } // comment', { allowTrailingComma: false }), { foo: "bar" });
2818
* ```
2919
*
3020
* @throws {SyntaxError} If the JSONC string is invalid.
3121
* @param text A valid JSONC string.
3222
* @param options Options for parsing.
3323
* @returns The parsed JsonValue from the JSONC string.
3424
*/
35-
export function parse(
36-
text: string,
37-
options?: ParseOptions,
38-
): JsonValue {
39-
const { allowTrailingComma = true } = { ...options };
25+
export function parse(text: string): JsonValue {
4026
if (new.target) {
4127
throw new TypeError("parse is not a constructor");
4228
}
43-
return new JSONCParser(text, { allowTrailingComma }).parse();
29+
return new JSONCParser(text).parse();
4430
}
4531

4632
type TokenType =
@@ -77,12 +63,10 @@ class JSONCParser {
7763
#text: string;
7864
#length: number;
7965
#tokenized: Generator<Token, void>;
80-
#options: ParseOptions;
81-
constructor(text: string, options: ParseOptions) {
66+
constructor(text: string) {
8267
this.#text = `${text}`;
8368
this.#length = this.#text.length;
8469
this.#tokenized = this.#tokenize();
85-
this.#options = options;
8670
}
8771
parse(): JsonValue {
8872
const token = this.#getNext();
@@ -238,12 +222,9 @@ class JSONCParser {
238222
// │ │ │ │ │ │ ┌─────token3
239223
// │ │ │ │ │ │ │ ┌─token4
240224
// { "key" : value , "key" : value }
241-
for (let isFirst = true;; isFirst = false) {
225+
while (true) {
242226
const token1 = this.#getNext();
243-
if (
244-
(isFirst || this.#options.allowTrailingComma) &&
245-
token1.type === "EndObject"
246-
) {
227+
if (token1.type === "EndObject") {
247228
return target;
248229
}
249230
if (token1.type !== "String") {
@@ -290,12 +271,9 @@ class JSONCParser {
290271
// │ │ ┌─────token1
291272
// │ │ │ ┌─token2
292273
// [ value , value ]
293-
for (let isFirst = true;; isFirst = false) {
274+
while (true) {
294275
const token1 = this.#getNext();
295-
if (
296-
(isFirst || this.#options.allowTrailingComma) &&
297-
token1.type === "EndArray"
298-
) {
276+
if (token1.type === "EndArray") {
299277
return target;
300278
}
301279
target.push(this.#parseJsonValue(token1));

jsonc/parse_test.ts

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
22

3-
import { parse, type ParseOptions } from "./parse.ts";
3+
import { parse } from "./parse.ts";
44
import {
55
assert,
66
assertEquals,
@@ -14,23 +14,18 @@ import "./testdata/test262/test.ts";
1414

1515
// The test code for the jsonc module can also be found in the testcode directory.
1616

17-
function assertValidParse(
18-
text: string,
19-
expected: unknown,
20-
options?: ParseOptions,
21-
) {
22-
assertEquals(parse(text, options), expected);
17+
function assertValidParse(text: string, expected: unknown) {
18+
assertEquals(parse(text), expected);
2319
}
2420

2521
function assertInvalidParse(
2622
text: string,
2723
// deno-lint-ignore no-explicit-any
2824
ErrorClass: new (...args: any[]) => Error,
2925
msgIncludes?: string,
30-
options?: ParseOptions,
3126
) {
3227
assertThrows(
33-
() => parse(text, options),
28+
() => parse(text),
3429
ErrorClass,
3530
msgIncludes,
3631
);
@@ -231,3 +226,7 @@ Deno.test({
231226
);
232227
},
233228
});
229+
230+
Deno.test("parse() handles lone continuation byte in key and tailing comma", () => {
231+
assertEquals(parse('{"�":"0",}'), { "�": "0" });
232+
});

jsonc/testdata/JSONTestSuite/test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ for await (
3434
JSON.parse(text);
3535
});
3636
const [hasJsoncError, jsoncError, jsoncResult] = getError(() => {
37-
JSONC.parse(text, { allowTrailingComma: false });
37+
JSONC.parse(text);
3838
});
3939

4040
// If an error occurs in JSON.parse() but no error occurs in JSONC.parse(), or vice versa, an error is thrown.

jsonc/testdata/JSONTestSuite/test_parsing/n_object_lone_continuation_byte_in_key_and_trailing_comma.json

Lines changed: 0 additions & 1 deletion
This file was deleted.

jsonc/testdata/node-jsonc-parser/test.ts

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,17 @@ import { assertEquals, assertThrows } from "../../../assert/mod.ts";
1111
function assertValidParse(
1212
text: string,
1313
expected: unknown,
14-
options?: JSONC.ParseOptions,
1514
) {
16-
assertEquals(JSONC.parse(text, options), expected);
15+
assertEquals(JSONC.parse(text), expected);
1716
}
1817
function assertInvalidParse(
1918
text: string,
2019
// deno-lint-ignore no-explicit-any
2120
ErrorClass: (new (...args: any[]) => Error),
2221
msgIncludes?: string,
23-
options?: JSONC.ParseOptions,
2422
) {
2523
assertThrows(
26-
() => JSONC.parse(text, options),
24+
() => JSONC.parse(text),
2725
ErrorClass,
2826
msgIncludes,
2927
);
@@ -83,9 +81,6 @@ Deno.test("[jsonc] parse node-jsonc-parser:arrays", () => {
8381

8482
Deno.test("[jsonc] parse node-jsonc-parser:objects with errors", () => {
8583
assertInvalidParse("{,}", SyntaxError);
86-
assertInvalidParse('{ "foo": true, }', SyntaxError, undefined, {
87-
allowTrailingComma: false,
88-
});
8984
assertInvalidParse('{ "bar": 8 "xoo": "foo" }', SyntaxError);
9085
assertInvalidParse('{ ,"bar": 8 }', SyntaxError);
9186
assertInvalidParse('{ ,"bar": 8, "foo" }', SyntaxError);
@@ -119,13 +114,4 @@ Deno.test("[jsonc] parse node-jsonc-parser:trailing comma", () => {
119114
);
120115
assertValidParse("[ 1, 2, ]", [1, 2]);
121116
assertValidParse("[ 1, 2 ]", [1, 2]);
122-
123-
assertInvalidParse('{ "hello": [], }', SyntaxError, undefined, options);
124-
assertInvalidParse(
125-
'{ "hello": [], "world": {}, }',
126-
SyntaxError,
127-
undefined,
128-
options,
129-
);
130-
assertInvalidParse("[ 1, 2, ]", SyntaxError, undefined, options);
131117
});

0 commit comments

Comments
 (0)