Inversifyjs: Inversify doesn't work well when reflect-metadata is loaded again

Created on 4 Jan 2018  路  8Comments  路  Source: inversify/InversifyJS

I understand that reflelect-metadata needs to be loaded once per application. However I'd like to bring this up once again and hope we could somehow find a work around for this.

Recently our VS Code Python Extension for Visual Studio Code stopped working because another extension was loading reflect-metadata unconditionally. As our extension is used by a million users, this was a fairly serious issue. We (both VS Code extensions) have adopted the solution of conditionally importing reflect-metadata.

However this doesn't prevent others from creating extensions that directly or indirectly load reflect-metadata. E.g. other IOC libraries such as typescript-ioc load reflect-metadata regardless.

https://github.com/Microsoft/vscode-python/issues/432

Is there any other solution to this, or alternative to reflect-metadata?

Most helpful comment

This should now be fixed in [email protected] or later. However, if an earlier version of reflect-metadata (<= 0.1.10) is loaded after the 0.1.12 version, this problem will still occur.

All 8 comments

Hi @DonJayamanne,

I think this issue should be fixed by the reflect-metadata module. The reflect-metadata module is supposed to be a polyfill. I think it should not override itself everytime it is loaded.

The problem is somewhere in https://github.com/rbuckton/reflect-metadata/blob/master/Reflect.ts#L1697-L1715

Many people have already reported similar issues:

https://github.com/rbuckton/reflect-metadata/issues/78
https://github.com/rbuckton/reflect-metadata/issues/45
...

But the module seems to not be actively maintained :cry: The module has been created by one of the TypeScript engineers at Microsoft. Since you guys work at vscode maybe you can contact him through Microsoft?

The reflect-metadata has actually become a very important module (It is used by +30K public repos) in the entire TypeScript ecosystem. I would actually like it to become something supported officially by Microsoft (like DefinitelyTyped). I wonder what @DanielRosenwasser thinks about this?

@remojansen Thanks for the response, I'll ping @rbuckton.

Is it possible for Inversify not to use reflect-metadata or for a user of Inversify to provide the functionality exposed by reflect-metadata (by providing its own API for storage and retrieval of the metadata)?

At the end of the day reflect-metadata is not an optional module of inversify, users of inversify MUST install reflect-metadata.

Hi @DonJayamanne about:

Is it possible for Inversify not to use reflect-metadata or for a user of Inversify to provide the functionality exposed by reflect-metadata (by providing its own API for storage and retrieval of the metadata)?

This feature is not avaiable righ now but I started to work on it last night. I will provide you with an interface to read and write metadata. The default implementation of the interface will use reflect-metadata but you should be able to create your own implementations.

About:

At the end of the day reflect-metadata is not an optional module of inversify, users of inversify MUST install reflect-metadata.

This is true, but only for a period of time. In theory, in the future reflect-metadata should only be required by browsers without native support for it. It could be conditionally loaded but we will still have problems if two other extensions use it.

@DonJayamanne I was trying to fix this issue in InversifyJS but after a few hours, I realized that there is not much that I can do. It needs to be fixed in the reflect-metadata package but even that is not a 100% safe solution because if an extension is using an outdated reflect-metadata or another polyfill that overrides the Reflect object we will hit the same issue.

This is something that needs to be addressed by the polyfill authors it should not have to be addressed by the lib authors or the vscode extension authors.

The other option would be that vscode could use isolated globals for each extension. That way extension and library authors would not have to worry but I don't know if this is an option. I have created an issue to ask for this https://github.com/Microsoft/vscode/issues/41297

This should now be fixed in [email protected] or later. However, if an earlier version of reflect-metadata (<= 0.1.10) is loaded after the 0.1.12 version, this problem will still occur.

Thanks a lot for the fix and release @rbuckton 馃憤

@DonJayamanne I'm closing this issue. Thanks a lot for using InversifyJS :smile:

I am hoping @remojansen & @rbuckton may be able to provide some insight here...

For one of our front-end projects we are currently using InversifyJS as well as Aurelia and Webpack 3 (via aurelia/webpack-plugin and aurelia/bootstrapper) The issue described above with [email protected] actually provided unintended behavior that we considered advantageous up until updating to [email protected].

I believe the recommended usage for the Aurelia webpack-plugin is to pair it with either the aurelia/bootstrapper or aurelia/bootstrapper-webpack module as the entry point being
specified in webpack.config.js. These modules bootstrap the aurelia app by searching the DOM and subsequently loading your main/index.js file where we have our import 'reflect-metadata'.

Unfortunately, the Aurelia bootstrapper(s) will first load aurelia/polyfills which includes a Reflection API implementation. For some reason, this implementation was causing the InversifyJS injectable() decorators to be ignored at run-time when resolving dependencies from the container. I am not sure how the implementations differ between rbuckton/reflect-metadata and aurelia/polyfills, but to make a long story short our application only works if reflect-metadata overrides the other Reflection polyfill.

Since the Aurelia Reflect polyfill always got "clobbered" by our initial import 'reflect-metadata', we never had any issues until the most recent changes came in [email protected]. However, a recent npm install revealed this issue (and led me here.)

I realize this is more of an issue with the Aurelia bootstrapping code for Webpack rather than InversifyJS or even reflect-metadata, but i still wanted to point out that the change in behavior could have adverse effects on users of InversifyJS / Aurelia / Webpack if they actually WANT reflect-metadata to override other polyfills.

Was this page helpful?
0 / 5 - 0 ratings