Skip to content

Commit 0015710

Browse files
bartlomiejunnmrtsclaude
authored
feat: allow passing Temporal objects to islands (#3701)
## Summary - Add serialization/deserialization for all 8 Temporal types in the jsonify module (used for island props): Instant, ZonedDateTime, PlainDate, PlainTime, PlainDateTime, PlainYearMonth, PlainMonthDay, Duration - Stringify side guards with `typeof Temporal !== "undefined"` to avoid ReferenceError when Temporal is unavailable - Uses `.toString()` for serialization and `Type.from()` for deserialization Co-authored-by: Nano Miratus <nanomiratus@gmail.com> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent b790c80 commit 0015710

4 files changed

Lines changed: 84 additions & 0 deletions

File tree

packages/fresh/src/jsonify/__snapshots__/round_trip_test.ts.snap

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,22 @@ snapshot[`round trip - [ 1, <1 empty item>, 3 ] 1`] = `"[[1,-7,2],1,3]"`;
5454

5555
snapshot[`round trip - /foo["]/ 1`] = `'[["RegExp","foo[\\\\"]", ""]]'`;
5656

57+
snapshot[`round trip - 2020-01-01T12:34:56.789101112Z 1`] = `'[["Temporal.Instant","2020-01-01T12:34:56.789101112Z"]]'`;
58+
59+
snapshot[`round trip - 2020-01-01T12:34:56.789101112+00:00[UTC] 1`] = `'[["Temporal.ZonedDateTime","2020-01-01T12:34:56.789101112+00:00[UTC]"]]'`;
60+
61+
snapshot[`round trip - 2020-01-01 1`] = `'[["Temporal.PlainDate","2020-01-01"]]'`;
62+
63+
snapshot[`round trip - 12:34:56.789101112 1`] = `'[["Temporal.PlainTime","12:34:56.789101112"]]'`;
64+
65+
snapshot[`round trip - 2020-01-01T12:34:56.789101112 1`] = `'[["Temporal.PlainDateTime","2020-01-01T12:34:56.789101112"]]'`;
66+
67+
snapshot[`round trip - 2020-01 1`] = `'[["Temporal.PlainYearMonth","2020-01"]]'`;
68+
69+
snapshot[`round trip - 01-01 1`] = `'[["Temporal.PlainMonthDay","01-01"]]'`;
70+
71+
snapshot[`round trip - P1Y2M3W4DT5H6M7.00800901S 1`] = `'[["Temporal.Duration","P1Y2M3W4DT5H6M7.00800901S"]]'`;
72+
5773
snapshot[`round trip - { a: { foo: 123 }, b: [ { foo: 123 }, { foo: 123 } ] } 1`] = `'[{"a":1,"b":3},{"foo":2},123,[1,1]]'`;
5874

5975
snapshot[`round trip - <ref *1> { a: 1, b: [Circular *1] } 1`] = `'[{"a":1,"b":0},1]'`;

packages/fresh/src/jsonify/parse.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,22 @@ function unpack(
9393
}
9494
case "Uint8Array":
9595
return hydrated[idx] = b64decode(current[1]);
96+
case "Temporal.Instant":
97+
return hydrated[idx] = Temporal.Instant.from(current[1]);
98+
case "Temporal.ZonedDateTime":
99+
return hydrated[idx] = Temporal.ZonedDateTime.from(current[1]);
100+
case "Temporal.PlainDate":
101+
return hydrated[idx] = Temporal.PlainDate.from(current[1]);
102+
case "Temporal.PlainTime":
103+
return hydrated[idx] = Temporal.PlainTime.from(current[1]);
104+
case "Temporal.PlainDateTime":
105+
return hydrated[idx] = Temporal.PlainDateTime.from(current[1]);
106+
case "Temporal.PlainYearMonth":
107+
return hydrated[idx] = Temporal.PlainYearMonth.from(current[1]);
108+
case "Temporal.PlainMonthDay":
109+
return hydrated[idx] = Temporal.PlainMonthDay.from(current[1]);
110+
case "Temporal.Duration":
111+
return hydrated[idx] = Temporal.Duration.from(current[1]);
96112
}
97113
} else {
98114
const actual = new Array(current.length);

packages/fresh/src/jsonify/round_trip_test.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,14 @@ const TESTS = [
3939
new Set([1, 2, null, -2, NaN]),
4040
[1, , 3],
4141
/foo["]/,
42+
Temporal.Instant.from("2020-01-01T12:34:56.789101112Z"),
43+
Temporal.ZonedDateTime.from("2020-01-01T12:34:56.789101112Z[UTC]"),
44+
Temporal.PlainDate.from("2020-01-01"),
45+
Temporal.PlainTime.from("12:34:56.789101112"),
46+
Temporal.PlainDateTime.from("2020-01-01T12:34:56.789101112"),
47+
Temporal.PlainYearMonth.from("2020-01"),
48+
Temporal.PlainMonthDay.from("2020-01-01"),
49+
Temporal.Duration.from("P1Y2M3W4DT5H6M7.00800901S"),
4250
references,
4351
circular,
4452
];

packages/fresh/src/jsonify/stringify.ts

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,14 @@ export type Stringifiers = Record<
3131
* - `RegExp`
3232
* - `Set`
3333
* - `Map`
34+
* - `Temporal.Instant`
35+
* - `Temporal.ZonedDateTime`
36+
* - `Temporal.PlainDate`
37+
* - `Temporal.PlainTime`
38+
* - `Temporal.PlainDateTime`
39+
* - `Temporal.PlainYearMonth`
40+
* - `Temporal.PlainMonthDay`
41+
* - `Temporal.Duration`
3442
*
3543
* Circular references are supported and objects with the same reference are
3644
* serialized only once.
@@ -134,6 +142,42 @@ function serializeInner(
134142
items[i++] = serializeInner(out, indexes, v, custom);
135143
});
136144
str += `["Map",[${items.join(",")}]]`;
145+
} else if (
146+
typeof Temporal !== "undefined" && value instanceof Temporal.Instant
147+
) {
148+
str += `["Temporal.Instant","${value.toString()}"]`;
149+
} else if (
150+
typeof Temporal !== "undefined" &&
151+
value instanceof Temporal.ZonedDateTime
152+
) {
153+
str += `["Temporal.ZonedDateTime","${value.toString()}"]`;
154+
} else if (
155+
typeof Temporal !== "undefined" && value instanceof Temporal.PlainDate
156+
) {
157+
str += `["Temporal.PlainDate","${value.toString()}"]`;
158+
} else if (
159+
typeof Temporal !== "undefined" && value instanceof Temporal.PlainTime
160+
) {
161+
str += `["Temporal.PlainTime","${value.toString()}"]`;
162+
} else if (
163+
typeof Temporal !== "undefined" &&
164+
value instanceof Temporal.PlainDateTime
165+
) {
166+
str += `["Temporal.PlainDateTime","${value.toString()}"]`;
167+
} else if (
168+
typeof Temporal !== "undefined" &&
169+
value instanceof Temporal.PlainYearMonth
170+
) {
171+
str += `["Temporal.PlainYearMonth","${value.toString()}"]`;
172+
} else if (
173+
typeof Temporal !== "undefined" &&
174+
value instanceof Temporal.PlainMonthDay
175+
) {
176+
str += `["Temporal.PlainMonthDay","${value.toString()}"]`;
177+
} else if (
178+
typeof Temporal !== "undefined" && value instanceof Temporal.Duration
179+
) {
180+
str += `["Temporal.Duration","${value.toString()}"]`;
137181
} else {
138182
str += "{";
139183
const keys = Object.keys(value);

0 commit comments

Comments
 (0)