Skip to content

Commit 0d13d3b

Browse files
committed
fix(live-debugger): remove TypeScript suppression comments and fix type safety
Remove @ts-nocheck from all transform files by introducing a local BabelPath interface that avoids the cross-package type conflict between @types/babel__traverse's bundled @babel/types and the directly imported @babel/types. Replace all `any` types and `as` casts with proper type narrowing. Convert require() calls to ESM imports. Use shared getContextMock test helper instead of hand-rolled mock. Delete orphaned rum/src/built/live-debugger-helpers.ts (stubs are already injected via context.inject in the plugin entry point).
1 parent ef20d9a commit 0d13d3b

10 files changed

Lines changed: 105 additions & 83 deletions

File tree

packages/plugins/live-debugger/package.json

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,6 @@
3131
"magic-string": "0.30.21"
3232
},
3333
"devDependencies": {
34-
"@types/babel__core": "^7.20.0",
35-
"@types/babel__traverse": "^7.20.0",
3634
"typescript": "5.4.3"
3735
}
3836
}

packages/plugins/live-debugger/src/index.test.ts

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1+
import { getContextMock } from '@dd/tests/_jest/helpers/mocks';
12
// Unless explicitly stated otherwise all files in this repository are licensed under the MIT License.
23
// This product includes software developed at Datadog (https://www.datadoghq.com/).
34
// Copyright 2019-Present Datadog, Inc.
4-
5-
import type { GlobalContext } from '@dd/core/types';
5+
import type { UnpluginBuildContext, UnpluginContext } from 'unplugin';
66

77
import { getLiveDebuggerPlugin } from './index';
88
import type { LiveDebuggerOptionsWithDefaults } from './types';
@@ -19,20 +19,35 @@ const makeOptions = (
1919
...overrides,
2020
});
2121

22-
const mockContext = {
23-
buildRoot: '/',
24-
getLogger: () => ({
25-
info: jest.fn(),
26-
warn: jest.fn(),
27-
error: jest.fn(),
28-
debug: jest.fn(),
29-
}),
30-
} as unknown as GlobalContext;
31-
32-
function getHandler(options: LiveDebuggerOptionsWithDefaults) {
22+
const mockContext = getContextMock({ buildRoot: '/' });
23+
24+
const mockBuildContext: UnpluginBuildContext & UnpluginContext = {
25+
addWatchFile: jest.fn(),
26+
emitFile: jest.fn(),
27+
getWatchFiles: jest.fn(() => []),
28+
parse: jest.fn(),
29+
error: jest.fn(),
30+
warn: jest.fn(),
31+
};
32+
33+
function getHandler(
34+
options: LiveDebuggerOptionsWithDefaults,
35+
): (code: string, id: string) => { code: string } {
3336
const plugin = getLiveDebuggerPlugin(options, mockContext);
34-
return (plugin.transform as { handler: (code: string, id: string) => { code: string } })
35-
.handler;
37+
const transform = plugin.transform;
38+
39+
if (typeof transform !== 'object' || transform === null || !('handler' in transform)) {
40+
throw new Error('Expected transform to be an ObjectHook with a handler');
41+
}
42+
43+
const { handler } = transform;
44+
return (code: string, id: string) => {
45+
const result = handler.call(mockBuildContext, code, id);
46+
if (typeof result === 'object' && result !== null && 'code' in result) {
47+
return { code: result.code };
48+
}
49+
throw new Error('Unexpected handler result');
50+
};
3651
}
3752

3853
describe('getLiveDebuggerPlugin', () => {
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Unless explicitly stated otherwise all files in this repository are licensed under the MIT License.
2+
// This product includes software developed at Datadog (https://www.datadoghq.com/).
3+
// Copyright 2019-Present Datadog, Inc.
4+
5+
import type * as t from '@babel/types';
6+
7+
/**
8+
* Minimal NodePath-compatible interface using types exclusively from
9+
* `@babel/types`. This avoids the type conflict between
10+
* `@types/babel__traverse`'s bundled copy of `@babel/types` and the
11+
* directly imported `@babel/types` package.
12+
*/
13+
export interface BabelPath<T extends t.Node = t.Node> {
14+
node: T;
15+
parent: t.Node;
16+
parentPath: BabelPath | null;
17+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Unless explicitly stated otherwise all files in this repository are licensed under the MIT License.
2+
// This product includes software developed at Datadog (https://www.datadoghq.com/).
3+
// Copyright 2019-Present Datadog, Inc.
4+
5+
/**
6+
* Local type declaration for `@babel/traverse` that avoids the structural
7+
* incompatibility between `@types/babel__traverse`'s bundled copy of
8+
* `@babel/types` and the directly imported `@babel/types` package.
9+
*
10+
* Only the subset of the API used by this plugin is declared.
11+
*/
12+
declare module '@babel/traverse' {
13+
import type * as t from '@babel/types';
14+
15+
import type { BabelPath } from './babel-path.types';
16+
17+
type VisitorHandler<T extends t.Node> = (path: BabelPath<T>) => void;
18+
19+
interface Visitor {
20+
Function?: VisitorHandler<t.Function>;
21+
}
22+
23+
function traverse(ast: object, visitor: Visitor): void;
24+
25+
export default traverse;
26+
}

packages/plugins/live-debugger/src/transform/functionId.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@
22
// This product includes software developed at Datadog (https://www.datadoghq.com/).
33
// Copyright 2019-Present Datadog, Inc.
44

5-
// @ts-nocheck - Babel type conflicts between @babel/parser and @babel/types versions
6-
import type { NodePath } from '@babel/traverse';
75
import * as t from '@babel/types';
86
import path from 'path';
97

8+
import type { BabelPath } from './babel-path.types';
9+
1010
/**
1111
* Generate a stable, unique function ID
1212
* Format (POC): <relative-file-path>;<function-name>
@@ -18,7 +18,7 @@ import path from 'path';
1818
export function generateFunctionId(
1919
filePath: string,
2020
buildRoot: string,
21-
functionPath: NodePath<t.Function>,
21+
functionPath: BabelPath<t.Function>,
2222
anonymousSiblingIndex: number,
2323
): string {
2424
const relativePath = path.relative(buildRoot, filePath).replace(/\\/g, '/');
@@ -36,12 +36,12 @@ export function generateFunctionId(
3636
/**
3737
* Get the name of a function if available
3838
*/
39-
export function getFunctionName(functionPath: NodePath<t.Function>): string | null {
39+
export function getFunctionName(functionPath: BabelPath<t.Function>): string | null {
4040
const node = functionPath.node;
4141
const parent = functionPath.parent;
4242

4343
// Named function declaration: function foo() {}
44-
if (t.isIdentifier(node.id)) {
44+
if ('id' in node && t.isIdentifier(node.id)) {
4545
return node.id.name;
4646
}
4747

@@ -145,7 +145,7 @@ function getPropertyLikeName(key: t.Expression | t.PrivateName | t.Identifier):
145145
return null;
146146
}
147147

148-
function getFunctionLocation(functionPath: NodePath<t.Function>): string {
148+
function getFunctionLocation(functionPath: BabelPath<t.Function>): string {
149149
const line = functionPath.node.loc?.start.line ?? 0;
150150
const column = functionPath.node.loc?.start.column ?? 0;
151151

packages/plugins/live-debugger/src/transform/index.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,7 @@ describe('transformCode', () => {
291291
});
292292

293293
expect(result.map).toBeDefined();
294-
expect(result.map.sources).toContain('/src/utils.ts');
294+
expect(result.map?.sources).toContain('/src/utils.ts');
295295
});
296296
});
297297

packages/plugins/live-debugger/src/transform/index.ts

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,20 @@
22
// This product includes software developed at Datadog (https://www.datadoghq.com/).
33
// Copyright 2019-Present Datadog, Inc.
44

5-
import type { NodePath } from '@babel/traverse';
5+
import { parse } from '@babel/parser';
6+
import traverse from '@babel/traverse';
67
import * as t from '@babel/types';
7-
// @ts-nocheck - Babel type conflicts between @babel/parser and @babel/types versions
8+
import type { SourceMap } from 'magic-string';
89
import MagicString from 'magic-string';
910

1011
import { SKIP_INSTRUMENTATION_COMMENT } from '../constants';
1112
import type { FunctionKind } from '../types';
1213

14+
import type { BabelPath } from './babel-path.types';
1315
import { generateFunctionId, getFunctionName } from './functionId';
1416
import { canInstrumentFunction, shouldSkipFunction } from './instrumentation';
1517
import { getVariableNames } from './scopeTracker';
1618

17-
const { parse } = require('@babel/parser');
18-
const traverse = require('@babel/traverse').default;
19-
2019
const HAS_FUNCTION_SYNTAX = /\bfunction\b|=>|\bclass\b|\)\s*\{/;
2120

2221
interface ReturnInfo {
@@ -51,7 +50,7 @@ export interface TransformOptions {
5150

5251
export interface TransformResult {
5352
code: string;
54-
map?: any;
53+
map?: SourceMap;
5554
failedCount: number;
5655
instrumentedCount: number;
5756
skippedByCommentCount: number;
@@ -109,7 +108,7 @@ export function transformCode(options: TransformOptions): TransformResult {
109108
let probeVarCounter = 0;
110109

111110
traverse(ast, {
112-
Function(path: NodePath<t.Function>) {
111+
Function(path: BabelPath<t.Function>) {
113112
totalFunctions++;
114113

115114
if (!canInstrumentFunction(path)) {
@@ -164,9 +163,10 @@ export function transformCode(options: TransformOptions): TransformResult {
164163
bodyEnd: node.body.end!,
165164
functionEnd: node.end!,
166165
isExpressionBody,
167-
bodyParenStart: isExpressionBody
168-
? (node.body.extra?.parenStart as number | undefined)
169-
: undefined,
166+
bodyParenStart:
167+
isExpressionBody && typeof node.body.extra?.parenStart === 'number'
168+
? node.body.extra.parenStart
169+
: undefined,
170170
functionId,
171171
probeVarName,
172172
probeIdx: String(idx),
@@ -425,7 +425,7 @@ export function validateSyntax(code: string, filePath: string): string | null {
425425
sourceFilename: filePath,
426426
});
427427
return null;
428-
} catch (e: any) {
429-
return e.message || String(e);
428+
} catch (e: unknown) {
429+
return e instanceof Error ? e.message : String(e);
430430
}
431431
}

packages/plugins/live-debugger/src/transform/instrumentation.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@
22
// This product includes software developed at Datadog (https://www.datadoghq.com/).
33
// Copyright 2019-Present Datadog, Inc.
44

5-
// @ts-nocheck - Babel type conflicts between @babel/parser and @babel/types versions
6-
import type { NodePath } from '@babel/traverse';
75
import * as t from '@babel/types';
86

9-
function hasSkipComment(path: NodePath, skipComment: string): boolean {
7+
import type { BabelPath } from './babel-path.types';
8+
9+
function hasSkipComment(path: BabelPath, skipComment: string): boolean {
1010
if (path.node.leadingComments) {
1111
for (const comment of path.node.leadingComments) {
1212
if (comment.value.includes(skipComment)) {
@@ -30,10 +30,10 @@ function hasSkipComment(path: NodePath, skipComment: string): boolean {
3030
* the comment to the ExportNamedDeclaration, one level above the statement.
3131
*/
3232
export function shouldSkipFunction(
33-
functionPath: NodePath<t.Function>,
33+
functionPath: BabelPath<t.Function>,
3434
skipComment: string,
3535
): boolean {
36-
let current: NodePath | null = functionPath;
36+
let current: BabelPath | null = functionPath;
3737

3838
while (current) {
3939
if (hasSkipComment(current, skipComment)) {
@@ -42,10 +42,10 @@ export function shouldSkipFunction(
4242

4343
// Stop once we reach a statement or export declaration — that is the
4444
// outermost node where Babel would attach a line-level leading comment.
45-
if (current.isStatement() || current.isExportDeclaration()) {
45+
if (t.isStatement(current.node) || t.isExportDeclaration(current.node)) {
4646
// For `export const fn = ...`, the comment is on the ExportDeclaration
4747
// which wraps the VariableDeclaration statement.
48-
if (current.parentPath?.isExportDeclaration()) {
48+
if (current.parentPath && t.isExportDeclaration(current.parentPath.node)) {
4949
return hasSkipComment(current.parentPath, skipComment);
5050
}
5151
break;
@@ -61,7 +61,7 @@ export function shouldSkipFunction(
6161
* Check if function should be instrumented
6262
* Skips: generators and constructors
6363
*/
64-
export function canInstrumentFunction(functionPath: NodePath<t.Function>): boolean {
64+
export function canInstrumentFunction(functionPath: BabelPath<t.Function>): boolean {
6565
const node = functionPath.node;
6666

6767
// Skip generators

packages/plugins/live-debugger/src/transform/scopeTracker.ts

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
// This product includes software developed at Datadog (https://www.datadoghq.com/).
33
// Copyright 2019-Present Datadog, Inc.
44

5-
// @ts-nocheck - Babel type conflicts between @babel/parser and @babel/types versions
65
import * as t from '@babel/types';
76

87
export const MAX_CAPTURE_VARIABLES = 25;
@@ -34,7 +33,8 @@ export function getVariableNames(
3433

3534
if (includeLocals && t.isBlockStatement(functionNode.body)) {
3635
const paramSet = new Set(functionNode.params.flatMap((p) => getPatternIdentifiers(p)));
37-
const functionName = t.isIdentifier(functionNode.id) ? functionNode.id.name : '';
36+
const functionName =
37+
'id' in functionNode && t.isIdentifier(functionNode.id) ? functionNode.id.name : '';
3838

3939
for (const stmt of functionNode.body.body) {
4040
if (t.isVariableDeclaration(stmt)) {
@@ -56,15 +56,7 @@ export function getVariableNames(
5656
return variables;
5757
}
5858

59-
function getPatternIdentifiers(
60-
pattern:
61-
| t.Identifier
62-
| t.RestElement
63-
| t.AssignmentPattern
64-
| t.ObjectPattern
65-
| t.ArrayPattern
66-
| t.TSParameterProperty,
67-
): string[] {
59+
function getPatternIdentifiers(pattern: t.Node): string[] {
6860
if (t.isIdentifier(pattern)) {
6961
return [pattern.name];
7062
}
@@ -85,7 +77,7 @@ function getPatternIdentifiers(
8577
return getPatternIdentifiers(property.argument);
8678
}
8779

88-
return getPatternIdentifiers(property.value as typeof pattern);
80+
return getPatternIdentifiers(property.value);
8981
});
9082
}
9183

@@ -95,7 +87,7 @@ function getPatternIdentifiers(
9587
return [];
9688
}
9789

98-
return getPatternIdentifiers(element as typeof pattern);
90+
return getPatternIdentifiers(element);
9991
});
10092
}
10193

packages/plugins/rum/src/built/live-debugger-helpers.ts

Lines changed: 0 additions & 26 deletions
This file was deleted.

0 commit comments

Comments
 (0)