Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Inversify doesn't work well when reflect-metadata is loaded again #737

Closed
DonJayamanne opened this issue Jan 4, 2018 · 8 comments
Closed
Projects

Comments

@DonJayamanne
Copy link
Contributor

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.

microsoft/vscode-python#432

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

@remojansen
Copy link
Member

remojansen commented Jan 4, 2018

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:

rbuckton/reflect-metadata#78
rbuckton/reflect-metadata#45
...

But the module seems to not be actively maintained 😢 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?

@DonJayamanne
Copy link
Contributor Author

DonJayamanne commented Jan 4, 2018

@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.

@remojansen
Copy link
Member

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.

@remojansen remojansen added this to TODO in Status Jan 8, 2018
@remojansen
Copy link
Member

remojansen commented Jan 8, 2018

@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 microsoft/vscode#41297

@rbuckton
Copy link

This should now be fixed in reflect-metadata@0.1.12 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.

@remojansen
Copy link
Member

Thanks a lot for the fix and release @rbuckton 👍

@remojansen
Copy link
Member

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

@NaJ64
Copy link

NaJ64 commented Mar 9, 2018

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 reflect-metadata@0.1.10 actually provided unintended behavior that we considered advantageous up until updating to reflect-metadata@0.1.12.

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 reflect-metadata@0.1.12. 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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Development

No branches or pull requests

4 participants