trickle-observe 0.2.113 → 0.2.115
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/call-trace.js +8 -0
- package/dist/db-observer.js +8 -0
- package/dist/express.js +68 -54
- package/dist/request-context.d.ts +32 -0
- package/dist/request-context.js +61 -0
- package/dist/vite-plugin.js +6 -2
- package/dist-esm/vite-plugin.js +6 -2
- package/package.json +1 -1
- package/src/call-trace.ts +9 -0
- package/src/db-observer.ts +7 -0
- package/src/express.ts +16 -1
- package/src/request-context.ts +64 -0
- package/src/vite-plugin.ts +6 -2
package/dist/call-trace.js
CHANGED
|
@@ -93,6 +93,13 @@ function traceCall(functionName, moduleName) {
|
|
|
93
93
|
function traceReturn(callId, functionName, moduleName, durationMs, error) {
|
|
94
94
|
const parentId = callStack.length >= 2 ? callStack[callStack.length - 2] : 0;
|
|
95
95
|
const depth = callStack.length - 1;
|
|
96
|
+
// Get request ID from async context (if inside an Express request)
|
|
97
|
+
let requestId;
|
|
98
|
+
try {
|
|
99
|
+
const { getRequestId } = require('./request-context');
|
|
100
|
+
requestId = getRequestId();
|
|
101
|
+
}
|
|
102
|
+
catch { }
|
|
96
103
|
writeEvent({
|
|
97
104
|
kind: 'call',
|
|
98
105
|
function: functionName,
|
|
@@ -103,6 +110,7 @@ function traceReturn(callId, functionName, moduleName, durationMs, error) {
|
|
|
103
110
|
timestamp: Date.now(),
|
|
104
111
|
durationMs: Math.round(durationMs * 100) / 100,
|
|
105
112
|
...(error ? { error } : {}),
|
|
113
|
+
...(requestId ? { requestId } : {}),
|
|
106
114
|
});
|
|
107
115
|
// Pop from stack
|
|
108
116
|
if (callStack[callStack.length - 1] === callId) {
|
package/dist/db-observer.js
CHANGED
|
@@ -80,6 +80,14 @@ function writeQuery(record) {
|
|
|
80
80
|
if (queryCount >= MAX_QUERIES)
|
|
81
81
|
return;
|
|
82
82
|
queryCount++;
|
|
83
|
+
// Add request ID from async context
|
|
84
|
+
try {
|
|
85
|
+
const { getRequestId } = require('./request-context');
|
|
86
|
+
const reqId = getRequestId();
|
|
87
|
+
if (reqId)
|
|
88
|
+
record.requestId = reqId;
|
|
89
|
+
}
|
|
90
|
+
catch { }
|
|
83
91
|
try {
|
|
84
92
|
fs.appendFileSync(getQueriesFile(), JSON.stringify(record) + '\n');
|
|
85
93
|
}
|
package/dist/express.js
CHANGED
|
@@ -293,63 +293,77 @@ function trickleMiddleware(userOpts) {
|
|
|
293
293
|
next();
|
|
294
294
|
return;
|
|
295
295
|
}
|
|
296
|
-
|
|
297
|
-
|
|
296
|
+
// Wrap in request context for per-request correlation
|
|
297
|
+
try {
|
|
298
|
+
const { withRequestContext } = require('./request-context');
|
|
299
|
+
withRequestContext(req, () => {
|
|
300
|
+
_handleRequest(req, res, next, opts, debug);
|
|
301
|
+
});
|
|
302
|
+
return;
|
|
298
303
|
}
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
// because req.route is only populated after the handler matches.
|
|
302
|
-
function getRouteName() {
|
|
303
|
-
try {
|
|
304
|
-
if (req.route && req.route.path) {
|
|
305
|
-
return `${req.method} ${req.baseUrl || ''}${req.route.path}`;
|
|
306
|
-
}
|
|
307
|
-
}
|
|
308
|
-
catch {
|
|
309
|
-
// ignore
|
|
310
|
-
}
|
|
311
|
-
return `${req.method || 'UNKNOWN'} ${req.originalUrl || req.url || '/'}`;
|
|
304
|
+
catch {
|
|
305
|
+
// Fall through to non-context version
|
|
312
306
|
}
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
res.json = originalJson;
|
|
329
|
-
return originalJson.call(res, data);
|
|
330
|
-
};
|
|
307
|
+
_handleRequest(req, res, next, opts, debug);
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
function _handleRequest(req, res, next, opts, debug) {
|
|
311
|
+
if (debug) {
|
|
312
|
+
console.log(`[trickle/middleware] Intercepting ${req.method} ${req.originalUrl || req.url}`);
|
|
313
|
+
}
|
|
314
|
+
let captured = false;
|
|
315
|
+
// We derive the route name lazily once the response is being sent,
|
|
316
|
+
// because req.route is only populated after the handler matches.
|
|
317
|
+
function getRouteName() {
|
|
318
|
+
try {
|
|
319
|
+
if (req.route && req.route.path) {
|
|
320
|
+
return `${req.method} ${req.baseUrl || ''}${req.route.path}`;
|
|
321
|
+
}
|
|
331
322
|
}
|
|
332
|
-
|
|
333
|
-
|
|
323
|
+
catch {
|
|
324
|
+
// ignore
|
|
334
325
|
}
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
emitExpressPayload(routeName, opts.environment, opts.maxDepth, latestInput, output);
|
|
326
|
+
return `${req.method || 'UNKNOWN'} ${req.originalUrl || req.url || '/'}`;
|
|
327
|
+
}
|
|
328
|
+
const input = extractRequestInput(req);
|
|
329
|
+
// Intercept res.json()
|
|
330
|
+
const originalJson = res.json;
|
|
331
|
+
if (typeof originalJson === 'function') {
|
|
332
|
+
res.json = function (data) {
|
|
333
|
+
if (!captured) {
|
|
334
|
+
captured = true;
|
|
335
|
+
const routeName = getRouteName();
|
|
336
|
+
if (debug) {
|
|
337
|
+
console.log(`[trickle/middleware] Captured res.json for ${routeName}`);
|
|
348
338
|
}
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
339
|
+
// Re-extract input here because body parsers may have run since middleware was entered
|
|
340
|
+
const latestInput = extractRequestInput(req);
|
|
341
|
+
emitExpressPayload(routeName, opts.environment, opts.maxDepth, latestInput, data);
|
|
342
|
+
}
|
|
343
|
+
res.json = originalJson;
|
|
344
|
+
return originalJson.call(res, data);
|
|
345
|
+
};
|
|
346
|
+
}
|
|
347
|
+
else if (debug) {
|
|
348
|
+
console.log(`[trickle/middleware] res.json is not a function: ${typeof originalJson}`);
|
|
349
|
+
}
|
|
350
|
+
// Intercept res.send()
|
|
351
|
+
const originalSend = res.send;
|
|
352
|
+
if (typeof originalSend === 'function') {
|
|
353
|
+
res.send = function (data) {
|
|
354
|
+
if (!captured) {
|
|
355
|
+
captured = true;
|
|
356
|
+
const routeName = getRouteName();
|
|
357
|
+
if (debug) {
|
|
358
|
+
console.log(`[trickle/middleware] Captured res.send for ${routeName}`);
|
|
359
|
+
}
|
|
360
|
+
const latestInput = extractRequestInput(req);
|
|
361
|
+
const output = typeof data === 'string' ? { __html: true } : data;
|
|
362
|
+
emitExpressPayload(routeName, opts.environment, opts.maxDepth, latestInput, output);
|
|
363
|
+
}
|
|
364
|
+
res.send = originalSend;
|
|
365
|
+
return originalSend.call(res, data);
|
|
366
|
+
};
|
|
367
|
+
}
|
|
368
|
+
next();
|
|
355
369
|
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Request context — propagates a request ID through async call chains.
|
|
3
|
+
*
|
|
4
|
+
* Uses Node.js AsyncLocalStorage so that all functions, queries, and logs
|
|
5
|
+
* within a single HTTP request share the same requestId, enabling
|
|
6
|
+
* per-request tracing (like Jaeger but with trickle's richer data).
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* import { withRequestContext, getRequestId } from './request-context';
|
|
10
|
+
* // In Express middleware:
|
|
11
|
+
* app.use((req, res, next) => withRequestContext(req, next));
|
|
12
|
+
* // Anywhere in the call chain:
|
|
13
|
+
* const id = getRequestId(); // returns the current request's ID
|
|
14
|
+
*/
|
|
15
|
+
export interface RequestContext {
|
|
16
|
+
requestId: string;
|
|
17
|
+
method?: string;
|
|
18
|
+
path?: string;
|
|
19
|
+
startTime: number;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Run a callback within a request context.
|
|
23
|
+
*/
|
|
24
|
+
export declare function withRequestContext(req: any, callback: () => void): void;
|
|
25
|
+
/**
|
|
26
|
+
* Get the current request ID (if inside a request context).
|
|
27
|
+
*/
|
|
28
|
+
export declare function getRequestId(): string | undefined;
|
|
29
|
+
/**
|
|
30
|
+
* Get the full request context.
|
|
31
|
+
*/
|
|
32
|
+
export declare function getRequestContext(): RequestContext | undefined;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Request context — propagates a request ID through async call chains.
|
|
4
|
+
*
|
|
5
|
+
* Uses Node.js AsyncLocalStorage so that all functions, queries, and logs
|
|
6
|
+
* within a single HTTP request share the same requestId, enabling
|
|
7
|
+
* per-request tracing (like Jaeger but with trickle's richer data).
|
|
8
|
+
*
|
|
9
|
+
* Usage:
|
|
10
|
+
* import { withRequestContext, getRequestId } from './request-context';
|
|
11
|
+
* // In Express middleware:
|
|
12
|
+
* app.use((req, res, next) => withRequestContext(req, next));
|
|
13
|
+
* // Anywhere in the call chain:
|
|
14
|
+
* const id = getRequestId(); // returns the current request's ID
|
|
15
|
+
*/
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.withRequestContext = withRequestContext;
|
|
18
|
+
exports.getRequestId = getRequestId;
|
|
19
|
+
exports.getRequestContext = getRequestContext;
|
|
20
|
+
let als = null;
|
|
21
|
+
let counter = 0;
|
|
22
|
+
try {
|
|
23
|
+
const { AsyncLocalStorage } = require('async_hooks');
|
|
24
|
+
als = new AsyncLocalStorage();
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
// AsyncLocalStorage not available (older Node versions)
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Run a callback within a request context.
|
|
31
|
+
*/
|
|
32
|
+
function withRequestContext(req, callback) {
|
|
33
|
+
if (!als) {
|
|
34
|
+
callback();
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
const ctx = {
|
|
38
|
+
requestId: `req-${++counter}-${Date.now().toString(36)}`,
|
|
39
|
+
method: req?.method,
|
|
40
|
+
path: req?.path || req?.url,
|
|
41
|
+
startTime: Date.now(),
|
|
42
|
+
};
|
|
43
|
+
als.run(ctx, callback);
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Get the current request ID (if inside a request context).
|
|
47
|
+
*/
|
|
48
|
+
function getRequestId() {
|
|
49
|
+
if (!als)
|
|
50
|
+
return undefined;
|
|
51
|
+
const ctx = als.getStore();
|
|
52
|
+
return ctx?.requestId;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Get the full request context.
|
|
56
|
+
*/
|
|
57
|
+
function getRequestContext() {
|
|
58
|
+
if (!als)
|
|
59
|
+
return undefined;
|
|
60
|
+
return als.getStore();
|
|
61
|
+
}
|
package/dist/vite-plugin.js
CHANGED
|
@@ -1726,8 +1726,12 @@ ingestUrl) {
|
|
|
1726
1726
|
const catchInsertions = traceVars ? findCatchVars(source) : [];
|
|
1727
1727
|
// Find function parameter names for tracing
|
|
1728
1728
|
const funcParamInsertions = traceVars ? findFunctionParams(source, isReactFile) : [];
|
|
1729
|
-
// Find JSX text expressions for tracing (React files only)
|
|
1730
|
-
|
|
1729
|
+
// Find JSX text expressions for tracing (React files only).
|
|
1730
|
+
// Skip if JSX has already been compiled to _jsxDEV/jsx/jsxs calls (e.g. by Vite's React plugin).
|
|
1731
|
+
// In that case, the `{` characters in the source are plain JS (function bodies, object literals)
|
|
1732
|
+
// and findJsxExpressions would corrupt them by injecting __trickle_tv() calls.
|
|
1733
|
+
const jsxAlreadyCompiled = /\b_?jsxDEV\b|\bjsxs?\s*\(/.test(source);
|
|
1734
|
+
const jsxExprInsertions = (traceVars && isReactFile && !jsxAlreadyCompiled) ? findJsxExpressions(source) : [];
|
|
1731
1735
|
if (funcInsertions.length === 0 && importInsertions.length === 0 && varInsertions.length === 0 && destructInsertions.length === 0 && reassignInsertions.length === 0 && forLoopInsertions.length === 0 && catchInsertions.length === 0 && funcParamInsertions.length === 0 && jsxExprInsertions.length === 0 && bodyInsertions.length === 0 && hookInsertions.length === 0 && stateInsertions.length === 0 && conciseBodyInsertions.length === 0)
|
|
1732
1736
|
return source;
|
|
1733
1737
|
// Fix line numbers: Vite transforms (TypeScript stripping) may change line numbers.
|
package/dist-esm/vite-plugin.js
CHANGED
|
@@ -1713,8 +1713,12 @@ ingestUrl) {
|
|
|
1713
1713
|
const catchInsertions = traceVars ? findCatchVars(source) : [];
|
|
1714
1714
|
// Find function parameter names for tracing
|
|
1715
1715
|
const funcParamInsertions = traceVars ? findFunctionParams(source, isReactFile) : [];
|
|
1716
|
-
// Find JSX text expressions for tracing (React files only)
|
|
1717
|
-
|
|
1716
|
+
// Find JSX text expressions for tracing (React files only).
|
|
1717
|
+
// Skip if JSX has already been compiled to _jsxDEV/jsx/jsxs calls (e.g. by Vite's React plugin).
|
|
1718
|
+
// In that case, the `{` characters in the source are plain JS (function bodies, object literals)
|
|
1719
|
+
// and findJsxExpressions would corrupt them by injecting __trickle_tv() calls.
|
|
1720
|
+
const jsxAlreadyCompiled = /\b_?jsxDEV\b|\bjsxs?\s*\(/.test(source);
|
|
1721
|
+
const jsxExprInsertions = (traceVars && isReactFile && !jsxAlreadyCompiled) ? findJsxExpressions(source) : [];
|
|
1718
1722
|
if (funcInsertions.length === 0 && importInsertions.length === 0 && varInsertions.length === 0 && destructInsertions.length === 0 && reassignInsertions.length === 0 && forLoopInsertions.length === 0 && catchInsertions.length === 0 && funcParamInsertions.length === 0 && jsxExprInsertions.length === 0 && bodyInsertions.length === 0 && hookInsertions.length === 0 && stateInsertions.length === 0 && conciseBodyInsertions.length === 0)
|
|
1719
1723
|
return source;
|
|
1720
1724
|
// Fix line numbers: Vite transforms (TypeScript stripping) may change line numbers.
|
package/package.json
CHANGED
package/src/call-trace.ts
CHANGED
|
@@ -21,6 +21,7 @@ interface CallEvent {
|
|
|
21
21
|
timestamp: number;
|
|
22
22
|
durationMs: number;
|
|
23
23
|
error?: string;
|
|
24
|
+
requestId?: string;
|
|
24
25
|
}
|
|
25
26
|
|
|
26
27
|
let traceFile: string | null = null;
|
|
@@ -71,6 +72,13 @@ export function traceReturn(
|
|
|
71
72
|
const parentId = callStack.length >= 2 ? callStack[callStack.length - 2] : 0;
|
|
72
73
|
const depth = callStack.length - 1;
|
|
73
74
|
|
|
75
|
+
// Get request ID from async context (if inside an Express request)
|
|
76
|
+
let requestId: string | undefined;
|
|
77
|
+
try {
|
|
78
|
+
const { getRequestId } = require('./request-context');
|
|
79
|
+
requestId = getRequestId();
|
|
80
|
+
} catch {}
|
|
81
|
+
|
|
74
82
|
writeEvent({
|
|
75
83
|
kind: 'call',
|
|
76
84
|
function: functionName,
|
|
@@ -81,6 +89,7 @@ export function traceReturn(
|
|
|
81
89
|
timestamp: Date.now(),
|
|
82
90
|
durationMs: Math.round(durationMs * 100) / 100,
|
|
83
91
|
...(error ? { error } : {}),
|
|
92
|
+
...(requestId ? { requestId } : {}),
|
|
84
93
|
});
|
|
85
94
|
|
|
86
95
|
// Pop from stack
|
package/src/db-observer.ts
CHANGED
|
@@ -21,6 +21,7 @@ interface QueryRecord {
|
|
|
21
21
|
columns?: string[];
|
|
22
22
|
error?: string;
|
|
23
23
|
timestamp: number;
|
|
24
|
+
requestId?: string;
|
|
24
25
|
}
|
|
25
26
|
|
|
26
27
|
let queriesFile: string | null = null;
|
|
@@ -42,6 +43,12 @@ function getQueriesFile(): string {
|
|
|
42
43
|
function writeQuery(record: QueryRecord): void {
|
|
43
44
|
if (queryCount >= MAX_QUERIES) return;
|
|
44
45
|
queryCount++;
|
|
46
|
+
// Add request ID from async context
|
|
47
|
+
try {
|
|
48
|
+
const { getRequestId } = require('./request-context');
|
|
49
|
+
const reqId = getRequestId();
|
|
50
|
+
if (reqId) record.requestId = reqId;
|
|
51
|
+
} catch {}
|
|
45
52
|
try {
|
|
46
53
|
fs.appendFileSync(getQueriesFile(), JSON.stringify(record) + '\n');
|
|
47
54
|
} catch {}
|
package/src/express.ts
CHANGED
|
@@ -334,6 +334,22 @@ export function trickleMiddleware(
|
|
|
334
334
|
return;
|
|
335
335
|
}
|
|
336
336
|
|
|
337
|
+
// Wrap in request context for per-request correlation
|
|
338
|
+
try {
|
|
339
|
+
const { withRequestContext } = require('./request-context');
|
|
340
|
+
withRequestContext(req, () => {
|
|
341
|
+
_handleRequest(req, res, next, opts, debug);
|
|
342
|
+
});
|
|
343
|
+
return;
|
|
344
|
+
} catch {
|
|
345
|
+
// Fall through to non-context version
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
_handleRequest(req, res, next, opts, debug);
|
|
349
|
+
};
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
function _handleRequest(req: any, res: any, next: any, opts: any, debug: boolean): void {
|
|
337
353
|
if (debug) {
|
|
338
354
|
console.log(`[trickle/middleware] Intercepting ${req.method} ${req.originalUrl || req.url}`);
|
|
339
355
|
}
|
|
@@ -396,5 +412,4 @@ export function trickleMiddleware(
|
|
|
396
412
|
}
|
|
397
413
|
|
|
398
414
|
next();
|
|
399
|
-
};
|
|
400
415
|
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Request context — propagates a request ID through async call chains.
|
|
3
|
+
*
|
|
4
|
+
* Uses Node.js AsyncLocalStorage so that all functions, queries, and logs
|
|
5
|
+
* within a single HTTP request share the same requestId, enabling
|
|
6
|
+
* per-request tracing (like Jaeger but with trickle's richer data).
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* import { withRequestContext, getRequestId } from './request-context';
|
|
10
|
+
* // In Express middleware:
|
|
11
|
+
* app.use((req, res, next) => withRequestContext(req, next));
|
|
12
|
+
* // Anywhere in the call chain:
|
|
13
|
+
* const id = getRequestId(); // returns the current request's ID
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
let als: any = null;
|
|
17
|
+
let counter = 0;
|
|
18
|
+
|
|
19
|
+
try {
|
|
20
|
+
const { AsyncLocalStorage } = require('async_hooks');
|
|
21
|
+
als = new AsyncLocalStorage();
|
|
22
|
+
} catch {
|
|
23
|
+
// AsyncLocalStorage not available (older Node versions)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface RequestContext {
|
|
27
|
+
requestId: string;
|
|
28
|
+
method?: string;
|
|
29
|
+
path?: string;
|
|
30
|
+
startTime: number;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Run a callback within a request context.
|
|
35
|
+
*/
|
|
36
|
+
export function withRequestContext(req: any, callback: () => void): void {
|
|
37
|
+
if (!als) { callback(); return; }
|
|
38
|
+
|
|
39
|
+
const ctx: RequestContext = {
|
|
40
|
+
requestId: `req-${++counter}-${Date.now().toString(36)}`,
|
|
41
|
+
method: req?.method,
|
|
42
|
+
path: req?.path || req?.url,
|
|
43
|
+
startTime: Date.now(),
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
als.run(ctx, callback);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Get the current request ID (if inside a request context).
|
|
51
|
+
*/
|
|
52
|
+
export function getRequestId(): string | undefined {
|
|
53
|
+
if (!als) return undefined;
|
|
54
|
+
const ctx = als.getStore() as RequestContext | undefined;
|
|
55
|
+
return ctx?.requestId;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Get the full request context.
|
|
60
|
+
*/
|
|
61
|
+
export function getRequestContext(): RequestContext | undefined {
|
|
62
|
+
if (!als) return undefined;
|
|
63
|
+
return als.getStore() as RequestContext | undefined;
|
|
64
|
+
}
|
package/src/vite-plugin.ts
CHANGED
|
@@ -1658,8 +1658,12 @@ export function transformEsmSource(
|
|
|
1658
1658
|
// Find function parameter names for tracing
|
|
1659
1659
|
const funcParamInsertions = traceVars ? findFunctionParams(source, isReactFile) : [];
|
|
1660
1660
|
|
|
1661
|
-
// Find JSX text expressions for tracing (React files only)
|
|
1662
|
-
|
|
1661
|
+
// Find JSX text expressions for tracing (React files only).
|
|
1662
|
+
// Skip if JSX has already been compiled to _jsxDEV/jsx/jsxs calls (e.g. by Vite's React plugin).
|
|
1663
|
+
// In that case, the `{` characters in the source are plain JS (function bodies, object literals)
|
|
1664
|
+
// and findJsxExpressions would corrupt them by injecting __trickle_tv() calls.
|
|
1665
|
+
const jsxAlreadyCompiled = /\b_?jsxDEV\b|\bjsxs?\s*\(/.test(source);
|
|
1666
|
+
const jsxExprInsertions = (traceVars && isReactFile && !jsxAlreadyCompiled) ? findJsxExpressions(source) : [];
|
|
1663
1667
|
|
|
1664
1668
|
if (funcInsertions.length === 0 && importInsertions.length === 0 && varInsertions.length === 0 && destructInsertions.length === 0 && reassignInsertions.length === 0 && forLoopInsertions.length === 0 && catchInsertions.length === 0 && funcParamInsertions.length === 0 && jsxExprInsertions.length === 0 && bodyInsertions.length === 0 && hookInsertions.length === 0 && stateInsertions.length === 0 && conciseBodyInsertions.length === 0) return source;
|
|
1665
1669
|
|