-
Notifications
You must be signed in to change notification settings - Fork 27.5k
Warn on injection by name that will fail when minified #4504
Comments
Something like this wouldn't be too bad, but IMO it would have to be a custom build of angular --- The "primary" build would need to remove it via a preprocessor or something. We often like to use tools like ngmin in order to use minify-safe DI notation, but use the simple notation for readability. Tests will often use the pre-ngmin'd code, and you don't really want your test runner being spammed with "WARNING: BADNESS -- USE SAFER DI NOTATION". I guess what I'm saying is, it should ideally be an opt-in warning, and preferably one which wouldn't add unused bytes to the default build (although it probably wouldn't be that big of a deal). |
It definitely would have to be opt in. I actually have those lines commented out most of the time because they do spam my tests with warnings (I write my tests using the name based injection), but then I turn it on and check things before pushing to production. It would work with 2 builds of angular, one I could require for tests, and the other I could require for dev/production. Similar to the way I use angular-mocks to help stub things during tests. |
+1 This would help so much in dev |
I agree that we should do this. but we need to figure out how to do it so that we don't require strict token declaration for test code and prototyping code. in short, I think we should have an option that would enable/disable DI token inference via argument names. When strict token annotation mode is of, the argument name inference will be disabled, but we should then change the This would allow us to complain if we see any of this in production code:
but not complain if the code above is mixed with a test code like this:
|
Anybody wants to work on this? it shouldn't be that hard. we just need to figure out the configuration api and what the default should be. |
It would be nice if all of the examples just assumed that minification would be taking place at some point as the error messages for this problem are pretty obtuse. It had me stymied for a couple of hours. Everything worked perfectly locally (because it wasn't being minified) -- however once I put it into my test environment on Azure it gave me the white screen of death. Once I figured out that it was the minification process that was causing dependency injection to fail, I went back through all my code and used the array syntax. Bravo -- but then it still didn't work. Then the fine tooth comb came out and I found one pesky little omitted array after a couple of hours. app.config(['$provide', function ($provide) { instead of: app.config(['$provide', function ($provide) { See how I thoughtfully changed it on the line directly above while simultaneously forgetting to make the same change on the line below? Dammit. That said, I learned a lot about Angular while figuring it out -- three cheers for user error. Better error messages are always good, of course. |
Good news, we'll have a fix for this shortly. |
…annotation This modifies the injector to prevent automatic annotation from occurring for a given injector. This behaviour can be enabled when bootstrapping the application by using the attribute "ng-strict-di" on the root element (the element containing "ng-app"), or alternatively by passing an object with the property "strictDi" set to "true" in angular.bootstrap, when bootstrapping manually. JS example: angular.module("name", ["dependencies", "otherdeps"]) .provider("$willBreak", function() { this.$get = function($rootScope) { }; }) .run(["$willBreak", function($willBreak) { // This block will never run because the noMagic flag was set to true, // and the $willBreak '$get' function does not have an explicit // annotation. }]); angular.bootstrap(document, ["name"], { strictDi: true }); HTML: <html ng-app="name" ng-strict-di> <!-- ... --> </html> This will only affect functions with an arity greater than 0, and without an $inject property. Closes angular#6719 Closes angular#6717 Closes angular#4504 Closes angular#6069 Closes angular#3611
…annotation This modifies the injector to prevent automatic annotation from occurring for a given injector. This behaviour can be enabled when bootstrapping the application by using the attribute "ng-strict-di" on the root element (the element containing "ng-app"), or alternatively by passing an object with the property "strictDi" set to "true" in angular.bootstrap, when bootstrapping manually. JS example: angular.module("name", ["dependencies", "otherdeps"]) .provider("$willBreak", function() { this.$get = function($rootScope) { }; }) .run(["$willBreak", function($willBreak) { // This block will never run because the noMagic flag was set to true, // and the $willBreak '$get' function does not have an explicit // annotation. }]); angular.bootstrap(document, ["name"], { strictDi: true }); HTML: <html ng-app="name" ng-strict-di> <!-- ... --> </html> This will only affect functions with an arity greater than 0, and without an $inject property. Closes #6719 Closes #6717 Closes #4504 Closes #6069 Closes #3611
Being that this is opt-in by using the ngStrictDi directive, Is there anything stopping us from backporting this to the 1.2.x line? |
it was initially backported, and I had to revert it because it was too featureful :( only bugfixes in 1.2* I'm afraid. |
@caitp is that the final word on Angular 1.2 support? I'd leap at the opportunity to use this feature -- I've wasted hours on bugs caused by DI annotations. I can't update to Angular 1.3 because of the lack of IE8 support. |
you could always cherrypick that feature into 1.2 manually, but yeah we can't include it in a release unfortunately |
Just a tip for ppl debugging such issues in 1.2 - Object.defineProperty(Function.prototype, '$inject', {
configurable: true,
get: function() {
return this.$injectHooked;
},
set: function (arr) {
if (arr.length && arr[0].length < 3) {
console.error('missing @ngInject:', this);
}
return this.$injectHooked = arr;
}
}); |
Thank you @shahata! This saved my entire day! :-) 👍 |
@shahata! Thank's a lot, it works like a charm! |
It would be awesome to be able to set some sort of configuration to cause angular to throw warnings (or errors) when it is injecting by function argument name.
I'm working on a project that has it's javascript minified in production and therefore need to specify injection arguments explicitly using either the array syntax:
or the $inject syntax:
I'm using those (almost) everywhere in my project, but one of them snuck by me into the minified javascript and was a huge pain to find. I just got errors like
I did eventually find it, but only by trial and error and a lot of searching through the code.
I've modified the angular source a bit to help me find these down the road. I've modified the
annotate
function as follows:That way I am warned in development mode if my code won't work when minified. I know this isn't the right way to do it because it prevents injection by name from working at all (which is why this isn't a pull request), but maybe there is a way we can figure out to make this a configurable option.
Or if we can't maybe angular should always throw a warning (not exception) because shouldn't we all be planning to minify our javascript in production?
The text was updated successfully, but these errors were encountered: