Skip to content

Commit f59ff40

Browse files
authored
fix: Updated module patch to only wrap _compile as it calls _resolveFileName (#13)
1 parent 428c8fe commit f59ff40

File tree

7 files changed

+24
-53
lines changed

7 files changed

+24
-53
lines changed
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
"const { tracingChannel: tr_ch_apm_tracingChannel } = require(\"diagnostics_channel\");\nconst tr_ch_apm$unitTestCjs = tr_ch_apm_tracingChannel(\"orchestrion:pkg-1:unitTestCjs\");\nclass Foo {\n constructor(){\n this.name = 'foo';\n }\n doStuff() {\n const __apm$original_args = arguments;\n const __apm$traced = async ()=>{\n const __apm$wrapped = async ()=>{\n return 'doing stuff';\n };\n return __apm$wrapped.apply(null, __apm$original_args);\n };\n if (!tr_ch_apm$unitTestCjs.hasSubscribers) return __apm$traced();\n return tr_ch_apm$unitTestCjs.tracePromise(__apm$traced, {\n arguments,\n self: this,\n moduleVersion: \"1.0.0\"\n });\n }\n}\nmodule.exports = Foo;\n"
1+
"const { tracingChannel: tr_ch_apm_tracingChannel } = require(\"diagnostics_channel\");\nconst tr_ch_apm$unitTestCjs = tr_ch_apm_tracingChannel(\"orchestrion:pkg-1:unitTestCjs\");\nclass Foo {\n constructor(){\n this.name = 'foo';\n }\n doStuff() {\n const __apm$original_args = arguments;\n const __apm$traced = ()=>{\n const __apm$wrapped = ()=>{\n return 'doing stuff';\n };\n return __apm$wrapped.apply(null, __apm$original_args);\n };\n if (!tr_ch_apm$unitTestCjs.hasSubscribers) return __apm$traced();\n return tr_ch_apm$unitTestCjs.tracePromise(__apm$traced, {\n arguments,\n self: this,\n moduleVersion: \"1.0.0\"\n });\n }\n}\nmodule.exports = Foo;\n"
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
"const { tracingChannel: tr_ch_apm_tracingChannel } = require(\"diagnostics_channel\");\nconst tr_ch_apm$unitTestCjs = tr_ch_apm_tracingChannel(\"orchestrion:pkg-1:unitTestCjs\");\nclass Foo {\n constructor(){\n this.name = 'foo';\n }\n doStuff() {\n const __apm$original_args = arguments;\n const __apm$traced = async ()=>{\n const __apm$wrapped = async ()=>{\n return 'doing stuff';\n };\n return __apm$wrapped.apply(null, __apm$original_args);\n };\n if (!tr_ch_apm$unitTestCjs.hasSubscribers) return __apm$traced();\n return tr_ch_apm$unitTestCjs.tracePromise(__apm$traced, {\n arguments,\n self: this,\n moduleVersion: \"1.0.0\"\n });\n }\n}\nmodule.exports = Foo;\n"
1+
"const { tracingChannel: tr_ch_apm_tracingChannel } = require(\"diagnostics_channel\");\nconst tr_ch_apm$unitTestCjs = tr_ch_apm_tracingChannel(\"orchestrion:pkg-1:unitTestCjs\");\nclass Foo {\n constructor(){\n this.name = 'foo';\n }\n doStuff() {\n const __apm$original_args = arguments;\n const __apm$traced = ()=>{\n const __apm$wrapped = ()=>{\n return 'doing stuff';\n };\n return __apm$wrapped.apply(null, __apm$original_args);\n };\n if (!tr_ch_apm$unitTestCjs.hasSubscribers) return __apm$traced();\n return tr_ch_apm$unitTestCjs.tracePromise(__apm$traced, {\n arguments,\n self: this,\n moduleVersion: \"1.0.0\"\n });\n }\n}\nmodule.exports = Foo;\n"
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
"import { tracingChannel as tr_ch_apm_tracingChannel } from \"diagnostics_channel\";\nconst tr_ch_apm$unitTestEsm = tr_ch_apm_tracingChannel(\"orchestrion:esm-pkg:unitTestEsm\");\nclass Foo {\n constructor(){\n this.name = 'foo';\n }\n doStuff() {\n const __apm$original_args = arguments;\n const __apm$traced = async ()=>{\n const __apm$wrapped = async ()=>{\n return 'doing stuff';\n };\n return __apm$wrapped.apply(null, __apm$original_args);\n };\n if (!tr_ch_apm$unitTestEsm.hasSubscribers) return __apm$traced();\n return tr_ch_apm$unitTestEsm.tracePromise(__apm$traced, {\n arguments,\n self: this,\n moduleVersion: \"1.0.0\"\n });\n }\n}\nexport default Foo;\n"
1+
"import { tracingChannel as tr_ch_apm_tracingChannel } from \"diagnostics_channel\";\nconst tr_ch_apm$unitTestEsm = tr_ch_apm_tracingChannel(\"orchestrion:esm-pkg:unitTestEsm\");\nclass Foo {\n constructor(){\n this.name = 'foo';\n }\n doStuff() {\n const __apm$original_args = arguments;\n const __apm$traced = ()=>{\n const __apm$wrapped = ()=>{\n return 'doing stuff';\n };\n return __apm$wrapped.apply(null, __apm$original_args);\n };\n if (!tr_ch_apm$unitTestEsm.hasSubscribers) return __apm$traced();\n return tr_ch_apm$unitTestEsm.tracePromise(__apm$traced, {\n arguments,\n self: this,\n moduleVersion: \"1.0.0\"\n });\n }\n}\nexport default Foo;\n"
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
"class Foo {\n constructor(){\n this.name = 'foo';\n }\n doStuff() {\n const __apm$original_args = arguments;\n const __apm$traced = async ()=>{\n const __apm$wrapped = async ()=>{\n return 'doing stuff';\n };\n return __apm$wrapped.apply(null, __apm$original_args);\n };\n if (!tr_ch_apm$unitTest.hasSubscribers) return __apm$traced();\n return tr_ch_apm$unitTest.tracePromise(__apm$traced, {\n arguments,\n self: this,\n moduleVersion: \"1.0.0\"\n });\n }\n}"
1+
"class Foo {\n constructor(){\n this.name = 'foo';\n }\n doStuff() {\n const __apm$original_args = arguments;\n const __apm$traced = ()=>{\n const __apm$wrapped = ()=>{\n return 'doing stuff';\n };\n return __apm$wrapped.apply(null, __apm$original_args);\n };\n if (!tr_ch_apm$unitTest.hasSubscribers) return __apm$traced();\n return tr_ch_apm$unitTest.tracePromise(__apm$traced, {\n arguments,\n self: this,\n moduleVersion: \"1.0.0\"\n });\n }\n}"

index.js

Lines changed: 17 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -9,45 +9,36 @@ class ModulePatch {
99
constructor({ instrumentations = [] } = {}) {
1010
this.packages = new Set(instrumentations.map(i => i.module.name))
1111
this.instrumentator = create(instrumentations)
12-
this.transformers = new Map()
13-
this.resolve = Module._resolveFilename
1412
this.compile = Module.prototype._compile
1513
}
1614

1715
/**
18-
* Patches the Node.js module class methods that are responsible for resolving filePaths and compiling code.
16+
* Patches the Node.js module class method that is responsible for compiling code.
1917
* If a module is found that has an instrumentator, it will transform the code before compiling it
2018
* with tracing channel methods.
2119
*/
2220
patch() {
2321
const self = this
24-
Module._resolveFilename = function wrappedResolveFileName() {
25-
const resolvedName = self.resolve.apply(this, arguments)
26-
const resolvedModule = parse(resolvedName)
22+
Module.prototype._compile = function wrappedCompile(...args) {
23+
const [content, filename] = args
24+
const resolvedModule = parse(filename)
2725
if (resolvedModule && self.packages.has(resolvedModule.name)) {
26+
debug('found resolved module, checking if there is a transformer %s', filename)
2827
const version = getPackageVersion(resolvedModule.basedir, resolvedModule.name)
2928
const transformer = self.instrumentator.getTransformer(resolvedModule.name, version, resolvedModule.path)
3029
if (transformer) {
31-
self.transformers.set(resolvedName, transformer)
32-
}
33-
}
34-
return resolvedName
35-
}
36-
37-
Module.prototype._compile = function wrappedCompile(...args) {
38-
const [content, filename] = args
39-
if (self.transformers.has(filename)) {
40-
const transformer = self.transformers.get(filename)
41-
try {
42-
const transformedCode = transformer.transform(content, 'unknown')
43-
args[0] = transformedCode?.code
44-
if (process.env.TRACING_DUMP) {
45-
dump(args[0], filename)
30+
debug('transforming file %s', filename)
31+
try {
32+
const transformedCode = transformer.transform(content, 'unknown')
33+
args[0] = transformedCode?.code
34+
if (process.env.TRACING_DUMP) {
35+
dump(args[0], filename)
36+
}
37+
} catch (error) {
38+
debug('Error transforming module %s: %o', filename, error)
39+
} finally {
40+
transformer.free()
4641
}
47-
} catch (error) {
48-
debug('Error transforming module %s: %o', filename, error)
49-
} finally {
50-
transformer.free()
5142
}
5243
}
5344

@@ -56,12 +47,10 @@ class ModulePatch {
5647
}
5748

5849
/**
59-
* Clears all the transformers and restores the original Module methods that were wrapped.
50+
* Restores the original Module.prototype._compile method
6051
* **Note**: This is intended to be used in testing only.
6152
*/
6253
unpatch() {
63-
this.transformers.clear()
64-
Module._resolveFilename = this.resolve
6554
Module.prototype._compile = this.compile
6655
}
6756
}

package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@
1010
},
1111
"main": "index.js",
1212
"scripts": {
13-
"test": "c8 borp 'test/**/*.test.{js,mjs}'"
13+
"test": "c8 borp 'test/**/*.test.{js,mjs}'",
14+
"test:update-snapshots": "SNAP_UPDATE=1 npm test"
1415
},
1516
"files": [
1617
"index.js",
@@ -27,4 +28,4 @@
2728
"borp": "^0.20.1",
2829
"c8": "^10.1.3"
2930
}
30-
}
31+
}

test/index.test.js

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -41,26 +41,7 @@ test('should init ModulePatch', (t) => {
4141
const { modulePatch } = t.ctx
4242
assert.ok(modulePatch instanceof ModulePatch)
4343
assert.ok(modulePatch.instrumentator)
44-
assert.equal(modulePatch.resolve, Module._resolveFilename)
4544
assert.ok(modulePatch.compile, Module.prototype._compile)
46-
assert.ok(modulePatch.transformers instanceof Map)
47-
})
48-
49-
test('should set a transformer for a matched patch', (t) => {
50-
const { modulePath, modulePatch } = t.ctx
51-
modulePatch.patch()
52-
Module._resolveFilename(modulePath, null, false)
53-
assert.ok(modulePatch.transformers.has(modulePath))
54-
modulePatch.unpatch()
55-
assert.equal(modulePatch.transformers.size, 0)
56-
})
57-
58-
test('should not set a transformer for an unmatched patch', (t) => {
59-
const { modulePatch } = t.ctx
60-
modulePatch.patch()
61-
const modulePath = path.join(__dirname, './example-deps/lib/node_modules/pkg-2/index.js')
62-
Module._resolveFilename(modulePath, null, false)
63-
assert.equal(modulePatch.transformers.size, 0)
6445
})
6546

6647
test('should rewrite code for a match transformer', async (t) => {

0 commit comments

Comments
 (0)