@rootcat/node 0.0.0-stage → 0.2.0
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/CHANGELOG.md +83 -0
- package/LICENSE +202 -0
- package/README.md +294 -2
- package/dist/attach.d.ts +1 -0
- package/dist/attach.js +24 -0
- package/dist/attach.js.map +1 -0
- package/dist/callsite.d.ts +109 -0
- package/dist/callsite.js +565 -0
- package/dist/callsite.js.map +1 -0
- package/dist/coexist.d.ts +183 -0
- package/dist/coexist.js +587 -0
- package/dist/coexist.js.map +1 -0
- package/dist/config.d.ts +75 -0
- package/dist/config.js +182 -0
- package/dist/config.js.map +1 -0
- package/dist/drizzle.d.ts +21 -0
- package/dist/drizzle.js +127 -0
- package/dist/drizzle.js.map +1 -0
- package/dist/esm.mjs +57 -0
- package/dist/esmhook.d.ts +52 -0
- package/dist/esmhook.js +158 -0
- package/dist/esmhook.js.map +1 -0
- package/dist/iitm-hook.mjs +83 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.js +52 -0
- package/dist/index.js.map +1 -0
- package/dist/intake.d.ts +40 -0
- package/dist/intake.js +164 -0
- package/dist/intake.js.map +1 -0
- package/dist/keys.d.ts +20 -0
- package/dist/keys.js +33 -0
- package/dist/keys.js.map +1 -0
- package/dist/notices.d.ts +2 -0
- package/dist/notices.js +21 -0
- package/dist/notices.js.map +1 -0
- package/dist/otlp.d.ts +75 -0
- package/dist/otlp.js +449 -0
- package/dist/otlp.js.map +1 -0
- package/dist/pg.d.ts +16 -0
- package/dist/pg.js +170 -0
- package/dist/pg.js.map +1 -0
- package/dist/pgpool.d.ts +20 -0
- package/dist/pgpool.js +99 -0
- package/dist/pgpool.js.map +1 -0
- package/dist/postgresjs.d.ts +60 -0
- package/dist/postgresjs.js +400 -0
- package/dist/postgresjs.js.map +1 -0
- package/dist/privacy.d.ts +38 -0
- package/dist/privacy.js +161 -0
- package/dist/privacy.js.map +1 -0
- package/dist/processor.d.ts +197 -0
- package/dist/processor.js +494 -0
- package/dist/processor.js.map +1 -0
- package/dist/register.d.ts +1 -0
- package/dist/register.js +12 -0
- package/dist/register.js.map +1 -0
- package/dist/sampler.d.ts +30 -0
- package/dist/sampler.js +101 -0
- package/dist/sampler.js.map +1 -0
- package/dist/sdk.d.ts +129 -0
- package/dist/sdk.js +606 -0
- package/dist/sdk.js.map +1 -0
- package/package.json +72 -4
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { TraceMap } from '@jridgewell/trace-mapping';
|
|
2
|
+
/** CallSiteLocation is one resolved frame. */
|
|
3
|
+
export interface CallSiteLocation {
|
|
4
|
+
/** file is an absolute path, or a bundler path such as app/route.ts. */
|
|
5
|
+
file: string;
|
|
6
|
+
/** line is 1-based. */
|
|
7
|
+
line: number;
|
|
8
|
+
/** column is 1-based, 0 when unknown. */
|
|
9
|
+
column: number;
|
|
10
|
+
/** function is the enclosing function's name, "" when anonymous. */
|
|
11
|
+
function: string;
|
|
12
|
+
}
|
|
13
|
+
type V8CallSite = NodeJS.CallSite;
|
|
14
|
+
/** defaultDepth is how many frames a full capture walks. */
|
|
15
|
+
export declare const defaultDepth = 32;
|
|
16
|
+
/**
|
|
17
|
+
* shortDepth is the first walk from an entry wrapper: its caller is the
|
|
18
|
+
* application or an ORM a few frames above it. A stack frame costs about
|
|
19
|
+
* a microsecond to collect; the full walk is the fallback.
|
|
20
|
+
*/
|
|
21
|
+
export declare const shortDepth = 3;
|
|
22
|
+
/** Bounds on source maps: per map, and for all maps held at once. */
|
|
23
|
+
export declare const maxSourceMapBytes: number;
|
|
24
|
+
export declare const sourceMapBudgetBytes: number;
|
|
25
|
+
/** maxDisplayPathBytes keeps code.filepath within the agent's 128-byte bound. */
|
|
26
|
+
export declare const maxDisplayPathBytes = 120;
|
|
27
|
+
/**
|
|
28
|
+
* captureFrames returns up to depth frames as V8 CallSite objects,
|
|
29
|
+
* starting below the topmost call of above (or of captureFrames itself).
|
|
30
|
+
* Error.prepareStackTrace and Error.stackTraceLimit are swapped for the
|
|
31
|
+
* duration of the capture only. When above is not on the stack, V8 gives
|
|
32
|
+
* nothing; the caller falls back to an uncut walk.
|
|
33
|
+
*/
|
|
34
|
+
export declare function captureFrames(depth: number, above?: Function): V8CallSite[];
|
|
35
|
+
/**
|
|
36
|
+
* normalizeFile turns a CallSite file name into a path: file URLs become
|
|
37
|
+
* paths, webpack-internal URLs lose their prefix; node: internals, eval
|
|
38
|
+
* and other non-paths give undefined.
|
|
39
|
+
*/
|
|
40
|
+
export declare function normalizeFile(file: string | null | undefined): string | undefined;
|
|
41
|
+
/**
|
|
42
|
+
* isAppFile reports whether a path belongs to the application: no
|
|
43
|
+
* node_modules segment (absolute or bundler-relative, as a source map
|
|
44
|
+
* names a bundled library) and not this package's own code.
|
|
45
|
+
*/
|
|
46
|
+
export declare function isAppFile(file: string, own?: readonly string[]): boolean;
|
|
47
|
+
/** firstAppFrame returns the first captured frame whose generated file is application code, unresolved. */
|
|
48
|
+
export declare function firstAppFrame(sites: readonly V8CallSite[], isApp?: (file: string) => boolean): CallSiteLocation | undefined;
|
|
49
|
+
/**
|
|
50
|
+
* appLocation walks the frames, resolves each candidate through its
|
|
51
|
+
* source map, and returns the first whose original source is application
|
|
52
|
+
* code: a frame in a bundle that maps into a bundled library is passed
|
|
53
|
+
* over, as an unbundled library frame is.
|
|
54
|
+
*/
|
|
55
|
+
export declare function appLocation(sites: readonly V8CallSite[], isApp?: (file: string) => boolean): CallSiteLocation | undefined;
|
|
56
|
+
/** resetSourceMapCache forgets loaded maps (tests). */
|
|
57
|
+
export declare function resetSourceMapCache(): void;
|
|
58
|
+
/** sourceMapBytesHeld reports what the cache holds (tests). */
|
|
59
|
+
export declare function sourceMapBytesHeld(): number;
|
|
60
|
+
/**
|
|
61
|
+
* sourceMapFor loads the source map a generated file points at through
|
|
62
|
+
* its sourceMappingURL comment (inline data URL or a file beside it),
|
|
63
|
+
* once per file, and remembers the result; null when none. A map over
|
|
64
|
+
* maxSourceMapBytes is not read; the maps held together stay within
|
|
65
|
+
* sourceMapBudgetBytes, the least recently loaded given up first (and
|
|
66
|
+
* read again if their file comes back). The read is synchronous and
|
|
67
|
+
* happens the first time a file is seen on a captured stack.
|
|
68
|
+
*/
|
|
69
|
+
export declare function sourceMapFor(file: string): TraceMap | null;
|
|
70
|
+
/** sourceMappingURL finds the last sourceMappingURL comment in text. */
|
|
71
|
+
export declare function sourceMappingURL(text: string): string | undefined;
|
|
72
|
+
/**
|
|
73
|
+
* originalPath makes a mapped source readable: file URLs become paths and
|
|
74
|
+
* bundler schemes (webpack://, turbopack://) are reduced to the project
|
|
75
|
+
* relative path they carry.
|
|
76
|
+
*/
|
|
77
|
+
export declare function originalPath(source: string): string;
|
|
78
|
+
/**
|
|
79
|
+
* resolveLocation maps a generated position to the original source when
|
|
80
|
+
* the file has a source map: the one Node already holds (with
|
|
81
|
+
* --enable-source-maps, or a loader such as tsx registering its maps),
|
|
82
|
+
* else the file's own. Otherwise the location is returned as is.
|
|
83
|
+
*/
|
|
84
|
+
export declare function resolveLocation(location: CallSiteLocation): CallSiteLocation;
|
|
85
|
+
/**
|
|
86
|
+
* parseStack finds the first application frame in a formatted V8 stack
|
|
87
|
+
* (one a driver captured itself, such as postgres.js's query origin) and
|
|
88
|
+
* resolves it. undefined when there is none.
|
|
89
|
+
*/
|
|
90
|
+
export declare function parseStack(stack: string, isApp?: (file: string) => boolean): CallSiteLocation | undefined;
|
|
91
|
+
/**
|
|
92
|
+
* captureCallSite is the whole operation: capture, pick the application
|
|
93
|
+
* frame, resolve it. From an entry wrapper (above), a short walk below
|
|
94
|
+
* the wrapper first, the full walk only when that finds no application
|
|
95
|
+
* frame. undefined when no application frame is on the stack.
|
|
96
|
+
*/
|
|
97
|
+
export declare function captureCallSite(depth?: number, isApp?: (file: string) => boolean, above?: Function): CallSiteLocation | undefined;
|
|
98
|
+
/**
|
|
99
|
+
* displayPath is what code.filepath carries: a bundler path as it is, a
|
|
100
|
+
* file under the working directory relative to it, any other file
|
|
101
|
+
* relative to the parent of its nearest package.json directory (so it
|
|
102
|
+
* names its package), and at most maxDisplayPathBytes from the end, so
|
|
103
|
+
* the file name survives the agent's bound. The server's absolute layout
|
|
104
|
+
* (a home directory, a deploy path) is not sent.
|
|
105
|
+
*/
|
|
106
|
+
export declare function displayPath(file: string, cwd?: string): string;
|
|
107
|
+
/** clipFromStart keeps the last bytes of a path, cut at a segment. */
|
|
108
|
+
export declare function clipFromStart(text: string, limit: number): string;
|
|
109
|
+
export {};
|
package/dist/callsite.js
ADDED
|
@@ -0,0 +1,565 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.maxDisplayPathBytes = exports.sourceMapBudgetBytes = exports.maxSourceMapBytes = exports.shortDepth = exports.defaultDepth = void 0;
|
|
37
|
+
exports.captureFrames = captureFrames;
|
|
38
|
+
exports.normalizeFile = normalizeFile;
|
|
39
|
+
exports.isAppFile = isAppFile;
|
|
40
|
+
exports.firstAppFrame = firstAppFrame;
|
|
41
|
+
exports.appLocation = appLocation;
|
|
42
|
+
exports.resetSourceMapCache = resetSourceMapCache;
|
|
43
|
+
exports.sourceMapBytesHeld = sourceMapBytesHeld;
|
|
44
|
+
exports.sourceMapFor = sourceMapFor;
|
|
45
|
+
exports.sourceMappingURL = sourceMappingURL;
|
|
46
|
+
exports.originalPath = originalPath;
|
|
47
|
+
exports.resolveLocation = resolveLocation;
|
|
48
|
+
exports.parseStack = parseStack;
|
|
49
|
+
exports.captureCallSite = captureCallSite;
|
|
50
|
+
exports.displayPath = displayPath;
|
|
51
|
+
exports.clipFromStart = clipFromStart;
|
|
52
|
+
// Call-site capture: the application frame that issued a client operation.
|
|
53
|
+
// The stack is captured as V8 CallSite objects (no string formatting),
|
|
54
|
+
// starting below the wrapper that asks when there is one, so the walk is
|
|
55
|
+
// a few frames rather than the whole driver; each frame outside
|
|
56
|
+
// node_modules, Node's internals and this package is resolved through its
|
|
57
|
+
// file's source map, and the first whose original source is itself
|
|
58
|
+
// application code (not a bundled library) is kept. Source maps are read
|
|
59
|
+
// once per file and held within a byte budget.
|
|
60
|
+
const fs = __importStar(require("node:fs"));
|
|
61
|
+
const nodeModule = __importStar(require("node:module"));
|
|
62
|
+
const path = __importStar(require("node:path"));
|
|
63
|
+
const node_url_1 = require("node:url");
|
|
64
|
+
const trace_mapping_1 = require("@jridgewell/trace-mapping");
|
|
65
|
+
/** defaultDepth is how many frames a full capture walks. */
|
|
66
|
+
exports.defaultDepth = 32;
|
|
67
|
+
/**
|
|
68
|
+
* shortDepth is the first walk from an entry wrapper: its caller is the
|
|
69
|
+
* application or an ORM a few frames above it. A stack frame costs about
|
|
70
|
+
* a microsecond to collect; the full walk is the fallback.
|
|
71
|
+
*/
|
|
72
|
+
exports.shortDepth = 3;
|
|
73
|
+
/** Bounds on source maps: per map, and for all maps held at once. */
|
|
74
|
+
exports.maxSourceMapBytes = 32 * 1024 * 1024;
|
|
75
|
+
exports.sourceMapBudgetBytes = 64 * 1024 * 1024;
|
|
76
|
+
const maxTailBytes = 4096;
|
|
77
|
+
const maxCachedFiles = 512;
|
|
78
|
+
/** maxDisplayPathBytes keeps code.filepath within the agent's 128-byte bound. */
|
|
79
|
+
exports.maxDisplayPathBytes = 120;
|
|
80
|
+
/** ownDirectories are this package's own code, never a call site. */
|
|
81
|
+
const packageRoot = path.resolve(__dirname, '..');
|
|
82
|
+
const ownDirectories = [path.join(packageRoot, 'dist'), path.join(packageRoot, 'src')];
|
|
83
|
+
/**
|
|
84
|
+
* captureFrames returns up to depth frames as V8 CallSite objects,
|
|
85
|
+
* starting below the topmost call of above (or of captureFrames itself).
|
|
86
|
+
* Error.prepareStackTrace and Error.stackTraceLimit are swapped for the
|
|
87
|
+
* duration of the capture only. When above is not on the stack, V8 gives
|
|
88
|
+
* nothing; the caller falls back to an uncut walk.
|
|
89
|
+
*/
|
|
90
|
+
function captureFrames(depth, above) {
|
|
91
|
+
const prepare = Error.prepareStackTrace;
|
|
92
|
+
const limit = Error.stackTraceLimit;
|
|
93
|
+
Error.stackTraceLimit = depth;
|
|
94
|
+
Error.prepareStackTrace = (_error, sites) => sites;
|
|
95
|
+
const holder = {};
|
|
96
|
+
try {
|
|
97
|
+
Error.captureStackTrace(holder, above ?? captureFrames);
|
|
98
|
+
const sites = holder.stack;
|
|
99
|
+
return Array.isArray(sites) ? sites : [];
|
|
100
|
+
}
|
|
101
|
+
finally {
|
|
102
|
+
Error.prepareStackTrace = prepare;
|
|
103
|
+
Error.stackTraceLimit = limit;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* normalizeFile turns a CallSite file name into a path: file URLs become
|
|
108
|
+
* paths, webpack-internal URLs lose their prefix; node: internals, eval
|
|
109
|
+
* and other non-paths give undefined.
|
|
110
|
+
*/
|
|
111
|
+
function normalizeFile(file) {
|
|
112
|
+
if (!file) {
|
|
113
|
+
return undefined;
|
|
114
|
+
}
|
|
115
|
+
if (file.startsWith('node:')) {
|
|
116
|
+
return undefined;
|
|
117
|
+
}
|
|
118
|
+
if (file.startsWith('file://')) {
|
|
119
|
+
try {
|
|
120
|
+
return (0, node_url_1.fileURLToPath)(file);
|
|
121
|
+
}
|
|
122
|
+
catch {
|
|
123
|
+
return undefined;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
if (file.startsWith('webpack-internal:///')) {
|
|
127
|
+
return stripBundlerPrefix(file);
|
|
128
|
+
}
|
|
129
|
+
if (!path.isAbsolute(file)) {
|
|
130
|
+
return undefined;
|
|
131
|
+
}
|
|
132
|
+
return file;
|
|
133
|
+
}
|
|
134
|
+
const nodeModulesSegment = /(^|[\\/])node_modules[\\/]/;
|
|
135
|
+
/**
|
|
136
|
+
* isAppFile reports whether a path belongs to the application: no
|
|
137
|
+
* node_modules segment (absolute or bundler-relative, as a source map
|
|
138
|
+
* names a bundled library) and not this package's own code.
|
|
139
|
+
*/
|
|
140
|
+
function isAppFile(file, own = ownDirectories) {
|
|
141
|
+
if (nodeModulesSegment.test(file)) {
|
|
142
|
+
return false;
|
|
143
|
+
}
|
|
144
|
+
for (const dir of own) {
|
|
145
|
+
if (file === dir || file.startsWith(dir + path.sep)) {
|
|
146
|
+
return false;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
return true;
|
|
150
|
+
}
|
|
151
|
+
/** firstAppFrame returns the first captured frame whose generated file is application code, unresolved. */
|
|
152
|
+
function firstAppFrame(sites, isApp = isAppFile) {
|
|
153
|
+
for (const site of sites) {
|
|
154
|
+
const frame = frameOf(site, isApp);
|
|
155
|
+
if (frame) {
|
|
156
|
+
return frame;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
return undefined;
|
|
160
|
+
}
|
|
161
|
+
function frameOf(site, isApp) {
|
|
162
|
+
let file;
|
|
163
|
+
try {
|
|
164
|
+
file = normalizeFile(site.getFileName());
|
|
165
|
+
}
|
|
166
|
+
catch {
|
|
167
|
+
return undefined;
|
|
168
|
+
}
|
|
169
|
+
if (!file || !isApp(file)) {
|
|
170
|
+
return undefined;
|
|
171
|
+
}
|
|
172
|
+
return { file, line: site.getLineNumber() ?? 0, column: site.getColumnNumber() ?? 0, function: functionName(site) };
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* appLocation walks the frames, resolves each candidate through its
|
|
176
|
+
* source map, and returns the first whose original source is application
|
|
177
|
+
* code: a frame in a bundle that maps into a bundled library is passed
|
|
178
|
+
* over, as an unbundled library frame is.
|
|
179
|
+
*/
|
|
180
|
+
function appLocation(sites, isApp = isAppFile) {
|
|
181
|
+
for (const site of sites) {
|
|
182
|
+
const frame = frameOf(site, isApp);
|
|
183
|
+
if (!frame) {
|
|
184
|
+
continue;
|
|
185
|
+
}
|
|
186
|
+
const resolved = resolveLocation(frame);
|
|
187
|
+
if (resolved !== frame && !isApp(resolved.file)) {
|
|
188
|
+
continue;
|
|
189
|
+
}
|
|
190
|
+
return resolved;
|
|
191
|
+
}
|
|
192
|
+
return undefined;
|
|
193
|
+
}
|
|
194
|
+
function functionName(site) {
|
|
195
|
+
try {
|
|
196
|
+
// getMethodName() searches the receiver's properties and costs more
|
|
197
|
+
// than the rest of a frame together; the function's own name suffices.
|
|
198
|
+
const name = site.getFunctionName() ?? '';
|
|
199
|
+
return name.length > 256 ? name.slice(0, 256) : name;
|
|
200
|
+
}
|
|
201
|
+
catch {
|
|
202
|
+
return '';
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
const sourceMaps = new Map();
|
|
206
|
+
let heldBytes = 0;
|
|
207
|
+
/** resetSourceMapCache forgets loaded maps (tests). */
|
|
208
|
+
function resetSourceMapCache() {
|
|
209
|
+
sourceMaps.clear();
|
|
210
|
+
resolvedPositions.clear();
|
|
211
|
+
heldBytes = 0;
|
|
212
|
+
}
|
|
213
|
+
/** sourceMapBytesHeld reports what the cache holds (tests). */
|
|
214
|
+
function sourceMapBytesHeld() {
|
|
215
|
+
return heldBytes;
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* sourceMapFor loads the source map a generated file points at through
|
|
219
|
+
* its sourceMappingURL comment (inline data URL or a file beside it),
|
|
220
|
+
* once per file, and remembers the result; null when none. A map over
|
|
221
|
+
* maxSourceMapBytes is not read; the maps held together stay within
|
|
222
|
+
* sourceMapBudgetBytes, the least recently loaded given up first (and
|
|
223
|
+
* read again if their file comes back). The read is synchronous and
|
|
224
|
+
* happens the first time a file is seen on a captured stack.
|
|
225
|
+
*/
|
|
226
|
+
function sourceMapFor(file) {
|
|
227
|
+
const cached = sourceMaps.get(file);
|
|
228
|
+
if (cached) {
|
|
229
|
+
return cached.map;
|
|
230
|
+
}
|
|
231
|
+
const entry = loadSourceMap(file);
|
|
232
|
+
while (sourceMaps.size > 0 && (sourceMaps.size >= maxCachedFiles || heldBytes + entry.bytes > exports.sourceMapBudgetBytes)) {
|
|
233
|
+
const oldest = sourceMaps.keys().next().value;
|
|
234
|
+
heldBytes -= sourceMaps.get(oldest).bytes;
|
|
235
|
+
sourceMaps.delete(oldest);
|
|
236
|
+
}
|
|
237
|
+
if (entry.bytes > exports.sourceMapBudgetBytes) {
|
|
238
|
+
sourceMaps.set(file, { map: null, bytes: 0 });
|
|
239
|
+
return null;
|
|
240
|
+
}
|
|
241
|
+
sourceMaps.set(file, entry);
|
|
242
|
+
heldBytes += entry.bytes;
|
|
243
|
+
return entry.map;
|
|
244
|
+
}
|
|
245
|
+
const none = { map: null, bytes: 0 };
|
|
246
|
+
function loadSourceMap(file) {
|
|
247
|
+
if (!path.isAbsolute(file)) {
|
|
248
|
+
return none;
|
|
249
|
+
}
|
|
250
|
+
const tail = readTail(file, maxTailBytes);
|
|
251
|
+
if (tail === undefined) {
|
|
252
|
+
return none;
|
|
253
|
+
}
|
|
254
|
+
const url = sourceMappingURL(tail);
|
|
255
|
+
if (!url) {
|
|
256
|
+
return none;
|
|
257
|
+
}
|
|
258
|
+
try {
|
|
259
|
+
if (url.startsWith('data:')) {
|
|
260
|
+
const text = inlineMap(url);
|
|
261
|
+
return parseMap(text, (0, node_url_1.pathToFileURL)(file).href);
|
|
262
|
+
}
|
|
263
|
+
if (/^[a-z]+:/i.test(url) && !url.startsWith('file:')) {
|
|
264
|
+
return none; // a remote map is never fetched
|
|
265
|
+
}
|
|
266
|
+
// A bundler may percent-encode the map's name ([chunk].js.map).
|
|
267
|
+
const mapFile = url.startsWith('file:') ? (0, node_url_1.fileURLToPath)(url) : path.resolve(path.dirname(file), decodeMapURL(url));
|
|
268
|
+
const stat = fs.statSync(mapFile);
|
|
269
|
+
if (!stat.isFile() || stat.size > exports.maxSourceMapBytes) {
|
|
270
|
+
return none;
|
|
271
|
+
}
|
|
272
|
+
return parseMap(fs.readFileSync(mapFile, 'utf8'), (0, node_url_1.pathToFileURL)(mapFile).href);
|
|
273
|
+
}
|
|
274
|
+
catch {
|
|
275
|
+
return none;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
function decodeMapURL(url) {
|
|
279
|
+
try {
|
|
280
|
+
return decodeURIComponent(url);
|
|
281
|
+
}
|
|
282
|
+
catch {
|
|
283
|
+
return url;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
function parseMap(text, mapUrl) {
|
|
287
|
+
if (text === undefined || text.length > exports.maxSourceMapBytes) {
|
|
288
|
+
return none;
|
|
289
|
+
}
|
|
290
|
+
const parsed = JSON.parse(text);
|
|
291
|
+
if (!parsed || typeof parsed !== 'object') {
|
|
292
|
+
return none;
|
|
293
|
+
}
|
|
294
|
+
// The decoded map holds about what its text did.
|
|
295
|
+
return { map: new trace_mapping_1.TraceMap(parsed, mapUrl), bytes: text.length };
|
|
296
|
+
}
|
|
297
|
+
function inlineMap(url) {
|
|
298
|
+
const comma = url.indexOf(',');
|
|
299
|
+
if (comma < 0) {
|
|
300
|
+
return undefined;
|
|
301
|
+
}
|
|
302
|
+
const header = url.slice(5, comma);
|
|
303
|
+
const payload = url.slice(comma + 1);
|
|
304
|
+
if (!header.startsWith('application/json')) {
|
|
305
|
+
return undefined;
|
|
306
|
+
}
|
|
307
|
+
if (header.endsWith(';base64')) {
|
|
308
|
+
if (payload.length > (exports.maxSourceMapBytes * 4) / 3) {
|
|
309
|
+
return undefined;
|
|
310
|
+
}
|
|
311
|
+
return Buffer.from(payload, 'base64').toString('utf8');
|
|
312
|
+
}
|
|
313
|
+
return decodeURIComponent(payload);
|
|
314
|
+
}
|
|
315
|
+
/** sourceMappingURL finds the last sourceMappingURL comment in text. */
|
|
316
|
+
function sourceMappingURL(text) {
|
|
317
|
+
const pattern = /\/[/*][#@]\s*sourceMappingURL=([^\s'"*]+)/g;
|
|
318
|
+
let url;
|
|
319
|
+
for (;;) {
|
|
320
|
+
const match = pattern.exec(text);
|
|
321
|
+
if (!match) {
|
|
322
|
+
return url;
|
|
323
|
+
}
|
|
324
|
+
url = match[1];
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
function readTail(file, bytes) {
|
|
328
|
+
let fd;
|
|
329
|
+
try {
|
|
330
|
+
fd = fs.openSync(file, 'r');
|
|
331
|
+
const size = fs.fstatSync(fd).size;
|
|
332
|
+
const length = Math.min(size, bytes);
|
|
333
|
+
const buffer = Buffer.alloc(length);
|
|
334
|
+
const n = fs.readSync(fd, buffer, 0, length, size - length);
|
|
335
|
+
return buffer.toString('utf8', 0, n);
|
|
336
|
+
}
|
|
337
|
+
catch {
|
|
338
|
+
return undefined;
|
|
339
|
+
}
|
|
340
|
+
finally {
|
|
341
|
+
if (fd !== undefined) {
|
|
342
|
+
fs.closeSync(fd);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
/**
|
|
347
|
+
* originalPath makes a mapped source readable: file URLs become paths and
|
|
348
|
+
* bundler schemes (webpack://, turbopack://) are reduced to the project
|
|
349
|
+
* relative path they carry.
|
|
350
|
+
*/
|
|
351
|
+
function originalPath(source) {
|
|
352
|
+
if (source.startsWith('file://')) {
|
|
353
|
+
try {
|
|
354
|
+
return (0, node_url_1.fileURLToPath)(source);
|
|
355
|
+
}
|
|
356
|
+
catch {
|
|
357
|
+
return source;
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
if (/^(webpack|turbopack|webpack-internal):/.test(source)) {
|
|
361
|
+
return stripBundlerPrefix(source);
|
|
362
|
+
}
|
|
363
|
+
return source;
|
|
364
|
+
}
|
|
365
|
+
function stripBundlerPrefix(source) {
|
|
366
|
+
// webpack:///./src/a.ts, webpack://name/./src/a.ts,
|
|
367
|
+
// webpack-internal:///(rsc)/./app/a.ts, turbopack://[project]/app/a.ts
|
|
368
|
+
let rest = source.replace(/^[a-z-]+:\/\/\/?/, '');
|
|
369
|
+
rest = rest.replace(/^\[project\]\//, '');
|
|
370
|
+
rest = rest.replace(/^[^/]*\/(?=\.\/)/, '');
|
|
371
|
+
rest = rest.replace(/^\([a-z-]+\)\//, '');
|
|
372
|
+
rest = rest.replace(/^(\.\/)+/, '');
|
|
373
|
+
return rest;
|
|
374
|
+
}
|
|
375
|
+
const findSourceMap = nodeModule.findSourceMap;
|
|
376
|
+
/**
|
|
377
|
+
* resolveLocation maps a generated position to the original source when
|
|
378
|
+
* the file has a source map: the one Node already holds (with
|
|
379
|
+
* --enable-source-maps, or a loader such as tsx registering its maps),
|
|
380
|
+
* else the file's own. Otherwise the location is returned as is.
|
|
381
|
+
*/
|
|
382
|
+
function resolveLocation(location) {
|
|
383
|
+
if (location.line < 1) {
|
|
384
|
+
return location;
|
|
385
|
+
}
|
|
386
|
+
// A call site recurs: its position is resolved once.
|
|
387
|
+
const key = location.file + ':' + location.line + ':' + location.column;
|
|
388
|
+
const known = resolvedPositions.get(key);
|
|
389
|
+
if (known) {
|
|
390
|
+
return known;
|
|
391
|
+
}
|
|
392
|
+
const resolved = resolveUncached(location);
|
|
393
|
+
if (resolvedPositions.size >= maxResolvedPositions) {
|
|
394
|
+
resolvedPositions.clear();
|
|
395
|
+
}
|
|
396
|
+
resolvedPositions.set(key, resolved);
|
|
397
|
+
return resolved;
|
|
398
|
+
}
|
|
399
|
+
const resolvedPositions = new Map();
|
|
400
|
+
const maxResolvedPositions = 8192;
|
|
401
|
+
function resolveUncached(location) {
|
|
402
|
+
try {
|
|
403
|
+
// Node holds maps only with source maps enabled (--enable-source-maps,
|
|
404
|
+
// or a loader such as tsx turning them on).
|
|
405
|
+
const enabled = process.sourceMapsEnabled !== false;
|
|
406
|
+
const held = enabled && typeof findSourceMap === 'function' ? findSourceMap(location.file) : undefined;
|
|
407
|
+
const origin = held?.findOrigin?.(location.line, Math.max(1, location.column));
|
|
408
|
+
if (origin && typeof origin.fileName === 'string' && typeof origin.lineNumber === 'number') {
|
|
409
|
+
return { file: originalPath(origin.fileName), line: origin.lineNumber, column: origin.columnNumber ?? 0, function: origin.name || location.function };
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
catch {
|
|
413
|
+
// fall through to the file's own map
|
|
414
|
+
}
|
|
415
|
+
const map = sourceMapFor(location.file);
|
|
416
|
+
if (!map) {
|
|
417
|
+
return location;
|
|
418
|
+
}
|
|
419
|
+
try {
|
|
420
|
+
const position = (0, trace_mapping_1.originalPositionFor)(map, { line: location.line, column: Math.max(0, location.column - 1) });
|
|
421
|
+
if (position.source == null || position.line == null) {
|
|
422
|
+
return location;
|
|
423
|
+
}
|
|
424
|
+
return {
|
|
425
|
+
file: originalPath(position.source),
|
|
426
|
+
line: position.line,
|
|
427
|
+
column: position.column == null ? 0 : position.column + 1,
|
|
428
|
+
function: position.name ?? location.function,
|
|
429
|
+
};
|
|
430
|
+
}
|
|
431
|
+
catch {
|
|
432
|
+
return location;
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
/** Bounds on parsing a stack a driver already holds. */
|
|
436
|
+
const maxParsedStackLines = 64;
|
|
437
|
+
const stackLine = /^\s*at (?:async )?(?:new )?(?:(.*?) )?\(?(.+?):(\d+):(\d+)\)?$/;
|
|
438
|
+
/**
|
|
439
|
+
* parseStack finds the first application frame in a formatted V8 stack
|
|
440
|
+
* (one a driver captured itself, such as postgres.js's query origin) and
|
|
441
|
+
* resolves it. undefined when there is none.
|
|
442
|
+
*/
|
|
443
|
+
function parseStack(stack, isApp = isAppFile) {
|
|
444
|
+
if (typeof stack !== 'string') {
|
|
445
|
+
return undefined;
|
|
446
|
+
}
|
|
447
|
+
const lines = stack.split('\n', maxParsedStackLines);
|
|
448
|
+
for (const line of lines) {
|
|
449
|
+
const match = stackLine.exec(line);
|
|
450
|
+
if (!match) {
|
|
451
|
+
continue;
|
|
452
|
+
}
|
|
453
|
+
const file = normalizeFile(match[2]);
|
|
454
|
+
if (!file || !isApp(file)) {
|
|
455
|
+
continue;
|
|
456
|
+
}
|
|
457
|
+
const name = match[1] ?? '';
|
|
458
|
+
const frame = { file, line: Number(match[3]), column: Number(match[4]), function: name === '<anonymous>' || name.endsWith('.<anonymous>') ? '' : name.slice(0, 256) };
|
|
459
|
+
const resolved = resolveLocation(frame);
|
|
460
|
+
if (resolved !== frame && !isApp(resolved.file)) {
|
|
461
|
+
continue;
|
|
462
|
+
}
|
|
463
|
+
return resolved;
|
|
464
|
+
}
|
|
465
|
+
return undefined;
|
|
466
|
+
}
|
|
467
|
+
/**
|
|
468
|
+
* captureCallSite is the whole operation: capture, pick the application
|
|
469
|
+
* frame, resolve it. From an entry wrapper (above), a short walk below
|
|
470
|
+
* the wrapper first, the full walk only when that finds no application
|
|
471
|
+
* frame. undefined when no application frame is on the stack.
|
|
472
|
+
*/
|
|
473
|
+
function captureCallSite(depth = exports.defaultDepth, isApp = isAppFile, above) {
|
|
474
|
+
const full = typeof depth === 'number' && depth > 0 ? depth : exports.defaultDepth;
|
|
475
|
+
if (above) {
|
|
476
|
+
const short = captureFrames(Math.min(exports.shortDepth, full), above);
|
|
477
|
+
const found = appLocation(short, isApp);
|
|
478
|
+
if (found) {
|
|
479
|
+
return found;
|
|
480
|
+
}
|
|
481
|
+
if (short.length > 0 && short.length < Math.min(exports.shortDepth, full)) {
|
|
482
|
+
return undefined; // the stack ended within the short walk
|
|
483
|
+
}
|
|
484
|
+
const rest = captureFrames(full, above);
|
|
485
|
+
return appLocation(rest.length > 0 ? rest : captureFrames(full), isApp);
|
|
486
|
+
}
|
|
487
|
+
return appLocation(captureFrames(full), isApp);
|
|
488
|
+
}
|
|
489
|
+
const displayPaths = new Map();
|
|
490
|
+
const packageRoots = new Map();
|
|
491
|
+
/**
|
|
492
|
+
* displayPath is what code.filepath carries: a bundler path as it is, a
|
|
493
|
+
* file under the working directory relative to it, any other file
|
|
494
|
+
* relative to the parent of its nearest package.json directory (so it
|
|
495
|
+
* names its package), and at most maxDisplayPathBytes from the end, so
|
|
496
|
+
* the file name survives the agent's bound. The server's absolute layout
|
|
497
|
+
* (a home directory, a deploy path) is not sent.
|
|
498
|
+
*/
|
|
499
|
+
function displayPath(file, cwd = process.cwd()) {
|
|
500
|
+
const key = cwd + '\0' + file;
|
|
501
|
+
const known = displayPaths.get(key);
|
|
502
|
+
if (known !== undefined) {
|
|
503
|
+
return known;
|
|
504
|
+
}
|
|
505
|
+
let shown = file;
|
|
506
|
+
if (path.isAbsolute(file)) {
|
|
507
|
+
const relative = path.relative(cwd, file);
|
|
508
|
+
if (relative !== '' && !relative.startsWith('..') && !path.isAbsolute(relative)) {
|
|
509
|
+
shown = relative;
|
|
510
|
+
}
|
|
511
|
+
else {
|
|
512
|
+
const root = packageRootOf(path.dirname(file));
|
|
513
|
+
shown = root ? path.relative(path.dirname(root), file) : path.join(path.basename(path.dirname(file)), path.basename(file));
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
shown = clipFromStart(shown.split(path.sep).join('/'), exports.maxDisplayPathBytes);
|
|
517
|
+
if (displayPaths.size >= 4096) {
|
|
518
|
+
displayPaths.clear();
|
|
519
|
+
}
|
|
520
|
+
displayPaths.set(key, shown);
|
|
521
|
+
return shown;
|
|
522
|
+
}
|
|
523
|
+
function packageRootOf(dir) {
|
|
524
|
+
const visited = [];
|
|
525
|
+
let current = dir;
|
|
526
|
+
let found = null;
|
|
527
|
+
for (let level = 0; level < 12; level++) {
|
|
528
|
+
const known = packageRoots.get(current);
|
|
529
|
+
if (known !== undefined) {
|
|
530
|
+
found = known;
|
|
531
|
+
break;
|
|
532
|
+
}
|
|
533
|
+
visited.push(current);
|
|
534
|
+
if (fs.existsSync(path.join(current, 'package.json'))) {
|
|
535
|
+
found = current;
|
|
536
|
+
break;
|
|
537
|
+
}
|
|
538
|
+
const parent = path.dirname(current);
|
|
539
|
+
if (parent === current) {
|
|
540
|
+
break;
|
|
541
|
+
}
|
|
542
|
+
current = parent;
|
|
543
|
+
}
|
|
544
|
+
for (const v of visited) {
|
|
545
|
+
packageRoots.set(v, found);
|
|
546
|
+
}
|
|
547
|
+
return found ?? undefined;
|
|
548
|
+
}
|
|
549
|
+
/** clipFromStart keeps the last bytes of a path, cut at a segment. */
|
|
550
|
+
function clipFromStart(text, limit) {
|
|
551
|
+
if (Buffer.byteLength(text) <= limit) {
|
|
552
|
+
return text;
|
|
553
|
+
}
|
|
554
|
+
let tail = text;
|
|
555
|
+
while (Buffer.byteLength(tail) > limit - 4) {
|
|
556
|
+
const slash = tail.indexOf('/', 1);
|
|
557
|
+
if (slash < 0) {
|
|
558
|
+
tail = tail.slice(tail.length - (limit - 4));
|
|
559
|
+
break;
|
|
560
|
+
}
|
|
561
|
+
tail = tail.slice(slash);
|
|
562
|
+
}
|
|
563
|
+
return '...' + (tail.startsWith('/') ? tail : '/' + tail);
|
|
564
|
+
}
|
|
565
|
+
//# sourceMappingURL=callsite.js.map
|