diff --git a/lib/transforms.js b/lib/transforms.js index 99de862..9ed138d 100644 --- a/lib/transforms.js +++ b/lib/transforms.js @@ -188,7 +188,9 @@ function traceInstanceMethod (state, node, program) { // If the method exists on the class, we return as it will be patched later // while traversing child nodes later on. - if (classBody.body.some(({ key }) => key.name === methodName)) return + // `key` is absent on members without one (e.g. ES2022 `static {}` blocks), + // so guard against reading `.name` on undefined. + if (classBody.body.some(({ key }) => key?.name === methodName)) return // Method doesn't exist on the class so we assume an instance method and // wrap it in the constructor instead. diff --git a/tests/static_block_cjs/mod.js b/tests/static_block_cjs/mod.js new file mode 100644 index 0000000..78b1635 --- /dev/null +++ b/tests/static_block_cjs/mod.js @@ -0,0 +1,18 @@ +/** + * Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. + * This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2025 Datadog, Inc. + **/ +class UndiciBase { + async fetch (url) { + return 42 + } +} +class Undici extends UndiciBase { + static { this.KIND = 'undici' } + static { this.VERSION = 1 } + async fetch (url) { + return super.fetch(url) + } +} + +module.exports = Undici diff --git a/tests/static_block_cjs/test.js b/tests/static_block_cjs/test.js new file mode 100644 index 0000000..70781ba --- /dev/null +++ b/tests/static_block_cjs/test.js @@ -0,0 +1,21 @@ +/** + * Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. + * This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2025 Datadog, Inc. + **/ +const Undici = require('./instrumented.js') +const { assert, getContext } = require('../common/preamble.js') +const context = getContext('orchestrion:undici:Undici:fetch'); +(async () => { + // Static init blocks are preserved and still run. + assert.strictEqual(Undici.KIND, 'undici') + assert.strictEqual(Undici.VERSION, 1) + const undici = new Undici() + const result = await undici.fetch('https://example.com') + assert.strictEqual(result, 42) + assert.deepStrictEqual(context, { + start: true, + end: true, + asyncStart: 42, + asyncEnd: 42 + }) +})() diff --git a/tests/tests.test.mjs b/tests/tests.test.mjs index 884e822..8b893a3 100644 --- a/tests/tests.test.mjs +++ b/tests/tests.test.mjs @@ -89,6 +89,18 @@ describe('class_method_cjs', () => { }) }) +describe('static_block_cjs', () => { + test('instruments class method when class body has static init blocks', () => { + runTest('static_block_cjs', [ + { + channelName: 'Undici:fetch', + module: { name: TEST_MODULE_NAME, versionRange: '>=0.0.1', filePath: TEST_MODULE_PATH }, + functionQuery: { className: 'Undici', methodName: 'fetch', kind: 'Async' }, + }, + ]) + }) +}) + describe('constructor_cjs', () => { test('instruments class constructor (cjs)', () => { runTest('constructor_cjs', [