| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent b0e3aec commit 3b9360d
2 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -11,6 +11,7 @@ const { | |||
| 11 | 11 | ErrorPrototypeToString, | |
| 12 | 12 | JSONStringify, | |
| 13 | 13 | Map, | |
| 14 | + MapPrototype, | ||
| 14 | 15 | MapPrototypeEntries, | |
| 15 | 16 | MathFloor, | |
| 16 | 17 | MathMax, | |
@@ -22,10 +23,8 @@ const { | |||
| 22 | 23 | NumberPrototypeValueOf, | |
| 23 | 24 | ObjectAssign, | |
| 24 | 25 | ObjectCreate, | |
| 25 | - ObjectDefineProperties, | ||
| 26 | 26 | ObjectDefineProperty, | |
| 27 | 27 | ObjectGetOwnPropertyDescriptor, | |
| 28 | - ObjectGetOwnPropertyDescriptors, | ||
| 29 | 28 | ObjectGetOwnPropertyNames, | |
| 30 | 29 | ObjectGetOwnPropertySymbols, | |
| 31 | 30 | ObjectGetPrototypeOf, | |
@@ -36,6 +35,7 @@ const { | |||
| 36 | 35 | ObjectSeal, | |
| 37 | 36 | RegExpPrototypeToString, | |
| 38 | 37 | Set, | |
| 38 | + SetPrototype, | ||
| 39 | 39 | SetPrototypeValues, | |
| 40 | 40 | StringPrototypeValueOf, | |
| 41 | 41 | SymbolPrototypeToString, | |
@@ -115,6 +115,11 @@ const assert = require('internal/assert'); | |||
| 115 | 115 | ||
| 116 | 116 | const { NativeModule } = require('internal/bootstrap/loaders'); | |
| 117 | 117 | ||
| 118 | + const setSizeGetter = uncurryThis( | ||
| 119 | + ObjectGetOwnPropertyDescriptor(SetPrototype, 'size').get); | ||
| 120 | + const mapSizeGetter = uncurryThis( | ||
| 121 | + ObjectGetOwnPropertyDescriptor(MapPrototype, 'size').get); | ||
| 122 | + | ||
| 118 | 123 | let hexSlice; | |
| 119 | 124 | ||
| 120 | 125 | const builtInObjects = new Set( | |
@@ -648,51 +653,6 @@ function findTypedConstructor(value) { | |||
| 648 | 653 | } | |
| 649 | 654 | } | |
| 650 | 655 | ||
| 651 | - let lazyNullPrototypeCache; | ||
| 652 | - // Creates a subclass and name | ||
| 653 | - // the constructor as `${clazz} : null prototype` | ||
| 654 | - function clazzWithNullPrototype(clazz, name) { | ||
| 655 | - if (lazyNullPrototypeCache === undefined) { | ||
| 656 | - lazyNullPrototypeCache = new Map(); | ||
| 657 | - } else { | ||
| 658 | - const cachedClass = lazyNullPrototypeCache.get(clazz); | ||
| 659 | - if (cachedClass !== undefined) { | ||
| 660 | - return cachedClass; | ||
| 661 | - } | ||
| 662 | - } | ||
| 663 | - class NullPrototype extends clazz { | ||
| 664 | - get [SymbolToStringTag]() { | ||
| 665 | - return ''; | ||
| 666 | - } | ||
| 667 | - } | ||
| 668 | - ObjectDefineProperty(NullPrototype.prototype.constructor, 'name', | ||
| 669 | - { value: `[${name}: null prototype]` }); | ||
| 670 | - lazyNullPrototypeCache.set(clazz, NullPrototype); | ||
| 671 | - return NullPrototype; | ||
| 672 | - } | ||
| 673 | - | ||
| 674 | - function noPrototypeIterator(ctx, value, recurseTimes) { | ||
| 675 | - let newVal; | ||
| 676 | - if (isSet(value)) { | ||
| 677 | - const clazz = clazzWithNullPrototype(Set, 'Set'); | ||
| 678 | - newVal = new clazz(SetPrototypeValues(value)); | ||
| 679 | - } else if (isMap(value)) { | ||
| 680 | - const clazz = clazzWithNullPrototype(Map, 'Map'); | ||
| 681 | - newVal = new clazz(MapPrototypeEntries(value)); | ||
| 682 | - } else if (ArrayIsArray(value)) { | ||
| 683 | - const clazz = clazzWithNullPrototype(Array, 'Array'); | ||
| 684 | - newVal = new clazz(value.length); | ||
| 685 | - } else if (isTypedArray(value)) { | ||
| 686 | - const constructor = findTypedConstructor(value); | ||
| 687 | - const clazz = clazzWithNullPrototype(constructor, constructor.name); | ||
| 688 | - newVal = new clazz(value); | ||
| 689 | - } | ||
| 690 | - if (newVal !== undefined) { | ||
| 691 | - ObjectDefineProperties(newVal, ObjectGetOwnPropertyDescriptors(value)); | ||
| 692 | - return formatRaw(ctx, newVal, recurseTimes); | ||
| 693 | - } | ||
| 694 | - } | ||
| 695 | - | ||
| 696 | 656 | // Note: using `formatValue` directly requires the indentation level to be | |
| 697 | 657 | // corrected by setting `ctx.indentationLvL += diff` and then to decrease the | |
| 698 | 658 | // value afterwards again. | |
@@ -795,7 +755,9 @@ function formatRaw(ctx, value, recurseTimes, typedArray) { | |||
| 795 | 755 | let extrasType = kObjectType; | |
| 796 | 756 | ||
| 797 | 757 | // Iterators and the rest are split to reduce checks. | |
| 798 | - if (value[SymbolIterator]) { | ||
| 758 | + // We have to check all values in case the constructor is set to null. | ||
| 759 | + // Otherwise it would not possible to identify all types properly. | ||
| 760 | + if (value[SymbolIterator] || constructor === null) { | ||
| 799 | 761 | noIterator = false; | |
| 800 | 762 | if (ArrayIsArray(value)) { | |
| 801 | 763 | keys = getOwnNonIndexProperties(value, filter); | |
@@ -807,37 +769,66 @@ function formatRaw(ctx, value, recurseTimes, typedArray) { | |||
| 807 | 769 | extrasType = kArrayExtrasType; | |
| 808 | 770 | formatter = formatArray; | |
| 809 | 771 | } else if (isSet(value)) { | |
| 772 | + const size = setSizeGetter(value); | ||
| 810 | 773 | keys = getKeys(value, ctx.showHidden); | |
| 811 | - const prefix = getPrefix(constructor, tag, 'Set'); | ||
| 812 | - if (value.size === 0 && keys.length === 0 && protoProps === undefined) | ||
| 774 | + let prefix = ''; | ||
| 775 | + if (constructor !== null) { | ||
| 776 | + if (constructor === tag) | ||
| 777 | + tag = ''; | ||
| 778 | + prefix = getPrefix(`${constructor}`, tag, ''); | ||
| 779 | + formatter = formatSet.bind(null, value, size); | ||
| 780 | + } else { | ||
| 781 | + prefix = getPrefix(constructor, tag, 'Set'); | ||
| 782 | + formatter = formatSet.bind(null, SetPrototypeValues(value), size); | ||
| 783 | + } | ||
| 784 | + if (size === 0 && keys.length === 0 && protoProps === undefined) | ||
| 813 | 785 | return `${prefix}{}`; | |
| 814 | 786 | braces = [`${prefix}{`, '}']; | |
| 815 | - formatter = formatSet; | ||
| 816 | 787 | } else if (isMap(value)) { | |
| 788 | + const size = mapSizeGetter(value); | ||
| 817 | 789 | keys = getKeys(value, ctx.showHidden); | |
| 818 | - const prefix = getPrefix(constructor, tag, 'Map'); | ||
| 819 | - if (value.size === 0 && keys.length === 0 && protoProps === undefined) | ||
| 790 | + let prefix = ''; | ||
| 791 | + if (constructor !== null) { | ||
| 792 | + if (constructor === tag) | ||
| 793 | + tag = ''; | ||
| 794 | + prefix = getPrefix(`${constructor}`, tag, ''); | ||
| 795 | + formatter = formatMap.bind(null, value, size); | ||
| 796 | + } else { | ||
| 797 | + prefix = getPrefix(constructor, tag, 'Map'); | ||
| 798 | + formatter = formatMap.bind(null, MapPrototypeEntries(value), size); | ||
| 799 | + } | ||
| 800 | + if (size === 0 && keys.length === 0 && protoProps === undefined) | ||
| 820 | 801 | return `${prefix}{}`; | |
| 821 | 802 | braces = [`${prefix}{`, '}']; | |
| 822 | - formatter = formatMap; | ||
| 823 | 803 | } else if (isTypedArray(value)) { | |
| 824 | 804 | keys = getOwnNonIndexProperties(value, filter); | |
| 825 | - const prefix = constructor !== null ? | ||
| 826 | - getPrefix(constructor, tag) : | ||
| 827 | - getPrefix(constructor, tag, findTypedConstructor(value).name); | ||
| 805 | + let bound = value; | ||
| 806 | + let prefix = ''; | ||
| 807 | + if (constructor === null) { | ||
| 808 | + const constr = findTypedConstructor(value); | ||
| 809 | + prefix = getPrefix(constructor, tag, constr.name); | ||
| 810 | + // Reconstruct the array information. | ||
| 811 | + bound = new constr(value); | ||
| 812 | + } else { | ||
| 813 | + prefix = getPrefix(constructor, tag); | ||
| 814 | + } | ||
| 828 | 815 | braces = [`${prefix}[`, ']']; | |
| 829 | 816 | if (value.length === 0 && keys.length === 0 && !ctx.showHidden) | |
| 830 | 817 | return `${braces[0]}]`; | |
| 831 | - formatter = formatTypedArray; | ||
| 818 | + // Special handle the value. The original value is required below. The | ||
| 819 | + // bound function is required to reconstruct missing information. | ||
| 820 | + formatter = formatTypedArray.bind(null, bound); | ||
| 832 | 821 | extrasType = kArrayExtrasType; | |
| 833 | 822 | } else if (isMapIterator(value)) { | |
| 834 | 823 | keys = getKeys(value, ctx.showHidden); | |
| 835 | 824 | braces = getIteratorBraces('Map', tag); | |
| 836 | - formatter = formatIterator; | ||
| 825 | + // Add braces to the formatter parameters. | ||
| 826 | + formatter = formatIterator.bind(null, braces); | ||
| 837 | 827 | } else if (isSetIterator(value)) { | |
| 838 | 828 | keys = getKeys(value, ctx.showHidden); | |
| 839 | 829 | braces = getIteratorBraces('Set', tag); | |
| 840 | - formatter = formatIterator; | ||
| 830 | + // Add braces to the formatter parameters. | ||
| 831 | + formatter = formatIterator.bind(null, braces); | ||
| 841 | 832 | } else { | |
| 842 | 833 | noIterator = true; | |
| 843 | 834 | } | |
@@ -915,36 +906,20 @@ function formatRaw(ctx, value, recurseTimes, typedArray) { | |||
| 915 | 906 | formatter = ctx.showHidden ? formatWeakMap : formatWeakCollection; | |
| 916 | 907 | } else if (isModuleNamespaceObject(value)) { | |
| 917 | 908 | braces[0] = `[${tag}] {`; | |
| 918 | - formatter = formatNamespaceObject; | ||
| 909 | + // Special handle keys for namespace objects. | ||
| 910 | + formatter = formatNamespaceObject.bind(null, keys); | ||
| 919 | 911 | } else if (isBoxedPrimitive(value)) { | |
| 920 | 912 | base = getBoxedBase(value, ctx, keys, constructor, tag); | |
| 921 | 913 | if (keys.length === 0 && protoProps === undefined) { | |
| 922 | 914 | return base; | |
| 923 | 915 | } | |
| 924 | 916 | } else { | |
| 925 | - // The input prototype got manipulated. Special handle these. We have to | ||
| 926 | - // rebuild the information so we are able to display everything. | ||
| 927 | - if (constructor === null) { | ||
| 928 | - const specialIterator = noPrototypeIterator(ctx, value, recurseTimes); | ||
| 929 | - if (specialIterator) { | ||
| 930 | - return specialIterator; | ||
| 931 | - } | ||
| 932 | - } | ||
| 933 | - if (isMapIterator(value)) { | ||
| 934 | - braces = getIteratorBraces('Map', tag); | ||
| 935 | - formatter = formatIterator; | ||
| 936 | - } else if (isSetIterator(value)) { | ||
| 937 | - braces = getIteratorBraces('Set', tag); | ||
| 938 | - formatter = formatIterator; | ||
| 939 | - // Handle other regular objects again. | ||
| 940 | - } else { | ||
| 941 | - if (keys.length === 0 && protoProps === undefined) { | ||
| 942 | - if (isExternal(value)) | ||
| 943 | - return ctx.stylize('[External]', 'special'); | ||
| 944 | - return `${getCtxStyle(value, constructor, tag)}{}`; | ||
| 945 | - } | ||
| 946 | - braces[0] = `${getCtxStyle(value, constructor, tag)}{`; | ||
| 917 | + if (keys.length === 0 && protoProps === undefined) { | ||
| 918 | + if (isExternal(value)) | ||
| 919 | + return ctx.stylize('[External]', 'special'); | ||
| 920 | + return `${getCtxStyle(value, constructor, tag)}{}`; | ||
| 947 | 921 | } | |
| 922 | + braces[0] = `${getCtxStyle(value, constructor, tag)}{`; | ||
| 948 | 923 | } | |
| 949 | 924 | } | |
| 950 | 925 | ||
@@ -961,7 +936,7 @@ function formatRaw(ctx, value, recurseTimes, typedArray) { | |||
| 961 | 936 | let output; | |
| 962 | 937 | const indentationLvl = ctx.indentationLvl; | |
| 963 | 938 | try { | |
| 964 | - output = formatter(ctx, value, recurseTimes, keys, braces); | ||
| 939 | + output = formatter(ctx, value, recurseTimes); | ||
| 965 | 940 | for (i = 0; i < keys.length; i++) { | |
| 966 | 941 | output.push( | |
| 967 | 942 | formatProperty(ctx, value, recurseTimes, keys[i], extrasType)); | |
@@ -1316,7 +1291,7 @@ function formatPrimitive(fn, value, ctx) { | |||
| 1316 | 1291 | return fn(SymbolPrototypeToString(value), 'symbol'); | |
| 1317 | 1292 | } | |
| 1318 | 1293 | ||
| 1319 | - function formatNamespaceObject(ctx, value, recurseTimes, keys) { | ||
| 1294 | + function formatNamespaceObject(keys, ctx, value, recurseTimes) { | ||
| 1320 | 1295 | const output = new Array(keys.length); | |
| 1321 | 1296 | for (let i = 0; i < keys.length; i++) { | |
| 1322 | 1297 | try { | |
@@ -1418,7 +1393,7 @@ function formatArray(ctx, value, recurseTimes) { | |||
| 1418 | 1393 | return output; | |
| 1419 | 1394 | } | |
| 1420 | 1395 | ||
| 1421 | - function formatTypedArray(ctx, value, recurseTimes) { | ||
| 1396 | + function formatTypedArray(value, ctx, ignored, recurseTimes) { | ||
| 1422 | 1397 | const maxLength = MathMin(MathMax(0, ctx.maxArrayLength), value.length); | |
| 1423 | 1398 | const remaining = value.length - maxLength; | |
| 1424 | 1399 | const output = new Array(maxLength); | |
@@ -1449,7 +1424,7 @@ function formatTypedArray(ctx, value, recurseTimes) { | |||
| 1449 | 1424 | return output; | |
| 1450 | 1425 | } | |
| 1451 | 1426 | ||
| 1452 | - function formatSet(ctx, value, recurseTimes) { | ||
| 1427 | + function formatSet(value, size, ctx, ignored, recurseTimes) { | ||
| 1453 | 1428 | const output = []; | |
| 1454 | 1429 | ctx.indentationLvl += 2; | |
| 1455 | 1430 | for (const v of value) { | |
@@ -1460,11 +1435,11 @@ function formatSet(ctx, value, recurseTimes) { | |||
| 1460 | 1435 | // arrays. For consistency's sake, do the same for `size`, even though this | |
| 1461 | 1436 | // property isn't selected by ObjectGetOwnPropertyNames(). | |
| 1462 | 1437 | if (ctx.showHidden) | |
| 1463 | - output.push(`[size]: ${ctx.stylize(`${value.size}`, 'number')}`); | ||
| 1438 | + output.push(`[size]: ${ctx.stylize(`${size}`, 'number')}`); | ||
| 1464 | 1439 | return output; | |
| 1465 | 1440 | } | |
| 1466 | 1441 | ||
| 1467 | - function formatMap(ctx, value, recurseTimes) { | ||
| 1442 | + function formatMap(value, size, ctx, ignored, recurseTimes) { | ||
| 1468 | 1443 | const output = []; | |
| 1469 | 1444 | ctx.indentationLvl += 2; | |
| 1470 | 1445 | for (const [k, v] of value) { | |
@@ -1474,7 +1449,7 @@ function formatMap(ctx, value, recurseTimes) { | |||
| 1474 | 1449 | ctx.indentationLvl -= 2; | |
| 1475 | 1450 | // See comment in formatSet | |
| 1476 | 1451 | if (ctx.showHidden) | |
| 1477 | - output.push(`[size]: ${ctx.stylize(`${value.size}`, 'number')}`); | ||
| 1452 | + output.push(`[size]: ${ctx.stylize(`${size}`, 'number')}`); | ||
| 1478 | 1453 | return output; | |
| 1479 | 1454 | } | |
| 1480 | 1455 | ||
@@ -1552,7 +1527,7 @@ function formatWeakMap(ctx, value, recurseTimes) { | |||
| 1552 | 1527 | return formatMapIterInner(ctx, recurseTimes, entries, kWeak); | |
| 1553 | 1528 | } | |
| 1554 | 1529 | ||
| 1555 | - function formatIterator(ctx, value, recurseTimes, keys, braces) { | ||
| 1530 | + function formatIterator(braces, ctx, value, recurseTimes) { | ||
| 1556 | 1531 | const [entries, isKeyValue] = previewEntries(value, true); | |
| 1557 | 1532 | if (isKeyValue) { | |
| 1558 | 1533 | // Mark entry iterators as such. | |
@@ -1587,7 +1562,7 @@ function formatProperty(ctx, value, recurseTimes, key, type, desc) { | |||
| 1587 | 1562 | desc = desc || ObjectGetOwnPropertyDescriptor(value, key) || | |
| 1588 | 1563 | { value: value[key], enumerable: true }; | |
| 1589 | 1564 | if (desc.value !== undefined) { | |
| 1590 | - const diff = (type !== kObjectType || ctx.compact !== true) ? 2 : 3; | ||
| 1565 | + const diff = (ctx.compact !== true || type !== kObjectType) ? 2 : 3; | ||
| 1591 | 1566 | ctx.indentationLvl += diff; | |
| 1592 | 1567 | str = formatValue(ctx, desc.value, recurseTimes); | |
| 1593 | 1568 | if (diff === 3) { | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -2216,6 +2216,19 @@ assert.strictEqual( | |||
| 2216 | 2216 | configurable: true | |
| 2217 | 2217 | }); | |
| 2218 | 2218 | assert.strictEqual(util.inspect(obj), '[Set: null prototype] { 1, 2 }'); | |
| 2219 | + Object.defineProperty(obj, Symbol.iterator, { | ||
| 2220 | + value: true, | ||
| 2221 | + configurable: true | ||
| 2222 | + }); | ||
| 2223 | + Object.defineProperty(obj, 'size', { | ||
| 2224 | + value: NaN, | ||
| 2225 | + configurable: true, | ||
| 2226 | + enumerable: true | ||
| 2227 | + }); | ||
| 2228 | + assert.strictEqual( | ||
| 2229 | + util.inspect(obj), | ||
| 2230 | + '[Set: null prototype] { 1, 2, size: NaN }' | ||
| 2231 | + ); | ||
| 2219 | 2232 | } | |
| 2220 | 2233 | ||
| 2221 | 2234 | // Check the getter option. | |
| Back | FazBrowse Home | New Git URL |
0 commit comments