1
- import { consoleText } from "../../core/consoleText" ;
1
+ import { type ConsoleText , consoleText } from "../../core/consoleText" ;
2
2
import inspectAny from "./inspectAny" ;
3
3
import consoleStyles from "../utils/consoleStyles" ;
4
4
import {
5
5
ConsoleInspectContext ,
6
6
ConsoleInspectOptions ,
7
7
} from "../consoleInspect" ;
8
- import { consoleObject } from "../../core/consoleObject" ;
8
+ import { type ConsoleObject , consoleObject } from "../../core/consoleObject" ;
9
9
import spansLength from "../../utils/spansLength" ;
10
10
import indent from "../../utils/indent" ;
11
11
import isPrimitive from "../../utils/isPrimitive" ;
@@ -35,9 +35,13 @@ export function inspectIterable(
35
35
36
36
// wrap is "auto", try to fit on one line
37
37
const inspection = inspectIterableSingleLine ( iterable , options , context ) ;
38
+ const array = iterableArray ( iterable ) ;
38
39
if (
39
- iterableArray ( iterable ) . every ( isPrimitive ) &&
40
- spansLength ( inspection . spans ) <= context . wrap
40
+ spansLength ( inspection . spans ) <= context . wrap &&
41
+ array . every ( isPrimitive ) &&
42
+ iterableExtraKeys ( iterable ) . every ( ( key ) =>
43
+ isPrimitive ( array [ key as keyof typeof array ] ) ,
44
+ )
41
45
) {
42
46
return inspection ;
43
47
}
@@ -52,6 +56,7 @@ export function inspectIterableSingleLine(
52
56
) : ConsoleInspection {
53
57
const type = iterableType ( iterable ) ;
54
58
const array = iterableArray ( iterable ) ;
59
+ const extraKeys = iterableExtraKeys ( iterable ) ;
55
60
return {
56
61
type : "inline" ,
57
62
spans : [
@@ -68,6 +73,20 @@ export function inspectIterableSingleLine(
68
73
? inspection . spans
69
74
: [ consoleText ( ", " ) , ...inspection . spans ] ;
70
75
} ) ,
76
+ ...extraKeys . flatMap ( ( key , i ) => {
77
+ const value = array [ key as keyof typeof array ] ;
78
+ const spans = [
79
+ consoleText ( key , consoleStyles [ options . theme ] . dimmed ) ,
80
+ consoleText ( ": " ) ,
81
+ ...inspectAny ( value , options , {
82
+ ...context ,
83
+ depth : context . depth + 1 ,
84
+ } ) . spans ,
85
+ ] ;
86
+ return i === 0 && array . length === 0
87
+ ? spans
88
+ : [ consoleText ( ", " ) , ...spans ] ;
89
+ } ) ,
71
90
consoleText ( type === undefined ? "]" : "}" ) ,
72
91
consoleText (
73
92
` ${ type ?? "" } (${ array . length } )` ,
@@ -85,33 +104,67 @@ export function inspectIterableMultiLine(
85
104
const array = iterableArray ( iterable ) ;
86
105
return {
87
106
type : "block" ,
88
- spans : array . flatMap ( ( value , i ) => {
89
- const indexText = `[${ i } ]: ` ;
90
- const inspection =
91
- iterableType ( iterable ) === "Map"
92
- ? inspectEntry ( value , options , context )
93
- : inspectAny ( value , options , {
94
- keys : context . keys ,
95
- depth : context . depth + 1 ,
96
- wrap : Math . max (
97
- context . wrap -
98
- Math . max ( indexText . length , options . indent ) ,
99
- 0 ,
100
- ) ,
101
- } ) ;
102
- const valueSpans =
103
- inspection . type === "block"
104
- ? [
105
- consoleText ( "\n" ) ,
106
- ...indent ( inspection . spans , options . indent ) ,
107
- ]
108
- : inspection . spans ;
109
- return [
110
- ...( i === 0 ? [ ] : [ consoleText ( "\n" ) ] ) ,
111
- consoleText ( indexText , consoleStyles [ options . theme ] . highlight ) ,
112
- ...valueSpans ,
113
- ] ;
114
- } ) ,
107
+ spans : [
108
+ ...array . flatMap ( ( value , i ) => {
109
+ const indexText = `[${ i } ]: ` ;
110
+ const inspection =
111
+ iterableType ( iterable ) === "Map"
112
+ ? inspectEntry ( value , options , context )
113
+ : inspectAny ( value , options , {
114
+ keys : context . keys ,
115
+ depth : context . depth + 1 ,
116
+ wrap : Math . max (
117
+ context . wrap -
118
+ Math . max (
119
+ indexText . length ,
120
+ options . indent ,
121
+ ) ,
122
+ 0 ,
123
+ ) ,
124
+ } ) ;
125
+ const valueSpans =
126
+ inspection . type === "block"
127
+ ? [
128
+ consoleText ( "\n" ) ,
129
+ ...indent ( inspection . spans , options . indent ) ,
130
+ ]
131
+ : inspection . spans ;
132
+ return [
133
+ ...( i === 0 ? [ ] : [ consoleText ( "\n" ) ] ) ,
134
+ consoleText (
135
+ indexText ,
136
+ consoleStyles [ options . theme ] . highlight ,
137
+ ) ,
138
+ ...valueSpans ,
139
+ ] ;
140
+ } ) ,
141
+ ...iterableExtraKeys ( iterable ) . flatMap ( ( key , i ) => {
142
+ const spans : ( ConsoleText | ConsoleObject ) [ ] = [ ] ;
143
+ if ( i !== 0 || array . length !== 0 ) {
144
+ spans . push ( consoleText ( "\n" ) ) ;
145
+ }
146
+
147
+ spans . push ( consoleText ( key , consoleStyles [ options . theme ] . highlight ) ) ;
148
+ spans . push ( consoleText ( ": " ) ) ;
149
+
150
+ const value = array [ key as keyof typeof array ] ;
151
+ const inspection = inspectAny ( value , options , {
152
+ keys : context . keys ,
153
+ depth : context . depth + 1 ,
154
+ wrap : Math . max (
155
+ context . wrap - Math . max ( key . length + 2 , options . indent ) ,
156
+ 0 ,
157
+ ) ,
158
+ } ) ;
159
+ if ( inspection . type === "block" ) {
160
+ spans . push ( consoleText ( "\n" ) ) ;
161
+ spans . push ( ...indent ( inspection . spans , options . indent ) ) ;
162
+ } else {
163
+ spans . push ( ...inspection . spans ) ;
164
+ }
165
+ return spans
166
+ } )
167
+ ] ,
115
168
} ;
116
169
}
117
170
@@ -145,20 +198,20 @@ function inspectEntry(
145
198
} ;
146
199
}
147
200
148
- const weakMap = new WeakMap < Iterable < unknown > , unknown [ ] > ( ) ;
201
+ const iterableArrayCache = new WeakMap < Iterable < unknown > , unknown [ ] > ( ) ;
149
202
function iterableArray ( iterable : Iterable < unknown > ) : unknown [ ] {
150
203
if ( Array . isArray ( iterable ) ) {
151
204
return iterable ;
152
205
}
153
206
154
- const cached = weakMap . get ( iterable ) ;
155
- if ( cached === undefined ) {
156
- const array = [ ...iterable ] ;
157
- weakMap . set ( iterable , array ) ;
158
- return array ;
159
- } else {
207
+ const cached = iterableArrayCache . get ( iterable ) ;
208
+ if ( cached !== undefined ) {
160
209
return cached ;
161
210
}
211
+
212
+ const array = [ ...iterable ] ;
213
+ iterableArrayCache . set ( iterable , array ) ;
214
+ return array ;
162
215
}
163
216
164
217
function iterableType ( iterable : Iterable < unknown > ) : "Set" | "Map" | undefined {
@@ -168,3 +221,22 @@ function iterableType(iterable: Iterable<unknown>): "Set" | "Map" | undefined {
168
221
? "Map"
169
222
: undefined ;
170
223
}
224
+
225
+ const iterableExtraKeysCache = new WeakMap < Iterable < unknown > , string [ ] > ( ) ;
226
+ function iterableExtraKeys ( iterable : Iterable < unknown > ) : string [ ] {
227
+ const cached = iterableExtraKeysCache . get ( iterable ) ;
228
+
229
+ if ( cached !== undefined ) {
230
+ return cached ;
231
+ }
232
+
233
+ const keys : string [ ] = [ ] ;
234
+ const array = iterableArray ( iterable ) ;
235
+ for ( const key of Object . keys ( array ) ) {
236
+ const index = Number . parseInt ( key , 10 ) ;
237
+ if ( Number . isNaN ( index ) || index < 0 || index >= array . length ) {
238
+ keys . push ( key ) ;
239
+ }
240
+ }
241
+ return keys ;
242
+ }
0 commit comments