22// https://github.com/joyent/node/blob/f8c335d0caf47f16d31413f89aa28eda3878e3aa/lib/util.js
33
44var getName = require ( 'get-func-name' ) ;
5- var getProperties = require ( './getProperties' ) ;
6- var getEnumerableProperties = require ( './getEnumerableProperties' ) ;
5+ var loupe = require ( 'loupe' ) ;
76var config = require ( '../config' ) ;
87
98module . exports = inspect ;
@@ -24,356 +23,11 @@ module.exports = inspect;
2423 * @name inspect
2524 */
2625function inspect ( obj , showHidden , depth , colors ) {
27- var ctx = {
26+ var options = {
27+ colors : colors ,
28+ depth : ( typeof depth === 'undefined' ? 2 : depth ) ,
2829 showHidden : showHidden ,
29- seen : [ ] ,
30- stylize : function ( str ) { return str ; }
30+ truncate : config . truncateThreshold ? config . truncateThreshold : Infinity ,
3131 } ;
32- return formatValue ( ctx , obj , ( typeof depth === 'undefined' ? 2 : depth ) ) ;
33- }
34-
35- // Returns true if object is a DOM element.
36- var isDOMElement = function ( object ) {
37- if ( typeof HTMLElement === 'object' ) {
38- return object instanceof HTMLElement ;
39- } else {
40- return object &&
41- typeof object === 'object' &&
42- 'nodeType' in object &&
43- object . nodeType === 1 &&
44- typeof object . nodeName === 'string' ;
45- }
46- } ;
47-
48- function formatValue ( ctx , value , recurseTimes ) {
49- // Provide a hook for user-specified inspect functions.
50- // Check that value is an object with an inspect function on it
51- if ( value && typeof value . inspect === 'function' &&
52- // Filter out the util module, it's inspect function is special
53- value . inspect !== exports . inspect &&
54- // Also filter out any prototype objects using the circular check.
55- ! ( value . constructor && value . constructor . prototype === value ) ) {
56- var ret = value . inspect ( recurseTimes , ctx ) ;
57- if ( typeof ret !== 'string' ) {
58- ret = formatValue ( ctx , ret , recurseTimes ) ;
59- }
60- return ret ;
61- }
62-
63- // Primitive types cannot have properties
64- var primitive = formatPrimitive ( ctx , value ) ;
65- if ( primitive ) {
66- return primitive ;
67- }
68-
69- // If this is a DOM element, try to get the outer HTML.
70- if ( isDOMElement ( value ) ) {
71- if ( 'outerHTML' in value ) {
72- return value . outerHTML ;
73- // This value does not have an outerHTML attribute,
74- // it could still be an XML element
75- } else {
76- // Attempt to serialize it
77- try {
78- if ( document . xmlVersion ) {
79- var xmlSerializer = new XMLSerializer ( ) ;
80- return xmlSerializer . serializeToString ( value ) ;
81- } else {
82- // Firefox 11- do not support outerHTML
83- // It does, however, support innerHTML
84- // Use the following to render the element
85- var ns = "http://www.w3.org/1999/xhtml" ;
86- var container = document . createElementNS ( ns , '_' ) ;
87-
88- container . appendChild ( value . cloneNode ( false ) ) ;
89- var html = container . innerHTML
90- . replace ( '><' , '>' + value . innerHTML + '<' ) ;
91- container . innerHTML = '' ;
92- return html ;
93- }
94- } catch ( err ) {
95- // This could be a non-native DOM implementation,
96- // continue with the normal flow:
97- // printing the element as if it is an object.
98- }
99- }
100- }
101-
102- // Look up the keys of the object.
103- var visibleKeys = getEnumerableProperties ( value ) ;
104- var keys = ctx . showHidden ? getProperties ( value ) : visibleKeys ;
105-
106- var name , nameSuffix ;
107-
108- // Some type of object without properties can be shortcut.
109- // In IE, errors have a single `stack` property, or if they are vanilla `Error`,
110- // a `stack` plus `description` property; ignore those for consistency.
111- if ( keys . length === 0 || ( isError ( value ) && (
112- ( keys . length === 1 && keys [ 0 ] === 'stack' ) ||
113- ( keys . length === 2 && keys [ 0 ] === 'description' && keys [ 1 ] === 'stack' )
114- ) ) ) {
115- if ( typeof value === 'function' ) {
116- name = getName ( value ) ;
117- nameSuffix = name ? ': ' + name : '' ;
118- return ctx . stylize ( '[Function' + nameSuffix + ']' , 'special' ) ;
119- }
120- if ( isRegExp ( value ) ) {
121- return ctx . stylize ( RegExp . prototype . toString . call ( value ) , 'regexp' ) ;
122- }
123- if ( isDate ( value ) ) {
124- return ctx . stylize ( Date . prototype . toUTCString . call ( value ) , 'date' ) ;
125- }
126- if ( isError ( value ) ) {
127- return formatError ( value ) ;
128- }
129- }
130-
131- var base = ''
132- , array = false
133- , typedArray = false
134- , braces = [ '{' , '}' ] ;
135-
136- if ( isTypedArray ( value ) ) {
137- typedArray = true ;
138- braces = [ '[' , ']' ] ;
139- }
140-
141- // Make Array say that they are Array
142- if ( isArray ( value ) ) {
143- array = true ;
144- braces = [ '[' , ']' ] ;
145- }
146-
147- // Make functions say that they are functions
148- if ( typeof value === 'function' ) {
149- name = getName ( value ) ;
150- nameSuffix = name ? ': ' + name : '' ;
151- base = ' [Function' + nameSuffix + ']' ;
152- }
153-
154- // Make RegExps say that they are RegExps
155- if ( isRegExp ( value ) ) {
156- base = ' ' + RegExp . prototype . toString . call ( value ) ;
157- }
158-
159- // Make dates with properties first say the date
160- if ( isDate ( value ) ) {
161- base = ' ' + Date . prototype . toUTCString . call ( value ) ;
162- }
163-
164- // Make error with message first say the error
165- if ( isError ( value ) ) {
166- return formatError ( value ) ;
167- }
168-
169- if ( keys . length === 0 && ( ! array || value . length == 0 ) ) {
170- return braces [ 0 ] + base + braces [ 1 ] ;
171- }
172-
173- if ( recurseTimes < 0 ) {
174- if ( isRegExp ( value ) ) {
175- return ctx . stylize ( RegExp . prototype . toString . call ( value ) , 'regexp' ) ;
176- } else {
177- return ctx . stylize ( '[Object]' , 'special' ) ;
178- }
179- }
180-
181- ctx . seen . push ( value ) ;
182-
183- var output ;
184- if ( array ) {
185- output = formatArray ( ctx , value , recurseTimes , visibleKeys , keys ) ;
186- } else if ( typedArray ) {
187- return formatTypedArray ( value ) ;
188- } else {
189- output = keys . map ( function ( key ) {
190- return formatProperty ( ctx , value , recurseTimes , visibleKeys , key , array ) ;
191- } ) ;
192- }
193-
194- ctx . seen . pop ( ) ;
195-
196- return reduceToSingleString ( output , base , braces ) ;
197- }
198-
199- function formatPrimitive ( ctx , value ) {
200- switch ( typeof value ) {
201- case 'undefined' :
202- return ctx . stylize ( 'undefined' , 'undefined' ) ;
203-
204- case 'string' :
205- var simple = '\'' + JSON . stringify ( value ) . replace ( / ^ " | " $ / g, '' )
206- . replace ( / ' / g, "\\'" )
207- . replace ( / \\ " / g, '"' ) + '\'' ;
208- return ctx . stylize ( simple , 'string' ) ;
209-
210- case 'number' :
211- if ( value === 0 && ( 1 / value ) === - Infinity ) {
212- return ctx . stylize ( '-0' , 'number' ) ;
213- }
214- return ctx . stylize ( '' + value , 'number' ) ;
215-
216- case 'boolean' :
217- return ctx . stylize ( '' + value , 'boolean' ) ;
218-
219- case 'symbol' :
220- return ctx . stylize ( value . toString ( ) , 'symbol' ) ;
221-
222- case 'bigint' :
223- return ctx . stylize ( value . toString ( ) + 'n' , 'bigint' ) ;
224- }
225- // For some reason typeof null is "object", so special case here.
226- if ( value === null ) {
227- return ctx . stylize ( 'null' , 'null' ) ;
228- }
229- }
230-
231- function formatError ( value ) {
232- return '[' + Error . prototype . toString . call ( value ) + ']' ;
233- }
234-
235- function formatArray ( ctx , value , recurseTimes , visibleKeys , keys ) {
236- var output = [ ] ;
237- for ( var i = 0 , l = value . length ; i < l ; ++ i ) {
238- if ( Object . prototype . hasOwnProperty . call ( value , String ( i ) ) ) {
239- output . push ( formatProperty ( ctx , value , recurseTimes , visibleKeys ,
240- String ( i ) , true ) ) ;
241- } else {
242- output . push ( '' ) ;
243- }
244- }
245-
246- keys . forEach ( function ( key ) {
247- if ( ! key . match ( / ^ \d + $ / ) ) {
248- output . push ( formatProperty ( ctx , value , recurseTimes , visibleKeys ,
249- key , true ) ) ;
250- }
251- } ) ;
252- return output ;
253- }
254-
255- function formatTypedArray ( value ) {
256- var str = '[ ' ;
257-
258- for ( var i = 0 ; i < value . length ; ++ i ) {
259- if ( str . length >= config . truncateThreshold - 7 ) {
260- str += '...' ;
261- break ;
262- }
263- str += value [ i ] + ', ' ;
264- }
265- str += ' ]' ;
266-
267- // Removing trailing `, ` if the array was not truncated
268- if ( str . indexOf ( ', ]' ) !== - 1 ) {
269- str = str . replace ( ', ]' , ' ]' ) ;
270- }
271-
272- return str ;
273- }
274-
275- function formatProperty ( ctx , value , recurseTimes , visibleKeys , key , array ) {
276- var name ;
277- var propDescriptor = Object . getOwnPropertyDescriptor ( value , key ) ;
278- var str ;
279-
280- if ( propDescriptor ) {
281- if ( propDescriptor . get ) {
282- if ( propDescriptor . set ) {
283- str = ctx . stylize ( '[Getter/Setter]' , 'special' ) ;
284- } else {
285- str = ctx . stylize ( '[Getter]' , 'special' ) ;
286- }
287- } else {
288- if ( propDescriptor . set ) {
289- str = ctx . stylize ( '[Setter]' , 'special' ) ;
290- }
291- }
292- }
293- if ( visibleKeys . indexOf ( key ) < 0 ) {
294- name = '[' + key + ']' ;
295- }
296- if ( ! str ) {
297- if ( ctx . seen . indexOf ( value [ key ] ) < 0 ) {
298- if ( recurseTimes === null ) {
299- str = formatValue ( ctx , value [ key ] , null ) ;
300- } else {
301- str = formatValue ( ctx , value [ key ] , recurseTimes - 1 ) ;
302- }
303- if ( str . indexOf ( '\n' ) > - 1 ) {
304- if ( array ) {
305- str = str . split ( '\n' ) . map ( function ( line ) {
306- return ' ' + line ;
307- } ) . join ( '\n' ) . substr ( 2 ) ;
308- } else {
309- str = '\n' + str . split ( '\n' ) . map ( function ( line ) {
310- return ' ' + line ;
311- } ) . join ( '\n' ) ;
312- }
313- }
314- } else {
315- str = ctx . stylize ( '[Circular]' , 'special' ) ;
316- }
317- }
318- if ( typeof name === 'undefined' ) {
319- if ( array && key . match ( / ^ \d + $ / ) ) {
320- return str ;
321- }
322- name = JSON . stringify ( '' + key ) ;
323- if ( name . match ( / ^ " ( [ a - z A - Z _ ] [ a - z A - Z _ 0 - 9 ] * ) " $ / ) ) {
324- name = name . substr ( 1 , name . length - 2 ) ;
325- name = ctx . stylize ( name , 'name' ) ;
326- } else {
327- name = name . replace ( / ' / g, "\\'" )
328- . replace ( / \\ " / g, '"' )
329- . replace ( / ( ^ " | " $ ) / g, "'" ) ;
330- name = ctx . stylize ( name , 'string' ) ;
331- }
332- }
333-
334- return name + ': ' + str ;
335- }
336-
337- function reduceToSingleString ( output , base , braces ) {
338- var length = output . reduce ( function ( prev , cur ) {
339- return prev + cur . length + 1 ;
340- } , 0 ) ;
341-
342- if ( length > 60 ) {
343- return braces [ 0 ] +
344- ( base === '' ? '' : base + '\n ' ) +
345- ' ' +
346- output . join ( ',\n ' ) +
347- ' ' +
348- braces [ 1 ] ;
349- }
350-
351- return braces [ 0 ] + base + ' ' + output . join ( ', ' ) + ' ' + braces [ 1 ] ;
352- }
353-
354- function isTypedArray ( ar ) {
355- // Unfortunately there's no way to check if an object is a TypedArray
356- // We have to check if it's one of these types
357- return ( typeof ar === 'object' && / \w + A r r a y ] $ / . test ( objectToString ( ar ) ) ) ;
358- }
359-
360- function isArray ( ar ) {
361- return Array . isArray ( ar ) ||
362- ( typeof ar === 'object' && objectToString ( ar ) === '[object Array]' ) ;
363- }
364-
365- function isRegExp ( re ) {
366- return typeof re === 'object' && objectToString ( re ) === '[object RegExp]' ;
367- }
368-
369- function isDate ( d ) {
370- return typeof d === 'object' && objectToString ( d ) === '[object Date]' ;
371- }
372-
373- function isError ( e ) {
374- return typeof e === 'object' && objectToString ( e ) === '[object Error]' ;
375- }
376-
377- function objectToString ( o ) {
378- return Object . prototype . toString . call ( o ) ;
32+ return loupe . inspect ( obj , options ) ;
37933}
0 commit comments