-
-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
pre-load source maps to minimize calls at exit
This is a workaround for whatever bug in node or V8 is causing tapjs/tapjs#934 Best guess is that it has something to do with the FinalizationRegistry, and Module.findSourceMap is triggering this somehow when it's called many times in rapid succession at the end of the process.
- Loading branch information
Showing
18 changed files
with
226 additions
and
54 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
// For some reason that is very mysterious as of the time of writing this, | ||
// node sporadically will in rare cases hang and fail to gracefully exit if | ||
// a sufficiently large number of findSourceMap calls are made during the | ||
// process exit event. | ||
// | ||
// However, we cannot look up source maps until *after* the module load | ||
// event is completely finished and the module is about to be executed, | ||
// because that is when the source map is added to node's cache. | ||
// | ||
// To work around this, every time a module is loaded, we attempt to | ||
// determine whether it likely has the magic sourceMappingURL comment. | ||
// If so, then we put it in a list, and at each message, attempt to load | ||
// the sources for all modules in the list. Then, on process exit, if | ||
// there's anything still pending that likely has a source map, we only | ||
// have to look up at most one module (ie, if the last module loaded had a | ||
// source map), which seems to not trigger the hang. | ||
|
||
import { findSourceMapSafe } from './find-source-map-safe.js' | ||
|
||
// the list of modules that likely have source maps | ||
const maybeSM = new Set<string>() | ||
export const sourcesCache = new Map<string, string[]>() | ||
|
||
export const loadPendingSourceMaps = () => { | ||
for (const url of maybeSM) { | ||
const sm = findSourceMapSafe(url) | ||
if (sm === false) { | ||
// can only happen if node found the SM comment, and tried to load it, | ||
// but got an error creating the sourcemap, because it's invalid or | ||
// the file is not present. No need to keep trying. | ||
maybeSM.delete(url) | ||
} else { | ||
const sources = sm?.payload?.sources | ||
if (sources) { | ||
sourcesCache.set(url, sources) | ||
maybeSM.delete(url) | ||
} | ||
} | ||
} | ||
} | ||
|
||
export const lookupSources = (url: string) => getSources().get(url) | ||
|
||
export const getSources = () => { | ||
if (maybeSM.size) loadPendingSourceMaps() | ||
return sourcesCache | ||
} | ||
|
||
export const likelyHasSourceMap = (url: string) => { | ||
if (!sourcesCache.has(url)) maybeSM.add(url) | ||
loadPendingSourceMaps() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,15 +1,19 @@ | ||
import { findSourceMapSafe } from './find-source-map-safe.js' | ||
import { getProcessInfo } from './get-process-info.js' | ||
import { fileURLToPath } from 'url' | ||
import { ProcessInfoNodeData } from './index.js' | ||
import { getSources } from './lookup-sources.js' | ||
import { urlToPath } from './url-to-path.js' | ||
|
||
let sourcesCache: Map<string, string[]> | ||
|
||
// set the processInfo.sources for a given file, but don't clobber | ||
// if called multiple times, or create duplicate entries. | ||
// Should only be called *after* the file in question has been loaded. | ||
export const setSources = (file: string) => { | ||
const sm = findSourceMapSafe(file) | ||
if (!sm) return | ||
const pi = getProcessInfo() | ||
const s = pi.sources[file] || [] | ||
s.push(...sm.payload.sources.map(s => urlToPath(s))) | ||
pi.sources[file] = [...new Set(s)] | ||
export const setSources = (pi: ProcessInfoNodeData) => { | ||
sourcesCache ??= getSources() | ||
for (const [url, sources] of sourcesCache.entries()) { | ||
const file = fileURLToPath(url) | ||
const s = pi.sources[file] || [] | ||
s.push(...sources.map(s => urlToPath(s))) | ||
pi.sources[file] = [...new Set(s)] | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,19 @@ | ||
import { findSourceMap } from 'module' | ||
import t from 'tap' | ||
import { findSourceMapSafe } from '../dist/commonjs/find-source-map-safe.js' | ||
t.strictSame( | ||
findSourceMapSafe(__filename)?.payload, | ||
findSourceMap(__filename)?.payload | ||
) | ||
const sm = findSourceMapSafe(__filename) | ||
t.ok(sm) | ||
t.strictSame(sm && sm?.payload, findSourceMap(__filename)?.payload) | ||
// run a second time to exercise cache path | ||
t.equal(sm, findSourceMapSafe(__filename)) | ||
|
||
t.test('throwing source map lookup returns false', async t => { | ||
await import('./fixtures/missing-sm.min.mjs') | ||
t.throws(() => findSourceMap( | ||
require.resolve('./fixtures/missing-sm.min.mjs') | ||
)) | ||
const missing = findSourceMapSafe( | ||
require.resolve('./fixtures/missing-sm.min.mjs') | ||
) | ||
t.equal(missing, false) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export const d: 1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
"use strict";export const d=1; | ||
//# sourceMappingURL=missing-sm.min.mjs.map |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.