diff --git a/package.json b/package.json index b82b55a..a2756cf 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ ], "types": "./types/index.d.ts", "devDependencies": { + "@js-temporal/polyfill": "^0.5.1", "dts-buddy": "^0.0.4", "publint": "^0.1.7", "typescript": "^3.1.3", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 07e4699..e2212ec 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1,6 +1,9 @@ lockfileVersion: '6.0' devDependencies: + '@js-temporal/polyfill': + specifier: ^0.5.1 + version: 0.5.1 dts-buddy: specifier: ^0.0.4 version: 0.0.4 @@ -57,6 +60,13 @@ packages: '@jridgewell/sourcemap-codec': 1.4.14 dev: true + /@js-temporal/polyfill@0.5.1: + resolution: {integrity: sha512-hloP58zRVCRSpgDxmqCWJNlizAlUgJFqG2ypq79DCvyv9tHjRYMDOcPFjzfl/A1/YxDvRCZz8wvZvmapQnKwFQ==} + engines: {node: '>=12'} + dependencies: + jsbi: 4.3.2 + dev: true + /balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} dev: true @@ -133,6 +143,10 @@ packages: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} dev: true + /jsbi@4.3.2: + resolution: {integrity: sha512-9fqMSQbhJykSeii05nxKl4m6Eqn2P6rOlYiS+C5Dr/HPIU/7yZxu5qzbs40tgaFORiw2Amd0mirjxatXYMkIew==} + dev: true + /kleur@4.1.5: resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} engines: {node: '>=6'} diff --git a/src/parse.js b/src/parse.js index f0fe2c1..fe1fd09 100644 --- a/src/parse.js +++ b/src/parse.js @@ -128,6 +128,20 @@ export function unflatten(parsed, revivers) { break; } + case 'Temporal.Duration': + case 'Temporal.Instant': + case 'Temporal.PlainDate': + case 'Temporal.PlainTime': + case 'Temporal.PlainDateTime': + case 'Temporal.PlainMonthDay': + case 'Temporal.PlainYearMonth': + case 'Temporal.ZonedDateTime': { + const temporalName = type.slice(9); + // @ts-expect-error TS doesn't know about Temporal yet + hydrated[index] = Temporal[temporalName].from(value[1]); + break; + } + default: throw new Error(`Unknown type ${type}`); } diff --git a/src/stringify.js b/src/stringify.js index df291fd..ce040c0 100644 --- a/src/stringify.js +++ b/src/stringify.js @@ -166,7 +166,18 @@ export function stringify(value, reducers) { str = `["ArrayBuffer","${base64}"]`; break; } - + + case 'Temporal.Duration': + case 'Temporal.Instant': + case 'Temporal.PlainDate': + case 'Temporal.PlainTime': + case 'Temporal.PlainDateTime': + case 'Temporal.PlainMonthDay': + case 'Temporal.PlainYearMonth': + case 'Temporal.ZonedDateTime': + str = `["${type}",${stringify_string(thing.toString())}]`; + break; + default: if (!is_plain_object(thing)) { throw new DevalueError( diff --git a/src/uneval.js b/src/uneval.js index ce3ef34..131f46a 100644 --- a/src/uneval.js +++ b/src/uneval.js @@ -99,6 +99,16 @@ export function uneval(value, replacer) { case "ArrayBuffer": return; + case 'Temporal.Duration': + case 'Temporal.Instant': + case 'Temporal.PlainDate': + case 'Temporal.PlainTime': + case 'Temporal.PlainDateTime': + case 'Temporal.PlainMonthDay': + case 'Temporal.PlainYearMonth': + case 'Temporal.ZonedDateTime': + return; + default: if (!is_plain_object(thing)) { throw new DevalueError( @@ -199,6 +209,16 @@ export function uneval(value, replacer) { return `new Uint8Array([${ui8.toString()}]).buffer`; } + case 'Temporal.Duration': + case 'Temporal.Instant': + case 'Temporal.PlainDate': + case 'Temporal.PlainTime': + case 'Temporal.PlainDateTime': + case 'Temporal.PlainMonthDay': + case 'Temporal.PlainYearMonth': + case 'Temporal.ZonedDateTime': + return `${type}.from(${stringify_string(thing.toString())})`; + default: const obj = `{${Object.keys(thing) .map((key) => `${safe_key(key)}:${stringify(thing[key])}`) diff --git a/test/test.js b/test/test.js index ebd4147..f1a5f2a 100644 --- a/test/test.js +++ b/test/test.js @@ -3,6 +3,11 @@ import * as assert from 'uvu/assert'; import * as uvu from 'uvu'; import { uneval, unflatten, parse, stringify } from '../index.js'; +import { Temporal } from '@js-temporal/polyfill' +if (!globalThis.Temporal) { + globalThis.Temporal = Temporal; +} + class Custom { constructor(value) { this.value = value; @@ -171,6 +176,61 @@ const fixtures = { value: new Uint8Array([1, 2, 3]).buffer, js: 'new Uint8Array([1,2,3]).buffer', json: '[["ArrayBuffer","AQID"]]' + }, + { + name: 'Temporal.Duration', + value: Temporal.Duration.from({ years: 1, months: 2, days: 3 }), + js: 'Temporal.Duration.from("P1Y2M3D")', + json: '[["Temporal.Duration","P1Y2M3D"]]' + }, + { + name: 'Temporal.Instant', + value: Temporal.Instant.from("1999-09-29T05:30:00Z"), + js: 'Temporal.Instant.from("1999-09-29T05:30:00Z")', + json: '[["Temporal.Instant","1999-09-29T05:30:00Z"]]' + }, + { + name: 'Temporal.PlainDate', + value: Temporal.PlainDate.from({ year: 1999, month: 9, day: 29 }), + js: 'Temporal.PlainDate.from("1999-09-29")', + json: '[["Temporal.PlainDate","1999-09-29"]]' + }, + { + name: 'Temporal.PlainTime', + value: Temporal.PlainTime.from({ hour: 12, minute: 34, second: 56 }), + js: 'Temporal.PlainTime.from("12:34:56")', + json: '[["Temporal.PlainTime","12:34:56"]]' + }, + { + name: 'Temporal.PlainDateTime', + value: Temporal.PlainDateTime.from({ + year: 1999, month: 9, day: 29, + hour: 12, minute: 34, second: 56 + }), + js: 'Temporal.PlainDateTime.from("1999-09-29T12:34:56")', + json: '[["Temporal.PlainDateTime","1999-09-29T12:34:56"]]' + }, + { + name: 'Temporal.PlainMonthDay', + value: Temporal.PlainMonthDay.from({ month: 9, day: 29 }), + js: 'Temporal.PlainMonthDay.from("09-29")', + json: '[["Temporal.PlainMonthDay","09-29"]]' + }, + { + name: 'Temporal.PlainYearMonth', + value: Temporal.PlainYearMonth.from({ year: 1999, month: 9 }), + js: 'Temporal.PlainYearMonth.from("1999-09")', + json: '[["Temporal.PlainYearMonth","1999-09"]]' + }, + { + name: 'Temporal.ZonedDateTime', + value: Temporal.ZonedDateTime.from({ + year: 1999, month: 9, day: 29, + hour: 12, minute: 34, second: 56, + timeZone: 'Europe/Rome' + }), + js: 'Temporal.ZonedDateTime.from("1999-09-29T12:34:56+02:00[Europe/Rome]")', + json: '[["Temporal.ZonedDateTime","1999-09-29T12:34:56+02:00[Europe/Rome]"]]' } ],