Skip to content

Commit b97d8f2

Browse files
committed
feat: support Date, Set, and Map to literalToAst
1 parent fd6f80f commit b97d8f2

File tree

2 files changed

+55
-4
lines changed

2 files changed

+55
-4
lines changed

src/proxy/_utils.ts

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,16 +64,44 @@ export function proxify<T>(node: ESNode): Proxified<T> {
6464

6565
const PROXY_KEY = "__magicast_proxy";
6666

67-
export function literalToAst(value: any): ESNode {
67+
export function literalToAst(value: any, seen = new Set()): ESNode {
6868
if (value === undefined) {
6969
return b.identifier("undefined") as any;
7070
}
7171
if (value === null) {
7272
// eslint-disable-next-line unicorn/no-null
7373
return b.literal(null) as any;
7474
}
75+
if (seen.has(value)) {
76+
throw new Error("Can not serialize circular reference");
77+
}
78+
seen.add(value);
79+
if (value instanceof Set) {
80+
return b.newExpression(b.identifier("Set"), [
81+
b.arrayExpression([...value].map((n) => literalToAst(n, seen)) as any),
82+
]) as any;
83+
}
84+
if (value instanceof Date) {
85+
return b.newExpression(b.identifier("Date"), [
86+
b.literal(value.toISOString()),
87+
]) as any;
88+
}
89+
if (value instanceof Map) {
90+
return b.newExpression(b.identifier("Map"), [
91+
b.arrayExpression(
92+
[...value].map(([key, value]) => {
93+
return b.arrayExpression([
94+
literalToAst(key, seen) as any,
95+
literalToAst(value, seen) as any,
96+
]) as any;
97+
}) as any
98+
),
99+
]) as any;
100+
}
75101
if (Array.isArray(value)) {
76-
return b.arrayExpression(value.map((n) => literalToAst(n)) as any) as any;
102+
return b.arrayExpression(
103+
value.map((n) => literalToAst(n, seen)) as any
104+
) as any;
77105
}
78106
if (typeof value === "object") {
79107
if (PROXY_KEY in value) {
@@ -84,7 +112,7 @@ export function literalToAst(value: any): ESNode {
84112
return b.property(
85113
"init",
86114
b.identifier(key),
87-
literalToAst(value) as any
115+
literalToAst(value, seen) as any
88116
) as any;
89117
})
90118
) as any;

test/utils.test.ts

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ describe("literalToAst", () => {
88
return print(literalToAst(value)).code;
99
}
1010

11-
it("should work", () => {
11+
it("basic", () => {
1212
expect(run(1)).toMatchInlineSnapshot('"1"');
1313
expect(run(true)).toMatchInlineSnapshot('"true"');
1414
expect(run(undefined)).toMatchInlineSnapshot('"undefined"');
@@ -20,4 +20,27 @@ describe("literalToAst", () => {
2020
}]"
2121
`);
2222
});
23+
24+
it("built-in objects", () => {
25+
expect(run(new Set(["foo", 1]))).toMatchInlineSnapshot(
26+
'"new Set([\\"foo\\", 1])"'
27+
);
28+
29+
expect(run(new Date("2010-01-01"))).toMatchInlineSnapshot(
30+
'"new Date(\\"2010-01-01T00:00:00.000Z\\")"'
31+
);
32+
33+
const map = new Map();
34+
map.set(1, "foo");
35+
map.set(2, "bar");
36+
expect(run(map)).toMatchInlineSnapshot(
37+
'"new Map([[1, \\"foo\\"], [2, \\"bar\\"]])"'
38+
);
39+
});
40+
41+
it("circular reference", () => {
42+
const obj: any = {};
43+
obj.foo = obj;
44+
expect(() => run(obj)).toThrowError("Can not serialize circular reference");
45+
});
2346
});

0 commit comments

Comments
 (0)