Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 15 additions & 11 deletions toml/stringify.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,33 +132,36 @@ class Dumper {
}
return onlyPrimitive ? "ONLY_PRIMITIVE" : "ONLY_OBJECT_EXCLUDING_ARRAY";
}
#printAsInlineValue(value: unknown): string | number {
#printPrimitive(value: unknown): string {
if (value instanceof Date) {
return `"${this.#printDate(value)}"`;
return this.#printDate(value);
} else if (typeof value === "string" || value instanceof RegExp) {
return JSON.stringify(value.toString());
} else if (typeof value === "number") {
return value;
if (Number.isNaN(value)) return "nan";
if (value === Infinity) return "inf";
if (value === -Infinity) return "-inf";
return String(value);
} else if (typeof value === "boolean") {
return value.toString();
} else if (
}
throw new Error("Should never reach");
}
#printAsInlineValue(value: unknown): string {
if (
value instanceof Array
) {
const str = value.map((x) => this.#printAsInlineValue(x)).join(",");
return `[${str}]`;
} else if (typeof value === "object") {
if (!value) {
throw new Error("Should never reach");
}
} else if (value && typeof value === "object" && !(value instanceof Date)) {
const str = Object.keys(value).map((key) => {
return `${joinKeys([key])} = ${
// deno-lint-ignore no-explicit-any
this.#printAsInlineValue((value as any)[key])}`;
}).join(",");
return `{${str}}`;
}

throw new Error("Should never reach");
return this.#printPrimitive(value);
}
#isSimplySerializable(value: unknown): boolean {
return (
Expand All @@ -185,7 +188,8 @@ class Dumper {
return `${title} = `;
}
#arrayDeclaration(keys: string[], value: unknown[]): string {
return `${this.#declaration(keys)}${JSON.stringify(value)}`;
const items = value.map((v) => this.#printPrimitive(v)).join(",");
return `${this.#declaration(keys)}[${items}]`;
}
#strDeclaration(keys: string[], value: string): string {
return `${this.#declaration(keys)}${JSON.stringify(value)}`;
Expand Down
73 changes: 72 additions & 1 deletion toml/stringify_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ Deno.test({
const expected = `emptyArray = []
mixedArray1 = [1,{b = 2}]
mixedArray2 = [{b = 2},1]
nestedArray1 = [[{b = 1,date = "2022-05-13T00:00:00.000"}]]
nestedArray1 = [[{b = 1,date = 2022-05-13T00:00:00.000}]]
nestedArray2 = [[[{b = 1}]]]
nestedArray3 = [[],[{b = 1}]]

Expand Down Expand Up @@ -275,3 +275,74 @@ Deno.test({
assertEquals(actual, expected);
},
});

// https://github.com/denoland/std/issues/7162
Deno.test({
name:
"stringify() emits TOML float literals for Infinity/NaN in primitive arrays",
fn() {
const actual = stringify({ x: [Infinity, -Infinity, NaN] });
assertEquals(actual, "x = [inf,-inf,nan]\n");
},
});

// https://github.com/denoland/std/issues/7162
Deno.test({
name: "stringify() emits TOML datetime literal for Date in primitive arrays",
fn() {
const actual = stringify({ x: [new Date(0)] });
assertEquals(actual, "x = [1970-01-01T00:00:00.000]\n");
},
});

// https://github.com/denoland/std/issues/7162
Deno.test({
name:
"stringify() emits TOML float literals for Infinity/NaN in mixed arrays",
fn() {
const actual = stringify({ x: [Infinity, -Infinity, NaN, {}] });
assertEquals(actual, "x = [inf,-inf,nan,{}]\n");
},
});

// https://github.com/denoland/std/issues/7162
Deno.test({
name: "stringify() emits TOML datetime literal for Date in mixed arrays",
fn() {
const actual = stringify({ x: [new Date(0), {}] });
assertEquals(actual, "x = [1970-01-01T00:00:00.000,{}]\n");
},
});

// https://github.com/denoland/std/issues/7162 - regression check for the new
// #printPrimitive path that replaced JSON.stringify: finite numbers in
// primitive arrays must keep their JSON representation.
Deno.test({
name: "stringify() preserves finite numbers in primitive arrays",
fn() {
const actual = stringify({ x: [1, -1, 0, 3.14, 1e6] });
assertEquals(actual, "x = [1,-1,0,3.14,1000000]\n");
},
});

// https://github.com/denoland/std/issues/7162 - bare numeric and Date scalar
// declarations (not array elements) must be unaffected by the array fixes.
Deno.test({
name: "stringify() preserves scalar Infinity/NaN/Date declarations",
fn() {
const actual = stringify({
pi: Infinity,
bad: NaN,
neg: -Infinity,
when: new Date(0),
});
assertEquals(
actual,
`pi = inf
bad = nan
neg = -inf
when = 1970-01-01T00:00:00.000
`,
);
},
});
Loading