Skip to content

Commit 3712b6d

Browse files
committed
Revert "fix: Updated transformer to prevent instrumenting a non-existent method on a class (#59)"
This reverts commit 661eb1a.
1 parent 661eb1a commit 3712b6d

7 files changed

Lines changed: 11 additions & 90 deletions

File tree

lib/transformer.js

Lines changed: 5 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -95,9 +95,8 @@ class Transformer {
9595
state.operator = this.#getOperator(state)
9696

9797
esquery.traverse(ast, esquery.parse(query), (...args) => {
98-
if (this.#visit(state, ...args)) {
99-
injectionCount++
100-
}
98+
injectionCount++
99+
this.#visit(state, ...args)
101100
})
102101
}
103102

@@ -138,12 +137,11 @@ class Transformer {
138137
*
139138
* @param {object} state - Merged config + runtime state for this traversal.
140139
* @param {...unknown} args - `(node, parent, ancestry)` from esquery traverse.
141-
* @returns {boolean} True if injection should be counted, false otherwise.
142140
*/
143141
#visit (state, ...args) {
144142
const transform = this.#customTransforms[state.operator] ?? transforms[state.operator]
145143
const { index = 0 } = state.functionQuery
146-
const [node, , ancestry] = args
144+
const [node] = args
147145
const type = node.init?.type || node.type
148146

149147
// Class nodes are visited for traceInstanceMethod (missing method patching),
@@ -153,41 +151,14 @@ class Transformer {
153151
// nested class like `let Server = (() => { class Server {} })()`) is only
154152
// matched because `[id.name="Server"]` is broad. It is not a function node
155153
// and should not be instrumented or counted toward the function index.
156-
if (node.type === 'VariableDeclarator') return false
154+
if (node.type === 'VariableDeclarator') return
157155

158156
state.functionIndex = ++state.functionIndex || 0
159157

160-
if (index !== null && index !== state.functionIndex) return false
161-
} else {
162-
// For class nodes, validate that the method exists before instrumenting
163-
const { methodName } = state.functionQuery
164-
if (methodName) {
165-
// Handle both ClassDeclaration/ClassExpression and VariableDeclarator with ClassExpression init
166-
const classNode = node.type === 'VariableDeclarator' ? node.init : node
167-
const classBody = classNode.body
168-
const methodExists = classBody.body.some(({ key }) => key?.name === methodName)
169-
170-
if (!methodExists) {
171-
// Method doesn't exist on the class. Check if any subclass has it.
172-
const className = classNode.id?.name || node.id?.name
173-
const program = ancestry[ancestry.length - 1]
174-
175-
if (className) {
176-
const hasMethodInSubclass = esquery.query(
177-
program,
178-
`ClassDeclaration[superClass.name="${className}"] > ClassBody > MethodDefinition[key.name="${methodName}"]`
179-
).length > 0
180-
181-
if (!hasMethodInSubclass) {
182-
throw new Error(`Method '${methodName}' not found on class '${className}' or any of its subclasses`)
183-
}
184-
}
185-
}
186-
}
158+
if (index !== null && index !== state.functionIndex) return
187159
}
188160

189161
transform(state, ...args)
190-
return true
191162
}
192163

193164
/**

tests/injection_failure/test.mjs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
1+
/**
2+
* Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License.
3+
* This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2025 Datadog, Inc.
4+
**/
15
import { existsSync } from 'node:fs'
26
import { assert } from '../common/preamble.js'
37

4-
const instrumented = existsSync('./instrumented.mjs')
5-
assert.strictEqual(instrumented, false, 'instrumented.mjs should not exist')
8+
const instrumented = existsSync('./instrumented.js')
9+
assert.strictEqual(instrumented, false, 'instrumented.js should not exist')

tests/injection_failure_method_name/mod.mjs

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

tests/injection_failure_method_name/test.mjs

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

tests/injection_failure_method_name_subclass/mod.mjs

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

tests/injection_failure_method_name_subclass/test.mjs

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

tests/tests.test.mjs

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -196,30 +196,6 @@ describe('injection_failure', () => {
196196
})
197197
})
198198

199-
describe('injection_failure_method_name', () => {
200-
test('does not write instrumented file when no injection points found', () => {
201-
runTest('injection_failure_method_name', [
202-
{
203-
channelName: 'injection_failure_method_name',
204-
module: { name: TEST_MODULE_NAME, versionRange: '>=0.0.1', filePath: TEST_MODULE_PATH },
205-
functionQuery: { className: 'Foo', methodName: 'nonExistentMethod', kind: 'Async' },
206-
},
207-
], { mjs: true })
208-
})
209-
})
210-
211-
describe('injection_failure_method_name_sub_class', () => {
212-
test('does not write instrumented file when no injection points found', () => {
213-
runTest('injection_failure_method_name_subclass', [
214-
{
215-
channelName: 'injection_failures_subclass_method_name',
216-
module: { name: TEST_MODULE_NAME, versionRange: '>=0.0.1', filePath: TEST_MODULE_PATH },
217-
functionQuery: { className: 'Base', methodName: 'nonExistentMethod', kind: 'Async' },
218-
},
219-
], { mjs: true })
220-
})
221-
})
222-
223199
describe('multiple_class_method_cjs', () => {
224200
test('instruments multiple class methods', () => {
225201
runTest('multiple_class_method_cjs', [

0 commit comments

Comments
 (0)