diff --git a/index.d.ts b/index.d.ts index 380e404..53be28a 100644 --- a/index.d.ts +++ b/index.d.ts @@ -52,10 +52,11 @@ export interface InstrumentationConfig { */ functionQuery: FunctionQuery; /** - * The name of a custom transform registered via `addTransform`. - * When set, takes precedence over `functionQuery.kind`. + * A custom transform to apply. When a string, it must match the name of a + * transform registered via `addTransform`. When a function, it is called + * directly. Either form takes precedence over `functionQuery.kind`. */ - transform?: string; + transform?: string | CustomTransform; } /** diff --git a/lib/transformer.js b/lib/transformer.js index 76d6c4d..2813958 100644 --- a/lib/transformer.js +++ b/lib/transformer.js @@ -164,7 +164,9 @@ class Transformer { * @param {...unknown} args - `(node, parent, ancestry)` from esquery traverse. */ #visit (state, ...args) { - const transform = this.#customTransforms[state.operator] ?? transforms[state.operator] + const transform = typeof state.transform === 'function' + ? state.transform + : (this.#customTransforms[state.operator] ?? transforms[state.operator]) const { index = 0 } = state.functionQuery const [node] = args const type = node.init?.type || node.type @@ -196,7 +198,7 @@ class Transformer { * @returns {string} Operator name, e.g. `'tracePromise'`. */ #getOperator ({ transform, functionQuery: { kind } }) { - if (transform) return transform + if (typeof transform === 'string') return transform switch (kind) { case 'Async': return 'tracePromise' diff --git a/tests/custom_transform_fn_cjs/mod.js b/tests/custom_transform_fn_cjs/mod.js new file mode 100644 index 0000000..4a6b8a9 --- /dev/null +++ b/tests/custom_transform_fn_cjs/mod.js @@ -0,0 +1,5 @@ +function fetch (url) { + return 42 +} + +module.exports = { fetch } diff --git a/tests/custom_transform_fn_cjs/test.js b/tests/custom_transform_fn_cjs/test.js new file mode 100644 index 0000000..0794b22 --- /dev/null +++ b/tests/custom_transform_fn_cjs/test.js @@ -0,0 +1,5 @@ +const { fetch } = require('./instrumented.js') +const assert = require('node:assert') + +fetch('https://example.com') +assert.strictEqual(global.__customCalled, true) diff --git a/tests/tests.test.mjs b/tests/tests.test.mjs index e2eccdc..402e889 100644 --- a/tests/tests.test.mjs +++ b/tests/tests.test.mjs @@ -418,6 +418,35 @@ describe('polyfill_mjs', () => { }) }) +describe('custom_transform_fn_cjs', () => { + test('applies a custom transform function passed directly in the config', () => { + runTest('custom_transform_fn_cjs', [ + { + channelName: 'fetch_custom', + module: { name: TEST_MODULE_NAME, versionRange: '>=0.0.1', filePath: TEST_MODULE_PATH }, + functionQuery: { functionName: 'fetch', kind: 'Sync' }, + transform (_state, node) { + node.body.body.unshift({ + type: 'ExpressionStatement', + expression: { + type: 'AssignmentExpression', + operator: '=', + left: { + type: 'MemberExpression', + object: { type: 'Identifier', name: 'global' }, + property: { type: 'Identifier', name: '__customCalled' }, + computed: false, + optional: false, + }, + right: { type: 'Literal', value: true, raw: 'true' }, + }, + }) + }, + }, + ]) + }) +}) + describe('custom_transform_cjs', () => { test('applies a custom transform registered via addTransform', () => { runTest('custom_transform_cjs', [