| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent a959f4f commit da87413
3 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1162,25 +1162,58 @@ function getFunctionBase(value, constructor, tag) { | |||
| 1162 | 1162 | return base; | |
| 1163 | 1163 | } | |
| 1164 | 1164 | ||
| 1165 | - function formatError(err, constructor, tag, ctx, keys) { | ||
| 1166 | - const name = err.name != null ? String(err.name) : 'Error'; | ||
| 1167 | - let len = name.length; | ||
| 1168 | - let stack = err.stack ? String(err.stack) : ErrorPrototypeToString(err); | ||
| 1165 | + function identicalSequenceRange(a, b) { | ||
| 1166 | + for (let i = 0; i < a.length - 3; i++) { | ||
| 1167 | + // Find the first entry of b that matches the current entry of a. | ||
| 1168 | + const pos = b.indexOf(a[i]); | ||
| 1169 | + if (pos !== -1) { | ||
| 1170 | + const rest = b.length - pos; | ||
| 1171 | + if (rest > 3) { | ||
| 1172 | + let len = 1; | ||
| 1173 | + const maxLen = MathMin(a.length - i, rest); | ||
| 1174 | + // Count the number of consecutive entries. | ||
| 1175 | + while (maxLen > len && a[i + len] === b[pos + len]) { | ||
| 1176 | + len++; | ||
| 1177 | + } | ||
| 1178 | + if (len > 3) { | ||
| 1179 | + return { len, offset: i }; | ||
| 1180 | + } | ||
| 1181 | + } | ||
| 1182 | + } | ||
| 1183 | + } | ||
| 1169 | 1184 | ||
| 1170 | - // Do not "duplicate" error properties that are already included in the output | ||
| 1171 | - // otherwise. | ||
| 1172 | - if (!ctx.showHidden && keys.length !== 0) { | ||
| 1173 | - for (const name of ['name', 'message', 'stack']) { | ||
| 1174 | - const index = keys.indexOf(name); | ||
| 1175 | - // Only hide the property in case it's part of the original stack | ||
| 1176 | - if (index !== -1 && stack.includes(err[name])) { | ||
| 1177 | - keys.splice(index, 1); | ||
| 1185 | + return { len: 0, offset: 0 }; | ||
| 1186 | + } | ||
| 1187 | + | ||
| 1188 | + function getStackString(error) { | ||
| 1189 | + return error.stack ? String(error.stack) : ErrorPrototypeToString(error); | ||
| 1190 | + } | ||
| 1191 | + | ||
| 1192 | + function getStackFrames(ctx, err, stack) { | ||
| 1193 | + const frames = stack.split('\n'); | ||
| 1194 | + | ||
| 1195 | + // Remove stack frames identical to frames in cause. | ||
| 1196 | + if (err.cause) { | ||
| 1197 | + const causeStack = getStackString(err.cause); | ||
| 1198 | + const causeStackStart = causeStack.indexOf('\n at'); | ||
| 1199 | + if (causeStackStart !== -1) { | ||
| 1200 | + const causeFrames = causeStack.slice(causeStackStart + 1).split('\n'); | ||
| 1201 | + const { len, offset } = identicalSequenceRange(frames, causeFrames); | ||
| 1202 | + if (len > 0) { | ||
| 1203 | + const skipped = len - 2; | ||
| 1204 | + const msg = ` ... ${skipped} lines matching cause stack trace ...`; | ||
| 1205 | + frames.splice(offset + 1, skipped, ctx.stylize(msg, 'undefined')); | ||
| 1178 | 1206 | } | |
| 1179 | 1207 | } | |
| 1180 | 1208 | } | |
| 1209 | + return frames; | ||
| 1210 | + } | ||
| 1181 | 1211 | ||
| 1212 | + function improveStack(stack, constructor, name, tag) { | ||
| 1182 | 1213 | // A stack trace may contain arbitrary data. Only manipulate the output | |
| 1183 | 1214 | // for "regular errors" (errors that "look normal") for now. | |
| 1215 | + let len = name.length; | ||
| 1216 | + | ||
| 1184 | 1217 | if (constructor === null || | |
| 1185 | 1218 | (name.endsWith('Error') && | |
| 1186 | 1219 | stack.startsWith(name) && | |
@@ -1206,6 +1239,33 @@ function formatError(err, constructor, tag, ctx, keys) { | |||
| 1206 | 1239 | } | |
| 1207 | 1240 | } | |
| 1208 | 1241 | } | |
| 1242 | + return stack; | ||
| 1243 | + } | ||
| 1244 | + | ||
| 1245 | + function removeDuplicateErrorKeys(ctx, keys, err, stack) { | ||
| 1246 | + if (!ctx.showHidden && keys.length !== 0) { | ||
| 1247 | + for (const name of ['name', 'message', 'stack']) { | ||
| 1248 | + const index = keys.indexOf(name); | ||
| 1249 | + // Only hide the property in case it's part of the original stack | ||
| 1250 | + if (index !== -1 && stack.includes(err[name])) { | ||
| 1251 | + keys.splice(index, 1); | ||
| 1252 | + } | ||
| 1253 | + } | ||
| 1254 | + } | ||
| 1255 | + } | ||
| 1256 | + | ||
| 1257 | + function formatError(err, constructor, tag, ctx, keys) { | ||
| 1258 | + const name = err.name != null ? String(err.name) : 'Error'; | ||
| 1259 | + let stack = getStackString(err); | ||
| 1260 | + | ||
| 1261 | + removeDuplicateErrorKeys(ctx, keys, err, stack); | ||
| 1262 | + | ||
| 1263 | + if (err.cause && (keys.length === 0 || !keys.includes('cause'))) { | ||
| 1264 | + keys.push('cause'); | ||
| 1265 | + } | ||
| 1266 | + | ||
| 1267 | + stack = improveStack(stack, constructor, name, tag); | ||
| 1268 | + | ||
| 1209 | 1269 | // Ignore the error message if it's contained in the stack. | |
| 1210 | 1270 | let pos = (err.message && stack.indexOf(err.message)) || -1; | |
| 1211 | 1271 | if (pos !== -1) | |
@@ -1214,27 +1274,31 @@ function formatError(err, constructor, tag, ctx, keys) { | |||
| 1214 | 1274 | const stackStart = stack.indexOf('\n at', pos); | |
| 1215 | 1275 | if (stackStart === -1) { | |
| 1216 | 1276 | stack = `[${stack}]`; | |
| 1217 | - } else if (ctx.colors) { | ||
| 1218 | - // Highlight userland code and node modules. | ||
| 1277 | + } else { | ||
| 1219 | 1278 | let newStack = stack.slice(0, stackStart); | |
| 1220 | - const lines = stack.slice(stackStart + 1).split('\n'); | ||
| 1221 | - for (const line of lines) { | ||
| 1222 | - const core = line.match(coreModuleRegExp); | ||
| 1223 | - if (core !== null && NativeModule.exists(core[1])) { | ||
| 1224 | - newStack += `\n${ctx.stylize(line, 'undefined')}`; | ||
| 1225 | - } else { | ||
| 1226 | - // This adds underscores to all node_modules to quickly identify them. | ||
| 1227 | - let nodeModule; | ||
| 1228 | - newStack += '\n'; | ||
| 1229 | - let pos = 0; | ||
| 1230 | - while (nodeModule = nodeModulesRegExp.exec(line)) { | ||
| 1231 | - // '/node_modules/'.length === 14 | ||
| 1232 | - newStack += line.slice(pos, nodeModule.index + 14); | ||
| 1233 | - newStack += ctx.stylize(nodeModule[1], 'module'); | ||
| 1234 | - pos = nodeModule.index + nodeModule[0].length; | ||
| 1279 | + const lines = getStackFrames(ctx, err, stack.slice(stackStart + 1)); | ||
| 1280 | + if (ctx.colors) { | ||
| 1281 | + // Highlight userland code and node modules. | ||
| 1282 | + for (const line of lines) { | ||
| 1283 | + const core = line.match(coreModuleRegExp); | ||
| 1284 | + if (core !== null && NativeModule.exists(core[1])) { | ||
| 1285 | + newStack += `\n${ctx.stylize(line, 'undefined')}`; | ||
| 1286 | + } else { | ||
| 1287 | + // This adds underscores to all node_modules to quickly identify them. | ||
| 1288 | + let nodeModule; | ||
| 1289 | + newStack += '\n'; | ||
| 1290 | + let pos = 0; | ||
| 1291 | + while (nodeModule = nodeModulesRegExp.exec(line)) { | ||
| 1292 | + // '/node_modules/'.length === 14 | ||
| 1293 | + newStack += line.slice(pos, nodeModule.index + 14); | ||
| 1294 | + newStack += ctx.stylize(nodeModule[1], 'module'); | ||
| 1295 | + pos = nodeModule.index + nodeModule[0].length; | ||
| 1296 | + } | ||
| 1297 | + newStack += pos === 0 ? line : line.slice(pos); | ||
| 1235 | 1298 | } | |
| 1236 | - newStack += pos === 0 ? line : line.slice(pos); | ||
| 1237 | 1299 | } | |
| 1300 | + } else { | ||
| 1301 | + newStack += `\n${lines.join('\n')}`; | ||
| 1238 | 1302 | } | |
| 1239 | 1303 | stack = newStack; | |
| 1240 | 1304 | } | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,31 @@ | |||
| 1 | + 'use strict'; | ||
| 2 | + | ||
| 3 | + require('../common'); | ||
| 4 | + | ||
| 5 | + const { inspect } = require('util'); | ||
| 6 | + | ||
| 7 | + class FoobarError extends Error { | ||
| 8 | + status = 'Feeling good'; | ||
| 9 | + } | ||
| 10 | + | ||
| 11 | + const cause1 = new TypeError('Inner error'); | ||
| 12 | + const cause2 = new FoobarError('Individual message', { cause: cause1 }); | ||
| 13 | + cause2.extraProperties = 'Yes!'; | ||
| 14 | + const cause3 = new Error('Stack causes', { cause: cause2 }); | ||
| 15 | + | ||
| 16 | + process.nextTick(() => { | ||
| 17 | + const error = new RangeError('New Stack Frames', { cause: cause2 }); | ||
| 18 | + const error2 = new RangeError('New Stack Frames', { cause: cause3 }); | ||
| 19 | + | ||
| 20 | + inspect.defaultOptions.colors = true; | ||
| 21 | + | ||
| 22 | + console.log(inspect(error)); | ||
| 23 | + console.log(inspect(cause3)); | ||
| 24 | + console.log(inspect(error2)); | ||
| 25 | + | ||
| 26 | + inspect.defaultOptions.colors = false; | ||
| 27 | + | ||
| 28 | + console.log(inspect(error)); | ||
| 29 | + console.log(inspect(cause3)); | ||
| 30 | + console.log(inspect(error2)); | ||
| 31 | + }); | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,136 @@ | |||
| 1 | + RangeError: New Stack Frames | ||
| 2 | + at * | ||
| 3 | + *[90m at *[39m { | ||
| 4 | + [cause]: FoobarError: Individual message | ||
| 5 | + at * | ||
| 6 | + *[90m at *[39m | ||
| 7 | + *[90m ... 4 lines matching cause stack trace ...*[39m | ||
| 8 | + *[90m at *[39m { | ||
| 9 | + status: *[32m'Feeling good'*[39m, | ||
| 10 | + extraProperties: *[32m'Yes!'*[39m, | ||
| 11 | + [cause]: TypeError: Inner error | ||
| 12 | + at * | ||
| 13 | + *[90m at *[39m | ||
| 14 | + *[90m at *[39m | ||
| 15 | + *[90m at *[39m | ||
| 16 | + *[90m at *[39m | ||
| 17 | + *[90m at *[39m | ||
| 18 | + *[90m at *[39m | ||
| 19 | + } | ||
| 20 | + } | ||
| 21 | + Error: Stack causes | ||
| 22 | + at * | ||
| 23 | + *[90m at *[39m | ||
| 24 | + *[90m ... 4 lines matching cause stack trace ...*[39m | ||
| 25 | + *[90m at *[39m { | ||
| 26 | + [cause]: FoobarError: Individual message | ||
| 27 | + at * | ||
| 28 | + *[90m at *[39m | ||
| 29 | + *[90m ... 4 lines matching cause stack trace ...*[39m | ||
| 30 | + *[90m at *[39m { | ||
| 31 | + status: *[32m'Feeling good'*[39m, | ||
| 32 | + extraProperties: *[32m'Yes!'*[39m, | ||
| 33 | + [cause]: TypeError: Inner error | ||
| 34 | + at * | ||
| 35 | + *[90m at *[39m | ||
| 36 | + *[90m at *[39m | ||
| 37 | + *[90m at *[39m | ||
| 38 | + *[90m at *[39m | ||
| 39 | + *[90m at *[39m | ||
| 40 | + *[90m at *[39m | ||
| 41 | + } | ||
| 42 | + } | ||
| 43 | + RangeError: New Stack Frames | ||
| 44 | + at * | ||
| 45 | + *[90m at *[39m { | ||
| 46 | + [cause]: Error: Stack causes | ||
| 47 | + at * | ||
| 48 | + *[90m at *[39m | ||
| 49 | + *[90m ... 4 lines matching cause stack trace ...*[39m | ||
| 50 | + *[90m at *[39m { | ||
| 51 | + [cause]: FoobarError: Individual message | ||
| 52 | + at * | ||
| 53 | + *[90m at *[39m | ||
| 54 | + *[90m ... 4 lines matching cause stack trace ...*[39m | ||
| 55 | + *[90m at *[39m { | ||
| 56 | + status: *[32m'Feeling good'*[39m, | ||
| 57 | + extraProperties: *[32m'Yes!'*[39m, | ||
| 58 | + [cause]: TypeError: Inner error | ||
| 59 | + at * | ||
| 60 | + *[90m at *[39m | ||
| 61 | + *[90m at *[39m | ||
| 62 | + *[90m at *[39m | ||
| 63 | + *[90m at *[39m | ||
| 64 | + *[90m at *[39m | ||
| 65 | + *[90m at *[39m | ||
| 66 | + } | ||
| 67 | + } | ||
| 68 | + } | ||
| 69 | + RangeError: New Stack Frames | ||
| 70 | + at * | ||
| 71 | + at * { | ||
| 72 | + [cause]: FoobarError: Individual message | ||
| 73 | + at * | ||
| 74 | + at * | ||
| 75 | + ... 4 lines matching cause stack trace ... | ||
| 76 | + at * { | ||
| 77 | + status: 'Feeling good', | ||
| 78 | + extraProperties: 'Yes!', | ||
| 79 | + [cause]: TypeError: Inner error | ||
| 80 | + at * | ||
| 81 | + at * | ||
| 82 | + at * | ||
| 83 | + at * | ||
| 84 | + at * | ||
| 85 | + at * | ||
| 86 | + at * | ||
| 87 | + } | ||
| 88 | + } | ||
| 89 | + Error: Stack causes | ||
| 90 | + at * | ||
| 91 | + at * | ||
| 92 | + ... 4 lines matching cause stack trace ... | ||
| 93 | + at * { | ||
| 94 | + [cause]: FoobarError: Individual message | ||
| 95 | + at * | ||
| 96 | + at * | ||
| 97 | + ... 4 lines matching cause stack trace ... | ||
| 98 | + at * | ||
| 99 | + status: 'Feeling good', | ||
| 100 | + extraProperties: 'Yes!', | ||
| 101 | + [cause]: TypeError: Inner error | ||
| 102 | + at * | ||
| 103 | + at * | ||
| 104 | + at * | ||
| 105 | + at * | ||
| 106 | + at * | ||
| 107 | + at * | ||
| 108 | + at * | ||
| 109 | + } | ||
| 110 | + } | ||
| 111 | + RangeError: New Stack Frames | ||
| 112 | + at * | ||
| 113 | + at * { | ||
| 114 | + [cause]: Error: Stack causes | ||
| 115 | + at * | ||
| 116 | + at * | ||
| 117 | + ... 4 lines matching cause stack trace ... | ||
| 118 | + at * { | ||
| 119 | + [cause]: FoobarError: Individual message | ||
| 120 | + at * | ||
| 121 | + at * | ||
| 122 | + ... 4 lines matching cause stack trace ... | ||
| 123 | + at * { | ||
| 124 | + status: 'Feeling good', | ||
| 125 | + extraProperties: 'Yes!', | ||
| 126 | + [cause]: TypeError: Inner error | ||
| 127 | + at * | ||
| 128 | + at * | ||
| 129 | + at * | ||
| 130 | + at * | ||
| 131 | + at * | ||
| 132 | + at * | ||
| 133 | + at * | ||
| 134 | + } | ||
| 135 | + } | ||
| 136 | + } | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments