| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -8,9 +8,15 @@ const { | |||
| 8 | 8 | const { | |
| 9 | 9 | getErrorSourcePositions, | |
| 10 | 10 | } = internalBinding('errors'); | |
| 11 | + const { | ||
| 12 | + getSourceMapsSupport, | ||
| 13 | + findSourceMap, | ||
| 14 | + getSourceLine, | ||
| 15 | + } = require('internal/source_map/source_map_cache'); | ||
| 11 | 16 | ||
| 12 | 17 | /** | |
| 13 | - * Get the source location of an error. | ||
| 18 | + * Get the source location of an error. If source map is enabled, resolve the source location | ||
| 19 | + * based on the source map. | ||
| 14 | 20 | * | |
| 15 | 21 | * The `error.stack` must not have been accessed. The resolution is based on the structured | |
| 16 | 22 | * error stack data. | |
@@ -21,10 +27,35 @@ function getErrorSourceLocation(error) { | |||
| 21 | 27 | const pos = getErrorSourcePositions(error); | |
| 22 | 28 | const { | |
| 23 | 29 | sourceLine, | |
| 30 | + scriptResourceName, | ||
| 31 | + lineNumber, | ||
| 24 | 32 | startColumn, | |
| 25 | 33 | } = pos; | |
| 26 | 34 | ||
| 27 | - return { sourceLine, startColumn }; | ||
| 35 | + // Source map is not enabled. Return the source line directly. | ||
| 36 | + if (!getSourceMapsSupport().enabled) { | ||
| 37 | + return { sourceLine, startColumn }; | ||
| 38 | + } | ||
| 39 | + | ||
| 40 | + const sm = findSourceMap(scriptResourceName); | ||
| 41 | + if (sm === undefined) { | ||
| 42 | + return; | ||
| 43 | + } | ||
| 44 | + const { | ||
| 45 | + originalLine, | ||
| 46 | + originalColumn, | ||
| 47 | + originalSource, | ||
| 48 | + } = sm.findEntry(lineNumber - 1, startColumn); | ||
| 49 | + const originalSourceLine = getSourceLine(sm, originalSource, originalLine, originalColumn); | ||
| 50 | + | ||
| 51 | + if (!originalSourceLine) { | ||
| 52 | + return; | ||
| 53 | + } | ||
| 54 | + | ||
| 55 | + return { | ||
| 56 | + sourceLine: originalSourceLine, | ||
| 57 | + startColumn: originalColumn, | ||
| 58 | + }; | ||
| 28 | 59 | } | |
| 29 | 60 | ||
| 30 | 61 | const memberAccessTokens = [ '.', '?.', '[', ']' ]; | |
@@ -111,7 +142,8 @@ function getFirstExpression(code, startColumn) { | |||
| 111 | 142 | } | |
| 112 | 143 | ||
| 113 | 144 | /** | |
| 114 | - * Get the source expression of an error. | ||
| 145 | + * Get the source expression of an error. If source map is enabled, resolve the source location | ||
| 146 | + * based on the source map. | ||
| 115 | 147 | * | |
| 116 | 148 | * The `error.stack` must not have been accessed, or the source location may be incorrect. The | |
| 117 | 149 | * resolution is based on the structured error stack data. | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1,11 +1,9 @@ | |||
| 1 | 1 | 'use strict'; | |
| 2 | 2 | ||
| 3 | 3 | const { | |
| 4 | - ArrayPrototypeIndexOf, | ||
| 5 | 4 | ArrayPrototypeJoin, | |
| 6 | 5 | ArrayPrototypeMap, | |
| 7 | 6 | ErrorPrototypeToString, | |
| 8 | - RegExpPrototypeSymbolSplit, | ||
| 9 | 7 | SafeStringIterator, | |
| 10 | 8 | StringPrototypeRepeat, | |
| 11 | 9 | StringPrototypeSlice, | |
@@ -16,8 +14,7 @@ let debug = require('internal/util/debuglog').debuglog('source_map', (fn) => { | |||
| 16 | 14 | debug = fn; | |
| 17 | 15 | }); | |
| 18 | 16 | const { getStringWidth } = require('internal/util/inspect'); | |
| 19 | - const { readFileSync } = require('fs'); | ||
| 20 | - const { findSourceMap } = require('internal/source_map/source_map_cache'); | ||
| 17 | + const { findSourceMap, getSourceLine } = require('internal/source_map/source_map_cache'); | ||
| 21 | 18 | const { | |
| 22 | 19 | kIsNodeError, | |
| 23 | 20 | } = require('internal/errors'); | |
@@ -155,21 +152,13 @@ function getErrorSource( | |||
| 155 | 152 | originalLine, | |
| 156 | 153 | originalColumn, | |
| 157 | 154 | ) { | |
| 158 | - const originalSourcePathNoScheme = | ||
| 159 | - StringPrototypeStartsWith(originalSourcePath, 'file://') ? | ||
| 160 | - fileURLToPath(originalSourcePath) : originalSourcePath; | ||
| 161 | - const source = getOriginalSource( | ||
| 162 | - sourceMap.payload, | ||
| 163 | - originalSourcePath, | ||
| 164 | - ); | ||
| 165 | - if (typeof source !== 'string') { | ||
| 166 | - return; | ||
| 167 | - } | ||
| 168 | - const lines = RegExpPrototypeSymbolSplit(/\r?\n/, source, originalLine + 1); | ||
| 169 | - const line = lines[originalLine]; | ||
| 155 | + const line = getSourceLine(sourceMap, originalSourcePath, originalLine); | ||
| 170 | 156 | if (!line) { | |
| 171 | 157 | return; | |
| 172 | 158 | } | |
| 159 | + const originalSourcePathNoScheme = | ||
| 160 | + StringPrototypeStartsWith(originalSourcePath, 'file://') ? | ||
| 161 | + fileURLToPath(originalSourcePath) : originalSourcePath; | ||
| 173 | 162 | ||
| 174 | 163 | // Display ^ in appropriate position, regardless of whether tabs or | |
| 175 | 164 | // spaces are used: | |
@@ -182,39 +171,10 @@ function getErrorSource( | |||
| 182 | 171 | prefix = StringPrototypeSlice(prefix, 0, -1); // The last character is '^'. | |
| 183 | 172 | ||
| 184 | 173 | const exceptionLine = | |
| 185 | - `${originalSourcePathNoScheme}:${originalLine + 1}\n${line}\n${prefix}^\n\n`; | ||
| 174 | + `${originalSourcePathNoScheme}:${originalLine + 1}\n${line}\n${prefix}^\n`; | ||
| 186 | 175 | return exceptionLine; | |
| 187 | 176 | } | |
| 188 | 177 | ||
| 189 | - /** | ||
| 190 | - * Retrieve the original source code from the source map's `sources` list or disk. | ||
| 191 | - * @param {import('internal/source_map/source_map').SourceMap.payload} payload | ||
| 192 | - * @param {string} originalSourcePath - path or url of the original source | ||
| 193 | - * @returns {string | undefined} - the source content or undefined if file not found | ||
| 194 | - */ | ||
| 195 | - function getOriginalSource(payload, originalSourcePath) { | ||
| 196 | - let source; | ||
| 197 | - // payload.sources has been normalized to be an array of absolute urls. | ||
| 198 | - const sourceContentIndex = | ||
| 199 | - ArrayPrototypeIndexOf(payload.sources, originalSourcePath); | ||
| 200 | - if (payload.sourcesContent?.[sourceContentIndex]) { | ||
| 201 | - // First we check if the original source content was provided in the | ||
| 202 | - // source map itself: | ||
| 203 | - source = payload.sourcesContent[sourceContentIndex]; | ||
| 204 | - } else if (StringPrototypeStartsWith(originalSourcePath, 'file://')) { | ||
| 205 | - // If no sourcesContent was found, attempt to load the original source | ||
| 206 | - // from disk: | ||
| 207 | - debug(`read source of ${originalSourcePath} from filesystem`); | ||
| 208 | - const originalSourcePathNoScheme = fileURLToPath(originalSourcePath); | ||
| 209 | - try { | ||
| 210 | - source = readFileSync(originalSourcePathNoScheme, 'utf8'); | ||
| 211 | - } catch (err) { | ||
| 212 | - debug(err); | ||
| 213 | - } | ||
| 214 | - } | ||
| 215 | - return source; | ||
| 216 | - } | ||
| 217 | - | ||
| 218 | 178 | /** | |
| 219 | 179 | * Retrieve exact line in the original source code from the source map's `sources` list or disk. | |
| 220 | 180 | * @param {string} fileName - actual file name | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1,13 +1,16 @@ | |||
| 1 | 1 | 'use strict'; | |
| 2 | 2 | ||
| 3 | 3 | const { | |
| 4 | + ArrayPrototypeIndexOf, | ||
| 4 | 5 | ArrayPrototypePush, | |
| 5 | 6 | JSONParse, | |
| 6 | 7 | ObjectFreeze, | |
| 7 | 8 | RegExpPrototypeExec, | |
| 9 | + RegExpPrototypeSymbolSplit, | ||
| 8 | 10 | SafeMap, | |
| 9 | 11 | StringPrototypeCodePointAt, | |
| 10 | 12 | StringPrototypeSplit, | |
| 13 | + StringPrototypeStartsWith, | ||
| 11 | 14 | } = primordials; | |
| 12 | 15 | ||
| 13 | 16 | // See https://tc39.es/ecma426/ for SourceMap V3 specification. | |
@@ -16,6 +19,7 @@ let debug = require('internal/util/debuglog').debuglog('source_map', (fn) => { | |||
| 16 | 19 | debug = fn; | |
| 17 | 20 | }); | |
| 18 | 21 | ||
| 22 | + const { readFileSync } = require('fs'); | ||
| 19 | 23 | const { validateBoolean, validateObject } = require('internal/validators'); | |
| 20 | 24 | const { | |
| 21 | 25 | setSourceMapsEnabled: setSourceMapsNative, | |
@@ -277,8 +281,7 @@ function lineLengths(content) { | |||
| 277 | 281 | */ | |
| 278 | 282 | function sourceMapFromFile(mapURL) { | |
| 279 | 283 | try { | |
| 280 | - const fs = require('fs'); | ||
| 281 | - const content = fs.readFileSync(fileURLToPath(mapURL), 'utf8'); | ||
| 284 | + const content = readFileSync(fileURLToPath(mapURL), 'utf8'); | ||
| 282 | 285 | const data = JSONParse(content); | |
| 283 | 286 | return sourcesToAbsolute(mapURL, data); | |
| 284 | 287 | } catch (err) { | |
@@ -400,8 +403,62 @@ function findSourceMap(sourceURL) { | |||
| 400 | 403 | } | |
| 401 | 404 | } | |
| 402 | 405 | ||
| 406 | + /** | ||
| 407 | + * Retrieve the original source code from the source map's `sources` list or disk. | ||
| 408 | + * @param {import('internal/source_map/source_map').SourceMap.payload} payload | ||
| 409 | + * @param {string} originalSourcePath - path or url of the original source | ||
| 410 | + * @returns {string | undefined} - the source content or undefined if file not found | ||
| 411 | + */ | ||
| 412 | + function getOriginalSource(payload, originalSourcePath) { | ||
| 413 | + let source; | ||
| 414 | + // payload.sources has been normalized to be an array of absolute urls. | ||
| 415 | + const sourceContentIndex = | ||
| 416 | + ArrayPrototypeIndexOf(payload.sources, originalSourcePath); | ||
| 417 | + if (payload.sourcesContent?.[sourceContentIndex]) { | ||
| 418 | + // First we check if the original source content was provided in the | ||
| 419 | + // source map itself: | ||
| 420 | + source = payload.sourcesContent[sourceContentIndex]; | ||
| 421 | + } else if (StringPrototypeStartsWith(originalSourcePath, 'file://')) { | ||
| 422 | + // If no sourcesContent was found, attempt to load the original source | ||
| 423 | + // from disk: | ||
| 424 | + debug(`read source of ${originalSourcePath} from filesystem`); | ||
| 425 | + const originalSourcePathNoScheme = fileURLToPath(originalSourcePath); | ||
| 426 | + try { | ||
| 427 | + source = readFileSync(originalSourcePathNoScheme, 'utf8'); | ||
| 428 | + } catch (err) { | ||
| 429 | + debug(err); | ||
| 430 | + } | ||
| 431 | + } | ||
| 432 | + return source; | ||
| 433 | + } | ||
| 434 | + | ||
| 435 | + /** | ||
| 436 | + * Get the line of source in the source map. | ||
| 437 | + * @param {import('internal/source_map/source_map').SourceMap} sourceMap | ||
| 438 | + * @param {string} originalSourcePath path or url of the original source | ||
| 439 | + * @param {number} originalLine line number in the original source | ||
| 440 | + * @returns {string|undefined} source line if found | ||
| 441 | + */ | ||
| 442 | + function getSourceLine( | ||
| 443 | + sourceMap, | ||
| 444 | + originalSourcePath, | ||
| 445 | + originalLine, | ||
| 446 | + ) { | ||
| 447 | + const source = getOriginalSource( | ||
| 448 | + sourceMap.payload, | ||
| 449 | + originalSourcePath, | ||
| 450 | + ); | ||
| 451 | + if (typeof source !== 'string') { | ||
| 452 | + return; | ||
| 453 | + } | ||
| 454 | + const lines = RegExpPrototypeSymbolSplit(/\r?\n/, source, originalLine + 1); | ||
| 455 | + const line = lines[originalLine]; | ||
| 456 | + return line; | ||
| 457 | + } | ||
| 458 | + | ||
| 403 | 459 | module.exports = { | |
| 404 | 460 | findSourceMap, | |
| 461 | + getSourceLine, | ||
| 405 | 462 | getSourceMapsSupport, | |
| 406 | 463 | setSourceMapsSupport, | |
| 407 | 464 | maybeCacheSourceMap, | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,20 @@ | |||
| 1 | + AssertionError [ERR_ASSERTION]: The expression evaluated to a falsy value: | ||
| 2 | + | ||
| 3 | + assert(false) | ||
| 4 | + | ||
| 5 | + at Object.<anonymous> (*/test/fixtures/source-map/output/source_map_assert_source_line.ts:11:3) | ||
| 6 | + * | ||
| 7 | + * | ||
| 8 | + * | ||
| 9 | + * | ||
| 10 | + at TracingChannel.traceSync (node:diagnostics_channel:322:14) | ||
| 11 | + * | ||
| 12 | + * | ||
| 13 | + * | ||
| 14 | + generatedMessage: true, | ||
| 15 | + code: 'ERR_ASSERTION', | ||
| 16 | + actual: false, | ||
| 17 | + expected: true, | ||
| 18 | + operator: '==', | ||
| 19 | + diff: 'simple' | ||
| 20 | + } | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,14 @@ | |||
| 1 | + // Flags: --enable-source-maps --experimental-transform-types --no-warnings | ||
| 2 | + | ||
| 3 | + require('../../../common'); | ||
| 4 | + const assert = require('node:assert'); | ||
| 5 | + | ||
| 6 | + enum Bar { | ||
| 7 | + makeSureTransformTypes, | ||
| 8 | + } | ||
| 9 | + | ||
| 10 | + try { | ||
| 11 | + assert(false); | ||
| 12 | + } catch (e) { | ||
| 13 | + console.log(e); | ||
| 14 | + } | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -2,7 +2,6 @@ | |||
| 2 | 2 | throw err | |
| 3 | 3 | ^ | |
| 4 | 4 | ||
| 5 | - | ||
| 6 | 5 | Error: an error! | |
| 7 | 6 | at functionD (*/test/fixtures/source-map/enclosing-call-site.js:16:17) | |
| 8 | 7 | at functionC (*/test/fixtures/source-map/enclosing-call-site.js:10:3) | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -2,7 +2,6 @@ | |||
| 2 | 2 | alert "I knew it!" | |
| 3 | 3 | ^ | |
| 4 | 4 | ||
| 5 | - | ||
| 6 | 5 | ReferenceError: alert is not defined | |
| 7 | 6 | at Object.eval (*/synthesized/workspace/tabs-source-url.coffee:26:2) | |
| 8 | 7 | at eval (*/synthesized/workspace/tabs-source-url.coffee:1:14) | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -2,7 +2,6 @@ | |||
| 2 | 2 | alert "I knew it!" | |
| 3 | 3 | ^ | |
| 4 | 4 | ||
| 5 | - | ||
| 6 | 5 | ReferenceError: alert is not defined | |
| 7 | 6 | at Object.<anonymous> (*/test/fixtures/source-map/tabs.coffee:26:2) | |
| 8 | 7 | at Object.<anonymous> (*/test/fixtures/source-map/tabs.coffee:1:14) | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -2,7 +2,6 @@ | |||
| 2 | 2 | throw new Error('message') | |
| 3 | 3 | ^ | |
| 4 | 4 | ||
| 5 | - | ||
| 6 | 5 | Error: message | |
| 7 | 6 | at Throw (*/test/fixtures/source-map/output/source_map_throw_async_stack_trace.mts:13:9) | |
| 8 | 7 | at async Promise.all (index 3) | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -2,7 +2,6 @@ | |||
| 2 | 2 | throw new Error('message'); | |
| 3 | 3 | ^ | |
| 4 | 4 | ||
| 5 | - | ||
| 6 | 5 | Error: message | |
| 7 | 6 | at new Foo (*/test/fixtures/source-map/output/source_map_throw_construct.mts:13:11) | |
| 8 | 7 | at <anonymous> (*/test/fixtures/source-map/output/source_map_throw_construct.mts:17:1) | |
| Back | FazBrowse Home | New Git URL |
0 commit comments