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,353 +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- // For some reason typeof null is "object", so special case here.
223- if ( value === null ) {
224- return ctx . stylize ( 'null' , 'null' ) ;
225- }
226- }
227-
228- function formatError ( value ) {
229- return '[' + Error . prototype . toString . call ( value ) + ']' ;
230- }
231-
232- function formatArray ( ctx , value , recurseTimes , visibleKeys , keys ) {
233- var output = [ ] ;
234- for ( var i = 0 , l = value . length ; i < l ; ++ i ) {
235- if ( Object . prototype . hasOwnProperty . call ( value , String ( i ) ) ) {
236- output . push ( formatProperty ( ctx , value , recurseTimes , visibleKeys ,
237- String ( i ) , true ) ) ;
238- } else {
239- output . push ( '' ) ;
240- }
241- }
242-
243- keys . forEach ( function ( key ) {
244- if ( ! key . match ( / ^ \d + $ / ) ) {
245- output . push ( formatProperty ( ctx , value , recurseTimes , visibleKeys ,
246- key , true ) ) ;
247- }
248- } ) ;
249- return output ;
250- }
251-
252- function formatTypedArray ( value ) {
253- var str = '[ ' ;
254-
255- for ( var i = 0 ; i < value . length ; ++ i ) {
256- if ( str . length >= config . truncateThreshold - 7 ) {
257- str += '...' ;
258- break ;
259- }
260- str += value [ i ] + ', ' ;
261- }
262- str += ' ]' ;
263-
264- // Removing trailing `, ` if the array was not truncated
265- if ( str . indexOf ( ', ]' ) !== - 1 ) {
266- str = str . replace ( ', ]' , ' ]' ) ;
267- }
268-
269- return str ;
270- }
271-
272- function formatProperty ( ctx , value , recurseTimes , visibleKeys , key , array ) {
273- var name ;
274- var propDescriptor = Object . getOwnPropertyDescriptor ( value , key ) ;
275- var str ;
276-
277- if ( propDescriptor ) {
278- if ( propDescriptor . get ) {
279- if ( propDescriptor . set ) {
280- str = ctx . stylize ( '[Getter/Setter]' , 'special' ) ;
281- } else {
282- str = ctx . stylize ( '[Getter]' , 'special' ) ;
283- }
284- } else {
285- if ( propDescriptor . set ) {
286- str = ctx . stylize ( '[Setter]' , 'special' ) ;
287- }
288- }
289- }
290- if ( visibleKeys . indexOf ( key ) < 0 ) {
291- name = '[' + key + ']' ;
292- }
293- if ( ! str ) {
294- if ( ctx . seen . indexOf ( value [ key ] ) < 0 ) {
295- if ( recurseTimes === null ) {
296- str = formatValue ( ctx , value [ key ] , null ) ;
297- } else {
298- str = formatValue ( ctx , value [ key ] , recurseTimes - 1 ) ;
299- }
300- if ( str . indexOf ( '\n' ) > - 1 ) {
301- if ( array ) {
302- str = str . split ( '\n' ) . map ( function ( line ) {
303- return ' ' + line ;
304- } ) . join ( '\n' ) . substr ( 2 ) ;
305- } else {
306- str = '\n' + str . split ( '\n' ) . map ( function ( line ) {
307- return ' ' + line ;
308- } ) . join ( '\n' ) ;
309- }
310- }
311- } else {
312- str = ctx . stylize ( '[Circular]' , 'special' ) ;
313- }
314- }
315- if ( typeof name === 'undefined' ) {
316- if ( array && key . match ( / ^ \d + $ / ) ) {
317- return str ;
318- }
319- name = JSON . stringify ( '' + key ) ;
320- if ( name . match ( / ^ " ( [ a - z A - Z _ ] [ a - z A - Z _ 0 - 9 ] * ) " $ / ) ) {
321- name = name . substr ( 1 , name . length - 2 ) ;
322- name = ctx . stylize ( name , 'name' ) ;
323- } else {
324- name = name . replace ( / ' / g, "\\'" )
325- . replace ( / \\ " / g, '"' )
326- . replace ( / ( ^ " | " $ ) / g, "'" ) ;
327- name = ctx . stylize ( name , 'string' ) ;
328- }
329- }
330-
331- return name + ': ' + str ;
332- }
333-
334- function reduceToSingleString ( output , base , braces ) {
335- var length = output . reduce ( function ( prev , cur ) {
336- return prev + cur . length + 1 ;
337- } , 0 ) ;
338-
339- if ( length > 60 ) {
340- return braces [ 0 ] +
341- ( base === '' ? '' : base + '\n ' ) +
342- ' ' +
343- output . join ( ',\n ' ) +
344- ' ' +
345- braces [ 1 ] ;
346- }
347-
348- return braces [ 0 ] + base + ' ' + output . join ( ', ' ) + ' ' + braces [ 1 ] ;
349- }
350-
351- function isTypedArray ( ar ) {
352- // Unfortunately there's no way to check if an object is a TypedArray
353- // We have to check if it's one of these types
354- return ( typeof ar === 'object' && / \w + A r r a y ] $ / . test ( objectToString ( ar ) ) ) ;
355- }
356-
357- function isArray ( ar ) {
358- return Array . isArray ( ar ) ||
359- ( typeof ar === 'object' && objectToString ( ar ) === '[object Array]' ) ;
360- }
361-
362- function isRegExp ( re ) {
363- return typeof re === 'object' && objectToString ( re ) === '[object RegExp]' ;
364- }
365-
366- function isDate ( d ) {
367- return typeof d === 'object' && objectToString ( d ) === '[object Date]' ;
368- }
369-
370- function isError ( e ) {
371- return typeof e === 'object' && objectToString ( e ) === '[object Error]' ;
372- }
373-
374- function objectToString ( o ) {
375- return Object . prototype . toString . call ( o ) ;
32+ return loupe . inspect ( obj , options ) ;
37633}
0 commit comments