| 108 | } |
| 109 | |
| 110 | function parseStepLine(stepLine) { |
| 111 | let line = stepLine.trim() |
| 112 | if (line.startsWith('at ')) line = line.substring(3).trim() |
| 113 | |
| 114 | const lastColon = line.lastIndexOf(':') |
| 115 | if (lastColon < 0) return null |
| 116 | const secondLastColon = line.lastIndexOf(':', lastColon - 1) |
| 117 | if (secondLastColon < 0) return null |
| 118 | |
| 119 | const file = line.substring(0, secondLastColon) |
| 120 | const lineNum = parseInt(line.substring(secondLastColon + 1, lastColon), 10) |
| 121 | |
| 122 | if (Number.isNaN(lineNum)) return null |
| 123 | return { file, line: lineNum } |
| 124 | } |
| 125 | |
| 126 | /** |
| 127 | * Match a URL string against a glob-style pattern (supports `*` wildcards). |