@@ -218,6 +218,47 @@ const builtInObjects = new SafeSet(
218218// https://tc39.es/ecma262/#sec-IsHTMLDDA-internal-slot
219219const isUndetectableObject = ( v ) => typeof v === 'undefined' && v !== undefined ;
220220
221+ const temporalConstructors = [
222+ { name : 'Duration' , fullName : 'Temporal.Duration' } ,
223+ { name : 'Instant' , fullName : 'Temporal.Instant' } ,
224+ { name : 'PlainDate' , fullName : 'Temporal.PlainDate' } ,
225+ { name : 'PlainDateTime' , fullName : 'Temporal.PlainDateTime' } ,
226+ { name : 'PlainMonthDay' , fullName : 'Temporal.PlainMonthDay' } ,
227+ { name : 'PlainTime' , fullName : 'Temporal.PlainTime' } ,
228+ { name : 'PlainYearMonth' , fullName : 'Temporal.PlainYearMonth' } ,
229+ { name : 'ZonedDateTime' , fullName : 'Temporal.ZonedDateTime' } ,
230+ ] ;
231+
232+ // Best-effort, using instanceof. Polyfills will likely pass these checks.
233+ // Returns void if either the type checks fail or the attempt at calling
234+ // .toString() fails, so that format() can fall back to standard object
235+ // formatting in either case.
236+ // TODO: Hopefully the V8 API will expose typechecks at some point.
237+ function getTemporalInfo ( value ) {
238+ try {
239+ const { Temporal } = globalThis ;
240+ if ( Temporal === undefined ) {
241+ return ;
242+ }
243+ for ( let i = 0 ; i < temporalConstructors . length ; i ++ ) {
244+ const entry = temporalConstructors [ i ] ;
245+ const constructor = Temporal [ entry . name ] ;
246+ if ( typeof constructor !== 'function' ) {
247+ return ;
248+ }
249+ if ( ! FunctionPrototypeSymbolHasInstance ( constructor , value ) ) {
250+ continue ;
251+ }
252+ const { prototype } = constructor ;
253+ if ( ! ObjectPrototypeHasOwnProperty ( prototype , 'toString' ) ) {
254+ return ;
255+ }
256+ const result = FunctionPrototypeCall ( prototype . toString , value ) ;
257+ return { ...entry , result } ;
258+ }
259+ } catch { /* void */ }
260+ }
261+
221262// These options must stay in sync with `getUserOptions`. So if any option will
222263// be added or removed, `getUserOptions` must also be updated accordingly.
223264const inspectDefaultOptions = ObjectSeal ( {
@@ -1321,6 +1362,7 @@ function formatRaw(ctx, value, recurseTimes, typedArray) {
13211362 if ( noIterator ) {
13221363 keys = getKeys ( value , ctx . showHidden ) ;
13231364 braces = [ '{' , '}' ] ;
1365+ let temporalInfo ;
13241366 if ( typeof value === 'function' ) {
13251367 base = getFunctionBase ( ctx , value , constructor , tag ) ;
13261368 if ( keys . length === 0 && protoProps === undefined )
@@ -1404,6 +1446,14 @@ function formatRaw(ctx, value, recurseTimes, typedArray) {
14041446 if ( keys . length === 0 && protoProps === undefined ) {
14051447 return base ;
14061448 }
1449+ } else if ( ( temporalInfo = getTemporalInfo ( value ) ) ) {
1450+ const prefix = constructor === temporalInfo . name && tag === temporalInfo . fullName ?
1451+ ( temporalInfo . fullName + ' ' ) :
1452+ getPrefix ( constructor , tag , temporalInfo . fullName ) ;
1453+ base = `${ prefix } ${ temporalInfo . result } ` ;
1454+ if ( keys . length === 0 && protoProps === undefined ) {
1455+ return ctx . stylize ( base , 'date' ) ;
1456+ }
14071457 } else {
14081458 if ( keys . length === 0 && protoProps === undefined ) {
14091459 if ( isExternal ( value ) ) {
0 commit comments