@@ -72,6 +72,7 @@ const { |
72 | 72 | ObjectPrototype, |
73 | 73 | ObjectPrototypeHasOwnProperty, |
74 | 74 | ObjectPrototypePropertyIsEnumerable, |
| 75 | + ObjectPrototypeToString, |
75 | 76 | ObjectSeal, |
76 | 77 | ObjectSetPrototypeOf, |
77 | 78 | Promise, |
@@ -1720,13 +1721,19 @@ function getDuplicateErrorFrameRanges(frames) { |
1720 | 1721 | } |
1721 | 1722 |
|
1722 | 1723 | function getStackString(ctx, error) { |
1723 | | - if (error.stack) { |
1724 | | - if (typeof error.stack === 'string') { |
1725 | | - return error.stack; |
| 1724 | + let stack; |
| 1725 | + try { |
| 1726 | + stack = error.stack; |
| 1727 | + } catch { |
| 1728 | + // If stack is getter that throws, we ignore the error. |
| 1729 | + } |
| 1730 | + if (stack) { |
| 1731 | + if (typeof stack === 'string') { |
| 1732 | + return stack; |
1726 | 1733 | } |
1727 | 1734 | ctx.seen.push(error); |
1728 | 1735 | ctx.indentationLvl += 4; |
1729 | | - const result = formatValue(ctx, error.stack); |
| 1736 | + const result = formatValue(ctx, stack); |
1730 | 1737 | ctx.indentationLvl -= 4; |
1731 | 1738 | ctx.seen.pop(); |
1732 | 1739 | return `${ErrorPrototypeToString(error)}\n ${result}`; |
@@ -1822,18 +1829,6 @@ function improveStack(stack, constructor, name, tag) { |
1822 | 1829 | return stack; |
1823 | 1830 | } |
1824 | 1831 |
|
1825 | | -function removeDuplicateErrorKeys(ctx, keys, err, stack) { |
1826 | | - if (!ctx.showHidden && keys.length !== 0) { |
1827 | | - for (const name of ['name', 'message', 'stack']) { |
1828 | | - const index = ArrayPrototypeIndexOf(keys, name); |
1829 | | - // Only hide the property if it's a string and if it's part of the original stack |
1830 | | - if (index !== -1 && (typeof err[name] !== 'string' || StringPrototypeIncludes(stack, err[name]))) { |
1831 | | - ArrayPrototypeSplice(keys, index, 1); |
1832 | | - } |
1833 | | - } |
1834 | | - } |
1835 | | -} |
1836 | | - |
1837 | 1832 | function markNodeModules(ctx, line) { |
1838 | 1833 | let tempLine = ''; |
1839 | 1834 | let lastPos = 0; |
@@ -1916,28 +1911,72 @@ function safeGetCWD() { |
1916 | 1911 | } |
1917 | 1912 |
|
1918 | 1913 | function formatError(err, constructor, tag, ctx, keys) { |
1919 | | - const name = err.name != null ? err.name : 'Error'; |
1920 | | - let stack = getStackString(ctx, err); |
| 1914 | + let message, name, stack; |
| 1915 | + try { |
| 1916 | + stack = getStackString(ctx, err); |
| 1917 | + } catch { |
| 1918 | + return ObjectPrototypeToString(err); |
| 1919 | + } |
1921 | 1920 |
|
1922 | | - removeDuplicateErrorKeys(ctx, keys, err, stack); |
| 1921 | + let messageIsGetterThatThrows = false; |
| 1922 | + try { |
| 1923 | + message = err.message; |
| 1924 | + } catch { |
| 1925 | + messageIsGetterThatThrows = true; |
| 1926 | + } |
| 1927 | + let nameIsGetterThatThrows = false; |
| 1928 | + try { |
| 1929 | + name = err.name; |
| 1930 | + } catch { |
| 1931 | + nameIsGetterThatThrows = true; |
| 1932 | + } |
| 1933 | + |
| 1934 | + if (!ctx.showHidden && keys.length !== 0) { |
| 1935 | + const index = ArrayPrototypeIndexOf(keys, 'stack'); |
| 1936 | + if (index !== -1) { |
| 1937 | + ArrayPrototypeSplice(keys, index, 1); |
| 1938 | + } |
| 1939 | + |
| 1940 | + if (!messageIsGetterThatThrows) { |
| 1941 | + const index = ArrayPrototypeIndexOf(keys, 'message'); |
| 1942 | + // Only hide the property if it's a string and if it's part of the original stack |
| 1943 | + if (index !== -1 && (typeof message !== 'string' || StringPrototypeIncludes(stack, message))) { |
| 1944 | + ArrayPrototypeSplice(keys, index, 1); |
| 1945 | + } |
| 1946 | + } |
| 1947 | + |
| 1948 | + if (!nameIsGetterThatThrows) { |
| 1949 | + const index = ArrayPrototypeIndexOf(keys, 'name'); |
| 1950 | + // Only hide the property if it's a string and if it's part of the original stack |
| 1951 | + if (index !== -1 && (typeof name !== 'string' || StringPrototypeIncludes(stack, name))) { |
| 1952 | + ArrayPrototypeSplice(keys, index, 1); |
| 1953 | + } |
| 1954 | + } |
| 1955 | + } |
| 1956 | + name ??= 'Error'; |
1923 | 1957 |
|
1924 | 1958 | if ('cause' in err && |
1925 | 1959 | (keys.length === 0 || !ArrayPrototypeIncludes(keys, 'cause'))) { |
1926 | 1960 | ArrayPrototypePush(keys, 'cause'); |
1927 | 1961 | } |
1928 | 1962 |
|
1929 | 1963 | // Print errors aggregated into AggregateError |
1930 | | - if (ArrayIsArray(err.errors) && |
| 1964 | + try { |
| 1965 | + const errors = err.errors; |
| 1966 | + if (ArrayIsArray(errors) && |
1931 | 1967 | (keys.length === 0 || !ArrayPrototypeIncludes(keys, 'errors'))) { |
1932 | | - ArrayPrototypePush(keys, 'errors'); |
| 1968 | + ArrayPrototypePush(keys, 'errors'); |
| 1969 | + } |
| 1970 | + } catch { |
| 1971 | + // If errors is a getter that throws, we ignore the error. |
1933 | 1972 | } |
1934 | 1973 |
|
1935 | 1974 | stack = improveStack(stack, constructor, name, tag); |
1936 | 1975 |
|
1937 | 1976 | // Ignore the error message if it's contained in the stack. |
1938 | | - let pos = (err.message && StringPrototypeIndexOf(stack, err.message)) || -1; |
| 1977 | + let pos = (message && StringPrototypeIndexOf(stack, message)) || -1; |
1939 | 1978 | if (pos !== -1) |
1940 | | - pos += err.message.length; |
| 1979 | + pos += message.length; |
1941 | 1980 | // Wrap the error in brackets in case it has no stack trace. |
1942 | 1981 | const stackStart = StringPrototypeIndexOf(stack, '\n at', pos); |
1943 | 1982 | if (stackStart === -1) { |
|