@openrewrite/recipes-nodejs 0.52.0-20261009-102010 → 0.52.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/migrate/code-style.d.ts +14 -0
- package/dist/migrate/code-style.d.ts.map +1 -0
- package/dist/migrate/code-style.js +70 -0
- package/dist/migrate/code-style.js.map +1 -0
- package/dist/migrate/hpagent/find-hpagent-manual-migrations.d.ts.map +1 -1
- package/dist/migrate/hpagent/find-hpagent-manual-migrations.js +36 -133
- package/dist/migrate/hpagent/find-hpagent-manual-migrations.js.map +1 -1
- package/dist/migrate/hpagent/hpagent-support.d.ts +36 -15
- package/dist/migrate/hpagent/hpagent-support.d.ts.map +1 -1
- package/dist/migrate/hpagent/hpagent-support.js +294 -55
- package/dist/migrate/hpagent/hpagent-support.js.map +1 -1
- package/dist/migrate/hpagent/replace-hpagent.d.ts.map +1 -1
- package/dist/migrate/hpagent/replace-hpagent.js +510 -153
- package/dist/migrate/hpagent/replace-hpagent.js.map +1 -1
- package/dist/migrate/source-map-support/enable-source-maps-at-launch.d.ts.map +1 -1
- package/dist/migrate/source-map-support/enable-source-maps-at-launch.js +8 -16
- package/dist/migrate/source-map-support/enable-source-maps-at-launch.js.map +1 -1
- package/dist/migrate/source-map-support/find-source-map-support-manual-migrations.d.ts.map +1 -1
- package/dist/migrate/source-map-support/find-source-map-support-manual-migrations.js +26 -9
- package/dist/migrate/source-map-support/find-source-map-support-manual-migrations.js.map +1 -1
- package/dist/migrate/source-map-support/migrate-source-map-support-to-native.d.ts.map +1 -1
- package/dist/migrate/source-map-support/migrate-source-map-support-to-native.js +7 -4
- package/dist/migrate/source-map-support/migrate-source-map-support-to-native.js.map +1 -1
- package/dist/migrate/source-map-support/replace-source-map-support-api.d.ts +9 -0
- package/dist/migrate/source-map-support/replace-source-map-support-api.d.ts.map +1 -0
- package/dist/migrate/source-map-support/replace-source-map-support-api.js +275 -0
- package/dist/migrate/source-map-support/replace-source-map-support-api.js.map +1 -0
- package/dist/migrate/source-map-support/replace-source-map-support-install.d.ts.map +1 -1
- package/dist/migrate/source-map-support/replace-source-map-support-install.js +2 -1
- package/dist/migrate/source-map-support/replace-source-map-support-install.js.map +1 -1
- package/dist/migrate/source-map-support/source-map-support-api-source.d.ts +14 -0
- package/dist/migrate/source-map-support/source-map-support-api-source.d.ts.map +1 -0
- package/dist/migrate/source-map-support/source-map-support-api-source.js +426 -0
- package/dist/migrate/source-map-support/source-map-support-api-source.js.map +1 -0
- package/dist/migrate/source-map-support/source-map-support-rewrites.d.ts.map +1 -1
- package/dist/migrate/source-map-support/source-map-support-rewrites.js +2 -0
- package/dist/migrate/source-map-support/source-map-support-rewrites.js.map +1 -1
- package/dist/migrate/source-map-support/source-map-support-support.d.ts +11 -3
- package/dist/migrate/source-map-support/source-map-support-support.d.ts.map +1 -1
- package/dist/migrate/source-map-support/source-map-support-support.js +69 -10
- package/dist/migrate/source-map-support/source-map-support-support.js.map +1 -1
- package/dist/resources/advisories-npm.csv +342 -6
- package/package.json +2 -2
- package/src/index.ts +2 -0
- package/src/migrate/code-style.ts +92 -0
- package/src/migrate/fs-extra/replace-fs-extra-native-methods.ts +2 -2
- package/src/migrate/hpagent/find-hpagent-manual-migrations.ts +45 -142
- package/src/migrate/hpagent/hpagent-support.ts +358 -60
- package/src/migrate/hpagent/replace-hpagent.ts +580 -189
- package/src/migrate/source-map-support/enable-source-maps-at-launch.ts +17 -26
- package/src/migrate/source-map-support/find-source-map-support-manual-migrations.ts +25 -9
- package/src/migrate/source-map-support/migrate-source-map-support-to-native.ts +7 -4
- package/src/migrate/source-map-support/replace-source-map-support-api.ts +281 -0
- package/src/migrate/source-map-support/replace-source-map-support-install.ts +2 -1
- package/src/migrate/source-map-support/source-map-support-api-source.ts +470 -0
- package/src/migrate/source-map-support/source-map-support-rewrites.ts +3 -0
- package/src/migrate/source-map-support/source-map-support-support.ts +79 -10
|
@@ -0,0 +1,470 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2026 the original author or authors.
|
|
3
|
+
*
|
|
4
|
+
* Moderne Proprietary. Only for use by Moderne customers under the terms of a commercial contract.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import {CodeStyle, restyle} from "../code-style";
|
|
8
|
+
|
|
9
|
+
/** A declaration the migration can write into a file in place of part of source-map-support's API. */
|
|
10
|
+
export type ApiDeclaration =
|
|
11
|
+
| 'UrlAndMap' | 'Position' | 'CallSiteState' | 'SourceMapSupportOptions' | 'SourceMapSupportEnvironment' | 'CallSite'
|
|
12
|
+
| 'SourceMapSupportState' | 'installSourceMapSupport' | 'wrapCallSite' | 'getErrorSource' | 'mapSourcePosition'
|
|
13
|
+
| 'retrieveSourceMap' | 'resetRetrieveHandlers' | 'sourceMapSupportState' | 'retrieveSourceFile'
|
|
14
|
+
| 'resolveSourceURL' | 'mapEvalOrigin' | 'scriptNameOf' | 'formatCallSite' | 'cloneCallSite'
|
|
15
|
+
| 'prepareSourceMappedStackTrace';
|
|
16
|
+
|
|
17
|
+
/** A Node builtin member the generated declarations call, keyed as `module#member`. */
|
|
18
|
+
export type ApiBuiltin = 'module#findSourceMap' | 'module#SourceMap' | 'fs#readFileSync' | 'path#dirname' |
|
|
19
|
+
'path#resolve' | 'url#fileURLToPath';
|
|
20
|
+
|
|
21
|
+
/** The declaration each of source-map-support's values stands for. */
|
|
22
|
+
export const VALUE_MEMBERS: ReadonlyMap<string, ApiDeclaration> = new Map<string, ApiDeclaration>([
|
|
23
|
+
['install', 'installSourceMapSupport'], ['wrapCallSite', 'wrapCallSite'], ['getErrorSource', 'getErrorSource'],
|
|
24
|
+
['mapSourcePosition', 'mapSourcePosition'], ['retrieveSourceMap', 'retrieveSourceMap'],
|
|
25
|
+
['resetRetrieveHandlers', 'resetRetrieveHandlers'],
|
|
26
|
+
]);
|
|
27
|
+
|
|
28
|
+
/** The declaration each of `@types/source-map-support`'s types stands for. */
|
|
29
|
+
export const TYPE_MEMBERS: ReadonlyMap<string, ApiDeclaration> = new Map<string, ApiDeclaration>([
|
|
30
|
+
['UrlAndMap', 'UrlAndMap'], ['Position', 'Position'], ['State', 'CallSiteState'],
|
|
31
|
+
['Options', 'SourceMapSupportOptions'], ['Environment', 'SourceMapSupportEnvironment'], ['CallSite', 'CallSite'],
|
|
32
|
+
]);
|
|
33
|
+
|
|
34
|
+
/** How the generated source spells each declaration and builtin, and whether it carries TypeScript's types. */
|
|
35
|
+
interface Spelling {
|
|
36
|
+
n: (declaration: ApiDeclaration) => string;
|
|
37
|
+
b: (builtin: ApiBuiltin) => string;
|
|
38
|
+
t: (typed: string) => string;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
interface Template {
|
|
42
|
+
/** Declarations this one names, which have to be written alongside it. */
|
|
43
|
+
uses: ApiDeclaration[];
|
|
44
|
+
builtins?: ApiBuiltin[];
|
|
45
|
+
typeOnly?: boolean;
|
|
46
|
+
source: (s: Spelling) => string;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Written in the default code style, to the rules `restyle` relies on.
|
|
50
|
+
const TEMPLATES: Record<ApiDeclaration, Template> = {
|
|
51
|
+
UrlAndMap: {
|
|
52
|
+
uses: [], typeOnly: true,
|
|
53
|
+
source: ({n}) => `
|
|
54
|
+
/** What \`retrieveSourceMap\` finds for a generated file: its source map, and where that was read from. */
|
|
55
|
+
interface ${n('UrlAndMap')} {
|
|
56
|
+
url?: string | undefined;
|
|
57
|
+
map: string | import('module').SourceMapPayload;
|
|
58
|
+
}`
|
|
59
|
+
},
|
|
60
|
+
Position: {
|
|
61
|
+
uses: [], typeOnly: true,
|
|
62
|
+
source: ({n}) => `
|
|
63
|
+
interface ${n('Position')} {
|
|
64
|
+
source: string;
|
|
65
|
+
line: number;
|
|
66
|
+
column: number;
|
|
67
|
+
name?: string | null | undefined;
|
|
68
|
+
}`
|
|
69
|
+
},
|
|
70
|
+
CallSiteState: {
|
|
71
|
+
uses: ['Position'], typeOnly: true,
|
|
72
|
+
source: ({n}) => `
|
|
73
|
+
/** The positions \`wrapCallSite\` passes between the frames of one stack, to name each frame's function. */
|
|
74
|
+
interface ${n('CallSiteState')} {
|
|
75
|
+
nextPosition: ${n('Position')} | null;
|
|
76
|
+
curPosition: ${n('Position')} | null;
|
|
77
|
+
}`
|
|
78
|
+
},
|
|
79
|
+
SourceMapSupportEnvironment: {
|
|
80
|
+
uses: [], typeOnly: true,
|
|
81
|
+
source: ({n}) => `
|
|
82
|
+
type ${n('SourceMapSupportEnvironment')} = 'auto' | 'browser' | 'node';`
|
|
83
|
+
},
|
|
84
|
+
CallSite: {
|
|
85
|
+
uses: [], typeOnly: true,
|
|
86
|
+
source: ({n}) => `
|
|
87
|
+
type ${n('CallSite')} = NodeJS.CallSite;`
|
|
88
|
+
},
|
|
89
|
+
SourceMapSupportOptions: {
|
|
90
|
+
uses: ['UrlAndMap'], typeOnly: true,
|
|
91
|
+
source: ({n}) => `
|
|
92
|
+
/** source-map-support's \`install\` options; Node prints uncaught errors and reads inline source maps itself. */
|
|
93
|
+
interface ${n('SourceMapSupportOptions')} {
|
|
94
|
+
handleUncaughtExceptions?: boolean | undefined;
|
|
95
|
+
hookRequire?: boolean | undefined;
|
|
96
|
+
emptyCacheBetweenOperations?: boolean | undefined;
|
|
97
|
+
environment?: 'auto' | 'browser' | 'node' | undefined;
|
|
98
|
+
overrideRetrieveFile?: boolean | undefined;
|
|
99
|
+
overrideRetrieveSourceMap?: boolean | undefined;
|
|
100
|
+
retrieveFile?(path: string): string | null;
|
|
101
|
+
retrieveSourceMap?(source: string): ${n('UrlAndMap')} | null;
|
|
102
|
+
}`
|
|
103
|
+
},
|
|
104
|
+
SourceMapSupportState: {
|
|
105
|
+
uses: ['UrlAndMap'], typeOnly: true,
|
|
106
|
+
builtins: ['module#SourceMap'],
|
|
107
|
+
source: ({n, b}) => `
|
|
108
|
+
interface ${n('SourceMapSupportState')} {
|
|
109
|
+
fileHandlers: ((path: string) => string | null)[];
|
|
110
|
+
mapHandlers: ((source: string) => ${n('UrlAndMap')} | null)[];
|
|
111
|
+
readFiles: boolean;
|
|
112
|
+
readMaps: boolean;
|
|
113
|
+
emptyCaches: boolean;
|
|
114
|
+
installed: boolean;
|
|
115
|
+
files: Map<string, string>;
|
|
116
|
+
maps: Map<string, {url?: string | undefined; map: ${b('module#SourceMap')}; root: string} | null>;
|
|
117
|
+
}`
|
|
118
|
+
},
|
|
119
|
+
installSourceMapSupport: {
|
|
120
|
+
uses: ['SourceMapSupportOptions', 'sourceMapSupportState', 'prepareSourceMappedStackTrace'],
|
|
121
|
+
source: ({n, t}) => `
|
|
122
|
+
/**
|
|
123
|
+
* source-map-support's \`install\`, on Node's own source map decoder: stack traces are mapped through the
|
|
124
|
+
* \`retrieveSourceMap\` and \`retrieveFile\` handlers first, then the \`sourceMappingURL\` of each generated file.
|
|
125
|
+
*/
|
|
126
|
+
function ${n('installSourceMapSupport')}(options${t(`: ${n('SourceMapSupportOptions')}`)} = {})${t(': void')} {
|
|
127
|
+
const state = ${n('sourceMapSupportState')}();
|
|
128
|
+
if (options.retrieveFile) {
|
|
129
|
+
if (options.overrideRetrieveFile) {
|
|
130
|
+
state.fileHandlers.length = 0;
|
|
131
|
+
state.readFiles = false;
|
|
132
|
+
}
|
|
133
|
+
state.fileHandlers.unshift(options.retrieveFile);
|
|
134
|
+
}
|
|
135
|
+
if (options.retrieveSourceMap) {
|
|
136
|
+
if (options.overrideRetrieveSourceMap) {
|
|
137
|
+
state.mapHandlers.length = 0;
|
|
138
|
+
state.readMaps = false;
|
|
139
|
+
}
|
|
140
|
+
state.mapHandlers.unshift(options.retrieveSourceMap);
|
|
141
|
+
}
|
|
142
|
+
state.emptyCaches = state.emptyCaches || !!options.emptyCacheBetweenOperations;
|
|
143
|
+
if (!state.installed) {
|
|
144
|
+
state.installed = true;
|
|
145
|
+
// Read reflectively, as older versions of @types/node don't declare it.
|
|
146
|
+
const setSourceMapsEnabled${t(': ((enabled: boolean) => void) | undefined')} = Reflect.get(process, 'setSourceMapsEnabled');
|
|
147
|
+
setSourceMapsEnabled?.call(process, true);
|
|
148
|
+
Error.prepareStackTrace = ${n('prepareSourceMappedStackTrace')};
|
|
149
|
+
}
|
|
150
|
+
}`
|
|
151
|
+
},
|
|
152
|
+
wrapCallSite: {
|
|
153
|
+
uses: ['CallSiteState', 'mapSourcePosition', 'cloneCallSite', 'mapEvalOrigin', 'scriptNameOf'],
|
|
154
|
+
source: ({n, t}) => `
|
|
155
|
+
/**
|
|
156
|
+
* A call site reporting its original position, and the original name of the function the next frame calls.
|
|
157
|
+
* \`state\` is ignored unless it is an object, as when this is passed to \`Array.prototype.map\`.
|
|
158
|
+
*/
|
|
159
|
+
function ${n('wrapCallSite')}(frame${t(': NodeJS.CallSite')}, state${t('?: unknown')})${t(': NodeJS.CallSite')} {
|
|
160
|
+
const positions${t(`: ${n('CallSiteState')}`)} = typeof state === 'object' && state ? state${t(` as ${n('CallSiteState')}`)} : {nextPosition: null, curPosition: null};
|
|
161
|
+
if (frame.isNative()) {
|
|
162
|
+
positions.curPosition = null;
|
|
163
|
+
return frame;
|
|
164
|
+
}
|
|
165
|
+
const source = frame.getFileName() || ${n('scriptNameOf')}(frame);
|
|
166
|
+
if (source) {
|
|
167
|
+
const position = ${n('mapSourcePosition')}({source, line: frame.getLineNumber()${t('!')}, column: frame.getColumnNumber()${t('!')} - 1});
|
|
168
|
+
positions.curPosition = position;
|
|
169
|
+
const clone = ${n('cloneCallSite')}(frame);
|
|
170
|
+
const functionName = clone.getFunctionName;
|
|
171
|
+
return Object.assign(clone, {
|
|
172
|
+
getFunctionName: () => positions.nextPosition?.name || functionName(),
|
|
173
|
+
getFileName: () => position.source,
|
|
174
|
+
getLineNumber: () => position.line,
|
|
175
|
+
getColumnNumber: () => position.column + 1,
|
|
176
|
+
getScriptNameOrSourceURL: () => position.source
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
const origin = frame.isEval() && frame.getEvalOrigin();
|
|
180
|
+
if (!origin) return frame;
|
|
181
|
+
const clone = ${n('cloneCallSite')}(frame);
|
|
182
|
+
const mapped = ${n('mapEvalOrigin')}(origin);
|
|
183
|
+
clone.getEvalOrigin = () => mapped;
|
|
184
|
+
return clone;
|
|
185
|
+
}`
|
|
186
|
+
},
|
|
187
|
+
getErrorSource: {
|
|
188
|
+
uses: ['sourceMapSupportState'],
|
|
189
|
+
builtins: ['fs#readFileSync'],
|
|
190
|
+
source: ({n, b, t}) => `
|
|
191
|
+
/** The original source line an error was thrown from, with a caret under its column, as Node prints it. */
|
|
192
|
+
function ${n('getErrorSource')}(error${t(': Error')})${t(': string | null')} {
|
|
193
|
+
const match = /\\n at [^(]+ \\((.*):(\\d+):(\\d+)\\)/.exec(error.stack ?? '');
|
|
194
|
+
if (!match) return null;
|
|
195
|
+
const [, source, line, column] = match;
|
|
196
|
+
let contents = ${n('sourceMapSupportState')}().files.get(source${t('!')});
|
|
197
|
+
if (!contents) {
|
|
198
|
+
try {
|
|
199
|
+
contents = ${b('fs#readFileSync')}(source${t('!')}, 'utf8');
|
|
200
|
+
} catch {
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
const code = contents?.split(/\\r\\n|\\r|\\n/)[+line${t('!')} - 1];
|
|
204
|
+
return code ? \`\${source}:\${line}\\n\${code}\\n\${' '.repeat(+column${t('!')} - 1)}^\` : null;
|
|
205
|
+
}`
|
|
206
|
+
},
|
|
207
|
+
mapSourcePosition: {
|
|
208
|
+
uses: ['Position', 'SourceMapSupportState', 'sourceMapSupportState', 'retrieveSourceMap', 'resolveSourceURL'],
|
|
209
|
+
builtins: ['module#SourceMap'],
|
|
210
|
+
source: ({n, b, t}) => `
|
|
211
|
+
/** The original position of a generated one, or the position itself where its source map has none. */
|
|
212
|
+
function ${n('mapSourcePosition')}(position${t(`: ${n('Position')}`)})${t(`: ${n('Position')}`)} {
|
|
213
|
+
const state = ${n('sourceMapSupportState')}();
|
|
214
|
+
if (!state.maps.has(position.source)) {
|
|
215
|
+
const urlAndMap = ${n('retrieveSourceMap')}(position.source);
|
|
216
|
+
let loaded${t(`: {url?: string | undefined; map: ${b('module#SourceMap')}; root: string} | null`)} = null;
|
|
217
|
+
if (urlAndMap) {
|
|
218
|
+
const payload = typeof urlAndMap.map === 'string' ? JSON.parse(urlAndMap.map.replace(/^\\)]}\\x27/, '')) : urlAndMap.map;
|
|
219
|
+
const root = payload.sourceRoot ? payload.sourceRoot.replace(/\\/?$/, '/') : '';
|
|
220
|
+
const url = urlAndMap.url;
|
|
221
|
+
loaded = {url, map: new ${b('module#SourceMap')}(payload), root};
|
|
222
|
+
payload.sourcesContent?.forEach((contents${t(': string | null')}, i${t(': number')}) => {
|
|
223
|
+
if (contents) state.files.set(${n('resolveSourceURL')}(url, root + payload.sources[i]), contents);
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
state.maps.set(position.source, loaded);
|
|
227
|
+
}
|
|
228
|
+
const loaded = state.maps.get(position.source);
|
|
229
|
+
// Node falls back to the last mapping of an earlier line, where the generated position says more.
|
|
230
|
+
const entry = loaded?.map.findEntry(position.line - 1, position.column);
|
|
231
|
+
if (!loaded || !entry || !('originalSource' in entry) || entry.generatedLine !== position.line - 1) return position;
|
|
232
|
+
return {
|
|
233
|
+
source: ${n('resolveSourceURL')}(loaded.url, loaded.root + entry.originalSource),
|
|
234
|
+
line: entry.originalLine + 1,
|
|
235
|
+
column: entry.originalColumn,
|
|
236
|
+
name: ${t('(')}entry${t(' as {name?: string})')}.name ?? null
|
|
237
|
+
};
|
|
238
|
+
}`
|
|
239
|
+
},
|
|
240
|
+
retrieveSourceMap: {
|
|
241
|
+
uses: ['UrlAndMap', 'sourceMapSupportState', 'retrieveSourceFile', 'resolveSourceURL'],
|
|
242
|
+
builtins: ['module#findSourceMap'],
|
|
243
|
+
source: ({n, b, t}) => `
|
|
244
|
+
/** The source map of a generated file: from the handlers, its \`sourceMappingURL\`, or what Node read as it loaded. */
|
|
245
|
+
function ${n('retrieveSourceMap')}(source${t(': string')})${t(`: ${n('UrlAndMap')} | null`)} {
|
|
246
|
+
const state = ${n('sourceMapSupportState')}();
|
|
247
|
+
for (const handler of state.mapHandlers) {
|
|
248
|
+
const urlAndMap = handler(source);
|
|
249
|
+
if (urlAndMap) return urlAndMap;
|
|
250
|
+
}
|
|
251
|
+
if (!state.readMaps) return null;
|
|
252
|
+
const pattern = /(?:\\/\\/[@#][\\s]*sourceMappingURL=([^\\s\\x27\\x22]+)[\\s]*$)|(?:\\/\\*[@#][\\s]*sourceMappingURL=([^\\s*\\x27\\x22]+)[\\s]*(?:\\*\\/)[\\s]*$)/mg;
|
|
253
|
+
const contents = ${n('retrieveSourceFile')}(source) ?? '';
|
|
254
|
+
let url${t(': string | undefined')};
|
|
255
|
+
for (let match = pattern.exec(contents); match; match = pattern.exec(contents)) url = match[1] ?? match[2];
|
|
256
|
+
if (url && /^data:application\\/json[^,]+base64,/.test(url)) {
|
|
257
|
+
return {url: source, map: Buffer.from(url.slice(url.indexOf(',') + 1), 'base64').toString()};
|
|
258
|
+
}
|
|
259
|
+
const map = url && ${n('retrieveSourceFile')}(url = ${n('resolveSourceURL')}(source, url));
|
|
260
|
+
if (map) return {url, map};
|
|
261
|
+
const cached = ${b('module#findSourceMap')}(source);
|
|
262
|
+
return cached ? {url: source, map: cached.payload} : null;
|
|
263
|
+
}`
|
|
264
|
+
},
|
|
265
|
+
resetRetrieveHandlers: {
|
|
266
|
+
uses: ['sourceMapSupportState'],
|
|
267
|
+
source: ({n, t}) => `
|
|
268
|
+
/** Drops the \`retrieveFile\` and \`retrieveSourceMap\` handlers \`install\` was given. */
|
|
269
|
+
function ${n('resetRetrieveHandlers')}()${t(': void')} {
|
|
270
|
+
const state = ${n('sourceMapSupportState')}();
|
|
271
|
+
state.fileHandlers.length = 0;
|
|
272
|
+
state.mapHandlers.length = 0;
|
|
273
|
+
state.readFiles = true;
|
|
274
|
+
state.readMaps = true;
|
|
275
|
+
}`
|
|
276
|
+
},
|
|
277
|
+
sourceMapSupportState: {
|
|
278
|
+
uses: ['SourceMapSupportState'],
|
|
279
|
+
source: ({n, t}) => `
|
|
280
|
+
/**
|
|
281
|
+
* What source-map-support kept between calls, which every file with these functions shares. It hangs off
|
|
282
|
+
* \`process\` rather than \`globalThis\`, where test runners such as lab would report it as a leaked global.
|
|
283
|
+
*/
|
|
284
|
+
function ${n('sourceMapSupportState')}()${t(`: ${n('SourceMapSupportState')}`)} {
|
|
285
|
+
const key = Symbol.for('source-map-support');
|
|
286
|
+
let state${t(`: ${n('SourceMapSupportState')} | undefined`)} = Reflect.get(process, key);
|
|
287
|
+
if (!state) {
|
|
288
|
+
state = {
|
|
289
|
+
fileHandlers: [], mapHandlers: [], readFiles: true, readMaps: true, emptyCaches: false, installed: false,
|
|
290
|
+
files: new Map(), maps: new Map()
|
|
291
|
+
};
|
|
292
|
+
Reflect.set(process, key, state);
|
|
293
|
+
}
|
|
294
|
+
return state;
|
|
295
|
+
}`
|
|
296
|
+
},
|
|
297
|
+
retrieveSourceFile: {
|
|
298
|
+
uses: ['sourceMapSupportState'],
|
|
299
|
+
builtins: ['fs#readFileSync', 'url#fileURLToPath'],
|
|
300
|
+
source: ({n, b, t}) => `
|
|
301
|
+
function ${n('retrieveSourceFile')}(path${t(': string')})${t(': string | null')} {
|
|
302
|
+
const state = ${n('sourceMapSupportState')}();
|
|
303
|
+
for (const handler of state.fileHandlers) {
|
|
304
|
+
const contents = handler(path);
|
|
305
|
+
if (contents) return contents;
|
|
306
|
+
}
|
|
307
|
+
if (!state.readFiles) return null;
|
|
308
|
+
path = path.trim();
|
|
309
|
+
if (path.startsWith('file:')) {
|
|
310
|
+
try {
|
|
311
|
+
path = ${b('url#fileURLToPath')}(path);
|
|
312
|
+
} catch {
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
if (!state.files.has(path)) {
|
|
316
|
+
let contents = '';
|
|
317
|
+
try {
|
|
318
|
+
contents = ${b('fs#readFileSync')}(path, 'utf8');
|
|
319
|
+
} catch {
|
|
320
|
+
}
|
|
321
|
+
state.files.set(path, contents);
|
|
322
|
+
}
|
|
323
|
+
return state.files.get(path)${t('!')};
|
|
324
|
+
}`
|
|
325
|
+
},
|
|
326
|
+
resolveSourceURL: {
|
|
327
|
+
uses: [],
|
|
328
|
+
builtins: ['path#dirname', 'path#resolve'],
|
|
329
|
+
source: ({n, b, t}) => `
|
|
330
|
+
/** \`url\` resolved against the directory of \`file\`, keeping a protocol such as \`file://\` in front. */
|
|
331
|
+
function ${n('resolveSourceURL')}(file${t(': string | undefined')}, url${t(': string')})${t(': string')} {
|
|
332
|
+
if (!file) return url;
|
|
333
|
+
const dir = ${b('path#dirname')}(file);
|
|
334
|
+
const protocol = /^\\w+:\\/\\/[^/]*/.exec(dir)?.[0] ?? '';
|
|
335
|
+
const start = dir.slice(protocol.length);
|
|
336
|
+
if (protocol && /^\\/\\w:/.test(start)) {
|
|
337
|
+
return protocol + '/' + ${b('path#resolve')}(dir.slice(protocol.length + 1), url).replace(/\\\\/g, '/');
|
|
338
|
+
}
|
|
339
|
+
return protocol + ${b('path#resolve')}(start, url);
|
|
340
|
+
}`
|
|
341
|
+
},
|
|
342
|
+
mapEvalOrigin: {
|
|
343
|
+
uses: ['mapSourcePosition'],
|
|
344
|
+
source: ({n, t}) => `
|
|
345
|
+
/** An \`eval\` origin as V8 formats it, with the position of each call site mapped. */
|
|
346
|
+
function ${n('mapEvalOrigin')}(origin${t(': string')})${t(': string')} {
|
|
347
|
+
let match = /^eval at ([^(]+) \\((.+):(\\d+):(\\d+)\\)$/.exec(origin);
|
|
348
|
+
if (match) {
|
|
349
|
+
const position = ${n('mapSourcePosition')}({source: match[2]${t('!')}, line: +match[3]${t('!')}, column: +match[4]${t('!')} - 1});
|
|
350
|
+
return \`eval at \${match[1]} (\${position.source}:\${position.line}:\${position.column + 1})\`;
|
|
351
|
+
}
|
|
352
|
+
match = /^eval at ([^(]+) \\((.+)\\)$/.exec(origin);
|
|
353
|
+
return match ? \`eval at \${match[1]} (\${${n('mapEvalOrigin')}(match[2]${t('!')})})\` : origin;
|
|
354
|
+
}`
|
|
355
|
+
},
|
|
356
|
+
scriptNameOf: {
|
|
357
|
+
uses: [],
|
|
358
|
+
source: ({n, t}) => `
|
|
359
|
+
/** The call site's \`getScriptNameOrSourceURL\`, which older versions of @types/node don't declare. */
|
|
360
|
+
function ${n('scriptNameOf')}(frame${t(': NodeJS.CallSite')})${t(': string | null')} {
|
|
361
|
+
return ${t('(')}frame${t(' as unknown as {getScriptNameOrSourceURL(): string | null})')}.getScriptNameOrSourceURL();
|
|
362
|
+
}`
|
|
363
|
+
},
|
|
364
|
+
formatCallSite: {
|
|
365
|
+
uses: ['scriptNameOf'],
|
|
366
|
+
source: ({n, t}) => `
|
|
367
|
+
/** V8's \`CallSite.prototype.toString\`, which reads the position through the call site's own methods. */
|
|
368
|
+
function ${n('formatCallSite')}(${t('this: NodeJS.CallSite')})${t(': string')} {
|
|
369
|
+
let location = '';
|
|
370
|
+
if (this.isNative()) {
|
|
371
|
+
location = 'native';
|
|
372
|
+
} else {
|
|
373
|
+
const fileName = ${n('scriptNameOf')}(this);
|
|
374
|
+
if (!fileName && this.isEval()) location = this.getEvalOrigin() + ', ';
|
|
375
|
+
location += fileName || '<anonymous>';
|
|
376
|
+
const line = this.getLineNumber();
|
|
377
|
+
if (line != null) {
|
|
378
|
+
location += ':' + line;
|
|
379
|
+
const column = this.getColumnNumber();
|
|
380
|
+
if (column) location += ':' + column;
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
const functionName = this.getFunctionName();
|
|
384
|
+
const isConstructor = this.isConstructor();
|
|
385
|
+
if (!(this.isToplevel() || isConstructor)) {
|
|
386
|
+
let typeName = this.getTypeName();
|
|
387
|
+
if (typeName === '[object Object]') typeName = 'null';
|
|
388
|
+
const methodName = this.getMethodName();
|
|
389
|
+
let call = '';
|
|
390
|
+
if (functionName) {
|
|
391
|
+
if (typeName && functionName.indexOf(typeName) !== 0) call += typeName + '.';
|
|
392
|
+
call += functionName;
|
|
393
|
+
if (methodName && functionName.indexOf('.' + methodName) !== functionName.length - methodName.length - 1) {
|
|
394
|
+
call += \` [as \${methodName}]\`;
|
|
395
|
+
}
|
|
396
|
+
} else {
|
|
397
|
+
call += typeName + '.' + (methodName || '<anonymous>');
|
|
398
|
+
}
|
|
399
|
+
return \`\${call} (\${location})\`;
|
|
400
|
+
}
|
|
401
|
+
if (isConstructor) return \`new \${functionName || '<anonymous>'} (\${location})\`;
|
|
402
|
+
return functionName ? \`\${functionName} (\${location})\` : location;
|
|
403
|
+
}`
|
|
404
|
+
},
|
|
405
|
+
cloneCallSite: {
|
|
406
|
+
uses: ['formatCallSite'],
|
|
407
|
+
source: ({n, t}) => `
|
|
408
|
+
/** A copy of a V8 call site whose methods can be replaced, which a call site's own can't. */
|
|
409
|
+
function ${n('cloneCallSite')}(frame${t(': NodeJS.CallSite')})${t(': NodeJS.CallSite')} {
|
|
410
|
+
const clone${t(': {[name: string]: unknown}')} = {};
|
|
411
|
+
for (const name of Object.getOwnPropertyNames(Object.getPrototypeOf(frame))) {
|
|
412
|
+
const member = ${t('(')}frame${t(' as unknown as {[name: string]: () => unknown})')}[name]${t('!')};
|
|
413
|
+
clone[name] = /^(?:is|get)/.test(name) ? () => member.call(frame) : member;
|
|
414
|
+
}
|
|
415
|
+
clone.toString = ${n('formatCallSite')};
|
|
416
|
+
return clone${t(' as unknown as NodeJS.CallSite')};
|
|
417
|
+
}`
|
|
418
|
+
},
|
|
419
|
+
prepareSourceMappedStackTrace: {
|
|
420
|
+
uses: ['sourceMapSupportState', 'CallSiteState', 'wrapCallSite'],
|
|
421
|
+
source: ({n, t}) => `
|
|
422
|
+
/** The \`Error.prepareStackTrace\` source-map-support installs, formatting each frame at its original position. */
|
|
423
|
+
function ${n('prepareSourceMappedStackTrace')}(error${t(': Error')}, stack${t(': NodeJS.CallSite[]')})${t(': string')} {
|
|
424
|
+
const state = ${n('sourceMapSupportState')}();
|
|
425
|
+
if (state.emptyCaches) {
|
|
426
|
+
state.files.clear();
|
|
427
|
+
state.maps.clear();
|
|
428
|
+
}
|
|
429
|
+
const positions${t(`: ${n('CallSiteState')}`)} = {nextPosition: null, curPosition: null};
|
|
430
|
+
const frames${t(': string[]')} = [];
|
|
431
|
+
for (let i = stack.length - 1; i >= 0; i--) {
|
|
432
|
+
frames.push('\\n at ' + ${n('wrapCallSite')}(stack[i]${t('!')}, positions));
|
|
433
|
+
positions.nextPosition = positions.curPosition;
|
|
434
|
+
}
|
|
435
|
+
return \`\${error.name || 'Error'}: \${error.message || ''}\${frames.reverse().join('')}\`;
|
|
436
|
+
}`
|
|
437
|
+
},
|
|
438
|
+
};
|
|
439
|
+
|
|
440
|
+
/** The order declarations are written in: the types, the API as source-map-support exports it, then its internals. */
|
|
441
|
+
const ORDER = Object.keys(TEMPLATES) as ApiDeclaration[];
|
|
442
|
+
|
|
443
|
+
/** `requested`, and every declaration they name, in the order they are written; JavaScript gets no types. */
|
|
444
|
+
export function declarationsFor(requested: Iterable<ApiDeclaration>, typeScript: boolean): ApiDeclaration[] {
|
|
445
|
+
const needed = new Set<ApiDeclaration>();
|
|
446
|
+
const visit = (declaration: ApiDeclaration) => {
|
|
447
|
+
if (needed.has(declaration)) return;
|
|
448
|
+
needed.add(declaration);
|
|
449
|
+
TEMPLATES[declaration].uses.forEach(visit);
|
|
450
|
+
};
|
|
451
|
+
[...requested].forEach(visit);
|
|
452
|
+
return ORDER.filter(d => needed.has(d) && (typeScript || !TEMPLATES[d].typeOnly));
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
/** The builtins `declarations` call, or name as a type in TypeScript. */
|
|
456
|
+
export function builtinsFor(declarations: ApiDeclaration[]): ApiBuiltin[] {
|
|
457
|
+
return [...new Set(declarations.flatMap(d => TEMPLATES[d].builtins ?? []))]
|
|
458
|
+
.sort((a, b) => a.localeCompare(b, 'en', {sensitivity: 'base'}));
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
/** The source of `declarations`, under the names given, in `style`. */
|
|
462
|
+
export function apiSource(declarations: ApiDeclaration[], spelling: {
|
|
463
|
+
names: (declaration: ApiDeclaration) => string;
|
|
464
|
+
builtins: (builtin: ApiBuiltin) => string;
|
|
465
|
+
typeScript: boolean;
|
|
466
|
+
style: CodeStyle;
|
|
467
|
+
}): string {
|
|
468
|
+
const s: Spelling = {n: spelling.names, b: spelling.builtins, t: typed => spelling.typeScript ? typed : ''};
|
|
469
|
+
return restyle(declarations.map(d => TEMPLATES[d].source(s).replace(/^\n/, '')).join('\n\n'), spelling.style);
|
|
470
|
+
}
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
import {Recipe} from "@openrewrite/rewrite";
|
|
8
8
|
import {EnableSourceMapsAtLaunch} from "./enable-source-maps-at-launch";
|
|
9
|
+
import {ReplaceSourceMapSupportApi} from "./replace-source-map-support-api";
|
|
9
10
|
import {ReplaceSourceMapSupportInstall} from "./replace-source-map-support-install";
|
|
10
11
|
import {ReplaceSourceMapSupportRegisterInPackageJson} from "./replace-source-map-support-register-in-package-json";
|
|
11
12
|
import {ReplaceSourceMapSupportRegisterInMochaConfig} from "./replace-source-map-support-register-in-mocha-config";
|
|
@@ -16,6 +17,8 @@ export function sourceMapSupportRewriteRecipes(): Recipe[] {
|
|
|
16
17
|
new ReplaceSourceMapSupportRegisterInPackageJson(),
|
|
17
18
|
new ReplaceSourceMapSupportRegisterInMochaConfig(),
|
|
18
19
|
new ReplaceSourceMapSupportInstall(),
|
|
20
|
+
// Takes the install() calls whose options the native rewrites can't map.
|
|
21
|
+
new ReplaceSourceMapSupportApi(),
|
|
19
22
|
// Last of the rewrites: it takes the entry points the in-place rewrite turned down.
|
|
20
23
|
new EnableSourceMapsAtLaunch(),
|
|
21
24
|
];
|
|
@@ -6,7 +6,8 @@
|
|
|
6
6
|
|
|
7
7
|
import {Column, Cursor, DataTable} from "@openrewrite/rewrite";
|
|
8
8
|
import {isIdentifier, J} from "@openrewrite/rewrite/java";
|
|
9
|
-
import {compilationUnitOf,
|
|
9
|
+
import {compilationUnitOf, JS, scopeOf, walk} from "@openrewrite/rewrite/javascript";
|
|
10
|
+
import {BuiltinBindingVisitor} from "../builtin-binding-visitor";
|
|
10
11
|
import {bindingsOf, isModuleScoped, ModuleBindings, requiredModule, stringLiteral} from "../module-bindings";
|
|
11
12
|
import {REGISTER_MODULES} from "./register-flag";
|
|
12
13
|
|
|
@@ -27,6 +28,12 @@ export const NON_INSTALL_MEMBERS = new Set([
|
|
|
27
28
|
'wrapCallSite', 'getErrorSource', 'mapSourcePosition', 'retrieveSourceMap', 'resetRetrieveHandlers',
|
|
28
29
|
]);
|
|
29
30
|
|
|
31
|
+
/** Trees that hold an identifier as a declaration or import rather than a use of it. */
|
|
32
|
+
export const DECLARING_KINDS = new Set<string>([
|
|
33
|
+
JS.Kind.Import, JS.Kind.ImportClause, JS.Kind.ImportSpecifier, JS.Kind.Alias, JS.Kind.NamedImports,
|
|
34
|
+
JS.Kind.ExportSpecifier, JS.Kind.BindingElement, JS.Kind.ObjectBindingPattern,
|
|
35
|
+
]);
|
|
36
|
+
|
|
30
37
|
export const REASONS = {
|
|
31
38
|
partialMapping: "Enabling source maps here would only map the modules loaded after it, where " +
|
|
32
39
|
"`source-map-support` maps every stack frame: this file loads another module first, either as a static " +
|
|
@@ -34,13 +41,17 @@ export const REASONS = {
|
|
|
34
41
|
"`--enable-source-maps` instead — which is what the `package.json` and mocha recipes set where they can — " +
|
|
35
42
|
"or re-run with `allowPartialMapping` enabled to accept the narrower mapping.",
|
|
36
43
|
nonNativeOption: (option: string) => `\`install\` is passed \`${option}\`, which Node's native source maps have ` +
|
|
37
|
-
"no equivalent for.
|
|
38
|
-
"
|
|
39
|
-
|
|
40
|
-
"
|
|
44
|
+
"no equivalent for. `ReplaceSourceMapSupportApi` writes source-map-support's `install` into the file as " +
|
|
45
|
+
"`installSourceMapSupport`, on Node's own `SourceMap`, but not for a call passing more than one argument or in " +
|
|
46
|
+
"a file it can't import Node's builtins into, such as an AMD module. Pass one options object, or bind the " +
|
|
47
|
+
"file's modules with `import` or `require`.",
|
|
48
|
+
browser: "`install` is configured for a browser, where Node's source maps don't run; browsers map stack traces " +
|
|
49
|
+
"in their developer tools. `ReplaceSourceMapSupportApi` removes such a call where it is a statement of its own " +
|
|
50
|
+
"at the top of the file, which this one isn't. Remove it by hand.",
|
|
41
51
|
member: (name: string) => `\`${name}\` is part of source-map-support's API that Node doesn't expose. ` +
|
|
42
|
-
"`
|
|
43
|
-
"
|
|
52
|
+
"`ReplaceSourceMapSupportApi` writes it into the file, on Node's own `SourceMap`, but not in a file it can't " +
|
|
53
|
+
"import Node's builtins into, such as an AMD module, nor through a binding a shorthand property also names. " +
|
|
54
|
+
"Bind the file's modules with `import` or `require`, or spell the property out.",
|
|
44
55
|
localProcess: "`process` here is a local binding rather than Node's, so `process.setSourceMapsEnabled(true)` " +
|
|
45
56
|
"can't be written at this point. Rename the local, or import `process` from `node:process`.",
|
|
46
57
|
bannerString: "A string names `source-map-support`, which looks like code injected into a bundle (a webpack " +
|
|
@@ -51,14 +62,21 @@ export const REASONS = {
|
|
|
51
62
|
"`NODE_OPTIONS=--enable-source-maps` for it.",
|
|
52
63
|
value: "`source-map-support` is used as a value rather than called, so the use can't be rewritten in place. " +
|
|
53
64
|
"Node offers `process.setSourceMapsEnabled(true)` and the `--enable-source-maps` flag, and nothing else.",
|
|
54
|
-
type: "
|
|
55
|
-
"
|
|
65
|
+
type: "This type from @types/source-map-support has no counterpart in Node's API, nor is it one of those " +
|
|
66
|
+
"`ReplaceSourceMapSupportApi` declares in the file (`Options`, `UrlAndMap`, `Position`, `State`, `CallSite`, " +
|
|
67
|
+
"`Environment`). Drop the type or declare a local one.",
|
|
56
68
|
reExport: "Re-exporting source-map-support makes it part of this module's API. Consumers have to call " +
|
|
57
69
|
"`process.setSourceMapsEnabled(true)` themselves, or the process has to be launched with `--enable-source-maps`.",
|
|
58
70
|
dynamicImport: "Dynamic import of source-map-support, which the automated migration doesn't follow. Call " +
|
|
59
71
|
"`process.setSourceMapsEnabled(true)` instead, as early in the process as possible.",
|
|
60
72
|
nestedRequire: "source-map-support required outside module scope, which the automated migration doesn't follow. " +
|
|
61
73
|
"Move the require to the top of the file or migrate its uses by hand.",
|
|
74
|
+
assigned: (name: string) => `\`${name}\` of source-map-support is assigned, changing the library for every ` +
|
|
75
|
+
"module that loads it, which functions written into this file can't stand in for. Remove the assignment, " +
|
|
76
|
+
"or keep the code it guards from loading source-map-support.",
|
|
77
|
+
specifierString: "A source-map-support specifier is held as a value, as the `--require` argument of a child " +
|
|
78
|
+
"process or a test runner's configuration is, rather than loaded here. Pass `--enable-source-maps` to the " +
|
|
79
|
+
"process instead, or set `NODE_OPTIONS=--enable-source-maps` for it.",
|
|
62
80
|
mock: "Test mocks source-map-support. Once the code under test calls `process.setSourceMapsEnabled(true)` there " +
|
|
63
81
|
"is no module left to mock; assert on `process.sourceMapsEnabled` instead.",
|
|
64
82
|
};
|
|
@@ -141,13 +159,64 @@ export function hasOnlyNativeOptions(arg: J | undefined): boolean {
|
|
|
141
159
|
return nonNativeOption(arg) === undefined;
|
|
142
160
|
}
|
|
143
161
|
|
|
162
|
+
/** Whether the tree at `cursor` is written to: assigned, incremented or deleted. */
|
|
163
|
+
export function isWriteTarget(cursor: Cursor): boolean {
|
|
164
|
+
const node = cursor.value as J;
|
|
165
|
+
const parent = cursor.parentTree()?.value as J | undefined;
|
|
166
|
+
switch (parent?.kind) {
|
|
167
|
+
case J.Kind.Assignment:
|
|
168
|
+
case J.Kind.AssignmentOperation:
|
|
169
|
+
case JS.Kind.AssignmentOperation:
|
|
170
|
+
return (parent as J.Assignment).variable === node;
|
|
171
|
+
case JS.Kind.Delete:
|
|
172
|
+
return (parent as JS.Delete).expression === node;
|
|
173
|
+
case J.Kind.Unary:
|
|
174
|
+
return [J.Unary.Type.PreIncrement, J.Unary.Type.PreDecrement, J.Unary.Type.PostIncrement,
|
|
175
|
+
J.Unary.Type.PostDecrement].includes((parent as J.Unary).operator.element);
|
|
176
|
+
default:
|
|
177
|
+
return false;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/** Whether an `install()` options literal sets `environment: 'browser'`. */
|
|
182
|
+
export function isBrowserInstall(arg: J | undefined): boolean {
|
|
183
|
+
if (arg?.kind !== J.Kind.NewClass || (arg as J.NewClass).class) return false;
|
|
184
|
+
return ((arg as J.NewClass).body?.statements ?? []).some(s => s.element.kind === JS.Kind.PropertyAssignment &&
|
|
185
|
+
propertyName(s.element as JS.PropertyAssignment) === 'environment' &&
|
|
186
|
+
stringLiteral((s.element as JS.PropertyAssignment).initializer) === 'browser');
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Drops the statements `remove` selects, handing the first of a removed run its successor's place
|
|
191
|
+
* in the layout, so the blank line that separated it from what came before isn't left behind. Only
|
|
192
|
+
* the whitespace moves: a comment sits in the prefix of the statement it documents, so taking the
|
|
193
|
+
* successor's prefix wholesale would delete the comment that belongs to it.
|
|
194
|
+
*/
|
|
195
|
+
export function withoutStatements(statements: J.RightPadded<any>[], remove: (s: J) => boolean): J.RightPadded<any>[] {
|
|
196
|
+
const kept: J.RightPadded<any>[] = [];
|
|
197
|
+
let pendingWhitespace: string | undefined;
|
|
198
|
+
for (const padded of statements) {
|
|
199
|
+
if (remove(padded.element)) {
|
|
200
|
+
pendingWhitespace ??= (padded.element.prefix as J.Space).whitespace;
|
|
201
|
+
continue;
|
|
202
|
+
}
|
|
203
|
+
kept.push(pendingWhitespace === undefined ? padded : {
|
|
204
|
+
...padded,
|
|
205
|
+
element: {...padded.element, prefix: {...padded.element.prefix, whitespace: pendingWhitespace}}
|
|
206
|
+
});
|
|
207
|
+
pendingWhitespace = undefined;
|
|
208
|
+
}
|
|
209
|
+
return kept;
|
|
210
|
+
}
|
|
211
|
+
|
|
144
212
|
/**
|
|
145
213
|
* Base visitor for the source-map-support migration: recognizes `install()` and the `register`
|
|
146
214
|
* entry points through any binding style, and judges whether enabling native source maps at a
|
|
147
215
|
* given point maps everything `source-map-support` would have. The rewrite and the finder share
|
|
148
216
|
* these so they agree on which sites can be migrated.
|
|
149
217
|
*/
|
|
150
|
-
export abstract class SourceMapSupportVisitor<P> extends
|
|
218
|
+
export abstract class SourceMapSupportVisitor<P> extends BuiltinBindingVisitor<P> {
|
|
219
|
+
protected readonly migratedModules: ReadonlySet<string> = MODULES;
|
|
151
220
|
protected bindings: ModuleBindings = new Map();
|
|
152
221
|
|
|
153
222
|
protected override async visitJsCompilationUnit(cu: JS.CompilationUnit, p: P): Promise<J | undefined> {
|