fix: rewrite plugin loader#686
Conversation
b210598 to
64b0bf2
Compare
Codecov Report
@@ Coverage Diff @@
## master #686 +/- ##
==========================================
+ Coverage 89.45% 90.54% +1.09%
==========================================
Files 29 29
Lines 1422 1439 +17
Branches 287 285 -2
==========================================
+ Hits 1272 1303 +31
+ Misses 66 57 -9
+ Partials 84 79 -5
Continue to review full report at Codecov.
|
57ae381 to
e3f0558
Compare
e3f0558 to
5cc7dad
Compare
a64a8e2 to
f330840
Compare
cc98657 to
8fa83cf
Compare
5badda4 to
019db1f
Compare
019db1f to
6f73473
Compare
jinwoo
left a comment
There was a problem hiding this comment.
Still reviewing. Sending some comments first.
| pluginLoader.deactivate(); | ||
| try { | ||
| const loader = pluginLoader.get(); | ||
| loader.deactivate(); |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
| try { | ||
| const loader = pluginLoader.get(); | ||
| loader.deactivate(); | ||
| } catch (e) { |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
| export type Instrumentation<T> = Patch<T>|Intercept<T>; | ||
|
|
||
| export type Plugin = Array<Instrumentation<any>>; | ||
| export type Plugin = Array<Partial<Patch<any>>>; |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
| export class ModulePluginWrapper implements PluginWrapper { | ||
| // Sentinel value to indicate that a plugin has not been loaded into memory | ||
| // yet. | ||
| private static readonly NOT_LOADED: Plugin = []; |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
| // ranges | ||
| let numFiles = 0; | ||
| plugin.forEach(instrumentation => { | ||
| const postLoadVersions = instrumentation.versions; |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
| } | ||
|
|
||
| unapplyAll() { | ||
| this.unpatchFns.reverse().forEach(fn => fn()); |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
| this.unpatchFns.push(() => { | ||
| this.logger.info( | ||
| `PluginWrapper#unapplyAll: [${logString}] Unpatching file.`); | ||
| instrumentation.unpatch!(exportedValue); |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
jinwoo
left a comment
There was a problem hiding this comment.
Sorry I didn't look at test code very closely.
| logger.error('Plugins activated more than once.'); | ||
| return; | ||
| /** | ||
| * A class that represents wrapper logic on top of plugins that patch core |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
| */ | ||
| applyPlugin<T>(moduleExports: T, file: string, version: string): T { | ||
| return this.children.reduce((exportedValue, child) => { | ||
| return child.applyPlugin(exportedValue, file, version); |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
| */ | ||
| export class PluginLoader { | ||
| // Key on which core modules are stored. | ||
| static readonly CORE_MODULE = '[core]'; |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
| * @param config The configuration for this instance. | ||
| */ | ||
| constructor(logger: Logger, config: PluginLoaderConfig) { | ||
| this.logger = logger; |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
| const value = config.plugins[key]; | ||
| // Core module plugins share a common key. | ||
| const coreModule = builtinModules.indexOf(key) !== -1 || | ||
| key === PluginLoader.CORE_MODULE; |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
| * loaded or applied, as well as unpatching any modules for which plugins | ||
| * specified an unpatching method. | ||
| */ | ||
| deactivate(): PluginLoader { |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
| * Adds a search path for plugin modules. Intended for testing purposes only. | ||
| * @param searchPath The path to add. | ||
| */ | ||
| static setPluginSearchPath(searchPath: string) { |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
| const parts = moduleStr.replace(/\\/g, '/').split('/'); | ||
| let indexOfFile = 1; | ||
| if (parts[0].startsWith('@')) { // for @org/package | ||
| indexOfFile = 2; |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
| @@ -1,5 +1,5 @@ | |||
| /** | |||
| * Copyright 2017 Google Inc. All Rights Reserved. | |||
| * Copyright 2018 Google Inc. All Rights Reserved. | |||
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
| 'module-h': 'module-h-plugin' | ||
| } | ||
|
|
||
| it('doesn\'t unpatch twice', () => { |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
065bc5b to
d7d46a0
Compare
d7d46a0 to
11a0fc9
Compare
| @@ -1,4 +1,5 @@ | |||
| node_modules/ | |||
| !test/fixtures/loader/node_modules/ | |||
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
| export type Instrumentation<T> = Patch<T>|Intercept<T>; | ||
|
|
||
| export type Plugin = Array<Instrumentation<any>>; | ||
| export type Plugin = Array<Partial<Patch<any>>>; |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
| var shimmer = require('shimmer'); | ||
| var util = require('util'); | ||
|
|
||
| // knex 0.10.x and 0.11.x do not need patching |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
11a0fc9 to
59644b1
Compare
59644b1 to
eb986a3
Compare
This change re-writes the Plugin Loader entirely.
The existing Plugin Loader code exists as a set of module-scope functions and variables. While there aren’t any major problems here, it’s worth re-writing it for the following reasons:
User-facing changes:
(Edit: This has been reverted.)Intercept<T>is no longer a type on the public interface of the Trace Agent; its definition was merged withPatch<T>. Arguably, they are all "patches". Users will still be warned if they provide bothpatchandintercept.patchorinterceptexist on aPatch. This is to prevent needless warnings when a module such asknexneeds patches for some versions but not others.'[core]'plugin key. A plugin loaded under this key would behave as if the key were any other core module, such as'http'. The plan is that at some point, we would use the'[core]'key to patch core modules rather than'http', because it's somewhat misleading that'http'also patches'https'.(All of these are up for discussion.)
Notes for Reviewers
trace-plugin-loader.tsis completely useless. I recommend looking at the commits separately -- the first commit is just the removal of the old file.