| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent ad97314 commit 459d676
2 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -43,6 +43,7 @@ const types = internalBinding('types'); | |||
| 43 | 43 | Object.assign(types, require('internal/util/types')); | |
| 44 | 44 | const { | |
| 45 | 45 | isAnyArrayBuffer, | |
| 46 | + isArrayBuffer, | ||
| 46 | 47 | isArgumentsObject, | |
| 47 | 48 | isDataView, | |
| 48 | 49 | isExternal, | |
@@ -55,7 +56,23 @@ const { | |||
| 55 | 56 | isWeakSet, | |
| 56 | 57 | isRegExp, | |
| 57 | 58 | isDate, | |
| 58 | - isTypedArray | ||
| 59 | + isTypedArray, | ||
| 60 | + isStringObject, | ||
| 61 | + isNumberObject, | ||
| 62 | + isBooleanObject, | ||
| 63 | + isSymbolObject, | ||
| 64 | + isBigIntObject, | ||
| 65 | + isUint8Array, | ||
| 66 | + isUint8ClampedArray, | ||
| 67 | + isUint16Array, | ||
| 68 | + isUint32Array, | ||
| 69 | + isInt8Array, | ||
| 70 | + isInt16Array, | ||
| 71 | + isInt32Array, | ||
| 72 | + isFloat32Array, | ||
| 73 | + isFloat64Array, | ||
| 74 | + isBigInt64Array, | ||
| 75 | + isBigUint64Array | ||
| 59 | 76 | } = types; | |
| 60 | 77 | ||
| 61 | 78 | const { | |
@@ -79,10 +96,31 @@ const inspectDefaultOptions = Object.seal({ | |||
| 79 | 96 | compact: true | |
| 80 | 97 | }); | |
| 81 | 98 | ||
| 82 | - const propertyIsEnumerable = Object.prototype.propertyIsEnumerable; | ||
| 83 | - const regExpToString = RegExp.prototype.toString; | ||
| 84 | - const dateToISOString = Date.prototype.toISOString; | ||
| 85 | - const errorToString = Error.prototype.toString; | ||
| 99 | + const ReflectApply = Reflect.apply; | ||
| 100 | + | ||
| 101 | + // This function is borrowed from the function with the same name on V8 Extras' | ||
| 102 | + // `utils` object. V8 implements Reflect.apply very efficiently in conjunction | ||
| 103 | + // with the spread syntax, such that no additional special case is needed for | ||
| 104 | + // function calls w/o arguments. | ||
| 105 | + // Refs: https://github.com/v8/v8/blob/d6ead37d265d7215cf9c5f768f279e21bd170212/src/js/prologue.js#L152-L156 | ||
| 106 | + function uncurryThis(func) { | ||
| 107 | + return (thisArg, ...args) => ReflectApply(func, thisArg, args); | ||
| 108 | + } | ||
| 109 | + | ||
| 110 | + const propertyIsEnumerable = uncurryThis(Object.prototype.propertyIsEnumerable); | ||
| 111 | + const regExpToString = uncurryThis(RegExp.prototype.toString); | ||
| 112 | + const dateToISOString = uncurryThis(Date.prototype.toISOString); | ||
| 113 | + const errorToString = uncurryThis(Error.prototype.toString); | ||
| 114 | + | ||
| 115 | + const bigIntValueOf = uncurryThis(BigInt.prototype.valueOf); | ||
| 116 | + const booleanValueOf = uncurryThis(Boolean.prototype.valueOf); | ||
| 117 | + const numberValueOf = uncurryThis(Number.prototype.valueOf); | ||
| 118 | + const symbolValueOf = uncurryThis(Symbol.prototype.valueOf); | ||
| 119 | + const stringValueOf = uncurryThis(String.prototype.valueOf); | ||
| 120 | + | ||
| 121 | + const setValues = uncurryThis(Set.prototype.values); | ||
| 122 | + const mapEntries = uncurryThis(Map.prototype.entries); | ||
| 123 | + const dateGetTime = uncurryThis(Date.prototype.getTime); | ||
| 86 | 124 | ||
| 87 | 125 | let CIRCULAR_ERROR_MESSAGE; | |
| 88 | 126 | let internalDeepEqual; | |
@@ -407,7 +445,7 @@ function getConstructorName(obj) { | |||
| 407 | 445 | return ''; | |
| 408 | 446 | } | |
| 409 | 447 | ||
| 410 | - function getPrefix(constructor, tag) { | ||
| 448 | + function getPrefix(constructor, tag, fallback) { | ||
| 411 | 449 | if (constructor !== '') { | |
| 412 | 450 | if (tag !== '' && constructor !== tag) { | |
| 413 | 451 | return `${constructor} [${tag}] `; | |
@@ -418,9 +456,42 @@ function getPrefix(constructor, tag) { | |||
| 418 | 456 | if (tag !== '') | |
| 419 | 457 | return `[${tag}] `; | |
| 420 | 458 | ||
| 459 | + if (fallback !== undefined) | ||
| 460 | + return `${fallback} `; | ||
| 461 | + | ||
| 421 | 462 | return ''; | |
| 422 | 463 | } | |
| 423 | 464 | ||
| 465 | + function addExtraKeys(source, target, keys) { | ||
| 466 | + for (const key of keys) { | ||
| 467 | + target[key] = source[key]; | ||
| 468 | + } | ||
| 469 | + return target; | ||
| 470 | + } | ||
| 471 | + | ||
| 472 | + function findTypedConstructor(value) { | ||
| 473 | + for (const [check, clazz] of [ | ||
| 474 | + [isUint8Array, Uint8Array], | ||
| 475 | + [isUint8ClampedArray, Uint8ClampedArray], | ||
| 476 | + [isUint16Array, Uint16Array], | ||
| 477 | + [isUint32Array, Uint32Array], | ||
| 478 | + [isInt8Array, Int8Array], | ||
| 479 | + [isInt16Array, Int16Array], | ||
| 480 | + [isInt32Array, Int32Array], | ||
| 481 | + [isFloat32Array, Float32Array], | ||
| 482 | + [isFloat64Array, Float64Array], | ||
| 483 | + [isBigInt64Array, BigInt64Array], | ||
| 484 | + [isBigUint64Array, BigUint64Array] | ||
| 485 | + ]) { | ||
| 486 | + if (check(value)) { | ||
| 487 | + return new clazz(value); | ||
| 488 | + } | ||
| 489 | + } | ||
| 490 | + return value; | ||
| 491 | + } | ||
| 492 | + | ||
| 493 | + const getBoxedValue = formatPrimitive.bind(null, stylizeNoColor); | ||
| 494 | + | ||
| 424 | 495 | function formatValue(ctx, value, recurseTimes) { | |
| 425 | 496 | // Primitive types cannot have properties | |
| 426 | 497 | if (typeof value !== 'object' && typeof value !== 'function') { | |
@@ -511,7 +582,7 @@ function formatValue(ctx, value, recurseTimes) { | |||
| 511 | 582 | } | |
| 512 | 583 | ||
| 513 | 584 | if (symbols.length !== 0) | |
| 514 | - symbols = symbols.filter((key) => propertyIsEnumerable.call(value, key)); | ||
| 585 | + symbols = symbols.filter((key) => propertyIsEnumerable(value, key)); | ||
| 515 | 586 | } | |
| 516 | 587 | ||
| 517 | 588 | const keyLength = keys.length + symbols.length; | |
@@ -524,8 +595,8 @@ function formatValue(ctx, value, recurseTimes) { | |||
| 524 | 595 | let formatter = formatObject; | |
| 525 | 596 | let braces; | |
| 526 | 597 | let noIterator = true; | |
| 527 | - let raw; | ||
| 528 | 598 | let extra; | |
| 599 | + let i = 0; | ||
| 529 | 600 | ||
| 530 | 601 | // Iterators and the rest are split to reduce checks | |
| 531 | 602 | if (value[Symbol.iterator]) { | |
@@ -559,34 +630,16 @@ function formatValue(ctx, value, recurseTimes) { | |||
| 559 | 630 | braces = [`[${tag}] {`, '}']; | |
| 560 | 631 | formatter = formatSetIterator; | |
| 561 | 632 | } else { | |
| 562 | - // Check for boxed strings with valueOf() | ||
| 563 | - // The .valueOf() call can fail for a multitude of reasons | ||
| 564 | - try { | ||
| 565 | - raw = value.valueOf(); | ||
| 566 | - } catch (e) { /* ignore */ } | ||
| 567 | - | ||
| 568 | - if (typeof raw === 'string') { | ||
| 569 | - const formatted = formatPrimitive(stylizeNoColor, raw, ctx); | ||
| 570 | - if (keyLength === raw.length) | ||
| 571 | - return ctx.stylize(`[String: ${formatted}]`, 'string'); | ||
| 572 | - base = `[String: ${formatted}]`; | ||
| 573 | - // For boxed Strings, we have to remove the 0-n indexed entries, | ||
| 574 | - // since they just noisy up the output and are redundant | ||
| 575 | - // Make boxed primitive Strings look like such | ||
| 576 | - keys = keys.slice(value.length); | ||
| 577 | - braces = ['{', '}']; | ||
| 578 | - } else { | ||
| 579 | - noIterator = true; | ||
| 580 | - } | ||
| 633 | + noIterator = true; | ||
| 581 | 634 | } | |
| 582 | 635 | } | |
| 583 | 636 | if (noIterator) { | |
| 584 | 637 | braces = ['{', '}']; | |
| 585 | 638 | if (constructor === 'Object') { | |
| 586 | 639 | if (isArgumentsObject(value)) { | |
| 587 | - braces[0] = '[Arguments] {'; | ||
| 588 | 640 | if (keyLength === 0) | |
| 589 | 641 | return '[Arguments] {}'; | |
| 642 | + braces[0] = '[Arguments] {'; | ||
| 590 | 643 | } else if (tag !== '') { | |
| 591 | 644 | braces[0] = `${getPrefix(constructor, tag)}{`; | |
| 592 | 645 | if (keyLength === 0) { | |
@@ -596,24 +649,24 @@ function formatValue(ctx, value, recurseTimes) { | |||
| 596 | 649 | return '{}'; | |
| 597 | 650 | } | |
| 598 | 651 | } else if (typeof value === 'function') { | |
| 599 | - const name = | ||
| 600 | - `${constructor || tag}${value.name ? `: ${value.name}` : ''}`; | ||
| 652 | + const type = constructor || tag || 'Function'; | ||
| 653 | + const name = `${type}${value.name ? `: ${value.name}` : ''}`; | ||
| 601 | 654 | if (keyLength === 0) | |
| 602 | 655 | return ctx.stylize(`[${name}]`, 'special'); | |
| 603 | 656 | base = `[${name}]`; | |
| 604 | 657 | } else if (isRegExp(value)) { | |
| 605 | 658 | // Make RegExps say that they are RegExps | |
| 606 | 659 | if (keyLength === 0 || recurseTimes < 0) | |
| 607 | - return ctx.stylize(regExpToString.call(value), 'regexp'); | ||
| 608 | - base = `${regExpToString.call(value)}`; | ||
| 660 | + return ctx.stylize(regExpToString(value), 'regexp'); | ||
| 661 | + base = `${regExpToString(value)}`; | ||
| 609 | 662 | } else if (isDate(value)) { | |
| 663 | + // Make dates with properties first say the date | ||
| 610 | 664 | if (keyLength === 0) { | |
| 611 | - if (Number.isNaN(value.getTime())) | ||
| 612 | - return ctx.stylize(value.toString(), 'date'); | ||
| 613 | - return ctx.stylize(dateToISOString.call(value), 'date'); | ||
| 665 | + if (Number.isNaN(dateGetTime(value))) | ||
| 666 | + return ctx.stylize(String(value), 'date'); | ||
| 667 | + return ctx.stylize(dateToISOString(value), 'date'); | ||
| 614 | 668 | } | |
| 615 | - // Make dates with properties first say the date | ||
| 616 | - base = dateToISOString.call(value); | ||
| 669 | + base = dateToISOString(value); | ||
| 617 | 670 | } else if (isError(value)) { | |
| 618 | 671 | // Make error with message first say the error | |
| 619 | 672 | base = formatError(value); | |
@@ -638,28 +691,31 @@ function formatValue(ctx, value, recurseTimes) { | |||
| 638 | 691 | // Fast path for ArrayBuffer and SharedArrayBuffer. | |
| 639 | 692 | // Can't do the same for DataView because it has a non-primitive | |
| 640 | 693 | // .buffer property that we need to recurse for. | |
| 641 | - const prefix = getPrefix(constructor, tag); | ||
| 694 | + let prefix = getPrefix(constructor, tag); | ||
| 695 | + if (prefix === '') { | ||
| 696 | + prefix = isArrayBuffer(value) ? 'ArrayBuffer ' : 'SharedArrayBuffer '; | ||
| 697 | + } | ||
| 642 | 698 | if (keyLength === 0) | |
| 643 | 699 | return prefix + | |
| 644 | 700 | `{ byteLength: ${formatNumber(ctx.stylize, value.byteLength)} }`; | |
| 645 | 701 | braces[0] = `${prefix}{`; | |
| 646 | 702 | keys.unshift('byteLength'); | |
| 647 | 703 | } else if (isDataView(value)) { | |
| 648 | - braces[0] = `${getPrefix(constructor, tag)}{`; | ||
| 704 | + braces[0] = `${getPrefix(constructor, tag, 'DataView')}{`; | ||
| 649 | 705 | // .buffer goes last, it's not a primitive like the others. | |
| 650 | 706 | keys.unshift('byteLength', 'byteOffset', 'buffer'); | |
| 651 | 707 | } else if (isPromise(value)) { | |
| 652 | - braces[0] = `${getPrefix(constructor, tag)}{`; | ||
| 708 | + braces[0] = `${getPrefix(constructor, tag, 'Promise')}{`; | ||
| 653 | 709 | formatter = formatPromise; | |
| 654 | 710 | } else if (isWeakSet(value)) { | |
| 655 | - braces[0] = `${getPrefix(constructor, tag)}{`; | ||
| 711 | + braces[0] = `${getPrefix(constructor, tag, 'WeakSet')}{`; | ||
| 656 | 712 | if (ctx.showHidden) { | |
| 657 | 713 | formatter = formatWeakSet; | |
| 658 | 714 | } else { | |
| 659 | 715 | extra = '[items unknown]'; | |
| 660 | 716 | } | |
| 661 | 717 | } else if (isWeakMap(value)) { | |
| 662 | - braces[0] = `${getPrefix(constructor, tag)}{`; | ||
| 718 | + braces[0] = `${getPrefix(constructor, tag, 'WeakMap')}{`; | ||
| 663 | 719 | if (ctx.showHidden) { | |
| 664 | 720 | formatter = formatWeakMap; | |
| 665 | 721 | } else { | |
@@ -668,43 +724,67 @@ function formatValue(ctx, value, recurseTimes) { | |||
| 668 | 724 | } else if (types.isModuleNamespaceObject(value)) { | |
| 669 | 725 | braces[0] = `[${tag}] {`; | |
| 670 | 726 | formatter = formatNamespaceObject; | |
| 727 | + } else if (isNumberObject(value)) { | ||
| 728 | + base = `[Number: ${getBoxedValue(numberValueOf(value))}]`; | ||
| 729 | + if (keyLength === 0) | ||
| 730 | + return ctx.stylize(base, 'number'); | ||
| 731 | + } else if (isBooleanObject(value)) { | ||
| 732 | + base = `[Boolean: ${getBoxedValue(booleanValueOf(value))}]`; | ||
| 733 | + if (keyLength === 0) | ||
| 734 | + return ctx.stylize(base, 'boolean'); | ||
| 735 | + } else if (isBigIntObject(value)) { | ||
| 736 | + base = `[BigInt: ${getBoxedValue(bigIntValueOf(value))}]`; | ||
| 737 | + if (keyLength === 0) | ||
| 738 | + return ctx.stylize(base, 'bigint'); | ||
| 739 | + } else if (isSymbolObject(value)) { | ||
| 740 | + base = `[Symbol: ${getBoxedValue(symbolValueOf(value))}]`; | ||
| 741 | + if (keyLength === 0) | ||
| 742 | + return ctx.stylize(base, 'symbol'); | ||
| 743 | + } else if (isStringObject(value)) { | ||
| 744 | + const raw = stringValueOf(value); | ||
| 745 | + base = `[String: ${getBoxedValue(raw, ctx)}]`; | ||
| 746 | + if (keyLength === raw.length) | ||
| 747 | + return ctx.stylize(base, 'string'); | ||
| 748 | + // For boxed Strings, we have to remove the 0-n indexed entries, | ||
| 749 | + // since they just noisy up the output and are redundant | ||
| 750 | + // Make boxed primitive Strings look like such | ||
| 751 | + keys = keys.slice(value.length); | ||
| 752 | + braces = ['{', '}']; | ||
| 753 | + // The input prototype got manipulated. Special handle these. | ||
| 754 | + // We have to rebuild the information so we are able to display everything. | ||
| 755 | + } else if (isSet(value)) { | ||
| 756 | + const newVal = addExtraKeys(value, new Set(setValues(value)), keys); | ||
| 757 | + return formatValue(ctx, newVal, recurseTimes); | ||
| 758 | + } else if (isMap(value)) { | ||
| 759 | + const newVal = addExtraKeys(value, new Map(mapEntries(value)), keys); | ||
| 760 | + return formatValue(ctx, newVal, recurseTimes); | ||
| 761 | + } else if (Array.isArray(value)) { | ||
| 762 | + // The prefix is not always possible to fully reconstruct. | ||
| 763 | + const prefix = getPrefix(constructor, tag); | ||
| 764 | + braces = [`${prefix === 'Array ' ? '' : prefix}[`, ']']; | ||
| 765 | + formatter = formatArray; | ||
| 766 | + const newValue = []; | ||
| 767 | + newValue.length = value.length; | ||
| 768 | + value = addExtraKeys(value, newValue, keys); | ||
| 769 | + } else if (isTypedArray(value)) { | ||
| 770 | + const newValue = findTypedConstructor(value); | ||
| 771 | + value = addExtraKeys(value, newValue, keys.slice(newValue.length)); | ||
| 772 | + // The prefix is not always possible to fully reconstruct. | ||
| 773 | + braces = [`${getPrefix(getConstructorName(value), tag)}[`, ']']; | ||
| 774 | + formatter = formatTypedArray; | ||
| 775 | + } else if (isMapIterator(value)) { | ||
| 776 | + braces = [`[${tag || 'Map Iterator'}] {`, '}']; | ||
| 777 | + formatter = formatMapIterator; | ||
| 778 | + } else if (isSetIterator(value)) { | ||
| 779 | + braces = [`[${tag || 'Set Iterator'}] {`, '}']; | ||
| 780 | + formatter = formatSetIterator; | ||
| 781 | + // Handle other regular objects again. | ||
| 782 | + } else if (keyLength === 0) { | ||
| 783 | + if (isExternal(value)) | ||
| 784 | + return ctx.stylize('[External]', 'special'); | ||
| 785 | + return `${getPrefix(constructor, tag)}{}`; | ||
| 671 | 786 | } else { | |
| 672 | - // Check boxed primitives other than string with valueOf() | ||
| 673 | - // NOTE: `Date` has to be checked first! | ||
| 674 | - // The .valueOf() call can fail for a multitude of reasons | ||
| 675 | - try { | ||
| 676 | - raw = value.valueOf(); | ||
| 677 | - } catch (e) { /* ignore */ } | ||
| 678 | - | ||
| 679 | - if (typeof raw === 'number') { | ||
| 680 | - // Make boxed primitive Numbers look like such | ||
| 681 | - const formatted = formatPrimitive(stylizeNoColor, raw); | ||
| 682 | - if (keyLength === 0) | ||
| 683 | - return ctx.stylize(`[Number: ${formatted}]`, 'number'); | ||
| 684 | - base = `[Number: ${formatted}]`; | ||
| 685 | - } else if (typeof raw === 'boolean') { | ||
| 686 | - // Make boxed primitive Booleans look like such | ||
| 687 | - const formatted = formatPrimitive(stylizeNoColor, raw); | ||
| 688 | - if (keyLength === 0) | ||
| 689 | - return ctx.stylize(`[Boolean: ${formatted}]`, 'boolean'); | ||
| 690 | - base = `[Boolean: ${formatted}]`; | ||
| 691 | - // eslint-disable-next-line valid-typeof | ||
| 692 | - } else if (typeof raw === 'bigint') { | ||
| 693 | - // Make boxed primitive BigInts look like such | ||
| 694 | - const formatted = formatPrimitive(stylizeNoColor, raw); | ||
| 695 | - if (keyLength === 0) | ||
| 696 | - return ctx.stylize(`[BigInt: ${formatted}]`, 'bigint'); | ||
| 697 | - base = `[BigInt: ${formatted}]`; | ||
| 698 | - } else if (typeof raw === 'symbol') { | ||
| 699 | - const formatted = formatPrimitive(stylizeNoColor, raw); | ||
| 700 | - return ctx.stylize(`[Symbol: ${formatted}]`, 'symbol'); | ||
| 701 | - } else if (keyLength === 0) { | ||
| 702 | - if (isExternal(value)) | ||
| 703 | - return ctx.stylize('[External]', 'special'); | ||
| 704 | - return `${getPrefix(constructor, tag)}{}`; | ||
| 705 | - } else { | ||
| 706 | - braces[0] = `${getPrefix(constructor, tag)}{`; | ||
| 707 | - } | ||
| 787 | + braces[0] = `${getPrefix(constructor, tag)}{`; | ||
| 708 | 788 | } | |
| 709 | 789 | } | |
| 710 | 790 | ||
@@ -737,7 +817,7 @@ function formatValue(ctx, value, recurseTimes) { | |||
| 737 | 817 | if (extra !== undefined) | |
| 738 | 818 | output.unshift(extra); | |
| 739 | 819 | ||
| 740 | - for (var i = 0; i < symbols.length; i++) { | ||
| 820 | + for (i = 0; i < symbols.length; i++) { | ||
| 741 | 821 | output.push(formatProperty(ctx, value, recurseTimes, symbols[i], 0)); | |
| 742 | 822 | } | |
| 743 | 823 | ||
@@ -803,7 +883,7 @@ function formatPrimitive(fn, value, ctx) { | |||
| 803 | 883 | } | |
| 804 | 884 | ||
| 805 | 885 | function formatError(value) { | |
| 806 | - return value.stack || errorToString.call(value); | ||
| 886 | + return value.stack || errorToString(value); | ||
| 807 | 887 | } | |
| 808 | 888 | ||
| 809 | 889 | function formatObject(ctx, value, recurseTimes, keys) { | |
| Back | FazBrowse Home | New Git URL |
0 commit comments