├── util.inspect.js ├── .npmrc ├── example ├── circular.js ├── fn.js ├── inspect.js └── all.js ├── .github ├── workflows │ ├── node-pretest.yml │ ├── rebase.yml │ ├── require-allow-edits.yml │ ├── node-tens.yml │ ├── node-twenties.yml │ └── node-aught.yml └── FUNDING.yml ├── .gitignore ├── .nycrc ├── test ├── holes.js ├── lowbyte.js ├── undef.js ├── deep.js ├── global.js ├── browser │ └── dom.js ├── circular.js ├── has.js ├── fakes.js ├── quoteStyle.js ├── toStringTag.js ├── err.js ├── element.js ├── bigint.js ├── fn.js ├── number.js ├── inspect.js ├── indent-option.js └── values.js ├── package-support.json ├── test-core-js.js ├── LICENSE ├── .eslintrc ├── readme.markdown ├── package.json ├── index.js └── CHANGELOG.md /util.inspect.js: -------------------------------------------------------------------------------- 1 | module.exports = require('util').inspect; 2 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | package-lock=false 2 | allow-same-version=true 3 | message=v%s 4 | -------------------------------------------------------------------------------- /example/circular.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var inspect = require('../'); 4 | var obj = { a: 1, b: [3, 4] }; 5 | obj.c = obj; 6 | console.log(inspect(obj)); 7 | -------------------------------------------------------------------------------- /example/fn.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var inspect = require('../'); 4 | var obj = [1, 2, function f(n) { return n + 5; }, 4]; 5 | console.log(inspect(obj)); 6 | -------------------------------------------------------------------------------- /.github/workflows/node-pretest.yml: -------------------------------------------------------------------------------- 1 | name: 'Tests: pretest/posttest' 2 | 3 | on: [pull_request, push] 4 | 5 | jobs: 6 | tests: 7 | uses: ljharb/actions/.github/workflows/pretest.yml@main 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # gitignore 2 | node_modules 3 | 4 | # Only apps should have lockfiles 5 | npm-shrinkwrap.json 6 | package-lock.json 7 | yarn.lock 8 | 9 | # Coverage 10 | coverage 11 | .nyc_output 12 | 13 | .npmignore 14 | -------------------------------------------------------------------------------- /.github/workflows/rebase.yml: -------------------------------------------------------------------------------- 1 | name: Automatic Rebase 2 | 3 | on: [pull_request_target] 4 | 5 | jobs: 6 | _: 7 | uses: ljharb/actions/.github/workflows/rebase.yml@main 8 | secrets: 9 | token: ${{ secrets.GITHUB_TOKEN }} 10 | -------------------------------------------------------------------------------- /.github/workflows/require-allow-edits.yml: -------------------------------------------------------------------------------- 1 | name: Require “Allow Edits” 2 | 3 | on: [pull_request_target] 4 | 5 | jobs: 6 | _: 7 | name: "Require “Allow Edits”" 8 | 9 | runs-on: ubuntu-latest 10 | 11 | steps: 12 | - uses: ljharb/require-allow-edits@main 13 | -------------------------------------------------------------------------------- /.nycrc: -------------------------------------------------------------------------------- 1 | { 2 | "all": true, 3 | "check-coverage": false, 4 | "instrumentation": false, 5 | "sourceMap": false, 6 | "reporter": ["text-summary", "text", "html", "json"], 7 | "exclude": [ 8 | "coverage", 9 | "example", 10 | "test", 11 | "test-core-js.js" 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /example/inspect.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* eslint-env browser */ 4 | var inspect = require('../'); 5 | 6 | var d = document.createElement('div'); 7 | d.setAttribute('id', 'beep'); 8 | d.innerHTML = 'woooiiiii'; 9 | 10 | console.log(inspect([d, { a: 3, b: 4, c: [5, 6, [7, [8, [9]]]] }])); 11 | -------------------------------------------------------------------------------- /test/holes.js: -------------------------------------------------------------------------------- 1 | var test = require('tape'); 2 | var inspect = require('../'); 3 | 4 | var xs = ['a', 'b']; 5 | xs[5] = 'f'; 6 | xs[7] = 'j'; 7 | xs[8] = 'k'; 8 | 9 | test('holes', function (t) { 10 | t.plan(1); 11 | t.equal( 12 | inspect(xs), 13 | "[ 'a', 'b', , , , 'f', , 'j', 'k' ]" 14 | ); 15 | }); 16 | -------------------------------------------------------------------------------- /test/lowbyte.js: -------------------------------------------------------------------------------- 1 | var test = require('tape'); 2 | var inspect = require('../'); 3 | 4 | var obj = { x: 'a\r\nb', y: '\x05! \x1f \x12' }; 5 | 6 | test('interpolate low bytes', function (t) { 7 | t.plan(1); 8 | t.equal( 9 | inspect(obj), 10 | "{ x: 'a\\r\\nb', y: '\\x05! \\x1F \\x12' }" 11 | ); 12 | }); 13 | -------------------------------------------------------------------------------- /.github/workflows/node-tens.yml: -------------------------------------------------------------------------------- 1 | name: 'Tests: node.js 10 - 20' 2 | 3 | on: [pull_request, push] 4 | 5 | permissions: 6 | contents: read 7 | 8 | jobs: 9 | tests: 10 | uses: ljharb/actions/.github/workflows/node.yml@main 11 | with: 12 | range: '>= 10 < 20' 13 | type: minors 14 | command: npm run tests-only 15 | -------------------------------------------------------------------------------- /.github/workflows/node-twenties.yml: -------------------------------------------------------------------------------- 1 | name: 'Tests: node.js >= 20' 2 | 3 | on: [pull_request, push] 4 | 5 | permissions: 6 | contents: read 7 | 8 | jobs: 9 | tests: 10 | uses: ljharb/actions/.github/workflows/node.yml@main 11 | with: 12 | range: '>= 20' 13 | type: minors 14 | command: npm run tests-only 15 | -------------------------------------------------------------------------------- /test/undef.js: -------------------------------------------------------------------------------- 1 | var test = require('tape'); 2 | var inspect = require('../'); 3 | 4 | var obj = { a: 1, b: [3, 4, undefined, null], c: undefined, d: null }; 5 | 6 | test('undef and null', function (t) { 7 | t.plan(1); 8 | t.equal( 9 | inspect(obj), 10 | '{ a: 1, b: [ 3, 4, undefined, null ], c: undefined, d: null }' 11 | ); 12 | }); 13 | -------------------------------------------------------------------------------- /.github/workflows/node-aught.yml: -------------------------------------------------------------------------------- 1 | name: 'Tests: node.js < 10' 2 | 3 | on: [pull_request, push] 4 | 5 | jobs: 6 | tests: 7 | uses: ljharb/actions/.github/workflows/node.yml@main 8 | with: 9 | range: '< 10' 10 | type: minors 11 | command: npm run tests-only 12 | 13 | node: 14 | name: 'node < 10' 15 | needs: [tests] 16 | runs-on: ubuntu-latest 17 | steps: 18 | - run: 'echo tests completed' 19 | -------------------------------------------------------------------------------- /test/deep.js: -------------------------------------------------------------------------------- 1 | var inspect = require('../'); 2 | var test = require('tape'); 3 | 4 | test('deep', function (t) { 5 | t.plan(4); 6 | var obj = [[[[[[500]]]]]]; 7 | t.equal(inspect(obj), '[ [ [ [ [ [Array] ] ] ] ] ]'); 8 | t.equal(inspect(obj, { depth: 4 }), '[ [ [ [ [Array] ] ] ] ]'); 9 | t.equal(inspect(obj, { depth: 2 }), '[ [ [Array] ] ]'); 10 | 11 | t.equal(inspect([[[{ a: 1 }]]], { depth: 3 }), '[ [ [ [Object] ] ] ]'); 12 | }); 13 | -------------------------------------------------------------------------------- /test/global.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var inspect = require('../'); 4 | 5 | var test = require('tape'); 6 | var globalThis = require('globalthis')(); 7 | 8 | test('global object', function (t) { 9 | /* eslint-env browser */ 10 | var expected = typeof window === 'undefined' ? 'globalThis' : 'Window'; 11 | t.equal( 12 | inspect([globalThis]), 13 | '[ { [object ' + expected + '] } ]' 14 | ); 15 | 16 | t.end(); 17 | }); 18 | -------------------------------------------------------------------------------- /package-support.json: -------------------------------------------------------------------------------- 1 | { 2 | "versions": [ 3 | { 4 | "version": "*", 5 | "target": { 6 | "node": "all" 7 | }, 8 | "response": { 9 | "type": "time-permitting" 10 | }, 11 | "backing": { 12 | "npm-funding": true, 13 | "donations": [ 14 | "https://github.com/ljharb", 15 | "https://tidelift.com/funding/github/npm/object-inspect" 16 | ] 17 | } 18 | } 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /test/browser/dom.js: -------------------------------------------------------------------------------- 1 | var inspect = require('../../'); 2 | var test = require('tape'); 3 | 4 | test('dom element', function (t) { 5 | t.plan(1); 6 | 7 | var d = document.createElement('div'); 8 | d.setAttribute('id', 'beep'); 9 | d.innerHTML = 'woooiiiii'; 10 | 11 | t.equal( 12 | inspect([d, { a: 3, b: 4, c: [5, 6, [7, [8, [9]]]] }]), 13 | '[
...
, { a: 3, b: 4, c: [ 5, 6, [ 7, [ 8, [Object] ] ] ] } ]' 14 | ); 15 | }); 16 | -------------------------------------------------------------------------------- /example/all.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var inspect = require('../'); 4 | var Buffer = require('safer-buffer').Buffer; 5 | 6 | var holes = ['a', 'b']; 7 | holes[4] = 'e'; 8 | holes[6] = 'g'; 9 | 10 | var obj = { 11 | a: 1, 12 | b: [3, 4, undefined, null], 13 | c: undefined, 14 | d: null, 15 | e: { 16 | regex: /^x/i, 17 | buf: Buffer.from('abc'), 18 | holes: holes 19 | }, 20 | now: new Date() 21 | }; 22 | obj.self = obj; 23 | console.log(inspect(obj)); 24 | -------------------------------------------------------------------------------- /test/circular.js: -------------------------------------------------------------------------------- 1 | var inspect = require('../'); 2 | var test = require('tape'); 3 | 4 | test('circular', function (t) { 5 | t.plan(2); 6 | var obj = { a: 1, b: [3, 4] }; 7 | obj.c = obj; 8 | t.equal(inspect(obj), '{ a: 1, b: [ 3, 4 ], c: [Circular] }'); 9 | 10 | var double = {}; 11 | double.a = [double]; 12 | double.b = {}; 13 | double.b.inner = double.b; 14 | double.b.obj = double; 15 | t.equal(inspect(double), '{ a: [ [Circular] ], b: { inner: [Circular], obj: [Circular] } }'); 16 | }); 17 | -------------------------------------------------------------------------------- /test/has.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var inspect = require('../'); 4 | var test = require('tape'); 5 | var mockProperty = require('mock-property'); 6 | 7 | test('when Object#hasOwnProperty is deleted', function (t) { 8 | t.plan(1); 9 | var arr = [1, , 3]; // eslint-disable-line no-sparse-arrays 10 | 11 | t.teardown(mockProperty(Array.prototype, 1, { value: 2 })); // this is needed to account for "in" vs "hasOwnProperty" 12 | t.teardown(mockProperty(Object.prototype, 'hasOwnProperty', { 'delete': true })); 13 | 14 | t.equal(inspect(arr), '[ 1, , 3 ]'); 15 | }); 16 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: [ljharb] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: npm/object-inspect 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 13 | -------------------------------------------------------------------------------- /test-core-js.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | require('core-js'); 4 | 5 | var inspect = require('./'); 6 | var test = require('tape'); 7 | 8 | test('Maps', function (t) { 9 | t.equal(inspect(new Map([[1, 2]])), 'Map (1) {1 => 2}'); 10 | t.end(); 11 | }); 12 | 13 | test('WeakMaps', function (t) { 14 | t.equal(inspect(new WeakMap([[{}, 2]])), 'WeakMap { ? }'); 15 | t.end(); 16 | }); 17 | 18 | test('Sets', function (t) { 19 | t.equal(inspect(new Set([[1, 2]])), 'Set (1) {[ 1, 2 ]}'); 20 | t.end(); 21 | }); 22 | 23 | test('WeakSets', function (t) { 24 | t.equal(inspect(new WeakSet([[1, 2]])), 'WeakSet { ? }'); 25 | t.end(); 26 | }); 27 | -------------------------------------------------------------------------------- /test/fakes.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var inspect = require('../'); 4 | var test = require('tape'); 5 | var hasToStringTag = require('has-tostringtag/shams')(); 6 | var forEach = require('for-each'); 7 | 8 | test('fakes', { skip: !hasToStringTag }, function (t) { 9 | forEach([ 10 | 'Array', 11 | 'Boolean', 12 | 'Date', 13 | 'Error', 14 | 'Number', 15 | 'RegExp', 16 | 'String' 17 | ], function (expected) { 18 | var faker = {}; 19 | faker[Symbol.toStringTag] = expected; 20 | 21 | t.equal( 22 | inspect(faker), 23 | '{ [Symbol(Symbol.toStringTag)]: \'' + expected + '\' }', 24 | 'faker masquerading as ' + expected + ' is not shown as one' 25 | ); 26 | }); 27 | 28 | t.end(); 29 | }); 30 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2013 James Halliday 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "root": true, 3 | "extends": "@ljharb", 4 | "rules": { 5 | "complexity": 0, 6 | "func-style": [2, "declaration"], 7 | "indent": [2, 4], 8 | "max-lines": 1, 9 | "max-lines-per-function": 1, 10 | "max-params": [2, 4], 11 | "max-statements": 0, 12 | "max-statements-per-line": [2, { "max": 2 }], 13 | "no-magic-numbers": 0, 14 | "no-param-reassign": 1, 15 | "strict": 0, // TODO 16 | }, 17 | "overrides": [ 18 | { 19 | "files": ["test/**", "test-*", "example/**"], 20 | "extends": "@ljharb/eslint-config/tests", 21 | "rules": { 22 | "id-length": 0, 23 | }, 24 | }, 25 | { 26 | "files": ["example/**"], 27 | "rules": { 28 | "no-console": 0, 29 | }, 30 | }, 31 | { 32 | "files": ["test/browser/**"], 33 | "env": { 34 | "browser": true, 35 | }, 36 | }, 37 | { 38 | "files": ["test/bigint*"], 39 | "rules": { 40 | "new-cap": [2, { "capIsNewExceptions": ["BigInt"] }], 41 | }, 42 | }, 43 | { 44 | "files": "index.js", 45 | "globals": { 46 | "HTMLElement": false, 47 | }, 48 | "rules": { 49 | "no-use-before-define": 1, 50 | }, 51 | }, 52 | ], 53 | } 54 | -------------------------------------------------------------------------------- /test/quoteStyle.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var inspect = require('../'); 4 | var test = require('tape'); 5 | 6 | test('quoteStyle option', function (t) { 7 | t['throws'](function () { inspect(null, { quoteStyle: false }); }, 'false is not a valid value'); 8 | t['throws'](function () { inspect(null, { quoteStyle: true }); }, 'true is not a valid value'); 9 | t['throws'](function () { inspect(null, { quoteStyle: '' }); }, '"" is not a valid value'); 10 | t['throws'](function () { inspect(null, { quoteStyle: {} }); }, '{} is not a valid value'); 11 | t['throws'](function () { inspect(null, { quoteStyle: [] }); }, '[] is not a valid value'); 12 | t['throws'](function () { inspect(null, { quoteStyle: 42 }); }, '42 is not a valid value'); 13 | t['throws'](function () { inspect(null, { quoteStyle: NaN }); }, 'NaN is not a valid value'); 14 | t['throws'](function () { inspect(null, { quoteStyle: function () {} }); }, 'a function is not a valid value'); 15 | 16 | t.equal(inspect('"', { quoteStyle: 'single' }), '\'"\'', 'double quote, quoteStyle: "single"'); 17 | t.equal(inspect('"', { quoteStyle: 'double' }), '"\\""', 'double quote, quoteStyle: "double"'); 18 | 19 | t.equal(inspect('\'', { quoteStyle: 'single' }), '\'\\\'\'', 'single quote, quoteStyle: "single"'); 20 | t.equal(inspect('\'', { quoteStyle: 'double' }), '"\'"', 'single quote, quoteStyle: "double"'); 21 | 22 | t.equal(inspect('`', { quoteStyle: 'single' }), '\'`\'', 'backtick, quoteStyle: "single"'); 23 | t.equal(inspect('`', { quoteStyle: 'double' }), '"`"', 'backtick, quoteStyle: "double"'); 24 | 25 | t.end(); 26 | }); 27 | -------------------------------------------------------------------------------- /test/toStringTag.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var test = require('tape'); 4 | var hasToStringTag = require('has-tostringtag/shams')(); 5 | 6 | var inspect = require('../'); 7 | 8 | test('Symbol.toStringTag', { skip: !hasToStringTag }, function (t) { 9 | t.plan(4); 10 | 11 | var obj = { a: 1 }; 12 | t.equal(inspect(obj), '{ a: 1 }', 'object, no Symbol.toStringTag'); 13 | 14 | obj[Symbol.toStringTag] = 'foo'; 15 | t.equal(inspect(obj), '{ a: 1, [Symbol(Symbol.toStringTag)]: \'foo\' }', 'object with Symbol.toStringTag'); 16 | 17 | t.test('null objects', { skip: 'toString' in { __proto__: null } }, function (st) { 18 | st.plan(2); 19 | 20 | var dict = { __proto__: null, a: 1 }; 21 | st.equal(inspect(dict), '[Object: null prototype] { a: 1 }', 'null object with Symbol.toStringTag'); 22 | 23 | dict[Symbol.toStringTag] = 'Dict'; 24 | st.equal(inspect(dict), '[Dict: null prototype] { a: 1, [Symbol(Symbol.toStringTag)]: \'Dict\' }', 'null object with Symbol.toStringTag'); 25 | }); 26 | 27 | t.test('instances', function (st) { 28 | st.plan(4); 29 | 30 | function C() { 31 | this.a = 1; 32 | } 33 | st.equal(Object.prototype.toString.call(new C()), '[object Object]', 'instance, no toStringTag, Object.prototype.toString'); 34 | st.equal(inspect(new C()), 'C { a: 1 }', 'instance, no toStringTag'); 35 | 36 | C.prototype[Symbol.toStringTag] = 'Class!'; 37 | st.equal(Object.prototype.toString.call(new C()), '[object Class!]', 'instance, with toStringTag, Object.prototype.toString'); 38 | st.equal(inspect(new C()), 'C [Class!] { a: 1 }', 'instance, with toStringTag'); 39 | }); 40 | }); 41 | -------------------------------------------------------------------------------- /test/err.js: -------------------------------------------------------------------------------- 1 | var test = require('tape'); 2 | var ErrorWithCause = require('error-cause/Error'); 3 | 4 | var inspect = require('../'); 5 | 6 | test('type error', function (t) { 7 | t.plan(1); 8 | var aerr = new TypeError(); 9 | aerr.foo = 555; 10 | aerr.bar = [1, 2, 3]; 11 | 12 | var berr = new TypeError('tuv'); 13 | berr.baz = 555; 14 | 15 | var cerr = new SyntaxError(); 16 | cerr.message = 'whoa'; 17 | cerr['a-b'] = 5; 18 | 19 | var withCause = new ErrorWithCause('foo', { cause: 'bar' }); 20 | var withCausePlus = new ErrorWithCause('foo', { cause: 'bar' }); 21 | withCausePlus.foo = 'bar'; 22 | var withUndefinedCause = new ErrorWithCause('foo', { cause: undefined }); 23 | var withEnumerableCause = new Error('foo'); 24 | withEnumerableCause.cause = 'bar'; 25 | 26 | var obj = [ 27 | new TypeError(), 28 | new TypeError('xxx'), 29 | aerr, 30 | berr, 31 | cerr, 32 | withCause, 33 | withCausePlus, 34 | withUndefinedCause, 35 | withEnumerableCause 36 | ]; 37 | t.equal(inspect(obj), '[ ' + [ 38 | '[TypeError]', 39 | '[TypeError: xxx]', 40 | '{ [TypeError] foo: 555, bar: [ 1, 2, 3 ] }', 41 | '{ [TypeError: tuv] baz: 555 }', 42 | '{ [SyntaxError: whoa] message: \'whoa\', \'a-b\': 5 }', 43 | 'cause' in Error.prototype ? '[Error: foo]' : '{ [Error: foo] [cause]: \'bar\' }', 44 | '{ [Error: foo] ' + ('cause' in Error.prototype ? '' : '[cause]: \'bar\', ') + 'foo: \'bar\' }', 45 | 'cause' in Error.prototype ? '[Error: foo]' : '{ [Error: foo] [cause]: undefined }', 46 | '{ [Error: foo] cause: \'bar\' }' 47 | ].join(', ') + ' ]'); 48 | }); 49 | -------------------------------------------------------------------------------- /test/element.js: -------------------------------------------------------------------------------- 1 | var inspect = require('../'); 2 | var test = require('tape'); 3 | 4 | test('element', function (t) { 5 | t.plan(3); 6 | var elem = { 7 | nodeName: 'div', 8 | attributes: [{ name: 'class', value: 'row' }], 9 | getAttribute: function (key) { return key; }, 10 | childNodes: [] 11 | }; 12 | var obj = [1, elem, 3]; 13 | t.deepEqual(inspect(obj), '[ 1,
, 3 ]'); 14 | t.deepEqual(inspect(obj, { quoteStyle: 'single' }), "[ 1,
, 3 ]"); 15 | t.deepEqual(inspect(obj, { quoteStyle: 'double' }), '[ 1,
, 3 ]'); 16 | }); 17 | 18 | test('element no attr', function (t) { 19 | t.plan(1); 20 | var elem = { 21 | nodeName: 'div', 22 | getAttribute: function (key) { return key; }, 23 | childNodes: [] 24 | }; 25 | var obj = [1, elem, 3]; 26 | t.deepEqual(inspect(obj), '[ 1,
, 3 ]'); 27 | }); 28 | 29 | test('element with contents', function (t) { 30 | t.plan(1); 31 | var elem = { 32 | nodeName: 'div', 33 | getAttribute: function (key) { return key; }, 34 | childNodes: [{ nodeName: 'b' }] 35 | }; 36 | var obj = [1, elem, 3]; 37 | t.deepEqual(inspect(obj), '[ 1,
...
, 3 ]'); 38 | }); 39 | 40 | test('element instance', function (t) { 41 | t.plan(1); 42 | var h = global.HTMLElement; 43 | global.HTMLElement = function (name, attr) { 44 | this.nodeName = name; 45 | this.attributes = attr; 46 | }; 47 | global.HTMLElement.prototype.getAttribute = function () {}; 48 | 49 | var elem = new global.HTMLElement('div', []); 50 | var obj = [1, elem, 3]; 51 | t.deepEqual(inspect(obj), '[ 1,
, 3 ]'); 52 | global.HTMLElement = h; 53 | }); 54 | -------------------------------------------------------------------------------- /test/bigint.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var inspect = require('../'); 4 | var test = require('tape'); 5 | var hasToStringTag = require('has-tostringtag/shams')(); 6 | 7 | test('bigint', { skip: typeof BigInt === 'undefined' }, function (t) { 8 | t.test('primitives', function (st) { 9 | st.plan(3); 10 | 11 | st.equal(inspect(BigInt(-256)), '-256n'); 12 | st.equal(inspect(BigInt(0)), '0n'); 13 | st.equal(inspect(BigInt(256)), '256n'); 14 | }); 15 | 16 | t.test('objects', function (st) { 17 | st.plan(3); 18 | 19 | st.equal(inspect(Object(BigInt(-256))), 'Object(-256n)'); 20 | st.equal(inspect(Object(BigInt(0))), 'Object(0n)'); 21 | st.equal(inspect(Object(BigInt(256))), 'Object(256n)'); 22 | }); 23 | 24 | t.test('syntactic primitives', function (st) { 25 | st.plan(3); 26 | 27 | /* eslint-disable no-new-func */ 28 | st.equal(inspect(Function('return -256n')()), '-256n'); 29 | st.equal(inspect(Function('return 0n')()), '0n'); 30 | st.equal(inspect(Function('return 256n')()), '256n'); 31 | }); 32 | 33 | t.test('toStringTag', { skip: !hasToStringTag }, function (st) { 34 | st.plan(1); 35 | 36 | var faker = {}; 37 | faker[Symbol.toStringTag] = 'BigInt'; 38 | st.equal( 39 | inspect(faker), 40 | '{ [Symbol(Symbol.toStringTag)]: \'BigInt\' }', 41 | 'object lying about being a BigInt inspects as an object' 42 | ); 43 | }); 44 | 45 | t.test('numericSeparator', function (st) { 46 | st.equal(inspect(BigInt(0), { numericSeparator: false }), '0n', '0n, numericSeparator false'); 47 | st.equal(inspect(BigInt(0), { numericSeparator: true }), '0n', '0n, numericSeparator true'); 48 | 49 | st.equal(inspect(BigInt(1234), { numericSeparator: false }), '1234n', '1234n, numericSeparator false'); 50 | st.equal(inspect(BigInt(1234), { numericSeparator: true }), '1_234n', '1234n, numericSeparator true'); 51 | st.equal(inspect(BigInt(-1234), { numericSeparator: false }), '-1234n', '1234n, numericSeparator false'); 52 | st.equal(inspect(BigInt(-1234), { numericSeparator: true }), '-1_234n', '1234n, numericSeparator true'); 53 | 54 | st.end(); 55 | }); 56 | 57 | t.end(); 58 | }); 59 | -------------------------------------------------------------------------------- /test/fn.js: -------------------------------------------------------------------------------- 1 | var inspect = require('../'); 2 | var test = require('tape'); 3 | var arrow = require('make-arrow-function')(); 4 | var functionsHaveConfigurableNames = require('functions-have-names').functionsHaveConfigurableNames(); 5 | 6 | test('function', function (t) { 7 | t.plan(1); 8 | var obj = [1, 2, function f(n) { return n; }, 4]; 9 | t.equal(inspect(obj), '[ 1, 2, [Function: f], 4 ]'); 10 | }); 11 | 12 | test('function name', function (t) { 13 | t.plan(1); 14 | var f = (function () { 15 | return function () {}; 16 | }()); 17 | f.toString = function toStr() { return 'function xxx () {}'; }; 18 | var obj = [1, 2, f, 4]; 19 | t.equal(inspect(obj), '[ 1, 2, [Function (anonymous)] { toString: [Function: toStr] }, 4 ]'); 20 | }); 21 | 22 | test('anon function', function (t) { 23 | var f = (function () { 24 | return function () {}; 25 | }()); 26 | var obj = [1, 2, f, 4]; 27 | t.equal(inspect(obj), '[ 1, 2, [Function (anonymous)], 4 ]'); 28 | 29 | t.end(); 30 | }); 31 | 32 | test('arrow function', { skip: !arrow }, function (t) { 33 | t.equal(inspect(arrow), '[Function (anonymous)]'); 34 | 35 | t.end(); 36 | }); 37 | 38 | test('truly nameless function', { skip: !arrow || !functionsHaveConfigurableNames }, function (t) { 39 | function f() {} 40 | Object.defineProperty(f, 'name', { value: false }); 41 | t.equal(f.name, false); 42 | t.equal( 43 | inspect(f), 44 | '[Function: f]', 45 | 'named function with falsy `.name` does not hide its original name' 46 | ); 47 | 48 | function g() {} 49 | Object.defineProperty(g, 'name', { value: true }); 50 | t.equal(g.name, true); 51 | t.equal( 52 | inspect(g), 53 | '[Function: true]', 54 | 'named function with truthy `.name` hides its original name' 55 | ); 56 | 57 | var anon = function () {}; // eslint-disable-line func-style 58 | Object.defineProperty(anon, 'name', { value: null }); 59 | t.equal(anon.name, null); 60 | t.equal( 61 | inspect(anon), 62 | '[Function (anonymous)]', 63 | 'anon function with falsy `.name` does not hide its anonymity' 64 | ); 65 | 66 | var anon2 = function () {}; // eslint-disable-line func-style 67 | Object.defineProperty(anon2, 'name', { value: 1 }); 68 | t.equal(anon2.name, 1); 69 | t.equal( 70 | inspect(anon2), 71 | '[Function: 1]', 72 | 'anon function with truthy `.name` hides its anonymity' 73 | ); 74 | 75 | t.end(); 76 | }); 77 | -------------------------------------------------------------------------------- /test/number.js: -------------------------------------------------------------------------------- 1 | var test = require('tape'); 2 | var v = require('es-value-fixtures'); 3 | var forEach = require('for-each'); 4 | 5 | var inspect = require('../'); 6 | 7 | test('negative zero', function (t) { 8 | t.equal(inspect(0), '0', 'inspect(0) === "0"'); 9 | t.equal(inspect(Object(0)), 'Object(0)', 'inspect(Object(0)) === "Object(0)"'); 10 | 11 | t.equal(inspect(-0), '-0', 'inspect(-0) === "-0"'); 12 | t.equal(inspect(Object(-0)), 'Object(-0)', 'inspect(Object(-0)) === "Object(-0)"'); 13 | 14 | t.end(); 15 | }); 16 | 17 | test('numericSeparator', function (t) { 18 | forEach(v.nonBooleans, function (nonBoolean) { 19 | t['throws']( 20 | function () { inspect(true, { numericSeparator: nonBoolean }); }, 21 | TypeError, 22 | inspect(nonBoolean) + ' is not a boolean' 23 | ); 24 | }); 25 | 26 | t.test('3 digit numbers', function (st) { 27 | var failed = false; 28 | for (var i = -999; i < 1000; i += 1) { 29 | var actual = inspect(i); 30 | var actualSepNo = inspect(i, { numericSeparator: false }); 31 | var actualSepYes = inspect(i, { numericSeparator: true }); 32 | var expected = String(i); 33 | if (actual !== expected || actualSepNo !== expected || actualSepYes !== expected) { 34 | failed = true; 35 | t.equal(actual, expected); 36 | t.equal(actualSepNo, expected); 37 | t.equal(actualSepYes, expected); 38 | } 39 | } 40 | 41 | st.notOk(failed, 'all 3 digit numbers passed'); 42 | 43 | st.end(); 44 | }); 45 | 46 | t.equal(inspect(1e3), '1000', '1000'); 47 | t.equal(inspect(1e3, { numericSeparator: false }), '1000', '1000, numericSeparator false'); 48 | t.equal(inspect(1e3, { numericSeparator: true }), '1_000', '1000, numericSeparator true'); 49 | t.equal(inspect(-1e3), '-1000', '-1000'); 50 | t.equal(inspect(-1e3, { numericSeparator: false }), '-1000', '-1000, numericSeparator false'); 51 | t.equal(inspect(-1e3, { numericSeparator: true }), '-1_000', '-1000, numericSeparator true'); 52 | 53 | t.equal(inspect(1234.5678, { numericSeparator: true }), '1_234.567_8', 'fractional numbers get separators'); 54 | t.equal(inspect(1234.56789, { numericSeparator: true }), '1_234.567_89', 'fractional numbers get separators'); 55 | t.equal(inspect(1234.567891, { numericSeparator: true }), '1_234.567_891', 'fractional numbers get separators'); 56 | 57 | t.end(); 58 | }); 59 | -------------------------------------------------------------------------------- /readme.markdown: -------------------------------------------------------------------------------- 1 | # object-inspect [![Version Badge][npm-version-svg]][package-url] 2 | 3 | string representations of objects in node and the browser 4 | 5 | [![github actions][actions-image]][actions-url] 6 | [![coverage][codecov-image]][codecov-url] 7 | [![License][license-image]][license-url] 8 | [![Downloads][downloads-image]][downloads-url] 9 | 10 | [![npm badge][npm-badge-png]][package-url] 11 | 12 | # example 13 | 14 | ## circular 15 | 16 | ``` js 17 | var inspect = require('object-inspect'); 18 | var obj = { a: 1, b: [3,4] }; 19 | obj.c = obj; 20 | console.log(inspect(obj)); 21 | ``` 22 | 23 | ## dom element 24 | 25 | ``` js 26 | var inspect = require('object-inspect'); 27 | 28 | var d = document.createElement('div'); 29 | d.setAttribute('id', 'beep'); 30 | d.innerHTML = 'woooiiiii'; 31 | 32 | console.log(inspect([ d, { a: 3, b : 4, c: [5,6,[7,[8,[9]]]] } ])); 33 | ``` 34 | 35 | output: 36 | 37 | ``` 38 | [
...
, { a: 3, b: 4, c: [ 5, 6, [ 7, [ 8, [ ... ] ] ] ] } ] 39 | ``` 40 | 41 | # methods 42 | 43 | ``` js 44 | var inspect = require('object-inspect') 45 | ``` 46 | 47 | ## var s = inspect(obj, opts={}) 48 | 49 | Return a string `s` with the string representation of `obj` up to a depth of `opts.depth`. 50 | 51 | Additional options: 52 | - `quoteStyle`: must be "single" or "double", if present. Default `'single'` for strings, `'double'` for HTML elements. 53 | - `maxStringLength`: must be `0`, a positive integer, `Infinity`, or `null`, if present. Default `Infinity`. 54 | - `customInspect`: When `true`, a custom inspect method function will be invoked (either undere the `util.inspect.custom` symbol, or the `inspect` property). When the string `'symbol'`, only the symbol method will be invoked. Default `true`. 55 | - `indent`: must be "\t", `null`, or a positive integer. Default `null`. 56 | - `numericSeparator`: must be a boolean, if present. Default `false`. If `true`, all numbers will be printed with numeric separators (eg, `1234.5678` will be printed as `'1_234.567_8'`) 57 | 58 | # install 59 | 60 | With [npm](https://npmjs.org) do: 61 | 62 | ``` 63 | npm install object-inspect 64 | ``` 65 | 66 | # license 67 | 68 | MIT 69 | 70 | [package-url]: https://npmjs.org/package/object-inspect 71 | [npm-version-svg]: https://versionbadg.es/inspect-js/object-inspect.svg 72 | [deps-svg]: https://david-dm.org/inspect-js/object-inspect.svg 73 | [deps-url]: https://david-dm.org/inspect-js/object-inspect 74 | [dev-deps-svg]: https://david-dm.org/inspect-js/object-inspect/dev-status.svg 75 | [dev-deps-url]: https://david-dm.org/inspect-js/object-inspect#info=devDependencies 76 | [npm-badge-png]: https://nodei.co/npm/object-inspect.png?downloads=true&stars=true 77 | [license-image]: https://img.shields.io/npm/l/object-inspect.svg 78 | [license-url]: LICENSE 79 | [downloads-image]: https://img.shields.io/npm/dm/object-inspect.svg 80 | [downloads-url]: https://npm-stat.com/charts.html?package=object-inspect 81 | [codecov-image]: https://codecov.io/gh/inspect-js/object-inspect/branch/main/graphs/badge.svg 82 | [codecov-url]: https://app.codecov.io/gh/inspect-js/object-inspect/ 83 | [actions-image]: https://img.shields.io/endpoint?url=https://github-actions-badge-u3jn4tfpocch.runkit.sh/inspect-js/object-inspect 84 | [actions-url]: https://github.com/inspect-js/object-inspect/actions 85 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "object-inspect", 3 | "version": "1.13.4", 4 | "description": "string representations of objects in node and the browser", 5 | "main": "index.js", 6 | "sideEffects": false, 7 | "devDependencies": { 8 | "@ljharb/eslint-config": "^21.2.0", 9 | "@pkgjs/support": "^0.0.6", 10 | "auto-changelog": "^2.5.0", 11 | "core-js": "^2.6.12", 12 | "error-cause": "^1.0.9", 13 | "es-value-fixtures": "^1.7.1", 14 | "eslint": "=8.8.0", 15 | "for-each": "^0.3.5", 16 | "functions-have-names": "^1.2.3", 17 | "glob": "=10.3.7", 18 | "globalthis": "^1.0.4", 19 | "has-symbols": "^1.1.0", 20 | "has-tostringtag": "^1.0.2", 21 | "in-publish": "^2.0.1", 22 | "jackspeak": "=2.1.1", 23 | "make-arrow-function": "^1.2.0", 24 | "mock-property": "^1.1.0", 25 | "npmignore": "^0.3.1", 26 | "nyc": "^10.3.2", 27 | "safe-publish-latest": "^2.0.0", 28 | "safer-buffer": "^2.1.2", 29 | "semver": "^6.3.1", 30 | "string.prototype.repeat": "^1.0.0", 31 | "tape": "^5.9.0" 32 | }, 33 | "scripts": { 34 | "prepack": "npmignore --auto --commentLines=autogenerated", 35 | "prepublish": "not-in-publish || npm run prepublishOnly", 36 | "prepublishOnly": "safe-publish-latest", 37 | "pretest": "npm run lint", 38 | "lint": "eslint --ext=js,mjs .", 39 | "postlint": "npx @pkgjs/support validate", 40 | "test": "npm run tests-only && npm run test:corejs", 41 | "tests-only": "nyc tape 'test/*.js'", 42 | "test:corejs": "nyc tape test-core-js.js 'test/*.js'", 43 | "posttest": "npx npm@'>=10.2' audit --production", 44 | "version": "auto-changelog && git add CHANGELOG.md", 45 | "postversion": "auto-changelog && git add CHANGELOG.md && git commit --no-edit --amend && git tag -f \"v$(node -e \"console.log(require('./package.json').version)\")\"" 46 | }, 47 | "testling": { 48 | "files": [ 49 | "test/*.js", 50 | "test/browser/*.js" 51 | ], 52 | "browsers": [ 53 | "ie/6..latest", 54 | "chrome/latest", 55 | "firefox/latest", 56 | "safari/latest", 57 | "opera/latest", 58 | "iphone/latest", 59 | "ipad/latest", 60 | "android/latest" 61 | ] 62 | }, 63 | "repository": { 64 | "type": "git", 65 | "url": "git://github.com/inspect-js/object-inspect.git" 66 | }, 67 | "homepage": "https://github.com/inspect-js/object-inspect", 68 | "keywords": [ 69 | "inspect", 70 | "util.inspect", 71 | "object", 72 | "stringify", 73 | "pretty" 74 | ], 75 | "author": { 76 | "name": "James Halliday", 77 | "email": "mail@substack.net", 78 | "url": "http://substack.net" 79 | }, 80 | "funding": { 81 | "url": "https://github.com/sponsors/ljharb" 82 | }, 83 | "license": "MIT", 84 | "browser": { 85 | "./util.inspect.js": false 86 | }, 87 | "auto-changelog": { 88 | "output": "CHANGELOG.md", 89 | "template": "keepachangelog", 90 | "unreleased": false, 91 | "commitLimit": false, 92 | "backfillLimit": false, 93 | "hideCredit": true 94 | }, 95 | "publishConfig": { 96 | "ignore": [ 97 | ".github/workflows", 98 | "./test-core-js.js" 99 | ] 100 | }, 101 | "support": true, 102 | "engines": { 103 | "node": ">= 0.4" 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /test/inspect.js: -------------------------------------------------------------------------------- 1 | var test = require('tape'); 2 | var hasSymbols = require('has-symbols/shams')(); 3 | var utilInspect = require('../util.inspect'); 4 | var repeat = require('string.prototype.repeat'); 5 | 6 | var inspect = require('..'); 7 | 8 | test('inspect', function (t) { 9 | t.plan(5); 10 | 11 | var obj = [{ inspect: function xyzInspect() { return '!XYZ¡'; } }, []]; 12 | var stringResult = '[ !XYZ¡, [] ]'; 13 | var falseResult = '[ { inspect: [Function: xyzInspect] }, [] ]'; 14 | 15 | t.equal(inspect(obj), stringResult); 16 | t.equal(inspect(obj, { customInspect: true }), stringResult); 17 | t.equal(inspect(obj, { customInspect: 'symbol' }), falseResult); 18 | t.equal(inspect(obj, { customInspect: false }), falseResult); 19 | t['throws']( 20 | function () { inspect(obj, { customInspect: 'not a boolean or "symbol"' }); }, 21 | TypeError, 22 | '`customInspect` must be a boolean or the string "symbol"' 23 | ); 24 | }); 25 | 26 | test('inspect custom symbol', { skip: !hasSymbols || !utilInspect || !utilInspect.custom }, function (t) { 27 | t.plan(4); 28 | 29 | var obj = { inspect: function stringInspect() { return 'string'; } }; 30 | obj[utilInspect.custom] = function custom() { return 'symbol'; }; 31 | 32 | var symbolResult = '[ symbol, [] ]'; 33 | var stringResult = '[ string, [] ]'; 34 | var falseResult = '[ { inspect: [Function: stringInspect]' + (utilInspect.custom ? ', [' + inspect(utilInspect.custom) + ']: [Function: custom]' : '') + ' }, [] ]'; 35 | 36 | var symbolStringFallback = utilInspect.custom ? symbolResult : stringResult; 37 | var symbolFalseFallback = utilInspect.custom ? symbolResult : falseResult; 38 | 39 | t.equal(inspect([obj, []]), symbolStringFallback); 40 | t.equal(inspect([obj, []], { customInspect: true }), symbolStringFallback); 41 | t.equal(inspect([obj, []], { customInspect: 'symbol' }), symbolFalseFallback); 42 | t.equal(inspect([obj, []], { customInspect: false }), falseResult); 43 | }); 44 | 45 | test('symbols', { skip: !hasSymbols }, function (t) { 46 | t.plan(2); 47 | 48 | var obj = { a: 1 }; 49 | obj[Symbol('test')] = 2; 50 | obj[Symbol.iterator] = 3; 51 | Object.defineProperty(obj, Symbol('non-enum'), { 52 | enumerable: false, 53 | value: 4 54 | }); 55 | 56 | if (typeof Symbol.iterator === 'symbol') { 57 | t.equal(inspect(obj), '{ a: 1, [Symbol(test)]: 2, [Symbol(Symbol.iterator)]: 3 }', 'object with symbols'); 58 | t.equal(inspect([obj, []]), '[ { a: 1, [Symbol(test)]: 2, [Symbol(Symbol.iterator)]: 3 }, [] ]', 'object with symbols in array'); 59 | } else { 60 | // symbol sham key ordering is unreliable 61 | t.match( 62 | inspect(obj), 63 | /^(?:{ a: 1, \[Symbol\(test\)\]: 2, \[Symbol\(Symbol.iterator\)\]: 3 }|{ a: 1, \[Symbol\(Symbol.iterator\)\]: 3, \[Symbol\(test\)\]: 2 })$/, 64 | 'object with symbols (nondeterministic symbol sham key ordering)' 65 | ); 66 | t.match( 67 | inspect([obj, []]), 68 | /^\[ (?:{ a: 1, \[Symbol\(test\)\]: 2, \[Symbol\(Symbol.iterator\)\]: 3 }|{ a: 1, \[Symbol\(Symbol.iterator\)\]: 3, \[Symbol\(test\)\]: 2 }), \[\] \]$/, 69 | 'object with symbols in array (nondeterministic symbol sham key ordering)' 70 | ); 71 | } 72 | }); 73 | 74 | test('maxStringLength', function (t) { 75 | t['throws']( 76 | function () { inspect('', { maxStringLength: -1 }); }, 77 | TypeError, 78 | 'maxStringLength must be >= 0, or Infinity, not negative' 79 | ); 80 | 81 | var str = repeat('a', 1e8); 82 | 83 | t.equal( 84 | inspect([str], { maxStringLength: 10 }), 85 | '[ \'aaaaaaaaaa\'... 99999990 more characters ]', 86 | 'maxStringLength option limits output' 87 | ); 88 | 89 | t.equal( 90 | inspect(['f'], { maxStringLength: null }), 91 | '[ \'\'... 1 more character ]', 92 | 'maxStringLength option accepts `null`' 93 | ); 94 | 95 | t.equal( 96 | inspect([str], { maxStringLength: Infinity }), 97 | '[ \'' + str + '\' ]', 98 | 'maxStringLength option accepts ∞' 99 | ); 100 | 101 | t.end(); 102 | }); 103 | 104 | test('inspect options', { skip: !utilInspect.custom }, function (t) { 105 | var obj = {}; 106 | obj[utilInspect.custom] = function () { 107 | return JSON.stringify(arguments); 108 | }; 109 | t.equal( 110 | inspect(obj), 111 | utilInspect(obj, { depth: 5 }), 112 | 'custom symbols will use node\'s inspect' 113 | ); 114 | t.equal( 115 | inspect(obj, { depth: 2 }), 116 | utilInspect(obj, { depth: 2 }), 117 | 'a reduced depth will be passed to node\'s inspect' 118 | ); 119 | t.equal( 120 | inspect({ d1: obj }, { depth: 3 }), 121 | '{ d1: ' + utilInspect(obj, { depth: 2 }) + ' }', 122 | 'deep objects will receive a reduced depth' 123 | ); 124 | t.equal( 125 | inspect({ d1: obj }, { depth: 1 }), 126 | '{ d1: [Object] }', 127 | 'unlike nodejs inspect, customInspect will not be used once the depth is exceeded.' 128 | ); 129 | t.end(); 130 | }); 131 | 132 | test('inspect URL', { skip: typeof URL === 'undefined' }, function (t) { 133 | t.match( 134 | inspect(new URL('https://nodejs.org')), 135 | /nodejs\.org/, // Different environments stringify it differently 136 | 'url can be inspected' 137 | ); 138 | t.end(); 139 | }); 140 | -------------------------------------------------------------------------------- /test/indent-option.js: -------------------------------------------------------------------------------- 1 | var test = require('tape'); 2 | var forEach = require('for-each'); 3 | 4 | var inspect = require('../'); 5 | 6 | test('bad indent options', function (t) { 7 | forEach([ 8 | undefined, 9 | true, 10 | false, 11 | -1, 12 | 1.2, 13 | Infinity, 14 | -Infinity, 15 | NaN 16 | ], function (indent) { 17 | t['throws']( 18 | function () { inspect('', { indent: indent }); }, 19 | TypeError, 20 | inspect(indent) + ' is invalid' 21 | ); 22 | }); 23 | 24 | t.end(); 25 | }); 26 | 27 | test('simple object with indent', function (t) { 28 | t.plan(2); 29 | 30 | var obj = { a: 1, b: 2 }; 31 | 32 | var expectedSpaces = [ 33 | '{', 34 | ' a: 1,', 35 | ' b: 2', 36 | '}' 37 | ].join('\n'); 38 | var expectedTabs = [ 39 | '{', 40 | ' a: 1,', 41 | ' b: 2', 42 | '}' 43 | ].join('\n'); 44 | 45 | t.equal(inspect(obj, { indent: 2 }), expectedSpaces, 'two'); 46 | t.equal(inspect(obj, { indent: '\t' }), expectedTabs, 'tabs'); 47 | }); 48 | 49 | test('two deep object with indent', function (t) { 50 | t.plan(2); 51 | 52 | var obj = { a: 1, b: { c: 3, d: 4 } }; 53 | 54 | var expectedSpaces = [ 55 | '{', 56 | ' a: 1,', 57 | ' b: {', 58 | ' c: 3,', 59 | ' d: 4', 60 | ' }', 61 | '}' 62 | ].join('\n'); 63 | var expectedTabs = [ 64 | '{', 65 | ' a: 1,', 66 | ' b: {', 67 | ' c: 3,', 68 | ' d: 4', 69 | ' }', 70 | '}' 71 | ].join('\n'); 72 | 73 | t.equal(inspect(obj, { indent: 2 }), expectedSpaces, 'two'); 74 | t.equal(inspect(obj, { indent: '\t' }), expectedTabs, 'tabs'); 75 | }); 76 | 77 | test('simple array with all single line elements', function (t) { 78 | t.plan(2); 79 | 80 | var obj = [1, 2, 3, 'asdf\nsdf']; 81 | 82 | var expected = '[ 1, 2, 3, \'asdf\\nsdf\' ]'; 83 | 84 | t.equal(inspect(obj, { indent: 2 }), expected, 'two'); 85 | t.equal(inspect(obj, { indent: '\t' }), expected, 'tabs'); 86 | }); 87 | 88 | test('array with complex elements', function (t) { 89 | t.plan(2); 90 | 91 | var obj = [1, { a: 1, b: { c: 1 } }, 'asdf\nsdf']; 92 | 93 | var expectedSpaces = [ 94 | '[', 95 | ' 1,', 96 | ' {', 97 | ' a: 1,', 98 | ' b: {', 99 | ' c: 1', 100 | ' }', 101 | ' },', 102 | ' \'asdf\\nsdf\'', 103 | ']' 104 | ].join('\n'); 105 | var expectedTabs = [ 106 | '[', 107 | ' 1,', 108 | ' {', 109 | ' a: 1,', 110 | ' b: {', 111 | ' c: 1', 112 | ' }', 113 | ' },', 114 | ' \'asdf\\nsdf\'', 115 | ']' 116 | ].join('\n'); 117 | 118 | t.equal(inspect(obj, { indent: 2 }), expectedSpaces, 'two'); 119 | t.equal(inspect(obj, { indent: '\t' }), expectedTabs, 'tabs'); 120 | }); 121 | 122 | test('values', function (t) { 123 | t.plan(2); 124 | var obj = [{}, [], { 'a-b': 5 }]; 125 | 126 | var expectedSpaces = [ 127 | '[', 128 | ' {},', 129 | ' [],', 130 | ' {', 131 | ' \'a-b\': 5', 132 | ' }', 133 | ']' 134 | ].join('\n'); 135 | var expectedTabs = [ 136 | '[', 137 | ' {},', 138 | ' [],', 139 | ' {', 140 | ' \'a-b\': 5', 141 | ' }', 142 | ']' 143 | ].join('\n'); 144 | 145 | t.equal(inspect(obj, { indent: 2 }), expectedSpaces, 'two'); 146 | t.equal(inspect(obj, { indent: '\t' }), expectedTabs, 'tabs'); 147 | }); 148 | 149 | test('Map', { skip: typeof Map !== 'function' }, function (t) { 150 | var map = new Map(); 151 | map.set({ a: 1 }, ['b']); 152 | map.set(3, NaN); 153 | 154 | var expectedStringSpaces = [ 155 | 'Map (2) {', 156 | ' { a: 1 } => [ \'b\' ],', 157 | ' 3 => NaN', 158 | '}' 159 | ].join('\n'); 160 | var expectedStringTabs = [ 161 | 'Map (2) {', 162 | ' { a: 1 } => [ \'b\' ],', 163 | ' 3 => NaN', 164 | '}' 165 | ].join('\n'); 166 | var expectedStringTabsDoubleQuotes = [ 167 | 'Map (2) {', 168 | ' { a: 1 } => [ "b" ],', 169 | ' 3 => NaN', 170 | '}' 171 | ].join('\n'); 172 | 173 | t.equal( 174 | inspect(map, { indent: 2 }), 175 | expectedStringSpaces, 176 | 'Map keys are not indented (two)' 177 | ); 178 | t.equal( 179 | inspect(map, { indent: '\t' }), 180 | expectedStringTabs, 181 | 'Map keys are not indented (tabs)' 182 | ); 183 | t.equal( 184 | inspect(map, { indent: '\t', quoteStyle: 'double' }), 185 | expectedStringTabsDoubleQuotes, 186 | 'Map keys are not indented (tabs + double quotes)' 187 | ); 188 | 189 | t.equal(inspect(new Map(), { indent: 2 }), 'Map (0) {}', 'empty Map should show as empty (two)'); 190 | t.equal(inspect(new Map(), { indent: '\t' }), 'Map (0) {}', 'empty Map should show as empty (tabs)'); 191 | 192 | var nestedMap = new Map(); 193 | nestedMap.set(nestedMap, map); 194 | var expectedNestedSpaces = [ 195 | 'Map (1) {', 196 | ' [Circular] => Map (2) {', 197 | ' { a: 1 } => [ \'b\' ],', 198 | ' 3 => NaN', 199 | ' }', 200 | '}' 201 | ].join('\n'); 202 | var expectedNestedTabs = [ 203 | 'Map (1) {', 204 | ' [Circular] => Map (2) {', 205 | ' { a: 1 } => [ \'b\' ],', 206 | ' 3 => NaN', 207 | ' }', 208 | '}' 209 | ].join('\n'); 210 | t.equal(inspect(nestedMap, { indent: 2 }), expectedNestedSpaces, 'Map containing a Map should work (two)'); 211 | t.equal(inspect(nestedMap, { indent: '\t' }), expectedNestedTabs, 'Map containing a Map should work (tabs)'); 212 | 213 | t.end(); 214 | }); 215 | 216 | test('Set', { skip: typeof Set !== 'function' }, function (t) { 217 | var set = new Set(); 218 | set.add({ a: 1 }); 219 | set.add(['b']); 220 | var expectedStringSpaces = [ 221 | 'Set (2) {', 222 | ' {', 223 | ' a: 1', 224 | ' },', 225 | ' [ \'b\' ]', 226 | '}' 227 | ].join('\n'); 228 | var expectedStringTabs = [ 229 | 'Set (2) {', 230 | ' {', 231 | ' a: 1', 232 | ' },', 233 | ' [ \'b\' ]', 234 | '}' 235 | ].join('\n'); 236 | t.equal(inspect(set, { indent: 2 }), expectedStringSpaces, 'new Set([{ a: 1 }, ["b"]]) should show size and contents (two)'); 237 | t.equal(inspect(set, { indent: '\t' }), expectedStringTabs, 'new Set([{ a: 1 }, ["b"]]) should show size and contents (tabs)'); 238 | 239 | t.equal(inspect(new Set(), { indent: 2 }), 'Set (0) {}', 'empty Set should show as empty (two)'); 240 | t.equal(inspect(new Set(), { indent: '\t' }), 'Set (0) {}', 'empty Set should show as empty (tabs)'); 241 | 242 | var nestedSet = new Set(); 243 | nestedSet.add(set); 244 | nestedSet.add(nestedSet); 245 | var expectedNestedSpaces = [ 246 | 'Set (2) {', 247 | ' Set (2) {', 248 | ' {', 249 | ' a: 1', 250 | ' },', 251 | ' [ \'b\' ]', 252 | ' },', 253 | ' [Circular]', 254 | '}' 255 | ].join('\n'); 256 | var expectedNestedTabs = [ 257 | 'Set (2) {', 258 | ' Set (2) {', 259 | ' {', 260 | ' a: 1', 261 | ' },', 262 | ' [ \'b\' ]', 263 | ' },', 264 | ' [Circular]', 265 | '}' 266 | ].join('\n'); 267 | t.equal(inspect(nestedSet, { indent: 2 }), expectedNestedSpaces, 'Set containing a Set should work (two)'); 268 | t.equal(inspect(nestedSet, { indent: '\t' }), expectedNestedTabs, 'Set containing a Set should work (tabs)'); 269 | 270 | t.end(); 271 | }); 272 | -------------------------------------------------------------------------------- /test/values.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var inspect = require('../'); 4 | var test = require('tape'); 5 | var mockProperty = require('mock-property'); 6 | var hasSymbols = require('has-symbols/shams')(); 7 | var hasToStringTag = require('has-tostringtag/shams')(); 8 | var forEach = require('for-each'); 9 | var semver = require('semver'); 10 | 11 | test('values', function (t) { 12 | t.plan(1); 13 | var obj = [{}, [], { 'a-b': 5 }]; 14 | t.equal(inspect(obj), '[ {}, [], { \'a-b\': 5 } ]'); 15 | }); 16 | 17 | test('arrays with properties', function (t) { 18 | t.plan(1); 19 | var arr = [3]; 20 | arr.foo = 'bar'; 21 | var obj = [1, 2, arr]; 22 | obj.baz = 'quux'; 23 | obj.index = -1; 24 | t.equal(inspect(obj), '[ 1, 2, [ 3, foo: \'bar\' ], baz: \'quux\', index: -1 ]'); 25 | }); 26 | 27 | test('has', function (t) { 28 | t.plan(1); 29 | t.teardown(mockProperty(Object.prototype, 'hasOwnProperty', { 'delete': true })); 30 | 31 | t.equal(inspect({ a: 1, b: 2 }), '{ a: 1, b: 2 }'); 32 | }); 33 | 34 | test('indexOf seen', function (t) { 35 | t.plan(1); 36 | var xs = [1, 2, 3, {}]; 37 | xs.push(xs); 38 | 39 | var seen = []; 40 | seen.indexOf = undefined; 41 | 42 | t.equal( 43 | inspect(xs, {}, 0, seen), 44 | '[ 1, 2, 3, {}, [Circular] ]' 45 | ); 46 | }); 47 | 48 | test('seen seen', function (t) { 49 | t.plan(1); 50 | var xs = [1, 2, 3]; 51 | 52 | var seen = [xs]; 53 | seen.indexOf = undefined; 54 | 55 | t.equal( 56 | inspect(xs, {}, 0, seen), 57 | '[Circular]' 58 | ); 59 | }); 60 | 61 | test('seen seen seen', function (t) { 62 | t.plan(1); 63 | var xs = [1, 2, 3]; 64 | 65 | var seen = [5, xs]; 66 | seen.indexOf = undefined; 67 | 68 | t.equal( 69 | inspect(xs, {}, 0, seen), 70 | '[Circular]' 71 | ); 72 | }); 73 | 74 | test('symbols', { skip: !hasSymbols }, function (t) { 75 | var sym = Symbol('foo'); 76 | t.equal(inspect(sym), 'Symbol(foo)', 'Symbol("foo") should be "Symbol(foo)"'); 77 | if (typeof sym === 'symbol') { 78 | // Symbol shams are incapable of differentiating boxed from unboxed symbols 79 | t.equal(inspect(Object(sym)), 'Object(Symbol(foo))', 'Object(Symbol("foo")) should be "Object(Symbol(foo))"'); 80 | } 81 | 82 | t.test('toStringTag', { skip: !hasToStringTag }, function (st) { 83 | st.plan(1); 84 | 85 | var faker = {}; 86 | faker[Symbol.toStringTag] = 'Symbol'; 87 | st.equal( 88 | inspect(faker), 89 | '{ [Symbol(Symbol.toStringTag)]: \'Symbol\' }', 90 | 'object lying about being a Symbol inspects as an object' 91 | ); 92 | }); 93 | 94 | t.end(); 95 | }); 96 | 97 | test('Map', { skip: typeof Map !== 'function' }, function (t) { 98 | var map = new Map(); 99 | map.set({ a: 1 }, ['b']); 100 | map.set(3, NaN); 101 | var expectedString = 'Map (2) {' + inspect({ a: 1 }) + ' => ' + inspect(['b']) + ', 3 => NaN}'; 102 | t.equal(inspect(map), expectedString, 'new Map([[{ a: 1 }, ["b"]], [3, NaN]]) should show size and contents'); 103 | t.equal(inspect(new Map()), 'Map (0) {}', 'empty Map should show as empty'); 104 | 105 | var nestedMap = new Map(); 106 | nestedMap.set(nestedMap, map); 107 | t.equal(inspect(nestedMap), 'Map (1) {[Circular] => ' + expectedString + '}', 'Map containing a Map should work'); 108 | 109 | t.end(); 110 | }); 111 | 112 | test('WeakMap', { skip: typeof WeakMap !== 'function' }, function (t) { 113 | var map = new WeakMap(); 114 | map.set({ a: 1 }, ['b']); 115 | var expectedString = 'WeakMap { ? }'; 116 | t.equal(inspect(map), expectedString, 'new WeakMap([[{ a: 1 }, ["b"]]]) should not show size or contents'); 117 | t.equal(inspect(new WeakMap()), 'WeakMap { ? }', 'empty WeakMap should not show as empty'); 118 | 119 | t.end(); 120 | }); 121 | 122 | test('Set', { skip: typeof Set !== 'function' }, function (t) { 123 | var set = new Set(); 124 | set.add({ a: 1 }); 125 | set.add(['b']); 126 | var expectedString = 'Set (2) {' + inspect({ a: 1 }) + ', ' + inspect(['b']) + '}'; 127 | t.equal(inspect(set), expectedString, 'new Set([{ a: 1 }, ["b"]]) should show size and contents'); 128 | t.equal(inspect(new Set()), 'Set (0) {}', 'empty Set should show as empty'); 129 | 130 | var nestedSet = new Set(); 131 | nestedSet.add(set); 132 | nestedSet.add(nestedSet); 133 | t.equal(inspect(nestedSet), 'Set (2) {' + expectedString + ', [Circular]}', 'Set containing a Set should work'); 134 | 135 | t.end(); 136 | }); 137 | 138 | test('WeakSet', { skip: typeof WeakSet !== 'function' }, function (t) { 139 | var map = new WeakSet(); 140 | map.add({ a: 1 }); 141 | var expectedString = 'WeakSet { ? }'; 142 | t.equal(inspect(map), expectedString, 'new WeakSet([{ a: 1 }]) should not show size or contents'); 143 | t.equal(inspect(new WeakSet()), 'WeakSet { ? }', 'empty WeakSet should not show as empty'); 144 | 145 | t.end(); 146 | }); 147 | 148 | test('WeakRef', { skip: typeof WeakRef !== 'function' }, function (t) { 149 | var ref = new WeakRef({ a: 1 }); 150 | var expectedString = 'WeakRef { ? }'; 151 | t.equal(inspect(ref), expectedString, 'new WeakRef({ a: 1 }) should not show contents'); 152 | 153 | t.end(); 154 | }); 155 | 156 | test('FinalizationRegistry', { skip: typeof FinalizationRegistry !== 'function' }, function (t) { 157 | var registry = new FinalizationRegistry(function () {}); 158 | var expectedString = 'FinalizationRegistry [FinalizationRegistry] {}'; 159 | t.equal(inspect(registry), expectedString, 'new FinalizationRegistry(function () {}) should work normallys'); 160 | 161 | t.end(); 162 | }); 163 | 164 | test('Strings', function (t) { 165 | var str = 'abc'; 166 | 167 | t.equal(inspect(str), "'" + str + "'", 'primitive string shows as such'); 168 | t.equal(inspect(str, { quoteStyle: 'single' }), "'" + str + "'", 'primitive string shows as such, single quoted'); 169 | t.equal(inspect(str, { quoteStyle: 'double' }), '"' + str + '"', 'primitive string shows as such, double quoted'); 170 | t.equal(inspect(Object(str)), 'Object(' + inspect(str) + ')', 'String object shows as such'); 171 | t.equal(inspect(Object(str), { quoteStyle: 'single' }), 'Object(' + inspect(str, { quoteStyle: 'single' }) + ')', 'String object shows as such, single quoted'); 172 | t.equal(inspect(Object(str), { quoteStyle: 'double' }), 'Object(' + inspect(str, { quoteStyle: 'double' }) + ')', 'String object shows as such, double quoted'); 173 | 174 | t.end(); 175 | }); 176 | 177 | test('Numbers', function (t) { 178 | var num = 42; 179 | 180 | t.equal(inspect(num), String(num), 'primitive number shows as such'); 181 | t.equal(inspect(Object(num)), 'Object(' + inspect(num) + ')', 'Number object shows as such'); 182 | 183 | t.end(); 184 | }); 185 | 186 | test('Booleans', function (t) { 187 | t.equal(inspect(true), String(true), 'primitive true shows as such'); 188 | t.equal(inspect(Object(true)), 'Object(' + inspect(true) + ')', 'Boolean object true shows as such'); 189 | 190 | t.equal(inspect(false), String(false), 'primitive false shows as such'); 191 | t.equal(inspect(Object(false)), 'Object(' + inspect(false) + ')', 'Boolean false object shows as such'); 192 | 193 | t.end(); 194 | }); 195 | 196 | test('Date', function (t) { 197 | var now = new Date(); 198 | t.equal(inspect(now), String(now), 'Date shows properly'); 199 | t.equal(inspect(new Date(NaN)), 'Invalid Date', 'Invalid Date shows properly'); 200 | 201 | t.end(); 202 | }); 203 | 204 | test('RegExps', function (t) { 205 | t.equal(inspect(/a/g), '/a/g', 'regex shows properly'); 206 | t.equal(inspect(new RegExp('abc', 'i')), '/abc/i', 'new RegExp shows properly'); 207 | 208 | var match = 'abc abc'.match(/[ab]+/); 209 | delete match.groups; // for node < 10 210 | t.equal(inspect(match), '[ \'ab\', index: 0, input: \'abc abc\' ]', 'RegExp match object shows properly'); 211 | 212 | t.end(); 213 | }); 214 | 215 | test('Proxies', { skip: typeof Proxy !== 'function' || !hasToStringTag }, function (t) { 216 | var target = { proxy: true }; 217 | var fake = new Proxy(target, { has: function () { return false; } }); 218 | 219 | // needed to work around a weird difference in node v6.0 - v6.4 where non-present properties are not logged 220 | var isNode60 = semver.satisfies(process.version, '6.0 - 6.4'); 221 | 222 | forEach([ 223 | 'Boolean', 224 | 'Number', 225 | 'String', 226 | 'Symbol', 227 | 'Date' 228 | ], function (tag) { 229 | target[Symbol.toStringTag] = tag; 230 | 231 | t.equal( 232 | inspect(fake), 233 | '{ ' + (isNode60 ? '' : 'proxy: true, ') + '[Symbol(Symbol.toStringTag)]: \'' + tag + '\' }', 234 | 'Proxy for + ' + tag + ' shows as the target, which has no slots' 235 | ); 236 | }); 237 | 238 | t.end(); 239 | }); 240 | 241 | test('fakers', { skip: !hasToStringTag }, function (t) { 242 | var target = { proxy: false }; 243 | 244 | forEach([ 245 | 'Boolean', 246 | 'Number', 247 | 'String', 248 | 'Symbol', 249 | 'Date' 250 | ], function (tag) { 251 | target[Symbol.toStringTag] = tag; 252 | 253 | t.equal( 254 | inspect(target), 255 | '{ proxy: false, [Symbol(Symbol.toStringTag)]: \'' + tag + '\' }', 256 | 'Object pretending to be ' + tag + ' does not trick us' 257 | ); 258 | }); 259 | 260 | t.end(); 261 | }); 262 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | var hasMap = typeof Map === 'function' && Map.prototype; 2 | var mapSizeDescriptor = Object.getOwnPropertyDescriptor && hasMap ? Object.getOwnPropertyDescriptor(Map.prototype, 'size') : null; 3 | var mapSize = hasMap && mapSizeDescriptor && typeof mapSizeDescriptor.get === 'function' ? mapSizeDescriptor.get : null; 4 | var mapForEach = hasMap && Map.prototype.forEach; 5 | var hasSet = typeof Set === 'function' && Set.prototype; 6 | var setSizeDescriptor = Object.getOwnPropertyDescriptor && hasSet ? Object.getOwnPropertyDescriptor(Set.prototype, 'size') : null; 7 | var setSize = hasSet && setSizeDescriptor && typeof setSizeDescriptor.get === 'function' ? setSizeDescriptor.get : null; 8 | var setForEach = hasSet && Set.prototype.forEach; 9 | var hasWeakMap = typeof WeakMap === 'function' && WeakMap.prototype; 10 | var weakMapHas = hasWeakMap ? WeakMap.prototype.has : null; 11 | var hasWeakSet = typeof WeakSet === 'function' && WeakSet.prototype; 12 | var weakSetHas = hasWeakSet ? WeakSet.prototype.has : null; 13 | var hasWeakRef = typeof WeakRef === 'function' && WeakRef.prototype; 14 | var weakRefDeref = hasWeakRef ? WeakRef.prototype.deref : null; 15 | var booleanValueOf = Boolean.prototype.valueOf; 16 | var objectToString = Object.prototype.toString; 17 | var functionToString = Function.prototype.toString; 18 | var $match = String.prototype.match; 19 | var $slice = String.prototype.slice; 20 | var $replace = String.prototype.replace; 21 | var $toUpperCase = String.prototype.toUpperCase; 22 | var $toLowerCase = String.prototype.toLowerCase; 23 | var $test = RegExp.prototype.test; 24 | var $concat = Array.prototype.concat; 25 | var $join = Array.prototype.join; 26 | var $arrSlice = Array.prototype.slice; 27 | var $floor = Math.floor; 28 | var bigIntValueOf = typeof BigInt === 'function' ? BigInt.prototype.valueOf : null; 29 | var gOPS = Object.getOwnPropertySymbols; 30 | var symToString = typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol' ? Symbol.prototype.toString : null; 31 | var hasShammedSymbols = typeof Symbol === 'function' && typeof Symbol.iterator === 'object'; 32 | // ie, `has-tostringtag/shams 33 | var toStringTag = typeof Symbol === 'function' && Symbol.toStringTag && (typeof Symbol.toStringTag === hasShammedSymbols ? 'object' : 'symbol') 34 | ? Symbol.toStringTag 35 | : null; 36 | var isEnumerable = Object.prototype.propertyIsEnumerable; 37 | 38 | var gPO = (typeof Reflect === 'function' ? Reflect.getPrototypeOf : Object.getPrototypeOf) || ( 39 | [].__proto__ === Array.prototype // eslint-disable-line no-proto 40 | ? function (O) { 41 | return O.__proto__; // eslint-disable-line no-proto 42 | } 43 | : null 44 | ); 45 | 46 | function addNumericSeparator(num, str) { 47 | if ( 48 | num === Infinity 49 | || num === -Infinity 50 | || num !== num 51 | || (num && num > -1000 && num < 1000) 52 | || $test.call(/e/, str) 53 | ) { 54 | return str; 55 | } 56 | var sepRegex = /[0-9](?=(?:[0-9]{3})+(?![0-9]))/g; 57 | if (typeof num === 'number') { 58 | var int = num < 0 ? -$floor(-num) : $floor(num); // trunc(num) 59 | if (int !== num) { 60 | var intStr = String(int); 61 | var dec = $slice.call(str, intStr.length + 1); 62 | return $replace.call(intStr, sepRegex, '$&_') + '.' + $replace.call($replace.call(dec, /([0-9]{3})/g, '$&_'), /_$/, ''); 63 | } 64 | } 65 | return $replace.call(str, sepRegex, '$&_'); 66 | } 67 | 68 | var utilInspect = require('./util.inspect'); 69 | var inspectCustom = utilInspect.custom; 70 | var inspectSymbol = isSymbol(inspectCustom) ? inspectCustom : null; 71 | 72 | var quotes = { 73 | __proto__: null, 74 | 'double': '"', 75 | single: "'" 76 | }; 77 | var quoteREs = { 78 | __proto__: null, 79 | 'double': /(["\\])/g, 80 | single: /(['\\])/g 81 | }; 82 | 83 | module.exports = function inspect_(obj, options, depth, seen) { 84 | var opts = options || {}; 85 | 86 | if (has(opts, 'quoteStyle') && !has(quotes, opts.quoteStyle)) { 87 | throw new TypeError('option "quoteStyle" must be "single" or "double"'); 88 | } 89 | if ( 90 | has(opts, 'maxStringLength') && (typeof opts.maxStringLength === 'number' 91 | ? opts.maxStringLength < 0 && opts.maxStringLength !== Infinity 92 | : opts.maxStringLength !== null 93 | ) 94 | ) { 95 | throw new TypeError('option "maxStringLength", if provided, must be a positive integer, Infinity, or `null`'); 96 | } 97 | var customInspect = has(opts, 'customInspect') ? opts.customInspect : true; 98 | if (typeof customInspect !== 'boolean' && customInspect !== 'symbol') { 99 | throw new TypeError('option "customInspect", if provided, must be `true`, `false`, or `\'symbol\'`'); 100 | } 101 | 102 | if ( 103 | has(opts, 'indent') 104 | && opts.indent !== null 105 | && opts.indent !== '\t' 106 | && !(parseInt(opts.indent, 10) === opts.indent && opts.indent > 0) 107 | ) { 108 | throw new TypeError('option "indent" must be "\\t", an integer > 0, or `null`'); 109 | } 110 | if (has(opts, 'numericSeparator') && typeof opts.numericSeparator !== 'boolean') { 111 | throw new TypeError('option "numericSeparator", if provided, must be `true` or `false`'); 112 | } 113 | var numericSeparator = opts.numericSeparator; 114 | 115 | if (typeof obj === 'undefined') { 116 | return 'undefined'; 117 | } 118 | if (obj === null) { 119 | return 'null'; 120 | } 121 | if (typeof obj === 'boolean') { 122 | return obj ? 'true' : 'false'; 123 | } 124 | 125 | if (typeof obj === 'string') { 126 | return inspectString(obj, opts); 127 | } 128 | if (typeof obj === 'number') { 129 | if (obj === 0) { 130 | return Infinity / obj > 0 ? '0' : '-0'; 131 | } 132 | var str = String(obj); 133 | return numericSeparator ? addNumericSeparator(obj, str) : str; 134 | } 135 | if (typeof obj === 'bigint') { 136 | var bigIntStr = String(obj) + 'n'; 137 | return numericSeparator ? addNumericSeparator(obj, bigIntStr) : bigIntStr; 138 | } 139 | 140 | var maxDepth = typeof opts.depth === 'undefined' ? 5 : opts.depth; 141 | if (typeof depth === 'undefined') { depth = 0; } 142 | if (depth >= maxDepth && maxDepth > 0 && typeof obj === 'object') { 143 | return isArray(obj) ? '[Array]' : '[Object]'; 144 | } 145 | 146 | var indent = getIndent(opts, depth); 147 | 148 | if (typeof seen === 'undefined') { 149 | seen = []; 150 | } else if (indexOf(seen, obj) >= 0) { 151 | return '[Circular]'; 152 | } 153 | 154 | function inspect(value, from, noIndent) { 155 | if (from) { 156 | seen = $arrSlice.call(seen); 157 | seen.push(from); 158 | } 159 | if (noIndent) { 160 | var newOpts = { 161 | depth: opts.depth 162 | }; 163 | if (has(opts, 'quoteStyle')) { 164 | newOpts.quoteStyle = opts.quoteStyle; 165 | } 166 | return inspect_(value, newOpts, depth + 1, seen); 167 | } 168 | return inspect_(value, opts, depth + 1, seen); 169 | } 170 | 171 | if (typeof obj === 'function' && !isRegExp(obj)) { // in older engines, regexes are callable 172 | var name = nameOf(obj); 173 | var keys = arrObjKeys(obj, inspect); 174 | return '[Function' + (name ? ': ' + name : ' (anonymous)') + ']' + (keys.length > 0 ? ' { ' + $join.call(keys, ', ') + ' }' : ''); 175 | } 176 | if (isSymbol(obj)) { 177 | var symString = hasShammedSymbols ? $replace.call(String(obj), /^(Symbol\(.*\))_[^)]*$/, '$1') : symToString.call(obj); 178 | return typeof obj === 'object' && !hasShammedSymbols ? markBoxed(symString) : symString; 179 | } 180 | if (isElement(obj)) { 181 | var s = '<' + $toLowerCase.call(String(obj.nodeName)); 182 | var attrs = obj.attributes || []; 183 | for (var i = 0; i < attrs.length; i++) { 184 | s += ' ' + attrs[i].name + '=' + wrapQuotes(quote(attrs[i].value), 'double', opts); 185 | } 186 | s += '>'; 187 | if (obj.childNodes && obj.childNodes.length) { s += '...'; } 188 | s += ''; 189 | return s; 190 | } 191 | if (isArray(obj)) { 192 | if (obj.length === 0) { return '[]'; } 193 | var xs = arrObjKeys(obj, inspect); 194 | if (indent && !singleLineValues(xs)) { 195 | return '[' + indentedJoin(xs, indent) + ']'; 196 | } 197 | return '[ ' + $join.call(xs, ', ') + ' ]'; 198 | } 199 | if (isError(obj)) { 200 | var parts = arrObjKeys(obj, inspect); 201 | if (!('cause' in Error.prototype) && 'cause' in obj && !isEnumerable.call(obj, 'cause')) { 202 | return '{ [' + String(obj) + '] ' + $join.call($concat.call('[cause]: ' + inspect(obj.cause), parts), ', ') + ' }'; 203 | } 204 | if (parts.length === 0) { return '[' + String(obj) + ']'; } 205 | return '{ [' + String(obj) + '] ' + $join.call(parts, ', ') + ' }'; 206 | } 207 | if (typeof obj === 'object' && customInspect) { 208 | if (inspectSymbol && typeof obj[inspectSymbol] === 'function' && utilInspect) { 209 | return utilInspect(obj, { depth: maxDepth - depth }); 210 | } else if (customInspect !== 'symbol' && typeof obj.inspect === 'function') { 211 | return obj.inspect(); 212 | } 213 | } 214 | if (isMap(obj)) { 215 | var mapParts = []; 216 | if (mapForEach) { 217 | mapForEach.call(obj, function (value, key) { 218 | mapParts.push(inspect(key, obj, true) + ' => ' + inspect(value, obj)); 219 | }); 220 | } 221 | return collectionOf('Map', mapSize.call(obj), mapParts, indent); 222 | } 223 | if (isSet(obj)) { 224 | var setParts = []; 225 | if (setForEach) { 226 | setForEach.call(obj, function (value) { 227 | setParts.push(inspect(value, obj)); 228 | }); 229 | } 230 | return collectionOf('Set', setSize.call(obj), setParts, indent); 231 | } 232 | if (isWeakMap(obj)) { 233 | return weakCollectionOf('WeakMap'); 234 | } 235 | if (isWeakSet(obj)) { 236 | return weakCollectionOf('WeakSet'); 237 | } 238 | if (isWeakRef(obj)) { 239 | return weakCollectionOf('WeakRef'); 240 | } 241 | if (isNumber(obj)) { 242 | return markBoxed(inspect(Number(obj))); 243 | } 244 | if (isBigInt(obj)) { 245 | return markBoxed(inspect(bigIntValueOf.call(obj))); 246 | } 247 | if (isBoolean(obj)) { 248 | return markBoxed(booleanValueOf.call(obj)); 249 | } 250 | if (isString(obj)) { 251 | return markBoxed(inspect(String(obj))); 252 | } 253 | // note: in IE 8, sometimes `global !== window` but both are the prototypes of each other 254 | /* eslint-env browser */ 255 | if (typeof window !== 'undefined' && obj === window) { 256 | return '{ [object Window] }'; 257 | } 258 | if ( 259 | (typeof globalThis !== 'undefined' && obj === globalThis) 260 | || (typeof global !== 'undefined' && obj === global) 261 | ) { 262 | return '{ [object globalThis] }'; 263 | } 264 | if (!isDate(obj) && !isRegExp(obj)) { 265 | var ys = arrObjKeys(obj, inspect); 266 | var isPlainObject = gPO ? gPO(obj) === Object.prototype : obj instanceof Object || obj.constructor === Object; 267 | var protoTag = obj instanceof Object ? '' : 'null prototype'; 268 | var stringTag = !isPlainObject && toStringTag && Object(obj) === obj && toStringTag in obj ? $slice.call(toStr(obj), 8, -1) : protoTag ? 'Object' : ''; 269 | var constructorTag = isPlainObject || typeof obj.constructor !== 'function' ? '' : obj.constructor.name ? obj.constructor.name + ' ' : ''; 270 | var tag = constructorTag + (stringTag || protoTag ? '[' + $join.call($concat.call([], stringTag || [], protoTag || []), ': ') + '] ' : ''); 271 | if (ys.length === 0) { return tag + '{}'; } 272 | if (indent) { 273 | return tag + '{' + indentedJoin(ys, indent) + '}'; 274 | } 275 | return tag + '{ ' + $join.call(ys, ', ') + ' }'; 276 | } 277 | return String(obj); 278 | }; 279 | 280 | function wrapQuotes(s, defaultStyle, opts) { 281 | var style = opts.quoteStyle || defaultStyle; 282 | var quoteChar = quotes[style]; 283 | return quoteChar + s + quoteChar; 284 | } 285 | 286 | function quote(s) { 287 | return $replace.call(String(s), /"/g, '"'); 288 | } 289 | 290 | function canTrustToString(obj) { 291 | return !toStringTag || !(typeof obj === 'object' && (toStringTag in obj || typeof obj[toStringTag] !== 'undefined')); 292 | } 293 | function isArray(obj) { return toStr(obj) === '[object Array]' && canTrustToString(obj); } 294 | function isDate(obj) { return toStr(obj) === '[object Date]' && canTrustToString(obj); } 295 | function isRegExp(obj) { return toStr(obj) === '[object RegExp]' && canTrustToString(obj); } 296 | function isError(obj) { return toStr(obj) === '[object Error]' && canTrustToString(obj); } 297 | function isString(obj) { return toStr(obj) === '[object String]' && canTrustToString(obj); } 298 | function isNumber(obj) { return toStr(obj) === '[object Number]' && canTrustToString(obj); } 299 | function isBoolean(obj) { return toStr(obj) === '[object Boolean]' && canTrustToString(obj); } 300 | 301 | // Symbol and BigInt do have Symbol.toStringTag by spec, so that can't be used to eliminate false positives 302 | function isSymbol(obj) { 303 | if (hasShammedSymbols) { 304 | return obj && typeof obj === 'object' && obj instanceof Symbol; 305 | } 306 | if (typeof obj === 'symbol') { 307 | return true; 308 | } 309 | if (!obj || typeof obj !== 'object' || !symToString) { 310 | return false; 311 | } 312 | try { 313 | symToString.call(obj); 314 | return true; 315 | } catch (e) {} 316 | return false; 317 | } 318 | 319 | function isBigInt(obj) { 320 | if (!obj || typeof obj !== 'object' || !bigIntValueOf) { 321 | return false; 322 | } 323 | try { 324 | bigIntValueOf.call(obj); 325 | return true; 326 | } catch (e) {} 327 | return false; 328 | } 329 | 330 | var hasOwn = Object.prototype.hasOwnProperty || function (key) { return key in this; }; 331 | function has(obj, key) { 332 | return hasOwn.call(obj, key); 333 | } 334 | 335 | function toStr(obj) { 336 | return objectToString.call(obj); 337 | } 338 | 339 | function nameOf(f) { 340 | if (f.name) { return f.name; } 341 | var m = $match.call(functionToString.call(f), /^function\s*([\w$]+)/); 342 | if (m) { return m[1]; } 343 | return null; 344 | } 345 | 346 | function indexOf(xs, x) { 347 | if (xs.indexOf) { return xs.indexOf(x); } 348 | for (var i = 0, l = xs.length; i < l; i++) { 349 | if (xs[i] === x) { return i; } 350 | } 351 | return -1; 352 | } 353 | 354 | function isMap(x) { 355 | if (!mapSize || !x || typeof x !== 'object') { 356 | return false; 357 | } 358 | try { 359 | mapSize.call(x); 360 | try { 361 | setSize.call(x); 362 | } catch (s) { 363 | return true; 364 | } 365 | return x instanceof Map; // core-js workaround, pre-v2.5.0 366 | } catch (e) {} 367 | return false; 368 | } 369 | 370 | function isWeakMap(x) { 371 | if (!weakMapHas || !x || typeof x !== 'object') { 372 | return false; 373 | } 374 | try { 375 | weakMapHas.call(x, weakMapHas); 376 | try { 377 | weakSetHas.call(x, weakSetHas); 378 | } catch (s) { 379 | return true; 380 | } 381 | return x instanceof WeakMap; // core-js workaround, pre-v2.5.0 382 | } catch (e) {} 383 | return false; 384 | } 385 | 386 | function isWeakRef(x) { 387 | if (!weakRefDeref || !x || typeof x !== 'object') { 388 | return false; 389 | } 390 | try { 391 | weakRefDeref.call(x); 392 | return true; 393 | } catch (e) {} 394 | return false; 395 | } 396 | 397 | function isSet(x) { 398 | if (!setSize || !x || typeof x !== 'object') { 399 | return false; 400 | } 401 | try { 402 | setSize.call(x); 403 | try { 404 | mapSize.call(x); 405 | } catch (m) { 406 | return true; 407 | } 408 | return x instanceof Set; // core-js workaround, pre-v2.5.0 409 | } catch (e) {} 410 | return false; 411 | } 412 | 413 | function isWeakSet(x) { 414 | if (!weakSetHas || !x || typeof x !== 'object') { 415 | return false; 416 | } 417 | try { 418 | weakSetHas.call(x, weakSetHas); 419 | try { 420 | weakMapHas.call(x, weakMapHas); 421 | } catch (s) { 422 | return true; 423 | } 424 | return x instanceof WeakSet; // core-js workaround, pre-v2.5.0 425 | } catch (e) {} 426 | return false; 427 | } 428 | 429 | function isElement(x) { 430 | if (!x || typeof x !== 'object') { return false; } 431 | if (typeof HTMLElement !== 'undefined' && x instanceof HTMLElement) { 432 | return true; 433 | } 434 | return typeof x.nodeName === 'string' && typeof x.getAttribute === 'function'; 435 | } 436 | 437 | function inspectString(str, opts) { 438 | if (str.length > opts.maxStringLength) { 439 | var remaining = str.length - opts.maxStringLength; 440 | var trailer = '... ' + remaining + ' more character' + (remaining > 1 ? 's' : ''); 441 | return inspectString($slice.call(str, 0, opts.maxStringLength), opts) + trailer; 442 | } 443 | var quoteRE = quoteREs[opts.quoteStyle || 'single']; 444 | quoteRE.lastIndex = 0; 445 | // eslint-disable-next-line no-control-regex 446 | var s = $replace.call($replace.call(str, quoteRE, '\\$1'), /[\x00-\x1f]/g, lowbyte); 447 | return wrapQuotes(s, 'single', opts); 448 | } 449 | 450 | function lowbyte(c) { 451 | var n = c.charCodeAt(0); 452 | var x = { 453 | 8: 'b', 454 | 9: 't', 455 | 10: 'n', 456 | 12: 'f', 457 | 13: 'r' 458 | }[n]; 459 | if (x) { return '\\' + x; } 460 | return '\\x' + (n < 0x10 ? '0' : '') + $toUpperCase.call(n.toString(16)); 461 | } 462 | 463 | function markBoxed(str) { 464 | return 'Object(' + str + ')'; 465 | } 466 | 467 | function weakCollectionOf(type) { 468 | return type + ' { ? }'; 469 | } 470 | 471 | function collectionOf(type, size, entries, indent) { 472 | var joinedEntries = indent ? indentedJoin(entries, indent) : $join.call(entries, ', '); 473 | return type + ' (' + size + ') {' + joinedEntries + '}'; 474 | } 475 | 476 | function singleLineValues(xs) { 477 | for (var i = 0; i < xs.length; i++) { 478 | if (indexOf(xs[i], '\n') >= 0) { 479 | return false; 480 | } 481 | } 482 | return true; 483 | } 484 | 485 | function getIndent(opts, depth) { 486 | var baseIndent; 487 | if (opts.indent === '\t') { 488 | baseIndent = '\t'; 489 | } else if (typeof opts.indent === 'number' && opts.indent > 0) { 490 | baseIndent = $join.call(Array(opts.indent + 1), ' '); 491 | } else { 492 | return null; 493 | } 494 | return { 495 | base: baseIndent, 496 | prev: $join.call(Array(depth + 1), baseIndent) 497 | }; 498 | } 499 | 500 | function indentedJoin(xs, indent) { 501 | if (xs.length === 0) { return ''; } 502 | var lineJoiner = '\n' + indent.prev + indent.base; 503 | return lineJoiner + $join.call(xs, ',' + lineJoiner) + '\n' + indent.prev; 504 | } 505 | 506 | function arrObjKeys(obj, inspect) { 507 | var isArr = isArray(obj); 508 | var xs = []; 509 | if (isArr) { 510 | xs.length = obj.length; 511 | for (var i = 0; i < obj.length; i++) { 512 | xs[i] = has(obj, i) ? inspect(obj[i], obj) : ''; 513 | } 514 | } 515 | var syms = typeof gOPS === 'function' ? gOPS(obj) : []; 516 | var symMap; 517 | if (hasShammedSymbols) { 518 | symMap = {}; 519 | for (var k = 0; k < syms.length; k++) { 520 | symMap['$' + syms[k]] = syms[k]; 521 | } 522 | } 523 | 524 | for (var key in obj) { // eslint-disable-line no-restricted-syntax 525 | if (!has(obj, key)) { continue; } // eslint-disable-line no-restricted-syntax, no-continue 526 | if (isArr && String(Number(key)) === key && key < obj.length) { continue; } // eslint-disable-line no-restricted-syntax, no-continue 527 | if (hasShammedSymbols && symMap['$' + key] instanceof Symbol) { 528 | // this is to prevent shammed Symbols, which are stored as strings, from being included in the string key section 529 | continue; // eslint-disable-line no-restricted-syntax, no-continue 530 | } else if ($test.call(/[^\w$]/, key)) { 531 | xs.push(inspect(key, obj) + ': ' + inspect(obj[key], obj)); 532 | } else { 533 | xs.push(key + ': ' + inspect(obj[key], obj)); 534 | } 535 | } 536 | if (typeof gOPS === 'function') { 537 | for (var j = 0; j < syms.length; j++) { 538 | if (isEnumerable.call(obj, syms[j])) { 539 | xs.push('[' + inspect(syms[j]) + ']: ' + inspect(obj[syms[j]], obj)); 540 | } 541 | } 542 | } 543 | return xs; 544 | } 545 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) 6 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 7 | 8 | ## [v1.13.4](https://github.com/inspect-js/object-inspect/compare/v1.13.3...v1.13.4) - 2025-02-04 9 | 10 | ### Commits 11 | 12 | - [Fix] avoid being fooled by a `Symbol.toStringTag` [`fa5870d`](https://github.com/inspect-js/object-inspect/commit/fa5870da468a525d2f20193700f70752f506cbf7) 13 | - [Tests] fix tests in node v6.0 - v6.4 [`2abfe1b`](https://github.com/inspect-js/object-inspect/commit/2abfe1bc3c69f9293c07c5cd65a9d7d87a628b84) 14 | - [Dev Deps] update `es-value-fixtures`, `for-each`, `has-symbols` [`3edfb01`](https://github.com/inspect-js/object-inspect/commit/3edfb01cc8cce220fba0dfdfe2dc8bc955758cdd) 15 | 16 | ## [v1.13.3](https://github.com/inspect-js/object-inspect/compare/v1.13.2...v1.13.3) - 2024-11-09 17 | 18 | ### Commits 19 | 20 | - [actions] split out node 10-20, and 20+ [`44395a8`](https://github.com/inspect-js/object-inspect/commit/44395a8fc1deda6718a5e125e86b9ffcaa1c7580) 21 | - [Fix] `quoteStyle`: properly escape only the containing quotes [`5137f8f`](https://github.com/inspect-js/object-inspect/commit/5137f8f7bea69a7fc671bb683fd35f244f38fc52) 22 | - [Refactor] clean up `quoteStyle` code [`450680c`](https://github.com/inspect-js/object-inspect/commit/450680cd50de4e689ee3b8e1d6db3a1bcf3fc18c) 23 | - [Tests] add `quoteStyle` escaping tests [`e997c59`](https://github.com/inspect-js/object-inspect/commit/e997c595aeaea84fd98ca35d7e1c3b5ab3ae26e0) 24 | - [Dev Deps] update `auto-changelog`, `es-value-fixtures`, `tape` [`d5a469c`](https://github.com/inspect-js/object-inspect/commit/d5a469c99ec07ccaeafc36ac4b36a93285086d48) 25 | - [Tests] replace `aud` with `npm audit` [`fb7815f`](https://github.com/inspect-js/object-inspect/commit/fb7815f9b72cae277a04f65bbb0543f85b88be62) 26 | - [Dev Deps] update `mock-property` [`11c817b`](https://github.com/inspect-js/object-inspect/commit/11c817bf10392aa017755962ba6bc89d731359ee) 27 | 28 | ## [v1.13.2](https://github.com/inspect-js/object-inspect/compare/v1.13.1...v1.13.2) - 2024-06-21 29 | 30 | ### Commits 31 | 32 | - [readme] update badges [`8a51e6b`](https://github.com/inspect-js/object-inspect/commit/8a51e6bedaf389ec40cc4659e9df53e8543d176e) 33 | - [Dev Deps] update `@ljharb/eslint-config`, `tape` [`ef05f58`](https://github.com/inspect-js/object-inspect/commit/ef05f58c9761a41416ab907299bf0fa79517014b) 34 | - [Dev Deps] update `error-cause`, `has-tostringtag`, `tape` [`c0c6c26`](https://github.com/inspect-js/object-inspect/commit/c0c6c26c44cee6671f7c5d43d2b91d27c5c00d90) 35 | - [Fix] Don't throw when `global` is not defined [`d4d0965`](https://github.com/inspect-js/object-inspect/commit/d4d096570f7dbd0e03266a96de11d05eb7b63e0f) 36 | - [meta] add missing `engines.node` [`17a352a`](https://github.com/inspect-js/object-inspect/commit/17a352af6fe1ba6b70a19081674231eb1a50c940) 37 | - [Dev Deps] update `globalthis` [`9c08884`](https://github.com/inspect-js/object-inspect/commit/9c08884aa662a149e2f11403f413927736b97da7) 38 | - [Dev Deps] update `error-cause` [`6af352d`](https://github.com/inspect-js/object-inspect/commit/6af352d7c3929a4cc4c55768c27bf547a5e900f4) 39 | - [Dev Deps] update `npmignore` [`94e617d`](https://github.com/inspect-js/object-inspect/commit/94e617d38831722562fa73dff4c895746861d267) 40 | - [Dev Deps] update `mock-property` [`2ac24d7`](https://github.com/inspect-js/object-inspect/commit/2ac24d7e58cd388ad093c33249e413e05bbfd6c3) 41 | - [Dev Deps] update `tape` [`46125e5`](https://github.com/inspect-js/object-inspect/commit/46125e58f1d1dcfb170ed3d1ea69da550ea8d77b) 42 | 43 | ## [v1.13.1](https://github.com/inspect-js/object-inspect/compare/v1.13.0...v1.13.1) - 2023-10-19 44 | 45 | ### Commits 46 | 47 | - [Fix] in IE 8, global can !== window despite them being prototypes of each other [`30d0859`](https://github.com/inspect-js/object-inspect/commit/30d0859dc4606cf75c2410edcd5d5c6355f8d372) 48 | 49 | ## [v1.13.0](https://github.com/inspect-js/object-inspect/compare/v1.12.3...v1.13.0) - 2023-10-14 50 | 51 | ### Commits 52 | 53 | - [New] add special handling for the global object [`431bab2`](https://github.com/inspect-js/object-inspect/commit/431bab21a490ee51d35395966a504501e8c685da) 54 | - [Dev Deps] update `@ljharb/eslint-config`, `aud`, `tape` [`fd4f619`](https://github.com/inspect-js/object-inspect/commit/fd4f6193562b4b0e95dcf5c0201b4e8cbbc4f58d) 55 | - [Dev Deps] update `mock-property`, `tape` [`b453f6c`](https://github.com/inspect-js/object-inspect/commit/b453f6ceeebf8a1b738a1029754092e0367a4134) 56 | - [Dev Deps] update `error-cause` [`e8ffc57`](https://github.com/inspect-js/object-inspect/commit/e8ffc577d73b92bb6a4b00c44f14e3319e374888) 57 | - [Dev Deps] update `tape` [`054b8b9`](https://github.com/inspect-js/object-inspect/commit/054b8b9b98633284cf989e582450ebfbbe53503c) 58 | - [Dev Deps] temporarily remove `aud` due to breaking change in transitive deps [`2476845`](https://github.com/inspect-js/object-inspect/commit/2476845e0678dd290c541c81cd3dec8420782c52) 59 | - [Dev Deps] pin `glob`, since v10.3.8+ requires a broken `jackspeak` [`383fa5e`](https://github.com/inspect-js/object-inspect/commit/383fa5eebc0afd705cc778a4b49d8e26452e49a8) 60 | - [Dev Deps] pin `jackspeak` since 2.1.2+ depends on npm aliases, which kill the install process in npm < 6 [`68c244c`](https://github.com/inspect-js/object-inspect/commit/68c244c5174cdd877e5dcb8ee90aa3f44b2f25be) 61 | 62 | ## [v1.12.3](https://github.com/inspect-js/object-inspect/compare/v1.12.2...v1.12.3) - 2023-01-12 63 | 64 | ### Commits 65 | 66 | - [Fix] in eg FF 24, collections lack forEach [`75fc226`](https://github.com/inspect-js/object-inspect/commit/75fc22673c82d45f28322b1946bb0eb41b672b7f) 67 | - [actions] update rebase action to use reusable workflow [`250a277`](https://github.com/inspect-js/object-inspect/commit/250a277a095e9dacc029ab8454dcfc15de549dcd) 68 | - [Dev Deps] update `aud`, `es-value-fixtures`, `tape` [`66a19b3`](https://github.com/inspect-js/object-inspect/commit/66a19b3209ccc3c5ef4b34c3cb0160e65d1ce9d5) 69 | - [Dev Deps] update `@ljharb/eslint-config`, `aud`, `error-cause` [`c43d332`](https://github.com/inspect-js/object-inspect/commit/c43d3324b48384a16fd3dc444e5fc589d785bef3) 70 | - [Tests] add `@pkgjs/support` to `postlint` [`e2618d2`](https://github.com/inspect-js/object-inspect/commit/e2618d22a7a3fa361b6629b53c1752fddc9c4d80) 71 | 72 | ## [v1.12.2](https://github.com/inspect-js/object-inspect/compare/v1.12.1...v1.12.2) - 2022-05-26 73 | 74 | ### Commits 75 | 76 | - [Fix] use `util.inspect` for a custom inspection symbol method [`e243bf2`](https://github.com/inspect-js/object-inspect/commit/e243bf2eda6c4403ac6f1146fddb14d12e9646c1) 77 | - [meta] add support info [`ca20ba3`](https://github.com/inspect-js/object-inspect/commit/ca20ba35713c17068ca912a86c542f5e8acb656c) 78 | - [Fix] ignore `cause` in node v16.9 and v16.10 where it has a bug [`86aa553`](https://github.com/inspect-js/object-inspect/commit/86aa553a4a455562c2c56f1540f0bf857b9d314b) 79 | 80 | ## [v1.12.1](https://github.com/inspect-js/object-inspect/compare/v1.12.0...v1.12.1) - 2022-05-21 81 | 82 | ### Commits 83 | 84 | - [Tests] use `mock-property` [`4ec8893`](https://github.com/inspect-js/object-inspect/commit/4ec8893ea9bfd28065ca3638cf6762424bf44352) 85 | - [meta] use `npmignore` to autogenerate an npmignore file [`07f868c`](https://github.com/inspect-js/object-inspect/commit/07f868c10bd25a9d18686528339bb749c211fc9a) 86 | - [Dev Deps] update `eslint`, `@ljharb/eslint-config`, `aud`, `auto-changelog`, `tape` [`b05244b`](https://github.com/inspect-js/object-inspect/commit/b05244b4f331e00c43b3151bc498041be77ccc91) 87 | - [Dev Deps] update `@ljharb/eslint-config`, `error-cause`, `es-value-fixtures`, `functions-have-names`, `tape` [`d037398`](https://github.com/inspect-js/object-inspect/commit/d037398dcc5d531532e4c19c4a711ed677f579c1) 88 | - [Fix] properly handle callable regexes in older engines [`848fe48`](https://github.com/inspect-js/object-inspect/commit/848fe48bd6dd0064ba781ee6f3c5e54a94144c37) 89 | 90 | ## [v1.12.0](https://github.com/inspect-js/object-inspect/compare/v1.11.1...v1.12.0) - 2021-12-18 91 | 92 | ### Commits 93 | 94 | - [New] add `numericSeparator` boolean option [`2d2d537`](https://github.com/inspect-js/object-inspect/commit/2d2d537f5359a4300ce1c10241369f8024f89e11) 95 | - [Robustness] cache more prototype methods [`191533d`](https://github.com/inspect-js/object-inspect/commit/191533da8aec98a05eadd73a5a6e979c9c8653e8) 96 | - [New] ensure an Error’s `cause` is displayed [`53bc2ce`](https://github.com/inspect-js/object-inspect/commit/53bc2cee4e5a9cc4986f3cafa22c0685f340715e) 97 | - [Dev Deps] update `eslint`, `@ljharb/eslint-config` [`bc164b6`](https://github.com/inspect-js/object-inspect/commit/bc164b6e2e7d36b263970f16f54de63048b84a36) 98 | - [Robustness] cache `RegExp.prototype.test` [`a314ab8`](https://github.com/inspect-js/object-inspect/commit/a314ab8271b905cbabc594c82914d2485a8daf12) 99 | - [meta] fix auto-changelog settings [`5ed0983`](https://github.com/inspect-js/object-inspect/commit/5ed0983be72f73e32e2559997517a95525c7e20d) 100 | 101 | ## [v1.11.1](https://github.com/inspect-js/object-inspect/compare/v1.11.0...v1.11.1) - 2021-12-05 102 | 103 | ### Commits 104 | 105 | - [meta] add `auto-changelog` [`7dbdd22`](https://github.com/inspect-js/object-inspect/commit/7dbdd228401d6025d8b7391476d88aee9ea9bbdf) 106 | - [actions] reuse common workflows [`c8823bc`](https://github.com/inspect-js/object-inspect/commit/c8823bc0a8790729680709d45fb6e652432e91aa) 107 | - [Dev Deps] update `eslint`, `@ljharb/eslint-config`, `safe-publish-latest`, `tape` [`7532b12`](https://github.com/inspect-js/object-inspect/commit/7532b120598307497b712890f75af8056f6d37a6) 108 | - [Refactor] use `has-tostringtag` to behave correctly in the presence of symbol shams [`94abb5d`](https://github.com/inspect-js/object-inspect/commit/94abb5d4e745bf33253942dea86b3e538d2ff6c6) 109 | - [actions] update codecov uploader [`5ed5102`](https://github.com/inspect-js/object-inspect/commit/5ed51025267a00e53b1341357315490ac4eb0874) 110 | - [Dev Deps] update `eslint`, `tape` [`37b2ad2`](https://github.com/inspect-js/object-inspect/commit/37b2ad26c08d94bfd01d5d07069a0b28ef4e2ad7) 111 | - [meta] add `sideEffects` flag [`d341f90`](https://github.com/inspect-js/object-inspect/commit/d341f905ef8bffa6a694cda6ddc5ba343532cd4f) 112 | 113 | ## [v1.11.0](https://github.com/inspect-js/object-inspect/compare/v1.10.3...v1.11.0) - 2021-07-12 114 | 115 | ### Commits 116 | 117 | - [New] `customInspect`: add `symbol` option, to mimic modern util.inspect behavior [`e973a6e`](https://github.com/inspect-js/object-inspect/commit/e973a6e21f8140c5837cf25e9d89bdde88dc3120) 118 | - [Dev Deps] update `eslint` [`05f1cb3`](https://github.com/inspect-js/object-inspect/commit/05f1cb3cbcfe1f238e8b51cf9bc294305b7ed793) 119 | 120 | ## [v1.10.3](https://github.com/inspect-js/object-inspect/compare/v1.10.2...v1.10.3) - 2021-05-07 121 | 122 | ### Commits 123 | 124 | - [Fix] handle core-js Symbol shams [`4acfc2c`](https://github.com/inspect-js/object-inspect/commit/4acfc2c4b503498759120eb517abad6d51c9c5d6) 125 | - [readme] update badges [`95c323a`](https://github.com/inspect-js/object-inspect/commit/95c323ad909d6cbabb95dd6015c190ba6db9c1f2) 126 | - [Dev Deps] update `eslint`, `@ljharb/eslint-config`, `aud` [`cb38f48`](https://github.com/inspect-js/object-inspect/commit/cb38f485de6ec7a95109b5a9bbd0a1deba2f6611) 127 | 128 | ## [v1.10.2](https://github.com/inspect-js/object-inspect/compare/v1.10.1...v1.10.2) - 2021-04-17 129 | 130 | ### Commits 131 | 132 | - [Fix] use a robust check for a boxed Symbol [`87f12d6`](https://github.com/inspect-js/object-inspect/commit/87f12d6e69ce530be04659c81a4cd502943acac5) 133 | 134 | ## [v1.10.1](https://github.com/inspect-js/object-inspect/compare/v1.10.0...v1.10.1) - 2021-04-17 135 | 136 | ### Commits 137 | 138 | - [Fix] use a robust check for a boxed bigint [`d5ca829`](https://github.com/inspect-js/object-inspect/commit/d5ca8298b6d2e5c7b9334a5b21b96ed95d225c91) 139 | 140 | ## [v1.10.0](https://github.com/inspect-js/object-inspect/compare/v1.9.0...v1.10.0) - 2021-04-17 141 | 142 | ### Commits 143 | 144 | - [Tests] increase coverage [`d8abb8a`](https://github.com/inspect-js/object-inspect/commit/d8abb8a62c2f084919df994a433b346e0d87a227) 145 | - [actions] use `node/install` instead of `node/run`; use `codecov` action [`4bfec2e`](https://github.com/inspect-js/object-inspect/commit/4bfec2e30aaef6ddef6cbb1448306f9f8b9520b7) 146 | - [New] respect `Symbol.toStringTag` on objects [`799b58f`](https://github.com/inspect-js/object-inspect/commit/799b58f536a45e4484633a8e9daeb0330835f175) 147 | - [Fix] do not allow Symbol.toStringTag to masquerade as builtins [`d6c5b37`](https://github.com/inspect-js/object-inspect/commit/d6c5b37d7e94427796b82432fb0c8964f033a6ab) 148 | - [New] add `WeakRef` support [`b6d898e`](https://github.com/inspect-js/object-inspect/commit/b6d898ee21868c780a7ee66b28532b5b34ed7f09) 149 | - [meta] do not publish github action workflow files [`918cdfc`](https://github.com/inspect-js/object-inspect/commit/918cdfc4b6fe83f559ff6ef04fe66201e3ff5cbd) 150 | - [meta] create `FUNDING.yml` [`0bb5fc5`](https://github.com/inspect-js/object-inspect/commit/0bb5fc516dbcd2cd728bd89cee0b580acc5ce301) 151 | - [Dev Deps] update `eslint`, `@ljharb/eslint-config`, `aud`, `tape` [`22c8dc0`](https://github.com/inspect-js/object-inspect/commit/22c8dc0cac113d70f4781e49a950070923a671be) 152 | - [meta] use `prepublishOnly` script for npm 7+ [`e52ee09`](https://github.com/inspect-js/object-inspect/commit/e52ee09e8050b8dbac94ef57f786675567728223) 153 | - [Dev Deps] update `eslint` [`7c4e6fd`](https://github.com/inspect-js/object-inspect/commit/7c4e6fdedcd27cc980e13c9ad834d05a96f3d40c) 154 | 155 | ## [v1.9.0](https://github.com/inspect-js/object-inspect/compare/v1.8.0...v1.9.0) - 2020-11-30 156 | 157 | ### Commits 158 | 159 | - [Tests] migrate tests to Github Actions [`d262251`](https://github.com/inspect-js/object-inspect/commit/d262251e13e16d3490b5473672f6b6d6ff86675d) 160 | - [New] add enumerable own Symbols to plain object output [`ee60c03`](https://github.com/inspect-js/object-inspect/commit/ee60c033088cff9d33baa71e59a362a541b48284) 161 | - [Tests] add passing tests [`01ac3e4`](https://github.com/inspect-js/object-inspect/commit/01ac3e4b5a30f97875a63dc9b1416b3bd626afc9) 162 | - [actions] add "Require Allow Edits" action [`c2d7746`](https://github.com/inspect-js/object-inspect/commit/c2d774680cde4ca4af332d84d4121b26f798ba9e) 163 | - [Dev Deps] update `eslint`, `@ljharb/eslint-config`, `aud`, `core-js` [`70058de`](https://github.com/inspect-js/object-inspect/commit/70058de1579fc54d1d15ed6c2dbe246637ce70ff) 164 | - [Fix] hex characters in strings should be uppercased, to match node `assert` [`6ab8faa`](https://github.com/inspect-js/object-inspect/commit/6ab8faaa0abc08fe7a8e2afd8b39c6f1f0e00113) 165 | - [Tests] run `nyc` on all tests [`4c47372`](https://github.com/inspect-js/object-inspect/commit/4c473727879ddc8e28b599202551ddaaf07b6210) 166 | - [Tests] node 0.8 has an unpredictable property order; fix `groups` test by removing property [`f192069`](https://github.com/inspect-js/object-inspect/commit/f192069a978a3b60e6f0e0d45ac7df260ab9a778) 167 | - [New] add enumerable properties to Function inspect result, per node’s `assert` [`fd38e1b`](https://github.com/inspect-js/object-inspect/commit/fd38e1bc3e2a1dc82091ce3e021917462eee64fc) 168 | - [Tests] fix tests for node < 10, due to regex match `groups` [`2ac6462`](https://github.com/inspect-js/object-inspect/commit/2ac6462cc4f72eaa0b63a8cfee9aabe3008b2330) 169 | - [Dev Deps] update `eslint`, `@ljharb/eslint-config` [`44b59e2`](https://github.com/inspect-js/object-inspect/commit/44b59e2676a7f825ef530dfd19dafb599e3b9456) 170 | - [Robustness] cache `Symbol.prototype.toString` [`f3c2074`](https://github.com/inspect-js/object-inspect/commit/f3c2074d8f32faf8292587c07c9678ea931703dd) 171 | - [Dev Deps] update `eslint` [`9411294`](https://github.com/inspect-js/object-inspect/commit/94112944b9245e3302e25453277876402d207e7f) 172 | - [meta] `require-allow-edits` no longer requires an explicit github token [`36c0220`](https://github.com/inspect-js/object-inspect/commit/36c02205de3c2b0e84d53777c5c9fd54a36c48ab) 173 | - [actions] update rebase checkout action to v2 [`55a39a6`](https://github.com/inspect-js/object-inspect/commit/55a39a64e944f19c6a7d8efddf3df27700f20d14) 174 | - [actions] switch Automatic Rebase workflow to `pull_request_target` event [`f59fd3c`](https://github.com/inspect-js/object-inspect/commit/f59fd3cf406c3a7c7ece140904a80bbc6bacfcca) 175 | - [Dev Deps] update `eslint` [`a492bec`](https://github.com/inspect-js/object-inspect/commit/a492becec644b0155c9c4bc1caf6f9fac11fb2c7) 176 | 177 | ## [v1.8.0](https://github.com/inspect-js/object-inspect/compare/v1.7.0...v1.8.0) - 2020-06-18 178 | 179 | ### Fixed 180 | 181 | - [New] add `indent` option [`#27`](https://github.com/inspect-js/object-inspect/issues/27) 182 | 183 | ### Commits 184 | 185 | - [Tests] add codecov [`4324cbb`](https://github.com/inspect-js/object-inspect/commit/4324cbb1a2bd7710822a4151ff373570db22453e) 186 | - [New] add `maxStringLength` option [`b3995cb`](https://github.com/inspect-js/object-inspect/commit/b3995cb71e15b5ee127a3094c43994df9d973502) 187 | - [New] add `customInspect` option, to disable custom inspect methods [`28b9179`](https://github.com/inspect-js/object-inspect/commit/28b9179ee802bb3b90810100c11637db90c2fb6d) 188 | - [Tests] add Date and RegExp tests [`3b28eca`](https://github.com/inspect-js/object-inspect/commit/3b28eca57b0367aeadffac604ea09e8bdae7d97b) 189 | - [actions] add automatic rebasing / merge commit blocking [`0d9c6c0`](https://github.com/inspect-js/object-inspect/commit/0d9c6c044e83475ff0bfffb9d35b149834c83a2e) 190 | - [Dev Deps] update `eslint`, `@ljharb/eslint-config`, `core-js`, `tape`; add `aud` [`7c204f2`](https://github.com/inspect-js/object-inspect/commit/7c204f22b9e41bc97147f4d32d4cb045b17769a6) 191 | - [readme] fix repo URLs, remove testling [`34ca9a0`](https://github.com/inspect-js/object-inspect/commit/34ca9a0dabfe75bd311f806a326fadad029909a3) 192 | - [Fix] when truncating a deep array, note it as `[Array]` instead of just `[Object]` [`f74c82d`](https://github.com/inspect-js/object-inspect/commit/f74c82dd0b35386445510deb250f34c41be3ec0e) 193 | - [Dev Deps] update `eslint`, `@ljharb/eslint-config`, `tape` [`1a8a5ea`](https://github.com/inspect-js/object-inspect/commit/1a8a5ea069ea2bee89d77caedad83ffa23d35711) 194 | - [Fix] do not be fooled by a function’s own `toString` method [`7cb5c65`](https://github.com/inspect-js/object-inspect/commit/7cb5c657a976f94715c19c10556a30f15bb7d5d7) 195 | - [patch] indicate explicitly that anon functions are anonymous, to match node [`81ebdd4`](https://github.com/inspect-js/object-inspect/commit/81ebdd4215005144074bbdff3f6bafa01407910a) 196 | - [Dev Deps] loosen the `core-js` dep [`e7472e8`](https://github.com/inspect-js/object-inspect/commit/e7472e8e242117670560bd995830c2a4d12080f5) 197 | - [Dev Deps] update `tape` [`699827e`](https://github.com/inspect-js/object-inspect/commit/699827e6b37258b5203c33c78c009bf4b0e6a66d) 198 | - [meta] add `safe-publish-latest` [`c5d2868`](https://github.com/inspect-js/object-inspect/commit/c5d2868d6eb33c472f37a20f89ceef2787046088) 199 | - [Dev Deps] update `@ljharb/eslint-config` [`9199501`](https://github.com/inspect-js/object-inspect/commit/919950195d486114ccebacbdf9d74d7f382693b0) 200 | 201 | ## [v1.7.0](https://github.com/inspect-js/object-inspect/compare/v1.6.0...v1.7.0) - 2019-11-10 202 | 203 | ### Commits 204 | 205 | - [Tests] use shared travis-ci configs [`19899ed`](https://github.com/inspect-js/object-inspect/commit/19899edbf31f4f8809acf745ce34ad1ce1bfa63b) 206 | - [Tests] add linting [`a00f057`](https://github.com/inspect-js/object-inspect/commit/a00f057d917f66ea26dd37769c6b810ec4af97e8) 207 | - [Tests] lint last file [`2698047`](https://github.com/inspect-js/object-inspect/commit/2698047b58af1e2e88061598ef37a75f228dddf6) 208 | - [Tests] up to `node` `v12.7`, `v11.15`, `v10.16`, `v8.16`, `v6.17` [`589e87a`](https://github.com/inspect-js/object-inspect/commit/589e87a99cadcff4b600e6a303418e9d922836e8) 209 | - [New] add support for `WeakMap` and `WeakSet` [`3ddb3e4`](https://github.com/inspect-js/object-inspect/commit/3ddb3e4e0c8287130c61a12e0ed9c104b1549306) 210 | - [meta] clean up license so github can detect it properly [`27527bb`](https://github.com/inspect-js/object-inspect/commit/27527bb801520c9610c68cc3b55d6f20a2bee56d) 211 | - [Tests] cover `util.inspect.custom` [`36d47b9`](https://github.com/inspect-js/object-inspect/commit/36d47b9c59056a57ef2f1491602c726359561800) 212 | - [Dev Deps] update `eslint`, `@ljharb/eslint-config`, `core-js`, `tape` [`b614eaa`](https://github.com/inspect-js/object-inspect/commit/b614eaac901da0e5c69151f534671f990a94cace) 213 | - [Tests] fix coverage thresholds [`7b7b176`](https://github.com/inspect-js/object-inspect/commit/7b7b176e15f8bd6e8b2f261ff5a493c2fe78d9c2) 214 | - [Tests] bigint tests now can run on unflagged node [`063af31`](https://github.com/inspect-js/object-inspect/commit/063af31ce9cd13c202e3b67c07ba06dc9b7c0f81) 215 | - [Refactor] add early bailout to `isMap` and `isSet` checks [`fc51047`](https://github.com/inspect-js/object-inspect/commit/fc5104714a3671d37e225813db79470d6335683b) 216 | - [meta] add `funding` field [`7f9953a`](https://github.com/inspect-js/object-inspect/commit/7f9953a113eec7b064a6393cf9f90ba15f1d131b) 217 | - [Tests] Fix invalid strict-mode syntax with hexadecimal [`a8b5425`](https://github.com/inspect-js/object-inspect/commit/a8b542503b4af1599a275209a1a99f5fdedb1ead) 218 | - [Dev Deps] update `@ljharb/eslint-config` [`98df157`](https://github.com/inspect-js/object-inspect/commit/98df1577314d9188a3fc3f17fdcf2fba697ae1bd) 219 | - add copyright to LICENSE [`bb69fd0`](https://github.com/inspect-js/object-inspect/commit/bb69fd017a062d299e44da1f9b2c7dcd67f621e6) 220 | - [Tests] use `npx aud` in `posttest` [`4838353`](https://github.com/inspect-js/object-inspect/commit/4838353593974cf7f905b9ef04c03c094f0cdbe2) 221 | - [Tests] move `0.6` to allowed failures, because it won‘t build on travis [`1bff32a`](https://github.com/inspect-js/object-inspect/commit/1bff32aa52e8aea687f0856b28ba754b3e43ebf7) 222 | 223 | ## [v1.6.0](https://github.com/inspect-js/object-inspect/compare/v1.5.0...v1.6.0) - 2018-05-02 224 | 225 | ### Commits 226 | 227 | - [New] add support for boxed BigInt primitives [`356c66a`](https://github.com/inspect-js/object-inspect/commit/356c66a410e7aece7162c8319880a5ef647beaa9) 228 | - [Tests] up to `node` `v10.0`, `v9.11`, `v8.11`, `v6.14`, `v4.9` [`c77b65b`](https://github.com/inspect-js/object-inspect/commit/c77b65bba593811b906b9ec57561c5cba92e2db3) 229 | - [New] Add support for upcoming `BigInt` [`1ac548e`](https://github.com/inspect-js/object-inspect/commit/1ac548e4b27e26466c28c9a5e63e5d4e0591c31f) 230 | - [Tests] run bigint tests in CI with --harmony-bigint flag [`d31b738`](https://github.com/inspect-js/object-inspect/commit/d31b73831880254b5c6cf5691cda9a149fbc5f04) 231 | - [Dev Deps] update `core-js`, `tape` [`ff9eff6`](https://github.com/inspect-js/object-inspect/commit/ff9eff67113341ee1aaf80c1c22d683f43bfbccf) 232 | - [Docs] fix example to use `safer-buffer` [`48cae12`](https://github.com/inspect-js/object-inspect/commit/48cae12a73ec6cacc955175bc56bbe6aee6a211f) 233 | 234 | ## [v1.5.0](https://github.com/inspect-js/object-inspect/compare/v1.4.1...v1.5.0) - 2017-12-25 235 | 236 | ### Commits 237 | 238 | - [New] add `quoteStyle` option [`f5a72d2`](https://github.com/inspect-js/object-inspect/commit/f5a72d26edb3959b048f74c056ca7100a6b091e4) 239 | - [Tests] add more test coverage [`30ebe4e`](https://github.com/inspect-js/object-inspect/commit/30ebe4e1fa943b99ecbb85be7614256d536e2759) 240 | - [Tests] require 0.6 to pass [`99a008c`](https://github.com/inspect-js/object-inspect/commit/99a008ccace189a60fd7da18bf00e32c9572b980) 241 | 242 | ## [v1.4.1](https://github.com/inspect-js/object-inspect/compare/v1.4.0...v1.4.1) - 2017-12-19 243 | 244 | ### Commits 245 | 246 | - [Tests] up to `node` `v9.3`, `v8.9`, `v6.12` [`6674476`](https://github.com/inspect-js/object-inspect/commit/6674476cc56acaac1bde96c84fed5ef631911906) 247 | - [Fix] `inspect(Object(-0))` should be “Object(-0)”, not “Object(0)” [`d0a031f`](https://github.com/inspect-js/object-inspect/commit/d0a031f1cbb3024ee9982bfe364dd18a7e4d1bd3) 248 | 249 | ## [v1.4.0](https://github.com/inspect-js/object-inspect/compare/v1.3.0...v1.4.0) - 2017-10-24 250 | 251 | ### Commits 252 | 253 | - [Tests] add `npm run coverage` [`3b48fb2`](https://github.com/inspect-js/object-inspect/commit/3b48fb25db037235eeb808f0b2830aad7aa36f70) 254 | - [Tests] remove commented-out osx builds [`71e24db`](https://github.com/inspect-js/object-inspect/commit/71e24db8ad6ee3b9b381c5300b0475f2ba595a73) 255 | - [New] add support for `util.inspect.custom`, in node only. [`20cca77`](https://github.com/inspect-js/object-inspect/commit/20cca7762d7e17f15b21a90793dff84acce155df) 256 | - [Tests] up to `node` `v8.6`; use `nvm install-latest-npm` to ensure new npm doesn’t break old node [`252952d`](https://github.com/inspect-js/object-inspect/commit/252952d230d8065851dd3d4d5fe8398aae068529) 257 | - [Tests] up to `node` `v8.8` [`4aa868d`](https://github.com/inspect-js/object-inspect/commit/4aa868d3a62914091d489dd6ec6eed194ee67cd3) 258 | - [Dev Deps] update `core-js`, `tape` [`59483d1`](https://github.com/inspect-js/object-inspect/commit/59483d1df418f852f51fa0db7b24aa6b0209a27a) 259 | 260 | ## [v1.3.0](https://github.com/inspect-js/object-inspect/compare/v1.2.2...v1.3.0) - 2017-07-31 261 | 262 | ### Fixed 263 | 264 | - [Fix] Map/Set: work around core-js bug < v2.5.0 [`#9`](https://github.com/inspect-js/object-inspect/issues/9) 265 | 266 | ### Commits 267 | 268 | - [New] add support for arrays with additional object keys [`0d19937`](https://github.com/inspect-js/object-inspect/commit/0d199374ee37959e51539616666f420ccb29acb9) 269 | - [Tests] up to `node` `v8.2`, `v7.10`, `v6.11`; fix new npm breaking on older nodes [`e24784a`](https://github.com/inspect-js/object-inspect/commit/e24784a90c49117787157a12a63897c49cf89bbb) 270 | - Only apps should have lockfiles [`c6faebc`](https://github.com/inspect-js/object-inspect/commit/c6faebcb2ee486a889a4a1c4d78c0776c7576185) 271 | - [Dev Deps] update `tape` [`7345a0a`](https://github.com/inspect-js/object-inspect/commit/7345a0aeba7e91b888a079c10004d17696a7f586) 272 | 273 | ## [v1.2.2](https://github.com/inspect-js/object-inspect/compare/v1.2.1...v1.2.2) - 2017-03-24 274 | 275 | ### Commits 276 | 277 | - [Tests] up to `node` `v7.7`, `v6.10`, `v4.8`; improve test matrix [`a2ddc15`](https://github.com/inspect-js/object-inspect/commit/a2ddc15a1f2c65af18076eea1c0eb9cbceb478a0) 278 | - [Tests] up to `node` `v7.0`, `v6.9`, `v5.12`, `v4.6`, `io.js` `v3.3`; improve test matrix [`a48949f`](https://github.com/inspect-js/object-inspect/commit/a48949f6b574b2d4d2298109d8e8d0eb3e7a83e7) 279 | - [Performance] check for primitive types as early as possible. [`3b8092a`](https://github.com/inspect-js/object-inspect/commit/3b8092a2a4deffd0575f94334f00194e2d48dad3) 280 | - [Refactor] remove unneeded `else`s. [`7255034`](https://github.com/inspect-js/object-inspect/commit/725503402e08de4f96f6bf2d8edef44ac36f26b6) 281 | - [Refactor] avoid recreating `lowbyte` function every time. [`81edd34`](https://github.com/inspect-js/object-inspect/commit/81edd3475bd15bdd18e84de7472033dcf5004aaa) 282 | - [Fix] differentiate -0 from 0 [`521d345`](https://github.com/inspect-js/object-inspect/commit/521d3456b009da7bf1c5785c8a9df5a9f8718264) 283 | - [Refactor] move object key gathering into separate function [`aca6265`](https://github.com/inspect-js/object-inspect/commit/aca626536eaeef697196c6e9db3e90e7e0355b6a) 284 | - [Refactor] consolidate wrapping logic for boxed primitives into a function. [`4e440cd`](https://github.com/inspect-js/object-inspect/commit/4e440cd9065df04802a2a1dead03f48c353ca301) 285 | - [Robustness] use `typeof` instead of comparing to literal `undefined` [`5ca6f60`](https://github.com/inspect-js/object-inspect/commit/5ca6f601937506daff8ed2fcf686363b55807b69) 286 | - [Refactor] consolidate Map/Set notations. [`4e576e5`](https://github.com/inspect-js/object-inspect/commit/4e576e5d7ed2f9ec3fb7f37a0d16732eb10758a9) 287 | - [Tests] ensure that this function remains anonymous, despite ES6 name inference. [`7540ae5`](https://github.com/inspect-js/object-inspect/commit/7540ae591278756db614fa4def55ca413150e1a3) 288 | - [Refactor] explicitly coerce Error objects to strings. [`7f4ca84`](https://github.com/inspect-js/object-inspect/commit/7f4ca8424ee8dc2c0ca5a422d94f7fac40327261) 289 | - [Refactor] split up `var` declarations for debuggability [`6f2c11e`](https://github.com/inspect-js/object-inspect/commit/6f2c11e6a85418586a00292dcec5e97683f89bc3) 290 | - [Robustness] cache `Object.prototype.toString` [`df44a20`](https://github.com/inspect-js/object-inspect/commit/df44a20adfccf31529d60d1df2079bfc3c836e27) 291 | - [Dev Deps] update `tape` [`3ec714e`](https://github.com/inspect-js/object-inspect/commit/3ec714eba57bc3f58a6eb4fca1376f49e70d300a) 292 | - [Dev Deps] update `tape` [`beb72d9`](https://github.com/inspect-js/object-inspect/commit/beb72d969653747d7cde300393c28755375329b0) 293 | 294 | ## [v1.2.1](https://github.com/inspect-js/object-inspect/compare/v1.2.0...v1.2.1) - 2016-04-09 295 | 296 | ### Fixed 297 | 298 | - [Fix] fix Boolean `false` object inspection. [`#7`](https://github.com/substack/object-inspect/pull/7) 299 | 300 | ## [v1.2.0](https://github.com/inspect-js/object-inspect/compare/v1.1.0...v1.2.0) - 2016-04-09 301 | 302 | ### Fixed 303 | 304 | - [New] add support for inspecting String/Number/Boolean objects. [`#6`](https://github.com/inspect-js/object-inspect/issues/6) 305 | 306 | ### Commits 307 | 308 | - [Dev Deps] update `tape` [`742caa2`](https://github.com/inspect-js/object-inspect/commit/742caa262cf7af4c815d4821c8bd0129c1446432) 309 | 310 | ## [v1.1.0](https://github.com/inspect-js/object-inspect/compare/1.0.2...v1.1.0) - 2015-12-14 311 | 312 | ### Merged 313 | 314 | - [New] add ES6 Map/Set support. [`#4`](https://github.com/inspect-js/object-inspect/pull/4) 315 | 316 | ### Fixed 317 | 318 | - [New] add ES6 Map/Set support. [`#3`](https://github.com/inspect-js/object-inspect/issues/3) 319 | 320 | ### Commits 321 | 322 | - Update `travis.yml` to test on bunches of `iojs` and `node` versions. [`4c1fd65`](https://github.com/inspect-js/object-inspect/commit/4c1fd65cc3bd95307e854d114b90478324287fd2) 323 | - [Dev Deps] update `tape` [`88a907e`](https://github.com/inspect-js/object-inspect/commit/88a907e33afbe408e4b5d6e4e42a33143f88848c) 324 | 325 | ## [1.0.2](https://github.com/inspect-js/object-inspect/compare/1.0.1...1.0.2) - 2015-08-07 326 | 327 | ### Commits 328 | 329 | - [Fix] Cache `Object.prototype.hasOwnProperty` in case it's deleted later. [`1d0075d`](https://github.com/inspect-js/object-inspect/commit/1d0075d3091dc82246feeb1f9871cb2b8ed227b3) 330 | - [Dev Deps] Update `tape` [`ca8d5d7`](https://github.com/inspect-js/object-inspect/commit/ca8d5d75635ddbf76f944e628267581e04958457) 331 | - gitignore node_modules since this is a reusable modules. [`ed41407`](https://github.com/inspect-js/object-inspect/commit/ed41407811743ca530cdeb28f982beb96026af82) 332 | 333 | ## [1.0.1](https://github.com/inspect-js/object-inspect/compare/1.0.0...1.0.1) - 2015-07-19 334 | 335 | ### Commits 336 | 337 | - Make `inspect` work with symbol primitives and objects, including in node 0.11 and 0.12. [`ddf1b94`](https://github.com/inspect-js/object-inspect/commit/ddf1b94475ab951f1e3bccdc0a48e9073cfbfef4) 338 | - bump tape [`103d674`](https://github.com/inspect-js/object-inspect/commit/103d67496b504bdcfdd765d303a773f87ec106e2) 339 | - use newer travis config [`d497276`](https://github.com/inspect-js/object-inspect/commit/d497276c1da14234bb5098a59cf20de75fbc316a) 340 | 341 | ## [1.0.0](https://github.com/inspect-js/object-inspect/compare/0.4.0...1.0.0) - 2014-08-05 342 | 343 | ### Commits 344 | 345 | - error inspect works properly [`260a22d`](https://github.com/inspect-js/object-inspect/commit/260a22d134d3a8a482c67d52091c6040c34f4299) 346 | - seen coverage [`57269e8`](https://github.com/inspect-js/object-inspect/commit/57269e8baa992a7439047f47325111fdcbcb8417) 347 | - htmlelement instance coverage [`397ffe1`](https://github.com/inspect-js/object-inspect/commit/397ffe10a1980350868043ef9de65686d438979f) 348 | - more element coverage [`6905cc2`](https://github.com/inspect-js/object-inspect/commit/6905cc2f7df35600177e613b0642b4df5efd3eca) 349 | - failing test for type errors [`385b615`](https://github.com/inspect-js/object-inspect/commit/385b6152e49b51b68449a662f410b084ed7c601a) 350 | - fn name coverage [`edc906d`](https://github.com/inspect-js/object-inspect/commit/edc906d40fca6b9194d304062c037ee8e398c4c2) 351 | - server-side element test [`362d1d3`](https://github.com/inspect-js/object-inspect/commit/362d1d3e86f187651c29feeb8478110afada385b) 352 | - custom inspect fn [`e89b0f6`](https://github.com/inspect-js/object-inspect/commit/e89b0f6fe6d5e03681282af83732a509160435a6) 353 | - fixed browser test [`b530882`](https://github.com/inspect-js/object-inspect/commit/b5308824a1c8471c5617e394766a03a6977102a9) 354 | - depth test, matches node [`1cfd9e0`](https://github.com/inspect-js/object-inspect/commit/1cfd9e0285a4ae1dff44101ad482915d9bf47e48) 355 | - exercise hasOwnProperty path [`8d753fb`](https://github.com/inspect-js/object-inspect/commit/8d753fb362a534fa1106e4d80f2ee9bea06a66d9) 356 | - more cases covered for errors [`c5c46a5`](https://github.com/inspect-js/object-inspect/commit/c5c46a569ec4606583497e8550f0d8c7ad39a4a4) 357 | - \W obj key test case [`b0eceee`](https://github.com/inspect-js/object-inspect/commit/b0eceeea6e0eb94d686c1046e99b9e25e5005f75) 358 | - coverage for explicit depth param [`e12b91c`](https://github.com/inspect-js/object-inspect/commit/e12b91cd59683362f3a0e80f46481a0211e26c15) 359 | 360 | ## [0.4.0](https://github.com/inspect-js/object-inspect/compare/0.3.1...0.4.0) - 2014-03-21 361 | 362 | ### Commits 363 | 364 | - passing lowbyte interpolation test [`b847511`](https://github.com/inspect-js/object-inspect/commit/b8475114f5def7e7961c5353d48d3d8d9a520985) 365 | - lowbyte test [`4a2b0e1`](https://github.com/inspect-js/object-inspect/commit/4a2b0e142667fc933f195472759385ac08f3946c) 366 | 367 | ## [0.3.1](https://github.com/inspect-js/object-inspect/compare/0.3.0...0.3.1) - 2014-03-04 368 | 369 | ### Commits 370 | 371 | - sort keys [`a07b19c`](https://github.com/inspect-js/object-inspect/commit/a07b19cc3b1521a82d4fafb6368b7a9775428a05) 372 | 373 | ## [0.3.0](https://github.com/inspect-js/object-inspect/compare/0.2.0...0.3.0) - 2014-03-04 374 | 375 | ### Commits 376 | 377 | - [] and {} instead of [ ] and { } [`654c44b`](https://github.com/inspect-js/object-inspect/commit/654c44b2865811f3519e57bb8526e0821caf5c6b) 378 | 379 | ## [0.2.0](https://github.com/inspect-js/object-inspect/compare/0.1.3...0.2.0) - 2014-03-04 380 | 381 | ### Commits 382 | 383 | - failing holes test [`99cdfad`](https://github.com/inspect-js/object-inspect/commit/99cdfad03c6474740275a75636fe6ca86c77737a) 384 | - regex already work [`e324033`](https://github.com/inspect-js/object-inspect/commit/e324033267025995ec97d32ed0a65737c99477a6) 385 | - failing undef/null test [`1f88a00`](https://github.com/inspect-js/object-inspect/commit/1f88a00265d3209719dda8117b7e6360b4c20943) 386 | - holes in the all example [`7d345f3`](https://github.com/inspect-js/object-inspect/commit/7d345f3676dcbe980cff89a4f6c243269ebbb709) 387 | - check for .inspect(), fixes Buffer use-case [`c3f7546`](https://github.com/inspect-js/object-inspect/commit/c3f75466dbca125347d49847c05262c292f12b79) 388 | - fixes for holes [`ce25f73`](https://github.com/inspect-js/object-inspect/commit/ce25f736683de4b92ff27dc5471218415e2d78d8) 389 | - weird null behavior [`405c1ea`](https://github.com/inspect-js/object-inspect/commit/405c1ea72cd5a8cf3b498c3eaa903d01b9fbcab5) 390 | - tape is actually a devDependency, upgrade [`703b0ce`](https://github.com/inspect-js/object-inspect/commit/703b0ce6c5817b4245a082564bccd877e0bb6990) 391 | - put date in the example [`a342219`](https://github.com/inspect-js/object-inspect/commit/a3422190eeaa013215f46df2d0d37b48595ac058) 392 | - passing the null test [`4ab737e`](https://github.com/inspect-js/object-inspect/commit/4ab737ebf862a75d247ebe51e79307a34d6380d4) 393 | 394 | ## [0.1.3](https://github.com/inspect-js/object-inspect/compare/0.1.1...0.1.3) - 2013-07-26 395 | 396 | ### Commits 397 | 398 | - special isElement() check [`882768a`](https://github.com/inspect-js/object-inspect/commit/882768a54035d30747be9de1baf14e5aa0daa128) 399 | - oh right old IEs don't have indexOf either [`36d1275`](https://github.com/inspect-js/object-inspect/commit/36d12756c38b08a74370b0bb696c809e529913a5) 400 | 401 | ## [0.1.1](https://github.com/inspect-js/object-inspect/compare/0.1.0...0.1.1) - 2013-07-26 402 | 403 | ### Commits 404 | 405 | - tests! [`4422fd9`](https://github.com/inspect-js/object-inspect/commit/4422fd95532c2745aa6c4f786f35f1090be29998) 406 | - fix for ie<9, doesn't have hasOwnProperty [`6b7d611`](https://github.com/inspect-js/object-inspect/commit/6b7d61183050f6da801ea04473211da226482613) 407 | - fix for all IEs: no f.name [`4e0c2f6`](https://github.com/inspect-js/object-inspect/commit/4e0c2f6dfd01c306d067d7163319acc97c94ee50) 408 | - badges [`5ed0d88`](https://github.com/inspect-js/object-inspect/commit/5ed0d88e4e407f9cb327fa4a146c17921f9680f3) 409 | 410 | ## [0.1.0](https://github.com/inspect-js/object-inspect/compare/0.0.0...0.1.0) - 2013-07-26 411 | 412 | ### Commits 413 | 414 | - [Function] for functions [`ad5c485`](https://github.com/inspect-js/object-inspect/commit/ad5c485098fc83352cb540a60b2548ca56820e0b) 415 | 416 | ## 0.0.0 - 2013-07-26 417 | 418 | ### Commits 419 | 420 | - working browser example [`34be6b6`](https://github.com/inspect-js/object-inspect/commit/34be6b6548f9ce92bdc3c27572857ba0c4a1218d) 421 | - package.json etc [`cad51f2`](https://github.com/inspect-js/object-inspect/commit/cad51f23fc6bcf1a456ed6abe16088256c2f632f) 422 | - docs complete [`b80cce2`](https://github.com/inspect-js/object-inspect/commit/b80cce2490c4e7183a9ee11ea89071f0abec4446) 423 | - circular example [`4b4a7b9`](https://github.com/inspect-js/object-inspect/commit/4b4a7b92209e4e6b4630976cb6bcd17d14165a59) 424 | - string rep [`7afb479`](https://github.com/inspect-js/object-inspect/commit/7afb479baa798d27f09e0a178b72ea327f60f5c8) 425 | --------------------------------------------------------------------------------